2019-06-19 00:37:22 +00:00
|
|
|
from typing import Any
|
2019-05-27 19:46:14 +00:00
|
|
|
from eth2spec.utils.ssz.ssz_impl import hash_tree_root
|
2019-06-01 00:22:14 +00:00
|
|
|
from eth2spec.utils.ssz.ssz_typing import (
|
2020-01-24 23:43:43 +00:00
|
|
|
uint, Container, List, boolean,
|
2021-06-24 15:13:36 +00:00
|
|
|
Vector, ByteVector, ByteList, Union, View
|
2019-06-01 00:22:14 +00:00
|
|
|
)
|
2019-04-07 13:36:05 +00:00
|
|
|
|
|
|
|
|
2020-01-24 23:43:43 +00:00
|
|
|
def decode(data: Any, typ):
|
2019-06-27 08:51:06 +00:00
|
|
|
if issubclass(typ, (uint, boolean)):
|
2019-06-19 00:37:22 +00:00
|
|
|
return typ(data)
|
|
|
|
elif issubclass(typ, (List, Vector)):
|
2020-01-24 23:43:43 +00:00
|
|
|
return typ(decode(element, typ.element_cls()) for element in data)
|
|
|
|
elif issubclass(typ, ByteVector):
|
|
|
|
return typ(bytes.fromhex(data[2:]))
|
|
|
|
elif issubclass(typ, ByteList):
|
2019-06-19 00:37:22 +00:00
|
|
|
return typ(bytes.fromhex(data[2:]))
|
|
|
|
elif issubclass(typ, Container):
|
2019-04-07 13:36:05 +00:00
|
|
|
temp = {}
|
2020-01-24 23:43:43 +00:00
|
|
|
for field_name, field_type in typ.fields().items():
|
2019-06-19 00:37:22 +00:00
|
|
|
temp[field_name] = decode(data[field_name], field_type)
|
|
|
|
if field_name + "_hash_tree_root" in data:
|
|
|
|
assert (data[field_name + "_hash_tree_root"][2:] ==
|
|
|
|
hash_tree_root(temp[field_name]).hex())
|
2019-04-07 13:36:05 +00:00
|
|
|
ret = typ(**temp)
|
2019-05-27 19:46:14 +00:00
|
|
|
if "hash_tree_root" in data:
|
2019-06-19 00:37:22 +00:00
|
|
|
assert (data["hash_tree_root"][2:] ==
|
|
|
|
hash_tree_root(ret).hex())
|
2019-04-07 13:36:05 +00:00
|
|
|
return ret
|
2021-06-24 15:13:36 +00:00
|
|
|
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)
|
2019-04-07 13:36:05 +00:00
|
|
|
else:
|
2019-06-04 09:42:21 +00:00
|
|
|
raise Exception(f"Type not recognized: data={data}, typ={typ}")
|