Example #1
0
def decode(data, typ):
    if is_uint_type(typ):
        return data
    elif is_bool_type(typ):
        assert data in (True, False)
        return data
    elif is_list_type(typ):
        elem_typ = read_list_elem_type(typ)
        return [decode(element, elem_typ) for element in data]
    elif is_vector_type(typ):
        elem_typ = read_vector_elem_type(typ)
        return Vector(decode(element, elem_typ) for element in data)
    elif is_bytes_type(typ):
        return bytes.fromhex(data[2:])
    elif is_bytesn_type(typ):
        return BytesN(bytes.fromhex(data[2:]))
    elif is_container_type(typ):
        temp = {}
        for field, subtype in typ.get_fields():
            temp[field] = decode(data[field], subtype)
            if field + "_hash_tree_root" in data:
                assert (data[field + "_hash_tree_root"][2:] == hash_tree_root(
                    temp[field], subtype).hex())
        ret = typ(**temp)
        if "hash_tree_root" in data:
            assert (data["hash_tree_root"][2:] == hash_tree_root(ret,
                                                                 typ).hex())
        return ret
    else:
        raise Exception(f"Type not recognized: data={data}, typ={typ}")
Example #2
0
def signing_root(obj, typ):
    assert is_container_type(typ)
    # ignore last field
    leaves = [
        hash_tree_root(field_value, typ=field_typ)
        for field_value, field_typ in obj.get_typed_values()[:-1]
    ]
    return merkleize_chunks(chunkify(b''.join(leaves)))
Example #3
0
def get_typed_values(obj, typ=None):
    if is_container_type(typ):
        return obj.get_typed_values()
    elif is_list_kind(typ) or is_vector_kind(typ):
        elem_type = read_elem_type(typ)
        return list(zip(obj, [elem_type] * len(obj)))
    else:
        raise Exception("Invalid type")
Example #4
0
def serialize(obj, typ=None):
    if is_basic_type(typ):
        return serialize_basic(obj, typ)
    elif is_list_kind(typ) or is_vector_kind(typ):
        return encode_series(obj, [read_elem_type(typ)] * len(obj))
    elif is_container_type(typ):
        return encode_series(obj.get_field_values(), typ.get_field_types())
    else:
        raise Exception("Type not supported: {}".format(typ))
Example #5
0
def is_fixed_size(typ):
    if is_basic_type(typ):
        return True
    elif is_list_kind(typ):
        return False
    elif is_vector_kind(typ):
        return is_fixed_size(read_vector_elem_type(typ))
    elif is_container_type(typ):
        return all(is_fixed_size(t) for t in typ.get_field_types())
    else:
        raise Exception("Type not supported: {}".format(typ))
Example #6
0
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 value
    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,
                                                  typ.get_field_types())
            })
    else:
        raise TypeError("Type not supported: {}".format(typ))
Example #7
0
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([
            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 TypeError("Type not supported: {}".format(typ))
Example #8
0
def get_random_ssz_object(rng: Random,
                          typ: Any,
                          max_bytes_length: int,
                          max_list_length: int,
                          mode: RandomizationMode,
                          chaos: bool) -> Any:
    """
    Create an object for a given type, filled with random data.
    :param rng: The random number generator to use.
    :param typ: The type to instantiate
    :param max_bytes_length: the max. length for a random bytes array
    :param max_list_length: the max. length for a random list
    :param mode: how to randomize
    :param chaos: if true, the randomization-mode will be randomly changed
    :return: the random object instance, of the given type.
    """
    if chaos:
        mode = rng.choice(list(RandomizationMode))
    if is_bytes_type(typ):
        # Bytes array
        if mode == RandomizationMode.mode_nil_count:
            return b''
        elif mode == RandomizationMode.mode_max_count:
            return get_random_bytes_list(rng, max_bytes_length)
        elif mode == RandomizationMode.mode_one_count:
            return get_random_bytes_list(rng, 1)
        elif mode == RandomizationMode.mode_zero:
            return b'\x00'
        elif mode == RandomizationMode.mode_max:
            return b'\xff'
        else:
            return get_random_bytes_list(rng, rng.randint(0, max_bytes_length))
    elif is_bytesn_type(typ):
        # BytesN
        length = typ.length
        # Sanity, don't generate absurdly big random values
        # If a client is aiming to performance-test, they should create a benchmark suite.
        assert length <= max_bytes_length
        if mode == RandomizationMode.mode_zero:
            return b'\x00' * length
        elif mode == RandomizationMode.mode_max:
            return b'\xff' * length
        else:
            return get_random_bytes_list(rng, length)
    elif is_basic_type(typ):
        # Basic types
        if mode == RandomizationMode.mode_zero:
            return get_min_basic_value(typ)
        elif mode == RandomizationMode.mode_max:
            return get_max_basic_value(typ)
        else:
            return get_random_basic_value(rng, typ)
    elif is_vector_type(typ):
        # Vector
        elem_typ = read_vector_elem_type(typ)
        return [
            get_random_ssz_object(rng, elem_typ, max_bytes_length, max_list_length, mode, chaos)
            for _ in range(typ.length)
        ]
    elif is_list_type(typ):
        # List
        elem_typ = read_list_elem_type(typ)
        length = rng.randint(0, max_list_length)
        if mode == RandomizationMode.mode_one_count:
            length = 1
        elif mode == RandomizationMode.mode_max_count:
            length = max_list_length

        return [
            get_random_ssz_object(rng, elem_typ, max_bytes_length, max_list_length, mode, chaos)
            for _ in range(length)
        ]
    elif is_container_type(typ):
        # Container
        return typ(**{
            field:
                get_random_ssz_object(rng, subtype, max_bytes_length, max_list_length, mode, chaos)
                for field, subtype in typ.get_fields()
        })
    else:
        raise Exception(f"Type not recognized: typ={typ}")