def test_encode_text_string(string_value): encoder = TextStringEncoder() if not is_text(string_value): with pytest.raises(EncodingTypeError) as exception_info: encoder(string_value) assert 'TextStringEncoder' in str(exception_info.value) return string_value_as_bytes = codecs.encode(string_value, 'utf8') expected_value = ( encode_uint_256(len(string_value_as_bytes)) + ( zpad_right( string_value_as_bytes, ceil32(len(string_value_as_bytes)), ) if string_value else b'\x00' * 32 ) ) encoded_value = encoder(string_value) assert encoded_value == expected_value
def test_encode_text_string(string_value): encoder = TextStringEncoder.as_encoder() if not is_text(string_value): with pytest.raises(EncodingTypeError) as exception_info: encoder(string_value) assert 'TextStringEncoder' in str(exception_info.value) return string_value_as_bytes = codecs.encode(string_value, 'utf8') expected_value = ( encode_uint_256(len(string_value_as_bytes)) + ( zpad_right( string_value_as_bytes, ceil32(len(string_value_as_bytes)), ) if string_value else b'\x00' * 32 ) ) encoded_value = encoder(string_value) assert encoded_value == expected_value
def encode(cls, value): cls.validate_value(value) value_length = len(value) encoded_size = encode_uint_256(value_length) padded_value = zpad_right(value, ceil32(value_length)) return encoded_size + padded_value
def encode(cls, value): cls.validate_value(value) value_as_bytes = codecs.encode(value, 'utf8') value_length = len(value_as_bytes) encoded_size = encode_uint_256(value_length) padded_value = zpad_right(value_as_bytes, ceil32(value_length)) return encoded_size + padded_value
def encode(cls, value): cls.validate_value(value) if not value: padded_value = b'\x00' * 32 else: padded_value = zpad_right(value, ceil32(len(value))) encoded_size = encode_uint_256(len(value)) encoded_value = encoded_size + padded_value return encoded_value
def encode(cls, value): cls.validate_value(value) if not value: padded_value = b'\x00' * 32 else: padded_value = zpad_right(value, ceil32(len(value))) encoded_size = encode_uint_256(len(value)) encoded_value = encoded_size + padded_value return encoded_value
def encode(cls, value): cls.validate_value(value) value_as_bytes = codecs.encode(value, 'utf8') if not value_as_bytes: padded_value = b'\x00' * 32 else: padded_value = zpad_right(value_as_bytes, ceil32(len(value_as_bytes))) encoded_size = encode_uint_256(len(value_as_bytes)) encoded_value = encoded_size + padded_value return encoded_value
def encode(cls, value): cls.validate_value(value) value_as_bytes = codecs.encode(value, 'utf8') if not value_as_bytes: padded_value = b'\x00' * 32 else: padded_value = zpad_right(value_as_bytes, ceil32(len(value_as_bytes))) encoded_size = encode_uint_256(len(value_as_bytes)) encoded_value = encoded_size + padded_value return encoded_value
def test_encode_string(string_value): encoder = StringEncoder.as_encoder() if not is_bytes(string_value): with pytest.raises(EncodingTypeError): encoder(string_value) return expected_value = (encode_uint_256(len(string_value)) + (zpad_right(string_value, ceil32(len(string_value))) if string_value else b'\x00' * 32)) encoded_value = encoder(string_value) assert encoded_value == expected_value
def encode(cls, value): if not is_bytes(value): raise EncodingTypeError( "Value of type {0} cannot be encoded by ByteStringEncoder". format(type(value), )) encoded_size = encode_uint_256(len(value)) if not value: padded_value = b'\x00' * 32 else: padded_value = zpad_right(value, ceil32(len(value))) encoded_value = encoded_size + padded_value return encoded_value
def test_encode_byte_string(string_value): encoder = ByteStringEncoder() if not is_bytes(string_value): with pytest.raises(EncodingTypeError) as exception_info: encoder(string_value) assert 'ByteStringEncoder' in str(exception_info.value) return expected_value = (encode_uint_256(len(string_value)) + (zpad_right( string_value, ceil32(len(string_value))) if string_value else b'')) encoded_value = encoder(string_value) assert encoded_value == expected_value
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
def test_decode_bytes_and_string(string_bytes, pad_size): size_bytes = zpad32(int_to_big_endian(len(string_bytes))) padded_string_bytes = string_bytes + b'\x00' * pad_size stream_bytes = size_bytes + padded_string_bytes stream = BytesIO(stream_bytes) decoder = StringDecoder.as_decoder() if len(padded_string_bytes) < ceil32(len(string_bytes)): with pytest.raises(InsufficientDataBytes): decoder(stream) return decoded_value = decoder(stream) assert decoded_value == string_bytes
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
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)
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)
def read_padded_data_from_stream(self, stream): """ This function exists to work around a bug in Solidity: https://github.com/ethereum/web3.py/issues/602 https://github.com/ethereum/solidity/issues/3493 Data from logs differs if the event is emitted during an external or internal solidity function call. The workaround is to pad the data until if fits the padded length. :param self: :param stream: :return: """ from eth_abi.utils.numeric import ceil32 data_length = decode_uint_256(stream) padded_length = ceil32(data_length) data = stream.read(padded_length) # Start change # Manually pad data to force it to desired length if len(data) < padded_length: data += b'\x00' * (padded_length - data_length) # End change if len(data) < padded_length: from eth_abi.exceptions import InsufficientDataBytes raise InsufficientDataBytes( "Tried to read {0} bytes. Only got {1} bytes".format( padded_length, len(data), ) ) padding_bytes = data[data_length:] if padding_bytes != b'\x00' * (padded_length - data_length): from eth_abi.exceptions import NonEmptyPaddingBytes raise NonEmptyPaddingBytes( "Padding bytes were not empty: {0}".format(repr(padding_bytes)) ) return data[:data_length]
def test_encode_byte_string(string_value): encoder = ByteStringEncoder() if not is_bytes(string_value): with pytest.raises(EncodingTypeError) as exception_info: encoder(string_value) assert 'ByteStringEncoder' in str(exception_info.value) return expected_value = ( encode_uint_256(len(string_value)) + ( zpad_right(string_value, ceil32(len(string_value))) if string_value else b'\x00' * 32 ) ) encoded_value = encoder(string_value) assert encoded_value == expected_value
def read_data_from_stream(cls, stream): data_length = decode_uint_256(stream) padded_length = ceil32(data_length) data = stream.read(padded_length) if len(data) < padded_length: raise InsufficientDataBytes( "Tried to read {0} bytes. Only got {1} bytes".format( padded_length, len(data), )) padding_bytes = data[data_length:] if padding_bytes != b'\x00' * (padded_length - data_length): raise NonEmptyPaddingBytes( "Padding bytes were not empty: {0}".format( repr(padding_bytes))) return data[:data_length]
def read_data_from_stream(stream): data_length = decode_uint_256(stream) padded_length = ceil32(data_length) data = stream.read(padded_length) if len(data) < padded_length: raise InsufficientDataBytes( "Tried to read {0} bytes. Only got {1} bytes".format( padded_length, len(data), ) ) padding_bytes = data[data_length:] if padding_bytes != b'\x00' * (padded_length - data_length): raise NonEmptyPaddingBytes( "Padding bytes were not empty: {0}".format(repr(padding_bytes)) ) return data[:data_length]
def test_ceil32(value, expected): actual = ceil32(value) assert actual == expected
def test_ceil32(value, expected): actual = ceil32(value) assert actual == expected