示例#1
0
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])))]
示例#2
0
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)
    ]
示例#3
0
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]))),
    ]
示例#4
0
    def decode_payload(self, rlp_data: bytes) -> PayloadType:
        if isinstance(self.structure, sedes.CountableList):
            decoder = self.structure
        else:
            decoder = sedes.List([type_ for _, type_ in self.structure],
                                 strict=self.decode_strict)
        try:
            data = rlp.decode(rlp_data, sedes=decoder, recursive_cache=True)
        except rlp.DecodingError as err:
            raise MalformedMessage(
                f"Malformed {type(self).__name__} message: {err!r}") from err

        if isinstance(self.structure, sedes.CountableList):
            return data
        return {
            field_name: value
            for ((field_name, _), value) in zip(self.structure, data)
        }
示例#5
0
 def encode_payload(self, data: Union[PayloadType,
                                      sedes.CountableList]) -> bytes:
     if isinstance(data, dict):  # convert dict to ordered list
         if not isinstance(self.structure, list):
             raise ValueError(
                 "Command.structure must be a list when data is a dict")
         expected_keys = sorted(name for name, _ in self.structure)
         data_keys = sorted(data.keys())
         if data_keys != expected_keys:
             raise ValueError(
                 f"Keys in data dict ({data_keys}) do not match expected keys ({expected_keys})"
             )
         data = [data[name] for name, _ in self.structure]
     if isinstance(self.structure, sedes.CountableList):
         encoder = self.structure
     else:
         encoder = sedes.List([type_ for _, type_ in self.structure])
     return rlp.encode(data, sedes=encoder)
示例#6
0
            token_flag = b'\x00'
            msg = self.ephemeral_pubkey.to_bytes() + nonce + token_flag
        return msg

    def encrypt_auth_ack_message(self, ack_message: bytes) -> bytes:
        if self.use_eip8:
            auth_ack = encrypt_eip8_msg(ack_message, self.remote.pubkey)
        else:
            auth_ack = ecies.encrypt(ack_message, self.remote.pubkey)
        return auth_ack


eip8_ack_sedes = sedes.List(
    [
        sedes.Binary(min_length=64, max_length=64),  # ephemeral pubkey
        sedes.Binary(min_length=32, max_length=32),  # nonce
        sedes.BigEndianInt()  # version
    ],
    strict=False)
eip8_auth_sedes = sedes.List(
    [
        sedes.Binary(min_length=65, max_length=65),  # sig
        sedes.Binary(min_length=64, max_length=64),  # pubkey
        sedes.Binary(min_length=32, max_length=32),  # nonce
        sedes.BigEndianInt()  # version
    ],
    strict=False)


def _pad_eip8_data(data: bytes) -> bytes:
    # Pad with random amount of data, as per
示例#7
0
class NewBlockHashes(Command):
    _cmd_id = 1
    structure = sedes.CountableList(
        sedes.List([sedes.binary, sedes.big_endian_int]))
示例#8
0
class StakeForAddresses(Command):
    _cmd_id = 26
    structure = [
        ('stakes',
         sedes.CountableList(sedes.List([address, sedes.big_endian_int])))
    ]
示例#9
0
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]))
示例#10
0
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''