Merge pull request #2497 from ethereum/union-debug-utils

encode, decode and randomize ssz Union types
This commit is contained in:
Alex Stokes 2021-06-24 09:37:49 -07:00 committed by GitHub
commit 4f905551c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 3 deletions

View File

@ -2,7 +2,7 @@ from typing import Any
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
from eth2spec.utils.ssz.ssz_typing import (
uint, Container, List, boolean,
Vector, ByteVector, ByteList
Vector, ByteVector, ByteList, Union, View
)
@ -27,5 +27,16 @@ def decode(data: Any, typ):
assert (data["hash_tree_root"][2:] ==
hash_tree_root(ret).hex())
return ret
elif issubclass(typ, Union):
selector = int(data["selector"])
options = typ.options()
value_typ = options[selector]
value: View
if value_typ is None: # handle the "nil" type case
assert data["value"] is None
value = None
else:
value = decode(data["value"], value_typ)
return typ(selector=selector, value=value)
else:
raise Exception(f"Type not recognized: data={data}, typ={typ}")

View File

@ -1,7 +1,7 @@
from eth2spec.utils.ssz.ssz_impl import hash_tree_root, serialize
from eth2spec.utils.ssz.ssz_typing import (
uint, boolean,
Bitlist, Bitvector, Container, Vector, List
Bitlist, Bitvector, Container, Vector, List, Union
)
@ -31,5 +31,11 @@ def encode(value, include_hash_tree_roots=False):
if include_hash_tree_roots:
ret["hash_tree_root"] = '0x' + hash_tree_root(value).hex()
return ret
elif isinstance(value, Union):
inner_value = value.value()
return {
'selector': int(value.selector()),
'value': None if inner_value is None else encode(inner_value, include_hash_tree_roots)
}
else:
raise Exception(f"Type not recognized: value={value}, typ={type(value)}")

View File

@ -5,7 +5,7 @@ from typing import Type
from eth2spec.utils.ssz.ssz_typing import (
View, BasicView, uint, Container, List, boolean,
Vector, ByteVector, ByteList, Bitlist, Bitvector
Vector, ByteVector, ByteList, Bitlist, Bitvector, Union
)
# in bytes
@ -115,6 +115,22 @@ def get_random_ssz_object(rng: Random,
get_random_ssz_object(rng, field_type, max_bytes_length, max_list_length, mode, chaos)
for field_name, field_type in fields.items()
})
elif issubclass(typ, Union):
options = typ.options()
selector: int
if mode == RandomizationMode.mode_zero:
selector = 0
elif mode == RandomizationMode.mode_max:
selector = len(options) - 1
else:
selector = rng.randrange(0, len(options))
elem_type = options[selector]
elem: View
if elem_type is None:
elem = None
else:
elem = get_random_ssz_object(rng, elem_type, max_bytes_length, max_list_length, mode, chaos)
return typ(selector=selector, value=elem)
else:
raise Exception(f"Type not recognized: typ={typ}")