| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- import sys
- from typing import (
- Any,
- Dict,
- Union,
- cast,
- )
- from eth_utils import (
- keccak,
- )
- from eth_utils.toolz import (
- pipe,
- )
- from hexbytes import (
- HexBytes,
- )
- import rlp
- if sys.version_info >= (3, 11):
- from typing import (
- Self,
- )
- else:
- from typing_extensions import (
- Self,
- )
- class HashableRLP(rlp.Serializable): # type: ignore
- r"""
- An extension of :class:`rlp.Serializable`. In addition to the below
- functions, the class is iterable.
- Use like:
- ::
- class MyRLP(HashableRLP):
- fields = (
- ('name1', rlp.sedes.big_endian_int),
- ('name2', rlp.sedes.binary),
- etc...
- )
- my_obj = MyRLP(name2=b'\xff', name1=1)
- list(my_obj) == [1, b'\xff']
- # note that the iteration order is always in RLP-defined order
- """
- @classmethod
- def from_dict(cls, field_dict: Dict[str, Any]) -> Self:
- r"""
- In addition to the standard initialization of.
- ::
- my_obj = MyRLP(name1=1, name2=b'\xff')
- This method enables initialization with.
- ::
- my_obj = MyRLP.from_dict({'name1': 1, 'name2': b'\xff'})
- In general, the standard initialization is preferred, but
- some approaches might favor this API, like when using
- :meth:`toolz.functoolz.pipe`.
- ::
- return eth_utils.toolz.pipe(
- my_dict,
- normalize,
- validate,
- MyRLP.from_dict,
- )
- :param dict field_dict: the dictionary of values to initialize with
- :returns: the new rlp object
- :rtype: HashableRLP
- """
- return cls(**field_dict)
- @classmethod
- def from_bytes(cls, serialized_bytes: Union[bytes, bytearray]) -> Self:
- """
- Shorthand invocation for :meth:`rlp.decode` using this class.
- :param bytes serialized_bytes: the byte string to decode
- :return: the decoded object
- :rtype: HashableRLP
- """
- decoded = rlp.decode(serialized_bytes, cls)
- return cast(Self, decoded)
- def hash(self) -> HexBytes:
- """
- :returns: the hash of the encoded bytestring
- :rtype: ~hexbytes.main.HexBytes
- """
- return HexBytes(
- pipe(
- self,
- rlp.encode,
- keccak,
- )
- )
- def __iter__(self) -> Any:
- if hasattr(self, "fields"):
- return iter(getattr(self, field) for field, _ in self.fields)
- else:
- return super().__iter__()
- def as_dict(self) -> Dict[str, Any]:
- """
- Convert rlp object to a dict
- :returns: mapping of RLP field names to field values
- :rtype: dict
- """
- try:
- _as_dict = super().as_dict()
- return cast(Dict[str, Any], _as_dict)
- except AttributeError:
- _as_dict = vars(self)
- return cast(Dict[str, Any], _as_dict)
|