From d39f9e4415b4510909307a8157df5e3f5910d054 Mon Sep 17 00:00:00 2001 From: Jan Xie Date: Sun, 20 Mar 2016 14:30:15 +0800 Subject: [PATCH 1/2] fix abi.decint, be aware of signs --- ethereum/abi.py | 33 ++++++++++++++++++--------------- ethereum/tests/test_abi.py | 1 + 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/ethereum/abi.py b/ethereum/abi.py index 0e8e53c14..325ff3320 100644 --- a/ethereum/abi.py +++ b/ethereum/abi.py @@ -4,7 +4,7 @@ from ethereum import utils from rlp.utils import decode_hex, encode_hex from ethereum.utils import encode_int, zpad, big_endian_to_int, is_numeric, is_string, ceil32 -from ethereum.utils import isnumeric +from ethereum.utils import isnumeric, TT256, TT255 import ast @@ -145,20 +145,24 @@ class ValueOutOfBounds(EncodingError): pass -# Decode an integer -def decint(n): +# Decode an unsigned/signed integer +def decint(n, signed=False): if isinstance(n, str): n = utils.to_string(n) - if is_numeric(n) and n < 2**256 and n >= -2**255: + + if is_numeric(n): + min, max = (-TT255,TT255-1) if signed else (0,TT256-1) + if n > max or n < min: + raise EncodingError("Number out of range: %r" % n) return n - elif is_numeric(n): - raise EncodingError("Number out of range: %r" % n) - elif is_string(n) and len(n) == 40: - return big_endian_to_int(decode_hex(n)) - elif is_string(n) and len(n) <= 32: - return big_endian_to_int(n) - elif is_string(n) and len(n) > 32: - raise EncodingError("String too long: %r" % n) + elif is_string(n): + if len(n) == 40: + n = decode_hex(n) + if len(n) > 32: + raise EncodingError("String too long: %r" % n) + + i = big_endian_to_int(n) + return (i - TT256) if signed and i >= TT255 else i elif n is True: return 1 elif n is False or n is None: @@ -166,14 +170,13 @@ def decint(n): else: raise EncodingError("Cannot encode integer: %r" % n) - # Encodes a base datum def encode_single(typ, arg): base, sub, _ = typ # Unsigned integers: uint if base == 'uint': sub = int(sub) - i = decint(arg) + i = decint(arg, False) if not 0 <= i < 2**sub: raise ValueOutOfBounds(repr(arg)) @@ -185,7 +188,7 @@ def encode_single(typ, arg): # Signed integers: int elif base == 'int': sub = int(sub) - i = decint(arg) + i = decint(arg, True) if not -2**(sub - 1) <= i < 2**(sub - 1): raise ValueOutOfBounds(repr(arg)) return zpad(encode_int(i % 2**sub), 32) diff --git a/ethereum/tests/test_abi.py b/ethereum/tests/test_abi.py index 41aa6b6ea..03fd3933a 100644 --- a/ethereum/tests/test_abi.py +++ b/ethereum/tests/test_abi.py @@ -22,6 +22,7 @@ def test_abi_encode_signed_int(): def test_abi_encode_single_int(): assert abi.encode_single(['int', '256', []], -2**255) == (b'\x80'+b'\x00'*31) + assert abi.encode_single(['int', '256', []], (b'\x80'+b'\x00'*31)) == (b'\x80'+b'\x00'*31) assert abi.encode_single(['int', '8', []], -128) == zpad(b'\x80', 32) with pytest.raises(abi.ValueOutOfBounds): From a1e604d20f94e094812994c5a678d00df19989d6 Mon Sep 17 00:00:00 2001 From: Jan Xie Date: Sun, 20 Mar 2016 14:31:21 +0800 Subject: [PATCH 2/2] fix ecrecover contract test --- ethereum/tests/test_contracts.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethereum/tests/test_contracts.py b/ethereum/tests/test_contracts.py index 54c2ce3fb..5f25771b8 100644 --- a/ethereum/tests/test_contracts.py +++ b/ethereum/tests/test_contracts.py @@ -1190,7 +1190,7 @@ def test_types(): ecrecover_code = """ -def test_ecrecover(h, v, r, s): +def test_ecrecover(h:uint256, v:uint256, r:uint256, s:uint256): return(ecrecover(h, v, r, s)) """