class UnsignedChainId(HashableRLP): fields = ( ('directive', big_endian_int), ( 'stakeMsg', List( [ # list with the following members Binary.fixed_length( 20, allow_empty=True), # validatorAddress List([Text()] * 5, True), # description is Text of 5 elements List([big_endian_int], True), # new rate is in a list big_endian_int, # min self delegation big_endian_int, # max total delegation Binary.fixed_length( 48, allow_empty=True), # slot key to remove Binary.fixed_length( 48, allow_empty=True), # slot key to add ], True)), # strictly these number of elements ('nonce', big_endian_int), ('gasPrice', big_endian_int), ('gasLimit', big_endian_int), ('chainId', big_endian_int), )
def verify_eth_getProof_inclusion(proof, root): trie_root = Binary.fixed_length(32, allow_empty=True) hash32 = Binary.fixed_length(32) class _Account(rlp.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage', trie_root), ('code_hash', hash32)] acc = _Account(proof.nonce, proof.balance, proof.storageHash, proof.codeHash) rlp_account = rlp.encode(acc) trie_key = keccak(bytes.fromhex(proof.address[2:])) assert rlp_account == HexaryTrie.get_from_proof( root, trie_key, format_proof_nodes( proof.accountProof)), "Failed to verify account proof {}".format( proof.address) for storage_proof in proof.storageProof: trie_key = keccak(pad_bytes(b'\x00', 32, storage_proof.key)) root = proof.storageHash if storage_proof.value == b'\x00': rlp_value = b'' else: rlp_value = rlp.encode(storage_proof.value) assert rlp_value == HexaryTrie.get_from_proof( root, trie_key, format_proof_nodes(storage_proof.proof) ), "Failed to verify storage proof {}".format(storage_proof.key) return True
class UnsignedChainId(HashableRLP): fields = ( ('directive', big_endian_int), ( 'stakeMsg', List( [ # list with the following members Binary.fixed_length( 20, allow_empty=True), # validatorAddress List([Text()] * 5, True), # description is Text of 5 elements List( [List([big_endian_int], True)] * 3, True ), # commission rate is made up of 3 integers in an array [ [int1], [int2], [int3] ] big_endian_int, # min self delegation big_endian_int, # max total delegation CountableList( Binary.fixed_length(48, allow_empty=True) ), # bls-public-keys array of unspecified length, each key of 48 big_endian_int, # amount ], True)), # strictly these number of elements ('nonce', big_endian_int), ('gasPrice', big_endian_int), ('gasLimit', big_endian_int), ('chainId', big_endian_int), )
def verify_eth_get_proof(self, proof, root): values = [] trie_root = Binary.fixed_length(32, allow_empty=True) hash32 = Binary.fixed_length(32) class _Account(rlp.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage', trie_root), ('code_hash', hash32)] acc = _Account(proof.nonce, proof.balance, proof.storageHash, proof.codeHash) rlp_account = rlp.encode(acc) trie_key = keccak(bytes.fromhex(proof.address[2:])) if rlp_account != HexaryTrie.get_from_proof( root, trie_key, self.format_proof_nodes(proof.accountProof)): return False for storage_proof in proof.storageProof: trie_key = keccak(pad_bytes(b'\x00', 32, storage_proof.key)) root = proof.storageHash if storage_proof.value == b'\x00': rlp_value = b'' else: rlp_value = rlp.encode(storage_proof.value) if rlp_value != HexaryTrie.get_from_proof( root, trie_key, self.format_proof_nodes( storage_proof.proof)): return False else: values.append( {storage_proof.key.hex(): storage_proof.value.hex()}) return True, values
class Eight(rlp.Serializable): fields = [('f0', big_endian_int), ('f1', big_endian_int), ('f2', big_endian_int), ('f3', big_endian_int), ('f4', big_endian_int), ('f5', big_endian_int), ('f6', Binary.fixed_length(20)), ('f7', Binary.fixed_length(20))] def __init__(self, *args): args = normalize_args(args) super().__init__(*args)
def serialize(cls, obj): sedes_list = List([ big_endian_int, List([ Binary.fixed_length(20), Binary.fixed_length(20), big_endian_int ]) ]) tx_elems = [obj.output_type, [obj.output_guard, obj.token, obj.amount]] tx_sedes = rlp.sedes.List(sedes_list) return tx_sedes.serialize(tx_elems)
class UnsignedChainId(HashableRLP): fields = ( ('directive', big_endian_int), ('stakeMsg', List([ Binary.fixed_length(20, allow_empty=True), Binary.fixed_length(20, allow_empty=True), big_endian_int ], True)), ('nonce', big_endian_int), ('gasPrice', big_endian_int), ('gasLimit', big_endian_int), ('chainId', big_endian_int), )
class SignedTransaction(rlp.Serializable): fields = [ ('nonce', big_endian_int), ('gasprice', big_endian_int), ('startgas', big_endian_int), ('to', Binary.fixed_length(20, allow_empty=True)), ('value', big_endian_int), ('data', binary), ('v', big_endian_int), ('r', big_endian_int), ('s', big_endian_int), ] def __init__(self, nonce: int, gasprice: int, startgas: int, to: bytes, value: int, data: str, v: int, r: int, s: int): super(SignedTransaction, self).__init__(nonce, gasprice, startgas, to, value, data, v, r, s) def sender(self, value: str) -> None: self._sender = value def to_dict(self) -> dict: d = {} for name, _ in self.__class__._meta.fields: d[name] = getattr(self, name) return d
def test_binary_fixed_lenght_of_zero(): sedes = Binary.fixed_length(0) assert sedes.serialize(b'') == b'' with pytest.raises(SerializationError): sedes.serialize(b'a') with pytest.raises(SerializationError): sedes.serialize(b'arst')
class BlockHeader(rlp.Serializable): fields = [('parent_hash', hash32), ('uncles_hash', hash32), ('coinbase', address), ('state_root', trie_root), ('transaction_root', trie_root), ('receipt_root', trie_root), ('bloom', uint256), ('difficulty', big_endian_int), ('block_number', big_endian_int), ('gas_limit', big_endian_int), ('gas_used', big_endian_int), ('timestamp', big_endian_int), ('extra_data', binary), ('mix_hash', binary), ('nonce', Binary(8, allow_empty=True))]
class UnsignedHarmonyTxData(HashableRLP): fields = ( ('nonce', big_endian_int), ('gasPrice', big_endian_int), ('gas', big_endian_int), ('shardID', big_endian_int), ('toShardID', big_endian_int), ('to', Binary.fixed_length(20, allow_empty=True)), ('value', big_endian_int), ('data', binary), )
class Transaction(ExtendedRLP): fields = ( ('nonce', big_endian_int), ('gasPrice', big_endian_int), ('gas', big_endian_int), ('to', Binary.fixed_length(20, allow_empty=True)), ('value', big_endian_int), ('data', binary), ('v', big_endian_int), ('r', big_endian_int), ('s', big_endian_int), )
class Transaction(rlp.Serializable): fields = [ ("nonce", big_endian_int), ("gas_price", big_endian_int), ("gas", big_endian_int), ("to", Binary.fixed_length(20, allow_empty=True)), ("value", big_endian_int), ("data", binary), ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ]
def verify_eth_get_proof(proof, root): trie_root = Binary.fixed_length(32, allow_empty=True) hash32 = Binary.fixed_length(32) class _Account(rlp.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage', trie_root), ('code_hash', hash32)] acc = _Account(proof.nonce, proof.balance, w3.toBytes(hexstr=w3.toHex(proof.storageHash)), w3.toBytes(hexstr=w3.toHex(proof.codeHash))) rlp_account = rlp.encode(acc) trie_key = keccak(w3.toBytes(hexstr=proof.address)) trie_proof = format_proof_nodes(proof.accountProof) leaf = HexaryTrie.get_from_proof(root, trie_key, trie_proof) if acc == b'': print("Verify that the account does not exist") else: assert rlp_account == leaf, "Failed to verify account proof {}".format( proof.address) print("Succeed to verify account proof {}".format(proof.address)) return True
class RPLTransaction(rlp.Serializable): fields = [ ("nonce", big_endian_int), ("gas_price", big_endian_int), ("gas", big_endian_int), ("to", Binary.fixed_length(20, allow_empty=True)), ("value", big_endian_int), ("data", binary), ("v", big_endian_int), ("r", big_endian_int), ("s", big_endian_int), ] @staticmethod def new_tx(*, nonce, gas_price, gas, to, value, data, v, r, s): return RPLTransaction(nonce, gas_price, gas, to, value, data, v, r, s)
class BlockHeader(rlp.Serializable): fields = [('parent_hash', hash32), ('uncles_hash', hash32), ('coinbase', address), ('state_root', trie_root), ('transaction_root', trie_root), ('receipt_root', trie_root), ('bloom', int256), ('difficulty', big_endian_int), ('block_number', big_endian_int), ('gas_limit', big_endian_int), ('gas_used', big_endian_int), ('timestamp', big_endian_int), ('extra_data', binary), ('mix_hash', binary), ('nonce', Binary(8, allow_empty=True))] @property def hash(self) -> Hash32: return keccak(rlp.encode(self)) @property def mining_hash(self) -> Hash32: return keccak(rlp.encode(self[:-2], MiningHeader))
class BlockHeader(rlp.Serializable): fields = [('parent_hash', hash32), ('uncles_hash', hash32), ('coinbase', address), ('state_root', trie_root), ('transaction_root', trie_root), ('receipts_root', trie_root), ('bloom', int256), ('difficulty', big_endian_int), ('block_number', big_endian_int), ('gas_limit', big_endian_int), ('gas_used', big_endian_int), ('timestamp', big_endian_int), ('extra_data', binary), ('mix_hash', binary), ('nonce', Binary(8, allow_empty=True))] def __init__(self, coinbase, difficulty, block_number, gas_limit, timestamp, parent_hash=ZERO_HASH32, uncles_hash=EMPTY_UNCLE_HASH, state_root=BLANK_ROOT_HASH, transaction_root=BLANK_ROOT_HASH, receipts_root=BLANK_ROOT_HASH, bloom=0, gas_used=0, extra_data=b'', mix_hash=ZERO_HASH32, nonce=GENESIS_NONCE): super(BlockHeader, self).__init__( parent_hash=parent_hash, uncles_hash=uncles_hash, coinbase=coinbase, state_root=state_root, transaction_root=transaction_root, receipts_root=receipts_root, bloom=bloom, difficulty=difficulty, block_number=block_number, gas_limit=gas_limit, gas_used=gas_used, timestamp=timestamp, extra_data=extra_data, mix_hash=mix_hash, nonce=nonce, )
#!/usr/bin/env python from rlp.sedes import big_endian_int, binary, Binary from rlp import Serializable from Cryptodome.Hash import keccak def sha3_256(x): return keccak.new(digest_bits=256, data=x.encode()).digest() address = Binary.fixed_length(20, allow_empty=True) def sha3(seed): return sha3_256(str(seed)) class Transaction(Serializable): fields = [ ('nonce', big_endian_int), ('epoch', big_endian_int), ('txtype', big_endian_int), ('to', address), ('value', big_endian_int), ('maxfee', big_endian_int), ('tips', big_endian_int), ('data', binary), ] def __init__(self, nonce, epoch, txtype, to, value, maxfee, tips, data): super(Transaction, self).__init__(
from rlp.sedes import ( BigEndianInt, Binary, ) from eth.constants import ( COLLATION_SIZE, ) address = Binary.fixed_length(20, allow_empty=True) collation_body = Binary.fixed_length(COLLATION_SIZE) hash32 = Binary.fixed_length(32) int32 = BigEndianInt(32) int256 = BigEndianInt(256) trie_root = Binary.fixed_length(32, allow_empty=True)
if chain_id is None: return transaction_dict else: return dict(transaction_dict, v=chain_id, r=0, s=0) @curry def fill_transaction_defaults(transaction): return merge(TRANSACTION_DEFAULTS, transaction) UNSIGNED_TRANSACTION_FIELDS = ( ('nonce', big_endian_int), ('gasPrice', big_endian_int), ('gas', big_endian_int), ('to', Binary.fixed_length(20, allow_empty=True)), ('value', big_endian_int), ('data', binary), ) class Transaction(HashableRLP): fields = UNSIGNED_TRANSACTION_FIELDS + ( ('v', big_endian_int), ('r', big_endian_int), ('s', big_endian_int), ) class UnsignedTransaction(HashableRLP): fields = UNSIGNED_TRANSACTION_FIELDS
class BlockHeader(rlp.Serializable): fields = [('parent_hash', hash32), ('uncles_hash', hash32), ('coinbase', address), ('state_root', trie_root), ('transaction_root', trie_root), ('receipt_root', trie_root), ('bloom', int256), ('difficulty', big_endian_int), ('block_number', big_endian_int), ('gas_limit', big_endian_int), ('gas_used', big_endian_int), ('timestamp', big_endian_int), ('extra_data', binary), ('mix_hash', binary), ('nonce', Binary(8, allow_empty=True))] def __init__(self, difficulty, block_number, gas_limit, timestamp=None, coinbase=ZERO_ADDRESS, parent_hash=ZERO_HASH32, uncles_hash=EMPTY_UNCLE_HASH, state_root=BLANK_ROOT_HASH, transaction_root=BLANK_ROOT_HASH, receipt_root=BLANK_ROOT_HASH, bloom=0, gas_used=0, extra_data=b'', mix_hash=ZERO_HASH32, nonce=GENESIS_NONCE): if timestamp is None: timestamp = int(time.time()) super(BlockHeader, self).__init__( parent_hash=parent_hash, uncles_hash=uncles_hash, coinbase=coinbase, state_root=state_root, transaction_root=transaction_root, receipt_root=receipt_root, bloom=bloom, difficulty=difficulty, block_number=block_number, gas_limit=gas_limit, gas_used=gas_used, timestamp=timestamp, extra_data=extra_data, mix_hash=mix_hash, nonce=nonce, ) @property def hash(self): return keccak(rlp.encode(self)) @property def mining_hash(self): return keccak( rlp.encode(self, BlockHeader.exclude(['mix_hash', 'nonce']))) @property def hex_hash(self): return encode_hex(self.hash) @classmethod def from_parent(cls, parent, gas_limit, difficulty, coinbase=ZERO_ADDRESS, timestamp=None, nonce=None, extra_data=None): """ Initialize a new block header with the `parent` header as the block's parent hash. """ if timestamp is None: timestamp = int(time.time()) header_kwargs = { 'parent_hash': parent.hash, 'coinbase': coinbase, 'state_root': parent.state_root, 'gas_limit': gas_limit, 'difficulty': difficulty, 'block_number': parent.block_number + 1, 'timestamp': timestamp, } if nonce is not None: header_kwargs['nonce'] = nonce if extra_data is not None: header_kwargs['extra_data'] = extra_data header = cls(**header_kwargs) return header
class TypedTransaction(SignedTransactionMethods, SignedTransactionAPI, TransactionDecoderAPI): rlp_type = Binary(min_length=1) # must have at least one byte for the type _inner: SignedTransactionAPI decoders: Dict[int, Type[TransactionDecoderAPI]] = { ACCESS_LIST_TRANSACTION_TYPE: AccessListPayloadDecoder, } def __init__(self, type_id: int, proxy_target: SignedTransactionAPI) -> None: self.type_id = type_id self._inner = proxy_target @classmethod def get_payload_codec(cls, type_id: int) -> Type[TransactionDecoderAPI]: if type_id in cls.decoders: return cls.decoders[type_id] elif type_id in VALID_TRANSACTION_TYPES: raise UnrecognizedTransactionType(type_id, "Unknown transaction type") else: raise ValidationError( f"Cannot build typed transaction with {hex(type_id)} >= 0x80") def encode(self) -> bytes: return self._type_byte + self._inner.encode() @classmethod def decode(cls, encoded: bytes) -> SignedTransactionAPI: type_id = to_int(encoded[0]) payload = encoded[1:] payload_codec = cls.get_payload_codec(type_id) inner_transaction = payload_codec.decode(payload) return cls(type_id, inner_transaction) @classmethod def serialize(cls, obj: 'TypedTransaction') -> DecodedZeroOrOneLayerRLP: encoded = obj.encode() return cls.rlp_type.serialize(encoded) @classmethod def deserialize( cls, encoded_unchecked: DecodedZeroOrOneLayerRLP ) -> SignedTransactionAPI: # binary checks a few basics, like the length of the bytes encoded = cls.rlp_type.deserialize(encoded_unchecked) return cls.decode(encoded) @cached_property def _type_byte(self) -> bytes: return to_bytes(self.type_id) @property def chain_id(self) -> int: return self._inner.chain_id @property def nonce(self) -> int: return self._inner.nonce @property def gas_price(self) -> int: return self._inner.gas_price @property def gas(self) -> int: return self._inner.gas @property def to(self) -> Address: return self._inner.to @property def value(self) -> int: return self._inner.value @property def data(self) -> bytes: return self._inner.data @property def y_parity(self) -> int: return self._inner.y_parity @property def r(self) -> int: return self._inner.r @property def s(self) -> int: return self._inner.s @property def access_list(self) -> Sequence[Tuple[Address, Sequence[int]]]: return self._inner.access_list def get_sender(self) -> Address: return self._inner.get_sender() def get_message_for_signing(self) -> bytes: return self._inner.get_message_for_signing() def check_signature_validity(self) -> None: self._inner.check_signature_validity() @cached_property def hash(self) -> Hash32: return keccak(self.encode()) def get_intrinsic_gas(self) -> int: return self._inner.get_intrinsic_gas() def copy(self, **overrides: Any) -> 'TypedTransaction': inner_copy = self._inner.copy(**overrides) return type(self)(self.type_id, inner_copy) def __eq__(self, other: Any) -> bool: if not isinstance(other, TypedTransaction): return False else: return self.type_id == other.type_id and self._inner == other._inner def make_receipt( self, status: bytes, gas_used: int, log_entries: Tuple[Tuple[bytes, Tuple[int, ...], bytes], ...] ) -> ReceiptAPI: inner_receipt = self._inner.make_receipt(status, gas_used, log_entries) return TypedReceipt(ACCESS_LIST_TRANSACTION_TYPE, inner_receipt) def __hash__(self) -> int: return hash((self.type_id, self._inner))
class Denoms(): def __init__(self): self.wei = 1 self.babbage = 10**3 self.lovelace = 10**6 self.shannon = 10**9 self.szabo = 10**12 self.finney = 10**15 self.ether = 10**18 self.turing = 2**256 denoms = Denoms() address = Binary.fixed_length(20, allow_empty=True) int20 = BigEndianInt(20) int32 = BigEndianInt(32) int256 = BigEndianInt(256) hash32 = Binary.fixed_length(32) trie_root = Binary.fixed_length(32, allow_empty=True) class bcolors: HEADER = '\033[95m' OKBLUE = '\033[94m' OKGREEN = '\033[92m' WARNING = '\033[91m' FAIL = '\033[91m' ENDC = '\033[0m' BOLD = '\033[1m'
class BlockHeader(rlp.Serializable, BlockHeaderAPI): fields = [('parent_hash', hash32), ('uncles_hash', hash32), ('coinbase', address), ('state_root', trie_root), ('transaction_root', trie_root), ('receipt_root', trie_root), ('bloom', uint256), ('difficulty', big_endian_int), ('block_number', big_endian_int), ('gas_limit', big_endian_int), ('gas_used', big_endian_int), ('timestamp', big_endian_int), ('extra_data', binary), ('mix_hash', binary), ('nonce', Binary(8, allow_empty=True))] @overload def __init__(self, **kwargs: HeaderParams) -> None: ... @overload # noqa: F811 def __init__(self, difficulty: int, block_number: BlockNumber, gas_limit: int, timestamp: int = None, coinbase: Address = ZERO_ADDRESS, parent_hash: Hash32 = ZERO_HASH32, uncles_hash: Hash32 = EMPTY_UNCLE_HASH, state_root: Hash32 = BLANK_ROOT_HASH, transaction_root: Hash32 = BLANK_ROOT_HASH, receipt_root: Hash32 = BLANK_ROOT_HASH, bloom: int = 0, gas_used: int = 0, extra_data: bytes = b'', mix_hash: Hash32 = ZERO_HASH32, nonce: bytes = GENESIS_NONCE) -> None: ... def __init__( self, # type: ignore # noqa: F811 difficulty: int, block_number: BlockNumber, gas_limit: int, timestamp: int = None, coinbase: Address = ZERO_ADDRESS, parent_hash: Hash32 = ZERO_HASH32, uncles_hash: Hash32 = EMPTY_UNCLE_HASH, state_root: Hash32 = BLANK_ROOT_HASH, transaction_root: Hash32 = BLANK_ROOT_HASH, receipt_root: Hash32 = BLANK_ROOT_HASH, bloom: int = 0, gas_used: int = 0, extra_data: bytes = b'', mix_hash: Hash32 = ZERO_HASH32, nonce: bytes = GENESIS_NONCE) -> None: if timestamp is None: timestamp = int(time.time()) super().__init__( parent_hash=parent_hash, uncles_hash=uncles_hash, coinbase=coinbase, state_root=state_root, transaction_root=transaction_root, receipt_root=receipt_root, bloom=bloom, difficulty=difficulty, block_number=block_number, gas_limit=gas_limit, gas_used=gas_used, timestamp=timestamp, extra_data=extra_data, mix_hash=mix_hash, nonce=nonce, ) def __str__(self) -> str: return f'<BlockHeader #{self.block_number} {encode_hex(self.hash)[2:10]}>' _hash = None @property def hash(self) -> Hash32: if self._hash is None: self._hash = keccak(rlp.encode(self)) return self._hash @property def mining_hash(self) -> Hash32: return keccak(rlp.encode(self[:-2], MiningHeader)) @property def hex_hash(self) -> str: return encode_hex(self.hash) @classmethod def from_parent(cls, parent: BlockHeaderAPI, gas_limit: int, difficulty: int, timestamp: int, coinbase: Address = ZERO_ADDRESS, nonce: bytes = None, extra_data: bytes = None, transaction_root: bytes = None, receipt_root: bytes = None) -> 'BlockHeader': """ Initialize a new block header with the `parent` header as the block's parent hash. """ header_kwargs: Dict[str, HeaderParams] = { 'parent_hash': parent.hash, 'coinbase': coinbase, 'state_root': parent.state_root, 'gas_limit': gas_limit, 'difficulty': difficulty, 'block_number': parent.block_number + 1, 'timestamp': timestamp, } if nonce is not None: header_kwargs['nonce'] = nonce if extra_data is not None: header_kwargs['extra_data'] = extra_data if transaction_root is not None: header_kwargs['transaction_root'] = transaction_root if receipt_root is not None: header_kwargs['receipt_root'] = receipt_root header = cls(**header_kwargs) return header @property def is_genesis(self) -> bool: # if removing the block_number == 0 test, consider the validation consequences. # validate_header stops trying to check the current header against a parent header. # Can someone trick us into following a high difficulty header with genesis parent hash? return self.parent_hash == GENESIS_PARENT_HASH and self.block_number == 0
from rlp.sedes import ( BigEndianInt, Binary, ) hash32 = Binary.fixed_length(32) uint64 = BigEndianInt(64)
# Copyright (c) 2015 Heiko Hees from utils import big_endian_to_int, sha3, isaddress, ishash, int_to_big_endian, pex import rlp from rlp.sedes import Binary from rlp.sedes import big_endian_int as t_int from rlp.sedes import binary as t_binary from rlp.sedes import List as t_list t_address = Binary.fixed_length(20, allow_empty=False) t_hash = Binary.fixed_length(32, allow_empty=False) t_hash_optional = Binary.fixed_length(32, allow_empty=True) class RLPHashable(rlp.Serializable): rlp_ = None @property def hash(self): return sha3(getattr(self, 'rlp_', None) or rlp.encode(self)) def __eq__(self, other): return isinstance(other, self.__class__) and self.hash == other.hash def __hash__(self): return big_endian_to_int(self.hash) def __ne__(self, other): return not self.__eq__(other) def __repr__(self):
class Log(rlp.Serializable): fields = [ ('address', Binary.fixed_length(20, allow_empty=True)), ('topics', CountableList(BigEndianInt(32))), ('data', Binary()) ]
return hash(( self.signature, self.sequence_number, tuple(self.items()), )) def __repr__(self) -> str: base64_rlp = base64.urlsafe_b64encode(rlp.encode(self)) unpadded_base64_rlp = base64_rlp.rstrip(b"=") return "".join(( ENR_REPR_PREFIX, unpadded_base64_rlp.decode("ASCII"), )) IDENTITY_SCHEME_ENR_KEY = b"id" ENR_KEY_SEDES_MAPPING = { b"id": binary, b"secp256k1": Binary.fixed_length(33), b"ip": Binary.fixed_length(IP_V4_SIZE), b"tcp": big_endian_int, b"udp": big_endian_int, b"ip6": Binary.fixed_length(IP_V6_SIZE), b"tcp6": big_endian_int, b"udp6": big_endian_int, } # Must use raw for values with an unknown key as they may be lists or individual values. FALLBACK_ENR_VALUE_SEDES = raw
from p2p.discv5.constants import ( TOPIC_HASH_SIZE, IP_V4_SIZE, IP_V6_SIZE, ) # https://github.com/python/mypy/issues/5264#issuecomment-399407428 if TYPE_CHECKING: MessageTypeRegistryBaseType = UserDict[int, Type["BaseMessage"]] else: MessageTypeRegistryBaseType = UserDict # # Custom sedes objects # topic_sedes = Binary.fixed_length(TOPIC_HASH_SIZE) class IPAddressSedes(Binary): def __init__(self) -> None: super().__init__() def is_valid_length(self, length: int) -> bool: return length in (IP_V4_SIZE, IP_V6_SIZE) ip_address_sedes = IPAddressSedes() class MessageTypeRegistry(MessageTypeRegistryBaseType): def register(
def is_bitcoin_available(): try: import bitcoin # noqa except ImportError: return False else: return True # in the yellow paper it is specified that s should be smaller than secpk1n (eq.205) secpk1n = 115792089237316195423570985008687907852837564279074904382605163141518161494337 TT256 = 2 ** 256 address_sedes = Binary.fixed_length(20, allow_empty=True) class Transaction(rlp.Serializable): """ # Derived from `pyethereum.transaction.Transaction` A transaction is stored as: [nonce, gasprice, startgas, to, value, data, v, r, s] nonce is the number of transactions already sent by that account, encoded in binary form (eg. 0 -> '', 7 -> '\x07', 1000 -> '\x03\xd8'). (v,r,s) is the raw Electrum-style signature of the transaction without the signature made with the private key corresponding to the sending account, with 0 <= v <= 3. From an Electrum-style signature (65 bytes) it is
class BlockHeader(rlp.Serializable): fields = [('parent_hash', hash32), ('uncles_hash', hash32), ('coinbase', address), ('state_root', trie_root), ('transaction_root', trie_root), ('receipt_root', trie_root), ('bloom', int256), ('difficulty', big_endian_int), ('block_number', big_endian_int), ('gas_limit', big_endian_int), ('gas_used', big_endian_int), ('timestamp', big_endian_int), ('extra_data', binary), ('mix_hash', binary), ('nonce', Binary(8, allow_empty=True))] @overload def __init__(self, **kwargs: HeaderParams) -> None: ... @overload # noqa: F811 def __init__(self, difficulty: int, block_number: int, gas_limit: int, timestamp: int = None, coinbase: Address = ZERO_ADDRESS, parent_hash: Hash32 = ZERO_HASH32, uncles_hash: Hash32 = EMPTY_UNCLE_HASH, state_root: Hash32 = BLANK_ROOT_HASH, transaction_root: Hash32 = BLANK_ROOT_HASH, receipt_root: Hash32 = BLANK_ROOT_HASH, bloom: int = 0, gas_used: int = 0, extra_data: bytes = b'', mix_hash: Hash32 = ZERO_HASH32, nonce: bytes = GENESIS_NONCE) -> None: ... def __init__( self, # noqa: F811 difficulty, block_number, gas_limit, timestamp=None, coinbase=ZERO_ADDRESS, parent_hash=ZERO_HASH32, uncles_hash=EMPTY_UNCLE_HASH, state_root=BLANK_ROOT_HASH, transaction_root=BLANK_ROOT_HASH, receipt_root=BLANK_ROOT_HASH, bloom=0, gas_used=0, extra_data=b'', mix_hash=ZERO_HASH32, nonce=GENESIS_NONCE): if timestamp is None: timestamp = int(time.time()) super(BlockHeader, self).__init__( parent_hash=parent_hash, uncles_hash=uncles_hash, coinbase=coinbase, state_root=state_root, transaction_root=transaction_root, receipt_root=receipt_root, bloom=bloom, difficulty=difficulty, block_number=block_number, gas_limit=gas_limit, gas_used=gas_used, timestamp=timestamp, extra_data=extra_data, mix_hash=mix_hash, nonce=nonce, ) def __repr__(self) -> str: return '<BlockHeader #{0} {1}>'.format( self.block_number, encode_hex(self.hash)[2:10], ) _hash = None @property def hash(self) -> Hash32: if self._hash is None: self._hash = keccak(rlp.encode(self)) return self._hash @property def mining_hash(self) -> Hash32: return keccak(rlp.encode(self[:-2], MiningHeader)) @property def hex_hash(self): return encode_hex(self.hash) @classmethod def from_parent(cls, parent: 'BlockHeader', gas_limit: int, difficulty: int, timestamp: int, coinbase: Address = ZERO_ADDRESS, nonce: bytes = None, extra_data: bytes = None, transaction_root: bytes = None, receipt_root: bytes = None) -> 'BlockHeader': """ Initialize a new block header with the `parent` header as the block's parent hash. """ header_kwargs = { 'parent_hash': parent.hash, 'coinbase': coinbase, 'state_root': parent.state_root, 'gas_limit': gas_limit, 'difficulty': difficulty, 'block_number': parent.block_number + 1, 'timestamp': timestamp, } if nonce is not None: header_kwargs['nonce'] = nonce if extra_data is not None: header_kwargs['extra_data'] = extra_data if transaction_root is not None: header_kwargs['transaction_root'] = transaction_root if receipt_root is not None: header_kwargs['receipt_root'] = receipt_root header = cls(**header_kwargs) return header def create_execution_context( self, prev_hashes: Union[Tuple[bytes], Tuple[bytes, bytes]]) -> ExecutionContext: return ExecutionContext( coinbase=self.coinbase, timestamp=self.timestamp, block_number=self.block_number, difficulty=self.difficulty, gas_limit=self.gas_limit, prev_hashes=prev_hashes, )
def has_sig(self): if Binary.is_valid_type(self.signature) and sig65.is_valid_length( len(self.signature)): return True else: return False
from rlp.sedes import ( BigEndianInt, Binary, ) address = Binary.fixed_length(20, allow_empty=True) hash32 = Binary.fixed_length(32) int32 = BigEndianInt(32) int256 = BigEndianInt(256) trie_root = Binary.fixed_length(32, allow_empty=True)
def test_binary(): b1 = Binary() f = { '': b'', 'asdf': b'asdf', ('\x00' * 20): (b'\x00' * 20), 'fdsa': b'fdsa' } for k in f: assert b1.serialize(k) == f[k] for d in ([], 5, str): with pytest.raises(SerializationError): b1.serialize(d) b2 = Binary.fixed_length(5) f = { 'asdfg': b'asdfg', b'\x00\x01\x02\x03\x04': b'\x00\x01\x02\x03\x04', utils.str_to_bytes('ababa'): b'ababa' } for k in f: assert b2.serialize(k) == f[k] for d in ('asdf', 'asdfgh', '', 'bababa'): with pytest.raises(SerializationError): b2.serialize(d) b3 = Binary(2, 4) f = { 'as': b'as', 'dfg': b'dfg', 'hjkl': b'hjkl', b'\x00\x01\x02': b'\x00\x01\x02' } for k in f: assert b3.serialize(k) == f[k] for d in ('', 'a', 'abcde', 'รครครค'): with pytest.raises(SerializationError): b3.serialize(d) b4 = Binary(min_length=3) f = {'abc': b'abc', 'abcd': b'abcd', ('x' * 132): (b'x' * 132)} for k in f: assert b4.serialize(k) == f[k] for d in ('ab', '', 'a', 'xy'): with pytest.raises(SerializationError): b4.serialize(d) b5 = Binary(max_length=3) f = {'': b'', 'ab': b'ab', 'abc': b'abc'} for k in f: assert b5.serialize(k) == f[k] for d in ('abcd', 'vwxyz', 'a' * 32): with pytest.raises(SerializationError): b5.serialize(d) b6 = Binary(min_length=3, max_length=5, allow_empty=True) f = {'': b'', 'abc': b'abc', 'abcd': b'abcd', 'abcde': b'abcde'} for k in f: assert b6.serialize(k) == f[k] for d in ('a', 'ab', 'abcdef', 'abcdefgh' * 10): with pytest.raises(SerializationError): b6.serialize(d)