def serialize_prefix(self, f): VarIntSerializer.stream_serialize(len(self.txins), f) for txin in self.txins: txin.serialize_prefix(f) VectorSerializer.stream_serialize(TxOut, self.txouts, f) f.write(struct.pack(b'<I', self.locktime)) f.write(struct.pack(b'<I', self.expiry))
def stream_serialize(self, f): VarIntSerializer.stream_serialize(len(self.pubkeys), f) for pubkey in self.pubkeys: pubkey_bytes = pubkey.to_bytes() assert len(pubkey_bytes) == PUB_KEY_LENGTH f.write(pubkey_bytes) # BytesSerializer.stream_serialize(pubkey, f) f.write(struct.pack(b"<i", self.nMinBlockHeight)) f.write(struct.pack(b"<i", self.nMaxBlockHeight)) assert len(self.hashReplySqk) == HASH_LENGTH f.write(self.hashReplySqk)
def stream_serialize(self, f): super(CMerkleBlock, self).stream_serialize(f) f.write(struct.pack('<L', self.nTX)) VarIntSerializer.stream_serialize(len(self.vHashes), f) for hash in self.vHashes: f.write(hash) VarIntSerializer.stream_serialize(len(self.vFlags) / 8, f) bin_string = "" for bit in self.vFlags: bin_string += str(bit) if len(bin_string) == 8: f.write(struct.pack('B', int(bin_string[::-1], 2))) bin_string = ""
def stream_serialize(self, f): super(CMerkleBlock, self).stream_serialize(f) f.write(struct.pack('<L', self.nTX)) VarIntSerializer.stream_serialize(len(self.vHashes), f) for hash in self.vHashes: f.write(hash) VarIntSerializer.stream_serialize(len(self.vFlags)/8, f) bin_string = "" for bit in self.vFlags: bin_string += str(bit) if len(bin_string) == 8: f.write(struct.pack('B', int(bin_string[::-1], 2))) bin_string = ""
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 on_tx_selection(self, selected, deselected): if not self.block or not len(selected.indexes()): return index = selected.indexes()[0] row = index.row() def tx_len(i): return len(self.block.vtx[i].serialize()) * 2 start = BlockHeader.header_length() * 2 + sum(tx_len(i) for i in range(row)) # Account for VarInt. _buf = BytesIO() VarIntSerializer.stream_serialize(len(self.block.vtx), _buf) start += len(_buf.getvalue()) * 2 length = len(self.block.vtx[row].serialize()) * 2 self.select_block_text(start, length)
def on_tx_selection(self, selected, deselected): if not self.block or not len(selected.indexes()): return index = selected.indexes()[0] row = index.row() def tx_len(i): return len(self.block.vtx[i].serialize()) * 2 start = BlockHeader.header_length() * 2 + sum( tx_len(i) for i in range(row)) # Account for VarInt. _buf = BytesIO() VarIntSerializer.stream_serialize(len(self.block.vtx), _buf) start += len(_buf.getvalue()) * 2 length = len(self.block.vtx[row].serialize()) * 2 self.select_block_text(start, length)
def stream_deserialize(cls, f): n = VarIntSerializer.stream_deserialize(f) pubkeys = tuple( SqueakPublicKey.from_bytes(ser_read(f, PUB_KEY_LENGTH)) for i in range(n)) nMinBlockHeight = struct.unpack(b"<i", ser_read(f, 4))[0] nMaxBlockHeight = struct.unpack(b"<i", ser_read(f, 4))[0] hashReplySqk = ser_read(f, HASH_LENGTH) return cls(pubkeys, nMinBlockHeight, nMaxBlockHeight, hashReplySqk)
def deserialize_witness_value_signing(self, f): """Deserialize a witness for signing with value.""" txin_count = VarIntSerializer.stream_deserialize(f) txins = [] for i in range(txin_count): txin = TxIn() txin.deserialize_witness_value_signing(f) txins.append(txin) self.txins = list(txins)
def state_from_blob(self, blob: bytes) -> (any, int): if self.type is SealType.Type.balance: if blob[0] == 0xfd: shift = 3 elif blob[0] == 0xfe: shift = 5 elif blob[0] == 0xff: shift = 9 else: shift = 1 return VarIntSerializer.deserialize(blob), shift else: return None, 0
def stream_deserialize(cls, f): def bits(f, n): ret = [] bytes = (ord(b) for b in f.read(n)) for b in bytes: for i in xrange(8): ret.append((b >> i) & 1) return ret self = super(CMerkleBlock, cls).stream_deserialize(f) nTX = struct.unpack('<L', ser_read(f, 4))[0] nHashes = VarIntSerializer.stream_deserialize(f) vHashes = [] for i in range(nHashes): vHashes.append(ser_read(f, 32)) nFlags = VarIntSerializer.stream_deserialize(f) vFlags = bits(f, nFlags) object.__setattr__(self, 'nTX', nTX) object.__setattr__(self, 'vHashes', vHashes) object.__setattr__(self, 'vFlags', vFlags) return self
def stream_deserialize_value(self, f): if self.bounds is TypeRef.Usage.single: value = self.type.stream_deserialize_value(f) elif self.bounds.is_fixed(): value = [self.type.stream_deserialize_value(f) for n in range(0, self.bounds.min())] elif self.bounds is TypeRef.Usage.optional: if self.type.type is FieldType.Type.pubkey: key = ser_read(f, 1) if key[0] is 0: return None data = key + ser_read(f, 32) return PubKey.deserialize(data) elif self.type.type is FieldType.Type.ecdsa: key = ser_read(f, 1) if key[0] is 0: return None raise NotImplementedError('ECDSA deserealization is not implemented') try: value = self.type.stream_deserialize_value(f) 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_eof", None)): raise if ex.is_eof(): # -- met 0xFF separator byte, indicating absent value value = None else: raise if self.type.type is FieldType.Type.fvi: pass elif self.type.type is FieldType.Type.str: value = None if value is b'\x00' or len(value) is 0 else value elif self.type.type is FieldType.Type.bytes: value = None if len(value) is 0 else value elif self.type.type in [FieldType.Type.sha256, FieldType.Type.sha256d]: value = None if value is bytes([0] * 32) else value elif self.type.type in [FieldType.Type.ripmd160, FieldType.Type.hash160]: value = None if value is bytes([0] * 20) else value else: raise SchemaError(f'optional fields can be only of `str`, `fvi`, `bytes` and complex types') else: no = VarIntSerializer.stream_deserialize(f) value = [self.type.stream_deserialize_value(f) for n in range(0, no)] return value
def deserialize_prefix(self, f): """Deserialize the transaction prefix.""" txin_count = VarIntSerializer.stream_deserialize(f) txins = [] for i in range(txin_count): txin = TxIn() txin.deserialize_prefix(f) txins.append(txin) txouts = VectorSerializer.stream_deserialize(TxOut, f) locktime = struct.unpack(b'<I', ser_read(f, 4))[0] expiry = struct.unpack(b'<I', ser_read(f, 4))[0] self.txins = list(txins) self.txouts = list(txouts) self.locktime = locktime self.expiry = expiry
def deserialize_witness(self, f, txins_present): """Deserialize the transaction witnesses. If txins_present is True, existing txins will be populated with witness data. """ txin_count = VarIntSerializer.stream_deserialize(f) if not txins_present: txins = [] for i in range(txin_count): txin = TxIn() txin.deserialize_witness(f) txins.append(txin) self.txins = list(txins) else: for i in range(txin_count): txin = self.txins[i] txin.deserialize_witness(f)
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 SignatureHashForkId(script, txTo, inIdx, hashtype, amount): hashPrevouts = None hashSequence = None hashOutputs = None if not (hashtype & SIGHASH_ANYONECANPAY): serialize_prevouts = bytes() for i in txTo.vin: serialize_prevouts += i.prevout.serialize() hashPrevouts = bitcoin.core.Hash(serialize_prevouts) # uint256_from_str(hash256(serialize_prevouts)) if (not (hashtype & SIGHASH_ANYONECANPAY) and (hashtype & 0x1f) != SIGHASH_SINGLE and (hashtype & 0x1f) != SIGHASH_NONE): serialize_sequence = bytes() for i in txTo.vin: serialize_sequence += struct.pack("<I", i.nSequence) hashSequence = bitcoin.core.Hash(serialize_sequence) # uint256_from_str(hash256(serialize_sequence)) if ((hashtype & 0x1f) != SIGHASH_SINGLE and (hashtype & 0x1f) != SIGHASH_NONE): serialize_outputs = bytes() for o in txTo.vout: serialize_outputs += o.serialize() hashOutputs = bitcoin.core.Hash(serialize_outputs) elif ((hashtype & 0x1f) == SIGHASH_SINGLE and inIdx < len(txTo.vout)): serialize_outputs = txTo.vout[inIdx].serialize() hashOutputs = bitcoin.core.Hash(serialize_outputs) ss = bytes() ss += struct.pack("<i", txTo.nVersion) ss += hashPrevouts ss += hashSequence ss += txTo.vin[inIdx].prevout.serialize() ss += ( VarIntSerializer.serialize(len(script)) + script ) ss += struct.pack("<q", amount) ss += struct.pack("<I", txTo.vin[inIdx].nSequence) ss += hashOutputs ss += struct.pack("<i", txTo.nLockTime) ss += struct.pack("<I", hashtype) return bitcoin.core.Hash(ss)
def stream_serialize_state(self, state, f): if self.type is SealType.Type.balance: VarIntSerializer.stream_serialize(state, f)
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, **kwargs): # Serialize proof header # - version with flag ver = self.ver if self.ver is not None else 0 flag = self.format is ProofFormat.root or self.format is ProofFormat.upgrade FlagVarIntSerializer.stream_serialize((ver, flag), f) # - root proof fields if self.format is ProofFormat.root: self.schema.stream_serialize(f) VarIntSerializer.stream_serialize(self.network.value, f) self.root.stream_serialize(f, short_form=False) # - version upgrade proof fields elif self.format is ProofFormat.upgrade: if self.schema is not None: self.schema.stream_serialize(f) else: ZeroBytesSerializer.stream_serialize(32, f) ZeroBytesSerializer.stream_serialize(1, f) # Serialize proof body # - serializing proof type if self.type_no is None: raise ValueError( 'proof consensus serialization requires `type_no` to be known') f.write(bytes([self.type_no])) # - writing `seal_sequence` structure current_type_no = None for seal in self.seals: if current_type_no is None: current_type_no = seal.type_no elif seal.type_no is not current_type_no: # -- writing EOL byte to signify the change of the type [ f.write(bytes([0x7F])) for n in range(current_type_no, seal.type_no) ] current_type_no = seal.type_no seal.stream_serialize(f, state=False) f.write(bytes([0xFF])) # - writing raw data for the sealed state length = reduce( (lambda acc, seal: acc + len(seal.serialize({'state': True}))), [0] + self.seals) VarIntSerializer.stream_serialize(length, f) [seal.stream_serialize(f, state=True) for seal in self.seals] # - writing raw data for all metafields length = reduce((lambda acc, field: acc + len(field.serialize())), [0] + self.fields) VarIntSerializer.stream_serialize(length, f) [field.stream_serialize(f) for field in self.fields] # Serialize original public key if self.pubkey is not None: self.pubkey.stream_serialize(f) else: ZeroBytesSerializer.stream_serialize(1, f) # Serialize prunable data if self.txid is not None: if self.parents is not None: f.write(bytes(0x03)) self.txid.stream_serialize(f) else: f.write(bytes(0x01)) VectorSerializer.stream_serialize(Hash256Id, self.parents, f) elif self.parents is not None: f.write(bytes(0x02)) VectorSerializer.stream_serialize(Hash256Id, self.parents, f) else: f.write(bytes(0x00))
def serialize_witness(self, f): VarIntSerializer.stream_serialize(len(self.txins), f) for txin in self.txins: txin.serialize_witness(f)
def serialize_witness_value_signing(self, f): VarIntSerializer.stream_serialize(len(self.txins), f) for txin in self.txins: txin.serialize_witness_value_signing(f)
def stream_serialize(self, f): VarIntSerializer.stream_serialize(self.type_pos, f) f.write(bytes([self.bounds.min()])) f.write(bytes([self.bounds.max()]))