def stream_serialize(self, f): OutPoint.stream_serialize(self.prev_out, f) f.write(struct.pack(b'<I', self.sequence)) f.write(struct.pack(b'<q', self.value)) f.write(struct.pack(b'<I', self.block_height)) f.write(struct.pack(b'<I', self.block_index)) BytesSerializer.stream_serialize(self.sig_script, f)
def serialize_field(self, tx, attr, fmt, num_bytes, f): if fmt not in ['inputs', 'outputs', 'bytes']: f.write(struct.pack(fmt, getattr(tx, attr))) elif fmt == 'inputs': VectorSerializer.stream_serialize(CMutableTxIn, tx.vin, f) elif fmt == 'outputs': VectorSerializer.stream_serialize(CMutableTxOut, tx.vout, f) elif fmt == 'bytes': BytesSerializer.stream_serialize(getattr(tx, attr), f)
def stream_serialize(self, f): super(Block, self).stream_serialize(f) for attr, fmt, num_bytes, _ in self.block_fields: if fmt not in ['bytes', 'vectortx']: f.write(struct.pack(fmt, getattr(self, attr))) elif fmt == 'bytes': BytesSerializer.stream_serialize(getattr(self, attr), f) elif fmt == 'vectortx': VectorSerializer.stream_serialize(Transaction, getattr(self, attr), f)
def stream_serialize(self, f): for attr, fmt, num_bytes, _ in self.fields: if fmt not in ["inputs", "outputs", "bytes"]: f.write(struct.pack(fmt, getattr(self, attr))) elif fmt == "inputs": VectorSerializer.stream_serialize(CTxIn, self.vin, f) elif fmt == "outputs": VectorSerializer.stream_serialize(CTxOut, self.vout, f) elif fmt == "bytes": BytesSerializer.stream_serialize(getattr(self, attr), f)
def stream_serialize(self, f): for attr, fmt, num_bytes, _ in self.fields: if fmt not in ['inputs', 'outputs', 'bytes']: f.write(struct.pack(fmt, getattr(self, attr))) elif fmt == 'inputs': VectorSerializer.stream_serialize(CTxIn, self.vin, f) elif fmt == 'outputs': VectorSerializer.stream_serialize(CTxOut, self.vout, f) elif fmt == 'bytes': BytesSerializer.stream_serialize(getattr(self, attr), f)
def stream_serialize(self, f, **kwargs): state = kwargs['state'] if 'state' in kwargs else False if state is True: if self.seal_type is not None: self.seal_type.stream_serialize_state(self.state, f) elif self.state is not None: BytesSerializer.stream_serialize(self.state, f) else: raise SchemaError( f'''Unable to consensus-serialize sealed state: no binary state and no schema seal type are provided for the value `{self.dict_state}` ''') else: self.outpoint.stream_serialize(f, short=True)
def stream_deserialize_value(self, f): lut = { FieldType.Type.u8: lambda: ser_read(f, 1), FieldType.Type.u16: lambda: struct.unpack(b'<H', ser_read(f, 2))[0], FieldType.Type.u32: lambda: struct.unpack(b'<I', ser_read(f, 4))[0], FieldType.Type.u64: lambda: struct.unpack(b'<Q', ser_read(f, 8))[0], FieldType.Type.i8: lambda: ser_read(f, 1), FieldType.Type.i16: lambda: struct.unpack(b'<h', ser_read(f, 2))[0], FieldType.Type.i32: lambda: struct.unpack(b'<i', ser_read(f, 4))[0], FieldType.Type.i64: lambda: struct.unpack(b'<q', ser_read(f, 8))[0], FieldType.Type.vi: lambda: VarIntSerializer.stream_deserialize(f), FieldType.Type.fvi: lambda: FlagVarIntSerializer.stream_deserialize(f), FieldType.Type.str: lambda: VarStringSerializer.stream_deserialize(f).decode('utf-8'), FieldType.Type.bytes: lambda: BytesSerializer.stream_deserialize(f), FieldType.Type.sha256: lambda: Hash256Id.stream_deserialize(f), FieldType.Type.sha256d: lambda: Hash256Id.stream_deserialize(f), FieldType.Type.ripmd160: lambda: Hash160Id.stream_deserialize(f), FieldType.Type.hash160: lambda: Hash160Id.stream_deserialize(f), FieldType.Type.pubkey: lambda: PubKey.stream_deserialize(f), FieldType.Type.ecdsa: lambda: None, } if self.type in lut.keys(): return lut[self.type]() else: raise NotImplementedError()
def stream_deserialize(cls, f): prev_out = OutPoint.stream_deserialize(f) sequence = struct.unpack(b'<I', ser_read(f, 4))[0] value = struct.unpack(b'<q', ser_read(f, 8))[0] block_height = struct.unpack(b'<I', ser_read(f, 4))[0] block_index = struct.unpack(b'<I', ser_read(f, 4))[0] sig_script = BytesSerializer.stream_deserialize(f) return cls(prev_out, sequence, value, block_height, block_index, sig_script)
def deserialize_field(self, tx, kwargs, attr, fmt, num_bytes, f): if fmt not in ['inputs', 'outputs', 'bytes']: kwargs[attr] = struct.unpack(fmt, ser_read(f, num_bytes))[0] elif fmt == 'inputs': kwargs[attr] = VectorSerializer.stream_deserialize(CMutableTxIn, f) elif fmt == 'outputs': kwargs[attr] = VectorSerializer.stream_deserialize(CMutableTxOut, f) elif fmt == 'bytes': kwargs[attr] = BytesSerializer.stream_deserialize(f)
def deserialize_witness(self, f): value = struct.unpack(b'<q', ser_read(f, 8))[0] block_height = struct.unpack(b'<I', ser_read(f, 4))[0] block_index = struct.unpack(b'<I', ser_read(f, 4))[0] sig_script = BytesSerializer.stream_deserialize(f) self.value = value self.block_height = block_height self.block_index = block_index self.sig_script = sig_script
def stream_deserialize(cls, f): self = super(Block, cls).stream_deserialize(f) for attr, fmt, num_bytes, _ in self.block_fields: if fmt not in ['bytes', 'vectortx']: setattr(self, attr, struct.unpack(fmt, ser_read(f, num_bytes))[0]) elif fmt == 'bytes': setattr(self, attr, BytesSerializer.stream_deserialize(f)) elif fmt == 'vectortx': setattr(self, attr, VectorSerializer.stream_deserialize(Transaction, f)) setattr(self, 'vMerkleTree', tuple(Block.build_merkle_tree_from_txs(getattr(self, 'vtx')))) return self
def stream_deserialize(cls, f): self = cls() for attr, fmt, num_bytes, _ in self.fields: if fmt not in ['inputs', 'outputs', 'bytes']: setattr(self, attr, struct.unpack(fmt, ser_read(f, num_bytes))[0]) elif fmt == 'inputs': setattr(self, attr, VectorSerializer.stream_deserialize(CTxIn, f)) elif fmt == 'outputs': setattr(self, attr, VectorSerializer.stream_deserialize(CTxOut, f)) elif fmt == 'bytes': setattr(self, attr, BytesSerializer.stream_deserialize(f)) return self
def stream_serialize_value(self, value, f): if value is None: if self.type is FieldType.Type.str or self.type is FieldType.Type.bytes: f.write(bytes([0x00])) elif self.type is FieldType.Type.fvi: f.write(bytes([0xFF])) elif self.type in [FieldType.Type.sha256, FieldType.Type.sha256d]: f.write(bytes([0]*32)) elif self.type in [FieldType.Type.ripmd160, FieldType.Type.hash160]: f.write(bytes([0]*20)) elif self.type is FieldType.Type.pubkey: f.write(bytes([0x00])) elif self.type is FieldType.Type.ecdsa: f.write(bytes([0x00])) return lut = { FieldType.Type.u8: lambda x: f.write(bytes([x])), FieldType.Type.u16: lambda x: f.write(struct.pack(b'<H', x)), FieldType.Type.u32: lambda x: f.write(struct.pack(b'<I', x)), FieldType.Type.u64: lambda x: f.write(struct.pack(b'<Q', x)), FieldType.Type.i8: lambda x: f.write(bytes([x])), FieldType.Type.i16: lambda x: f.write(struct.pack(b'<h', x)), FieldType.Type.i32: lambda x: f.write(struct.pack(b'<i', x)), FieldType.Type.i64: lambda x: f.write(struct.pack(b'<q', x)), FieldType.Type.vi: lambda x: VarIntSerializer.stream_serialize(x, f), FieldType.Type.fvi: lambda x: FlagVarIntSerializer.stream_serialize((x, False), f), FieldType.Type.str: lambda x: VarStringSerializer.stream_serialize(x.encode('utf-8'), f), FieldType.Type.bytes: lambda x: BytesSerializer.stream_serialize(x, f), FieldType.Type.sha256: lambda x: x.stream_serealize(f), FieldType.Type.sha256d: lambda x: x.stream_serealize(f), FieldType.Type.ripmd160: lambda x: x.stream_serealize(f), FieldType.Type.hash160: lambda x: x.stream_serealize(f), FieldType.Type.pubkey: lambda x: x.stream_serealize(f), FieldType.Type.ecdsa: lambda _: None, } if self.type in lut.keys(): if self.type in [FieldType.Type.sha256, FieldType.Type.sha256d, FieldType.Type.ripmd160, FieldType.Type.hash160] and not issubclass(value, HashId): raise ValueError('in order to serialize hash value you need to provide an instance of HashId class') lut[self.type](value) else: raise NotImplementedError('ECDSA serialization is not implemented')
def stream_deserialize(cls, f): value = struct.unpack(b'<q', ser_read(f, 8))[0] version = struct.unpack(b'<H', ser_read(f, 2))[0] pk_script = BytesSerializer.stream_deserialize(f) return cls(value, version, pk_script)
def serialize_witness_value_signing(self, f): f.write(struct.pack(b'<q', self.value)) BytesSerializer.stream_serialize(self.sig_script, f)
def serialize_witness_signing(self, f): BytesSerializer.stream_serialize(self.sig_script, f)
def serialize_witness(self, f): f.write(struct.pack(b'<q', self.value)) f.write(struct.pack(b'<I', self.block_height)) f.write(struct.pack(b'<I', self.block_index)) BytesSerializer.stream_serialize(self.sig_script, f)
def stream_deserialize(cls, f): hash = ser_read(f, 32) vin = CTxIn.stream_deserialize(f) sig = BytesSerializer.stream_deserialize(f) height = struct.unpack(b"<I", ser_read(f, 4))[0] return cls(hash, vin, sig, height)
def deserialize_witness_value_signing(self, f): value = struct.unpack(b'<q', ser_read(f, 8))[0] sig_script = BytesSerializer.stream_deserialize(f) self.value = value self.sig_script = sig_script
def RawSignatureHash1(script, txTo, inIdx, amount, hashtype): """Consensus-correct SignatureHash Returns (hash, err) to precisely match the consensus-critical behavior of the SIGHASH_SINGLE bug. (inIdx is *not* checked for validity) If you're just writing wallet software you probably want SignatureHash() instead. Ref: https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki """ HASH_ONE = b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' if inIdx >= len(txTo.vin): return (HASH_ONE, "inIdx %d out of range (%d)" % (inIdx, len(txTo.vin))) txtmp = bitcoin.core.CMutableTransaction.from_tx(txTo) # Reusable parts for all the tx. # FIXME Compute them here is not a great idea hashPrevouts = b'\x00' * 32 hashSequence = b'\x00' * 32 hashOutputs = b'\x00' * 32 if not hashtype & SIGHASH_ANYONECANPAY: data = [] for vini in txTo.vin: data.append(vini.prevout.hash) # TODO: serialize using the COutPoint primitives data.append(struct.pack(b'<I', vini.prevout.n)) hashPrevouts = bitcoin.core.Hash(b''.join(data)) if not hashtype & SIGHASH_ANYONECANPAY and hashtype & 0x1f not in (SIGHASH_SINGLE, SIGHASH_NONE): data = [] for vini in txTo.vin: data.append(struct.pack(b'<I', vini.nSequence)) hashSequence = bitcoin.core.Hash(b''.join(data)) if hashtype & 0x1f not in (SIGHASH_SINGLE, SIGHASH_NONE): data = [] f = io.BytesIO() for vouti in txTo.vout: vouti.stream_serialize(f) # Serialize this using the tx serialization rules. TODO serialize data.append(f.getvalue()) hashOutputs = bitcoin.core.Hash(b''.join(data)) elif hashtype & 0x1f == SIGHASH_SINGLE and inIdx < len(txTo.vout): hashOutputs = bitcoin.core.Hash(txTo.vout[inIdx]) # TODO: serialize data = [] hash_data = lambda: bitcoin.core.Hash(b''.join(data)) data.append(struct.pack(b'<i', txTo.nVersion)) data.append(hashPrevouts) data.append(hashSequence) # The input being signed (replacing the scriptSig with scriptCode + amount) # The prevout may already be contained in hashPrevout, and the nSequence # may already be contain in hashSequence. #ss << txTo.vin[nIn].prevout; # data.append(txTo.vin[inIdx].prevout) # TODO serialize # Split: TODO temporary data.append(txTo.vin[inIdx].prevout.hash) data.append(struct.pack(b'<I', txTo.vin[inIdx].prevout.n)) # ss << static_cast<const CScriptBase&>(scriptCode); data.append(BytesSerializer.serialize(script)) # TODO Remember: OP_CODESEPERATOR is not supported # ss << amount; data.append(struct.pack(b'<Q', amount)) # ss << txTo.vin[nIn].nSequence; data.append(struct.pack(b'<I', txTo.vin[inIdx].nSequence)) # // Outputs (none/one/all, depending on flags) # ss << hashOutputs; data.append(hashOutputs) # // Locktime # ss << txTo.nLockTime; data.append(struct.pack(b'<I', txTo.nLockTime)) # // Sighash type # ss << nHashType; data.append(struct.pack(b'<I', hashtype)) return (hash_data(), None)
def stream_serialize(self, f): f.write(self.hash) f.write(self.vin.stream_serialize()) BytesSerializer.stream_serialize(self.sig, f) f.write(struct.pack(b"<I", self.height))
def stream_deserialize(cls, f, **kwargs): schema_obj = kwargs['schema_obj'] if 'schema_obj' in kwargs else None if not isinstance(schema_obj, Schema): raise ValueError( f'`schema_obj` parameter must be of Schema type; got `{schema_obj}` instead' ) # Deserialize proof header # - version with flag (ver, flag) = FlagVarIntSerializer.stream_deserialize(f) # - fields common for root and upgrade proofs if flag: schema = Hash256Id.stream_deserialize(f) network = VarIntSerializer.stream_deserialize(f) if network is 0x00: format = ProofFormat.upgrade # - root-specific fields else: network = Network(network) format = ProofFormat.root root = OutPoint.stream_deserialize(f, short=False) else: format = ProofFormat.ordinary # Deserialize proof body # - reading proof type type_no = ser_read(f, 1)[0] # - reading `seal_sequence` structure seals = [] seal_type_no = 0 # -- we iterate over the seals until 0xFF (=FlagVarIntSerializer.Separator.EOF) byte is met while True: try: # -- reading seal with the current type number seal = Seal.stream_deserialize(f, type_no=seal_type_no, schema_obj=schema_obj) except BaseException as ex: # due to some strange bug, python 3 is unable to capture SeparatorByteSignal exception by its type, # and `isinstance(ex, SeparatorByteSignal)` returns False as well :( # so we have to capture generic exception and re-raise if it is not SeparatorByteSignal, which # can be determined only by the presence of its method if not callable(getattr(ex, "is_eol", None)): raise if ex.is_eol(): # -- met 0xFE separator byte, increasing current type number seal_type_no = seal_type_no + 1 elif ex.is_eof(): # -- end of `seal_sequence` structure break else: # -- otherwise append read seal to the list of seals seals.append(seal) # -- if we had zero seals implies proof of state destruction format if len(seals) is 0: format = ProofFormat.burn # - reading unparsed state and metadata bytes state = BytesSerializer.stream_deserialize(f) metadata = BytesSerializer.stream_deserialize(f) # Deserialize original public key pkcode = ser_read(f, 1) if pkcode is 0x00: pubkey = None else: buf = pkcode + ser_read(f, 32) pubkey = PubKey.deserialize(buf) # Deserialize prunable data try: pruned_flag = ser_read(f, 1) except: pruned_flag = 0x00 txid, parents = None, None if pruned_flag & 0x01 > 0: txid = Hash256Id.stream_deserialize(f) if pruned_flag & 0x02 > 0: parents = VectorSerializer.stream_deserialize(Hash256Id, f) proof = Proof(schema_obj=schema_obj, type_no=type_no, ver=ver, format=format, schema=schema, network=network, root=root, pubkey=pubkey, fields=None, seals=seals, txid=txid, parents=parents, metadata=metadata, state=state) # Parsing raw seals and metadata and resolving types against the provided Schema if 'schema_obj' in kwargs: schema_obj = kwargs['schema_obj'] if isinstance(schema_obj, Schema): proof.resolve_schema(schema_obj) return proof
def stream_serialize(self, f): f.write(struct.pack(b'<q', self.value)) f.write(struct.pack(b'<H', self.version)) BytesSerializer.stream_serialize(self.pk_script, f)
def deserialize_witness_signing(self, f): sig_script = BytesSerializer.stream_deserialize(f) self.sig_script = sig_script