def generate(self, values): source = BCDataStream() for opcode in self.opcodes: if isinstance(opcode, PUSH_SINGLE): data = values[opcode.name] source.write_many(push_data(data)) elif isinstance(opcode, PUSH_INTEGER): data = values[opcode.name] source.write_many( push_data( data.to_bytes((data.bit_length() + 7) // 8, byteorder='little'))) elif isinstance(opcode, PUSH_SUBSCRIPT): data = values[opcode.name] source.write_many(push_data(data.source)) elif isinstance(opcode, PUSH_MANY): for data in values[opcode.name]: source.write_many(push_data(data)) elif isinstance(opcode, SMALL_INTEGER): data = values[opcode.name] source.write_many(push_small_integer(data)) else: source.write_uint8(opcode) return source.get_bytes()
def tokens(self): return tokenize(BCDataStream(self.source))
def size(self) -> int: """ Size of this input / output in bytes. """ stream = BCDataStream() self.serialize_to(stream) return len(stream.get_bytes())
def _serialize_for_signature(self, signing_input: int) -> bytes: stream = BCDataStream() stream.write_uint32(self.version) stream.write_compact_size(len(self._inputs)) for i, txin in enumerate(self._inputs): if signing_input == i: assert txin.txo_ref.txo is not None txin.serialize_to(stream, txin.txo_ref.txo.script.source) else: txin.serialize_to(stream, b'') stream.write_compact_size(len(self._outputs)) for txout in self._outputs: txout.serialize_to(stream) stream.write_uint32(self.locktime) stream.write_uint32(self.signature_hash_type(1)) # signature hash type: SIGHASH_ALL return stream.get_bytes()
def _serialize(self, with_inputs: bool = True) -> bytes: stream = BCDataStream() stream.write_uint32(self.version) if with_inputs: stream.write_compact_size(len(self._inputs)) for txin in self._inputs: txin.serialize_to(stream) stream.write_compact_size(len(self._outputs)) for txout in self._outputs: txout.serialize_to(stream) stream.write_uint32(self.locktime) return stream.get_bytes()
def _deserialize(self): if self._raw is not None: stream = BCDataStream(self._raw) self.version = stream.read_uint32() input_count = stream.read_compact_size() if input_count == 0: self.is_segwit_flag = stream.read_uint8() input_count = stream.read_compact_size() self._add(self._inputs, [ self.input_class.deserialize_from(stream) for _ in range(input_count) ]) output_count = stream.read_compact_size() self._add(self._outputs, [ self.output_class.deserialize_from(stream) for _ in range(output_count) ]) if self.is_segwit_flag: # drain witness portion of transaction # too many witnesses for no crime self.witnesses = [] for _ in range(input_count): for _ in range(stream.read_compact_size()): self.witnesses.append(stream.read(stream.read_compact_size())) self.locktime = stream.read_uint32()
def test_write_read(self): s = BCDataStream() s.write_string(b'a' * 252) s.write_string(b'b' * 254) s.write_string(b'c' * (0xFFFF + 1)) # s.write_string(b'd'*(0xFFFFFFFF + 1)) s.write_boolean(True) s.write_boolean(False) s.reset() self.assertEqual(s.read_string(), b'a' * 252) self.assertEqual(s.read_string(), b'b' * 254) self.assertEqual(s.read_string(), b'c' * (0xFFFF + 1)) # self.assertEqual(s.read_string(), b'd'*(0xFFFFFFFF + 1)) self.assertTrue(s.read_boolean()) self.assertFalse(s.read_boolean())