class Receipts(Command): _cmd_id = 7 structure = [ ('request_id', sedes.big_endian_int), ('buffer_value', sedes.big_endian_int), ('receipts', sedes.CountableList(sedes.CountableList(Receipt))), ]
class P2PBlock(rlp.Serializable): transaction_class = P2PSendTransaction receive_transaction_class = P2PReceiveTransaction fields = [ ('header', BlockHeader), ('transactions', sedes.CountableList(P2PSendTransaction)), ('receive_transactions', sedes.CountableList(P2PReceiveTransaction)), ('reward_bundle', StakeRewardBundle), ]
class MinGasParameters(Command): _cmd_id = 32 structure = [('hist_net_tpc_capability', sedes.CountableList( sedes.List([sedes.big_endian_int, sedes.big_endian_int]))), ('hist_min_allowed_gas_price', sedes.CountableList( sedes.List([sedes.big_endian_int, sedes.big_endian_int])))]
class ProofsV2(Command): _cmd_id = 16 structure = [ ('request_id', sedes.big_endian_int), ('buffer_value', sedes.big_endian_int), ('proof', sedes.CountableList(sedes.raw)), ]
class ContractCodes(Command): _cmd_id = 11 structure = [ ('request_id', sedes.big_endian_int), ('buffer_value', sedes.big_endian_int), ('codes', sedes.CountableList(sedes.binary)), ]
class BlockBodies(Command): _cmd_id = 5 structure = [ ('request_id', sedes.big_endian_int), ('buffer_value', sedes.big_endian_int), ('bodies', sedes.CountableList(BlockBody)), ]
class Proofs(Command): _cmd_id = 9 structure = [ ('request_id', sedes.big_endian_int), ('buffer_value', sedes.big_endian_int), ('proofs', sedes.CountableList(sedes.CountableList(sedes.raw))), ] def decode_payload(self, rlp_data: bytes) -> _DecodedMsgType: decoded = super().decode_payload(rlp_data) decoded = cast(Dict[str, Any], decoded) # This is just to make Proofs messages compatible with ProofsV2, so that LightPeerChain # doesn't have to special-case them. Soon we should be able to drop support for LES/1 # anyway, and then all this code will go away. if not decoded['proofs']: decoded['proof'] = [] else: decoded['proof'] = decoded['proofs'][0] return decoded
class Hello(Command): _cmd_id = 0 decode_strict = False structure = [ ('version', sedes.big_endian_int), ('client_version_string', sedes.text), ('capabilities', sedes.CountableList(sedes.List([sedes.text, sedes.big_endian_int]))), ('listen_port', sedes.big_endian_int), ('remote_pubkey', sedes.binary) ]
class Announce(Command): _cmd_id = 1 structure = [ ('head_hash', sedes.binary), ('head_number', sedes.big_endian_int), ('head_td', sedes.big_endian_int), ('reorg_depth', sedes.big_endian_int), # TODO: The params CountableList may contain any of the values from the # Status msg. Need to extend this command to process that too. ('params', sedes.CountableList(sedes.List([sedes.text, sedes.raw]))), ]
class BlockHeaders(BaseBlockHeaders): _cmd_id = 3 structure = [ ('request_id', sedes.big_endian_int), ('buffer_value', sedes.big_endian_int), ('headers', sedes.CountableList(BlockHeader)), ] def extract_headers(self, msg: _DecodedMsgType) -> Tuple[BlockHeader, ...]: msg = cast(Dict[str, Any], msg) return cast(Tuple[BlockHeader, ...], tuple(msg['headers']))
class BlockHeaders(Command): _cmd_id = 4 structure = sedes.CountableList(BlockHeader)
class Transactions(Command): _cmd_id = 2 structure = sedes.CountableList(P2PSendTransaction)
class NewBlockHashes(Command): _cmd_id = 1 structure = sedes.CountableList( sedes.List([sedes.binary, sedes.big_endian_int]))
class Blocks(Command): _cmd_id = 35 structure = sedes.CountableList(P2PBlock)
class GetBlocks(Command): _cmd_id = 34 structure = sedes.CountableList(hash32)
class ChainHeadTrieBranch(Command): _cmd_id = 18 structure = sedes.CountableList(hash32)
class NodeData(Command): _cmd_id = 14 structure = sedes.CountableList(sedes.binary)
class Chains(Command): _cmd_id = 28 structure = [('chains', sedes.CountableList(sedes.CountableList(P2PBlock))) ]
class GetReceipts(Command): _cmd_id = 15 structure = sedes.CountableList(sedes.binary)
class UnorderedBlockHeaderHash(Command): _cmd_id = 22 structure = sedes.CountableList(BlockHashKey)
class GetUnorderedBlockHeaderHash(Command): _cmd_id = 21 structure = sedes.CountableList(BlockNumberKey)
class ChainHeadRootHashTimestamps(Command): _cmd_id = 20 # this way is actually almost twice as fast as using a key... structure is [timestamp, root_hash] structure = sedes.CountableList( sedes.List([sedes.big_endian_int, sedes.binary]))
class GetBlockBodies(Command): _cmd_id = 5 structure = sedes.CountableList(sedes.binary)
class ChronologicalBlockWindow(Command): _cmd_id = 30 structure = [('blocks', sedes.CountableList(P2PBlock)), ('final_root_hash', hash32)]
class BlockBodies(Command): _cmd_id = 6 structure = sedes.CountableList(BlockBody)
class Status(Command): _cmd_id = 0 decode_strict = False # A list of (key, value) pairs is all a Status msg contains, but since the values can be of # any type, we need to use the raw sedes here and do the actual deserialization in # decode_payload(). structure = sedes.CountableList(sedes.List([sedes.text, sedes.raw])) # The sedes used for each key in the list above. Keys that use None as their sedes are # optional and have no value -- IOW, they just need to be present in the msg when appropriate. items_sedes = { 'protocolVersion': sedes.big_endian_int, 'networkId': sedes.big_endian_int, 'headTd': sedes.big_endian_int, 'headHash': sedes.binary, 'headNum': sedes.big_endian_int, 'genesisHash': sedes.binary, 'serveHeaders': None, 'serveChainSince': sedes.big_endian_int, 'serveStateSince': sedes.big_endian_int, 'txRelay': None, 'flowControl/BL': sedes.big_endian_int, 'flowControl/MRC': sedes.CountableList( sedes.List([ sedes.big_endian_int, sedes.big_endian_int, sedes.big_endian_int ])), 'flowControl/MRR': sedes.big_endian_int, } @to_dict def decode_payload(self, rlp_data: bytes) -> Iterator[Tuple[str, Any]]: data = cast(List[Tuple[str, bytes]], super().decode_payload(rlp_data)) # The LES/Status msg contains an arbitrary list of (key, value) pairs, where values can # have different types and unknown keys should be ignored for forward compatibility # reasons, so here we need an extra pass to deserialize each of the key/value pairs we # know about. for key, value in data: if key not in self.items_sedes: continue yield key, self._deserialize_item(key, value) def encode_payload( self, data: Union[_DecodedMsgType, sedes.CountableList]) -> bytes: response = [ (key, self._serialize_item(key, value)) for key, value in sorted(cast(Dict[str, Any], data).items()) ] return super().encode_payload(response) def _deserialize_item(self, key: str, value: bytes) -> Any: sedes = self.items_sedes[key] if sedes is not None: return sedes.deserialize(value) else: # See comment in the definition of item_sedes as to why we do this. return b'' def _serialize_item(self, key: str, value: bytes) -> bytes: sedes = self.items_sedes[key] if sedes is not None: return sedes.serialize(value) else: # See comment in the definition of item_sedes as to why we do this. return b''
class GetStakeForAddresses(Command): _cmd_id = 25 structure = [('addresses', sedes.CountableList(address))]
class Receipts(Command): _cmd_id = 16 structure = sedes.CountableList(sedes.CountableList(Receipt))
class BlockBody(rlp.Serializable): fields = [ ('send_transactions', sedes.CountableList(P2PSendTransaction)), ('receive_transactions', sedes.CountableList(P2PReceiveTransaction)), ]
class StakeForAddresses(Command): _cmd_id = 26 structure = [ ('stakes', sedes.CountableList(sedes.List([address, sedes.big_endian_int]))) ]