85 lines
3.0 KiB
Python
85 lines
3.0 KiB
Python
|
from eth2spec.utils.ssz import ssz_typing as spec_ssz
|
||
|
import ssz
|
||
|
|
||
|
|
||
|
def translate_typ(typ) -> ssz.BaseSedes:
|
||
|
"""
|
||
|
Translates a spec type to a Py-SSZ type description (sedes).
|
||
|
:param typ: The spec type, a class.
|
||
|
:return: The Py-SSZ equivalent.
|
||
|
"""
|
||
|
if spec_ssz.is_container_type(typ):
|
||
|
return ssz.Container(
|
||
|
[(field_name, translate_typ(field_typ)) for (field_name, field_typ) in typ.get_fields()])
|
||
|
elif spec_ssz.is_bytesn_type(typ):
|
||
|
return ssz.ByteVector(typ.length)
|
||
|
elif spec_ssz.is_bytes_type(typ):
|
||
|
return ssz.ByteList()
|
||
|
elif spec_ssz.is_vector_type(typ):
|
||
|
return ssz.Vector(translate_typ(spec_ssz.read_vector_elem_type(typ)), typ.length)
|
||
|
elif spec_ssz.is_list_type(typ):
|
||
|
return ssz.List(translate_typ(spec_ssz.read_list_elem_type(typ)))
|
||
|
elif spec_ssz.is_bool_type(typ):
|
||
|
return ssz.boolean
|
||
|
elif spec_ssz.is_uint_type(typ):
|
||
|
size = spec_ssz.uint_byte_size(typ)
|
||
|
if size == 1:
|
||
|
return ssz.uint8
|
||
|
elif size == 2:
|
||
|
return ssz.uint16
|
||
|
elif size == 4:
|
||
|
return ssz.uint32
|
||
|
elif size == 8:
|
||
|
return ssz.uint64
|
||
|
elif size == 16:
|
||
|
return ssz.uint128
|
||
|
elif size == 32:
|
||
|
return ssz.uint256
|
||
|
else:
|
||
|
raise TypeError("invalid uint size")
|
||
|
else:
|
||
|
raise Exception("Type not supported: {}".format(typ))
|
||
|
|
||
|
|
||
|
def translate_value(value, typ):
|
||
|
"""
|
||
|
Translate a value output from Py-SSZ deserialization into the given spec type.
|
||
|
:param value: The PySSZ value
|
||
|
:param typ: The type from the spec to translate into
|
||
|
:return: the translated value
|
||
|
"""
|
||
|
if spec_ssz.is_uint_type(typ):
|
||
|
size = spec_ssz.uint_byte_size(typ)
|
||
|
if size == 1:
|
||
|
return spec_ssz.uint8(value)
|
||
|
elif size == 2:
|
||
|
return spec_ssz.uint16(value)
|
||
|
elif size == 4:
|
||
|
return spec_ssz.uint32(value)
|
||
|
elif size == 8:
|
||
|
# uint64 is default (TODO this is changing soon)
|
||
|
return value
|
||
|
elif size == 16:
|
||
|
return spec_ssz.uint128(value)
|
||
|
elif size == 32:
|
||
|
return spec_ssz.uint256(value)
|
||
|
else:
|
||
|
raise TypeError("invalid uint size")
|
||
|
elif spec_ssz.is_list_type(typ):
|
||
|
elem_typ = spec_ssz.read_elem_type(typ)
|
||
|
return [translate_value(elem, elem_typ) for elem in value]
|
||
|
elif spec_ssz.is_bool_type(typ):
|
||
|
return False
|
||
|
elif spec_ssz.is_vector_type(typ):
|
||
|
elem_typ = spec_ssz.read_elem_type(typ)
|
||
|
return typ(translate_value(elem, elem_typ) for elem in value)
|
||
|
elif spec_ssz.is_bytesn_type(typ):
|
||
|
return typ(value)
|
||
|
elif spec_ssz.is_bytes_type(typ):
|
||
|
return value
|
||
|
elif spec_ssz.is_container_type(typ):
|
||
|
return typ(**{f_name: translate_value(f_val, f_typ) for (f_name, f_val, f_typ)
|
||
|
in zip(typ.get_field_names(), value.values(), typ.get_field_types())})
|
||
|
else:
|
||
|
raise Exception("Type not supported: {}".format(typ))
|