Ejemplo n.º 1
0
def test_decode_bytes_xx(value_byte_size, stream_bytes, data_byte_size):
    if value_byte_size > data_byte_size:
        with pytest.raises(ValueError):
            BytesDecoder(
                value_bit_size=value_byte_size * 8,
                data_byte_size=data_byte_size,
            )
        return
    else:
        decoder = BytesDecoder(
            value_bit_size=value_byte_size * 8,
            data_byte_size=data_byte_size,
        )

    stream = ContextFramesBytesIO(stream_bytes)
    actual_value = stream_bytes[:value_byte_size]
    padding_bytes = stream_bytes[value_byte_size:data_byte_size]

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return
    elif is_non_empty_non_null_byte_string(padding_bytes):
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return
    else:
        decoded_value = decoder(stream)

    assert decoded_value == actual_value
Ejemplo n.º 2
0
    def decode_abi(self, types: Iterable[TypeStr],
                   data: Decodable) -> Tuple[Any, ...]:
        """
        Decodes the binary value ``data`` as a sequence of values of the ABI types
        in ``types`` via the head-tail mechanism into a tuple of equivalent python
        values.

        :param types: An iterable of string representations of the ABI types that
            will be used for decoding e.g. ``('uint256', 'bytes[]', '(int,int)')``
        :param data: The binary value to be decoded.

        :returns: A tuple of equivalent python values for the ABI values
            represented in ``data``.
        """
        if not is_bytes(data):
            raise TypeError(
                "The `data` value must be of bytes type.  Got {0}".format(
                    type(data)))

        decoders = [self._registry.get_decoder(type_str) for type_str in types]

        decoder = TupleDecoder(decoders=decoders)
        stream = ContextFramesBytesIO(data)

        return decoder(stream)
Ejemplo n.º 3
0
def decode_single(typ: TypeStr, data: Decodable) -> Any:
    """
    Decodes the binary value ``data`` of the ABI type ``typ`` into its
    equivalent python value.

    :param typ: The string representation of the ABI type that will be used for
        decoding e.g. ``'uint256'``, ``'bytes[]'``, ``'(int,int)'``, etc.
    :param data: The binary value to be decoded.

    :returns: The equivalent python value of the ABI value represented in
        ``data``.
    """
    if not is_bytes(data):
        raise TypeError(
            "The `data` value must be of bytes type.  Got {0}".format(
                type(data)))

    if isinstance(typ, str):
        type_str = typ
    else:
        type_str = collapse_type(*typ)

    decoder = registry.get_decoder(type_str)
    stream = ContextFramesBytesIO(data)

    return decoder(stream)
