def test_unsign_integers_more_than_32_bytes(data, num_bits): uint_n = UInt(num_bits) value = data.draw(st.integers( min_value=0, max_value=2**num_bits - 1, )) expected = hash_eth2(value.to_bytes(num_bits // 8, "little")) assert hash_tree_root(value, uint_n) == expected
def test_unsign_integers_less_than_32_bytes(data, num_bits): uint_n = UInt(num_bits) value = data.draw(st.integers( min_value=0, max_value=2**num_bits - 1, )) expected = value.to_bytes(num_bits // 8, "little").ljust(32, b'\x00') assert hash_tree_root(value, uint_n) == expected
def generate_uint_out_of_bounds_test_cases(): common_tags = ("atomic", "uint") for bit_size in BIT_SIZES: sedes = UInt(bit_size) for value, tag in ((-1, "uint_underflow"), (2**bit_size, "uint_overflow")): yield render_test_case( sedes=sedes, valid=False, value=value, tags=common_tags + (tag, ), )
def generate_uint_bounds_test_cases(): common_tags = ("atomic", "uint") for bit_size in BIT_SIZES: sedes = UInt(bit_size) for value, tag in ((0, "uint_lower_bound"), (2**bit_size - 1, "uint_upper_bound")): serial = ssz.encode(value, sedes) yield render_test_case( sedes=sedes, valid=True, value=value, serial=serial, tags=common_tags + (tag, ), )
def generate_random_uint_test_cases(): for bit_size in BIT_SIZES: sedes = UInt(bit_size) for _ in range(RANDOM_TEST_CASES_PER_BIT_SIZE): value = random.randrange(0, 2**bit_size) serial = ssz.encode(value, sedes) # note that we need to create the tags in each loop cycle, otherwise ruamel will use # YAML references which makes the resulting file harder to read tags = tuple(["atomic", "uint", "random"]) yield render_test_case( sedes=sedes, valid=True, value=value, serial=serial, tags=tags, )
def generate_uint_wrong_length_test_cases(): for bit_size in BIT_SIZES: sedes = UInt(bit_size) lengths = sorted({ 0, sedes.length // 2, sedes.length - 1, sedes.length + 1, sedes.length * 2, }) for length in lengths: for _ in range(RANDOM_TEST_CASES_PER_LENGTH): tags = tuple(["atomic", "uint", "wrong_length"]) yield render_test_case( sedes=sedes, valid=False, serial=get_random_bytes(length), tags=tags, )
def uint_and_value_strategy(draw): num_bits = 8 * 2**draw(st.integers(min_value=0, max_value=5)) uint = UInt(num_bits) value = draw(st.integers(min_value=0, max_value=2**num_bits - 1)) return uint, value
def test_uint(bit_length, value, serialized): uint = UInt(bit_length) assert encode_hex(ssz.encode(value, uint)) == serialized assert ssz.decode(decode_hex(serialized), uint) == value
(16, 0, "0x0000"), (16, 256, "0x0001"), (16, 65536 - 1, "0xffff"), (32, sum((i + 1) * 256 ** i for i in range(4)), "0x01020304"), (256, 0, "0x" + "00" * 32), (256, 0xAA * sum(256 ** i for i in range(32)), "0x" + "aa" * 32), (256, 2 ** 256 - 1, "0x" + "ff" * 32), ), ) def test_uint(bit_length, value, serialized): uint = UInt(bit_length) assert encode_hex(ssz.encode(value, uint)) == serialized assert ssz.decode(decode_hex(serialized), uint) == value @pytest.mark.parametrize(("sedes", "id"), ((UInt(64), "UInt64"), (boolean, "Boolean"))) def test_get_sedes_id(sedes, id): assert sedes.get_sedes_id() == id @pytest.mark.parametrize( ("sedes1", "sedes2"), ((uint8, uint8), (UInt(8), UInt(8)), (UInt(256), UInt(256))) ) def test_uint_eq(sedes1, sedes2): assert sedes1 == sedes1 assert sedes2 == sedes2 assert sedes1 == sedes2 assert hash(sedes1) == hash(sedes2) @pytest.mark.parametrize(
def mk_ssz(): # # SSZ # from ssz.sedes import ( bytes32, UInt, bytes_sedes, List, ) address = bytes_sedes uint256 = UInt(2048) uint32 = UInt(256) big_endian_int = uint32 trie_root = bytes32 hash32 = bytes32 class BlockHeader(ssz.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', bytes_sedes), ('mix_hash', bytes_sedes), ('nonce', bytes_sedes), ] class Transaction(ssz.Serializable): fields = [ ('nonce', big_endian_int), ('gas_price', big_endian_int), ('gas', big_endian_int), ('to', address), ('value', big_endian_int), ('data', bytes_sedes), ('v', big_endian_int), ('r', big_endian_int), ('s', big_endian_int), ] class Block(ssz.Serializable): fields = [('header', BlockHeader), ('transactions', List(Transaction)), ('uncles', List(BlockHeader))] class Log(ssz.Serializable): fields = [('address', address), ('topics', List(uint32)), ('data', bytes_sedes)] class Receipt(ssz.Serializable): fields = [('state_root', bytes_sedes), ('gas_used', big_endian_int), ('bloom', uint256), ('logs', List(Log))] class Account(ssz.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage_root', trie_root), ('code_hash', hash32)] class MiniAccount(ssz.Serializable): fields = [('nonce', big_endian_int), ('balance', big_endian_int), ('storage_root', bytes_sedes), ('code_hash', bytes_sedes)] class Address(ssz.Serializable): fields = [ ('sender_ip', bytes_sedes), ('sender_udp_port', big_endian_int), ('sender_tcp_port', big_endian_int), ] class Ping(ssz.Serializable): fields = [ ('version', big_endian_int), ('from', Address), ('to', Address), ('expiration', big_endian_int), ] class Pong(ssz.Serializable): fields = [ ('to', Address), ('ping_hash', bytes_sedes), ('expiration', big_endian_int), ] class FindNode(ssz.Serializable): fields = [ ('target', bytes_sedes), ('expiration', big_endian_int), ] class Neighbour(ssz.Serializable): fields = [ ('ip', bytes_sedes), ('udp_port', big_endian_int), ('tcp_port', big_endian_int), ('node_id', bytes_sedes), ] class Neighbours(ssz.Serializable): fields = [ ('nodes', List(Neighbour)), ('expiration', big_endian_int), ] return BlockHeader, Block, Transaction, Receipt, List( Receipt ), Log, Account, MiniAccount, Ping, Pong, FindNode, Neighbours, List( bytes_sedes) # noqa: E501
Vector(Container((uint8, List(uint8, 2))), 2), "Vector(UInt8,List(UInt8,2),2)", ), ), ) def test_get_sedes_id(sedes, id): assert sedes.get_sedes_id() == id @pytest.mark.parametrize( ("sedes1", "sedes2"), ( (List(uint8, 2), List(uint8, 2)), (Vector(uint8, 2), Vector(uint8, 2)), (Container( (uint8, List(uint8, 2))), Container((UInt(8), List(UInt(8), 2)))), (Container([uint8, uint8]), Container((uint8, uint8))), ), ) def test_eq(sedes1, sedes2): assert sedes1 == sedes1 assert sedes2 == sedes2 assert sedes1 == sedes2 assert hash(sedes1) == hash(sedes2) @pytest.mark.parametrize( ("sedes1", "sedes2"), ( (List(uint8, 2), List(uint8, 3)), (List(uint8, 2), List(uint256, 2)),
from ddht.v5_1.alexandria.constants import GB class ByteList(List): # type: ignore def __init__(self, max_length: int) -> None: super().__init__(element_sedes=uint8, max_length=max_length) def serialize(self, value: bytes) -> bytes: return value def deserialize(self, value: bytes) -> bytes: return value byte_list = ByteList(max_length=2048) uint40 = UInt(40) content_key_sedes = ByteList(max_length=256) PingSedes = Container(field_sedes=(uint32, uint256)) PongSedes = Container(field_sedes=(uint32, uint256)) FindNodesSedes = Container(field_sedes=(List(uint16, max_length=256),)) FoundNodesSedes = Container(field_sedes=(uint8, List(byte_list, max_length=32))) GetContentSedes = Container(field_sedes=(byte_list, uint32, uint16)) ContentSedes = Container(field_sedes=(boolean, byte_list,)) AdvertisementSedes = Container( field_sedes=(byte_list, bytes32, uint40, uint8, uint256, uint256) )
def uint_sedes_and_values_st(draw): bytes_ = 2**draw(st.integers(0, 5)) bits = bytes_ * 8 return UInt(bits), uint_value_st(bits)