diff --git a/test_libs/fuzzing/decoder.py b/test_libs/fuzzing/decoder.py new file mode 100644 index 000000000..16d798f6f --- /dev/null +++ b/test_libs/fuzzing/decoder.py @@ -0,0 +1,84 @@ +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)) diff --git a/test_libs/fuzzing/requirements.txt b/test_libs/fuzzing/requirements.txt new file mode 100644 index 000000000..98dcd9564 --- /dev/null +++ b/test_libs/fuzzing/requirements.txt @@ -0,0 +1,3 @@ +../../test_libs/pyspec +../../test_libs/config_helpers +ssz==0.1.0a8