Ejemplo n.º 4
0
def test_decode_unsigned_fixed(value_bit_size, frac_places, stream_bytes,
                               data_byte_size):
    if value_bit_size > data_byte_size * 8:
        with pytest.raises(ValueError):
            UnsignedFixedDecoder(
                value_bit_size=value_bit_size,
                frac_places=frac_places,
                data_byte_size=data_byte_size,
            )
        return

    decoder = UnsignedFixedDecoder(
        value_bit_size=value_bit_size,
        frac_places=frac_places,
        data_byte_size=data_byte_size,
    )

    stream = ContextFramesBytesIO(stream_bytes)
    padding_bytes = stream_bytes[:data_byte_size][:data_byte_size -
                                                  value_bit_size // 8]

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return

    if is_non_empty_non_null_byte_string(padding_bytes):
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return

    # Ensure no exceptions
    decoder(stream)
Ejemplo n.º 5
0
def test_decode_boolean(stream_bytes, data_byte_size):
    stream = ContextFramesBytesIO(stream_bytes)

    decoder = BooleanDecoder(data_byte_size=data_byte_size)

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return

    padding_bytes = stream_bytes[:data_byte_size][:-1]
    if is_non_empty_non_null_byte_string(padding_bytes):
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return

    byte_value = stream_bytes[data_byte_size - 1]

    if byte_value in {0, b'\x00'}:
        actual_value = False
    elif byte_value in {1, b'\x01'}:
        actual_value = True
    else:
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return

    decoded_value = decoder(stream)
    assert decoded_value is actual_value
Ejemplo n.º 6
0
def test_decode_address(address_bytes, padding_size, data_byte_size):
    stream_bytes = b'\x00' * padding_size + address_bytes
    if data_byte_size < 20:
        with pytest.raises(ValueError):
            AddressDecoder(data_byte_size=data_byte_size, )
        return
    else:
        decoder = AddressDecoder(data_byte_size=data_byte_size, )

    stream = ContextFramesBytesIO(stream_bytes)
    padding_bytes = stream_bytes[:data_byte_size][:-20]

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return
    elif is_non_empty_non_null_byte_string(padding_bytes):
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return
    else:
        decoded_value = decoder(stream)

    actual_value = to_normalized_address(stream_bytes[:data_byte_size][-20:])

    assert decoded_value == actual_value
Ejemplo n.º 7
0
def decode_abi(types, data):
    if not is_bytes(data):
        raise TypeError(
            "The `data` value must be of bytes type.  Got {0}".format(
                type(data)))

    decoders = [registry.get_decoder(type_str) for type_str in types]

    decoder = TupleDecoder(decoders=decoders)
    stream = ContextFramesBytesIO(data)

    return decoder(stream)
Ejemplo n.º 8
0
def test_decode_unsigned_real(high_bit_size,
                              low_bit_size,
                              integer_bit_size,
                              stream_bytes,
                              data_byte_size):
    if integer_bit_size > data_byte_size * 8:
        with pytest.raises(ValueError):
            UnsignedRealDecoder(
                value_bit_size=integer_bit_size,
                high_bit_size=high_bit_size,
                low_bit_size=low_bit_size,
                data_byte_size=data_byte_size,
            )
        return
    elif high_bit_size + low_bit_size != integer_bit_size:
        with pytest.raises(ValueError):
            UnsignedRealDecoder(
                value_bit_size=integer_bit_size,
                high_bit_size=high_bit_size,
                low_bit_size=low_bit_size,
                data_byte_size=data_byte_size,
            )
        return
    else:
        decoder = UnsignedRealDecoder(
            value_bit_size=integer_bit_size,
            high_bit_size=high_bit_size,
            low_bit_size=low_bit_size,
            data_byte_size=data_byte_size,
        )

    stream = ContextFramesBytesIO(stream_bytes)
    padding_bytes = stream_bytes[:data_byte_size][:data_byte_size - integer_bit_size // 8]

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return
    elif is_non_empty_non_null_byte_string(padding_bytes):
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return
    else:
        decoded_value = decoder(stream)

    unsigned_integer_value = big_endian_to_int(stream_bytes[:data_byte_size])

    with decimal.localcontext(abi_decimal_context):
        raw_real_value = decimal.Decimal(unsigned_integer_value) / 2 ** low_bit_size

    actual_value = quantize_value(raw_real_value, low_bit_size)

    assert decoded_value == actual_value
Ejemplo n.º 9
0
def decode_single(typ, data):
    if not is_bytes(data):
        raise TypeError(
            "The `data` value must be of bytes type.  Got {0}".format(
                type(data)))

    if isinstance(typ, str):
        type_str = typ
    else:
        type_str = collapse_type(*typ)

    decoder = registry.get_decoder(type_str)
    stream = ContextFramesBytesIO(data)

    return decoder(stream)
Ejemplo n.º 10
0
def test_decode_strings_raises(_bytes, pad_size):
    size_bytes = zpad32(int_to_big_endian(len(_bytes)))
    padded_bytes = _bytes + b'\x00' * pad_size
    stream_bytes = size_bytes + padded_bytes
    stream = ContextFramesBytesIO(stream_bytes)

    decoder = StringDecoder()

    if len(padded_bytes) < ceil32(len(_bytes)):
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return

    with pytest.raises(DecodingError):
        decoder(stream)
Ejemplo n.º 11
0
def test_decode_strings(_strings, pad_size):
    size_bytes = zpad32(int_to_big_endian(len(_strings.encode("utf-8"))))
    padded_bytes = _strings.encode("utf-8") + b'\x00' * pad_size
    stream_bytes = size_bytes + padded_bytes
    stream = ContextFramesBytesIO(stream_bytes)

    decoder = StringDecoder()

    if len(padded_bytes) < ceil32(len(_strings.encode("utf-8"))):
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return

    decoded_value = decoder(stream)
    assert decoded_value == _strings
Ejemplo n.º 12
0
def test_decode_signed_int(integer_bit_size, stream_bytes, data_byte_size):
    if integer_bit_size % 8 != 0:
        with pytest.raises(ValueError):
            SignedIntegerDecoder(
                value_bit_size=integer_bit_size,
                data_byte_size=data_byte_size,
            )
        return
    elif integer_bit_size > data_byte_size * 8:
        with pytest.raises(ValueError):
            SignedIntegerDecoder(
                value_bit_size=integer_bit_size,
                data_byte_size=data_byte_size,
            )
        return
    else:
        decoder = SignedIntegerDecoder(
            value_bit_size=integer_bit_size,
            data_byte_size=data_byte_size,
        )


    stream = ContextFramesBytesIO(stream_bytes)

    padding_bytes = data_byte_size - integer_bit_size // 8

    raw_value = big_endian_to_int(stream_bytes[padding_bytes:data_byte_size])
    if raw_value >= 2 ** (integer_bit_size - 1):
        actual_value = raw_value - 2 ** integer_bit_size
    else:
        actual_value = raw_value

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return
    elif (
        (actual_value >= 0 and not all_bytes_equal(stream_bytes[:padding_bytes], 0)) or
        (actual_value < 0 and not all_bytes_equal(stream_bytes[:padding_bytes], 255))
    ):
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return
    else:
        decoded_value = decoder(stream)

    assert decoded_value == actual_value
Ejemplo n.º 13
0
def test_decode_array_of_unsigned_integers(array_size, array_values):
    size_bytes = zpad32(int_to_big_endian(array_size))
    values_bytes = b''.join(
        (zpad32(int_to_big_endian(v)) for v in array_values))
    stream_bytes = size_bytes + values_bytes

    decoder = DynamicArrayDecoder(
        item_decoder=UnsignedIntegerDecoder(value_bit_size=256), )
    stream = ContextFramesBytesIO(stream_bytes)

    if len(array_values) < array_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return

    actual_values = decoder(stream)
    assert actual_values == array_values[:array_size]
Ejemplo n.º 14
0
def test_decode_signed_fixed(value_bit_size,
                             frac_places,
                             stream_bytes,
                             data_byte_size):
    if value_bit_size > data_byte_size * 8:
        with pytest.raises(ValueError):
            SignedFixedDecoder(
                value_bit_size=value_bit_size,
                frac_places=frac_places,
                data_byte_size=data_byte_size,
            )
        return

    decoder = SignedFixedDecoder(
        value_bit_size=value_bit_size,
        frac_places=frac_places,
        data_byte_size=data_byte_size,
    )

    stream = ContextFramesBytesIO(stream_bytes)

    padding_offset = data_byte_size - value_bit_size // 8
    data_offset = padding_offset + value_bit_size // 8

    padding_bytes = stream_bytes[:data_byte_size][:padding_offset]
    data_bytes = stream_bytes[:data_byte_size][padding_offset:data_offset]

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return

    if not is_valid_padding_bytes(padding_bytes, data_bytes):
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return

    actual_value = decoder(stream)

    if padding_bytes:
        if actual_value >= 0:
            assert bytes(set(padding_bytes)) == b'\x00'
        else:
            assert bytes(set(padding_bytes)) == b'\xff'
Ejemplo n.º 15
0
def test_decode_unsigned_int(integer_bit_size, stream_bytes, data_byte_size):
    if integer_bit_size % 8 != 0:
        with pytest.raises(ValueError):
            UnsignedIntegerDecoder(
                value_bit_size=integer_bit_size,
                data_byte_size=data_byte_size,
            )
        return
    elif integer_bit_size > data_byte_size * 8:
        with pytest.raises(ValueError):
            UnsignedIntegerDecoder(
                value_bit_size=integer_bit_size,
                data_byte_size=data_byte_size,
            )
        return
    else:
        decoder = UnsignedIntegerDecoder(
            value_bit_size=integer_bit_size,
            data_byte_size=data_byte_size,
        )


    stream = ContextFramesBytesIO(stream_bytes)
    actual_value = big_endian_to_int(stream_bytes[:data_byte_size])

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return
    elif actual_value > 2 ** integer_bit_size - 1:
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return
    else:
        decoded_value = decoder(stream)

    assert decoded_value == actual_value
Ejemplo n.º 16
0
def byte_stream(byte_string):
    return ContextFramesBytesIO(byte_string)
Ejemplo n.º 17
0
def test_tuple_decoder(types, data, expected):
    decoders = [registry.get_decoder(t) for t in types]
    decoder = TupleDecoder(decoders=decoders)
    stream = ContextFramesBytesIO(decode_hex(data))
    actual = decoder(stream)
    assert actual == expected
Ejemplo n.º 18
0
def test_decode_signed_real(high_bit_size, low_bit_size, integer_bit_size,
                            stream_bytes, data_byte_size):
    if integer_bit_size > data_byte_size * 8:
        with pytest.raises(ValueError):
            SignedRealDecoder(
                value_bit_size=integer_bit_size,
                high_bit_size=high_bit_size,
                low_bit_size=low_bit_size,
                data_byte_size=data_byte_size,
            )
        return
    elif high_bit_size + low_bit_size != integer_bit_size:
        with pytest.raises(ValueError):
            SignedRealDecoder(
                value_bit_size=integer_bit_size,
                high_bit_size=high_bit_size,
                low_bit_size=low_bit_size,
                data_byte_size=data_byte_size,
            )
        return
    else:
        decoder = SignedRealDecoder(
            value_bit_size=integer_bit_size,
            high_bit_size=high_bit_size,
            low_bit_size=low_bit_size,
            data_byte_size=data_byte_size,
        )

    stream = ContextFramesBytesIO(stream_bytes)

    padding_offset = data_byte_size - integer_bit_size // 8
    data_offset = padding_offset + integer_bit_size // 8

    padding_bytes = stream_bytes[:data_byte_size][:padding_offset]
    data_bytes = stream_bytes[:data_byte_size][padding_offset:data_offset]

    if len(stream_bytes) < data_byte_size:
        with pytest.raises(InsufficientDataBytes):
            decoder(stream)
        return
    elif not is_valid_padding_bytes(padding_bytes, data_bytes):
        with pytest.raises(NonEmptyPaddingBytes):
            decoder(stream)
        return
    else:
        decoded_value = decoder(stream)

    if padding_bytes:
        if decoded_value >= 0:
            assert bytes(set(padding_bytes)) == b'\x00'
        else:
            assert bytes(set(padding_bytes)) == b'\xff'

    _, upper_bound = compute_signed_integer_bounds(high_bit_size +
                                                   low_bit_size)

    unsigned_integer_value = big_endian_to_int(data_bytes)
    if unsigned_integer_value >= upper_bound:
        signed_integer_value = unsigned_integer_value - 2**(high_bit_size +
                                                            low_bit_size)
    else:
        signed_integer_value = unsigned_integer_value

    with decimal.localcontext(abi_decimal_context):
        raw_actual_value = decimal.Decimal(
            signed_integer_value) / 2**low_bit_size

    actual_value = quantize_value(raw_actual_value, low_bit_size)

    assert decoded_value == actual_value