From f15849cf00ddc21137886e582cc064e80ee8c47e Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Wed, 1 Apr 2020 18:46:53 +0200 Subject: [PATCH] accounts/abi faster unpacking of int256 (#20850) --- accounts/abi/unpack.go | 22 +++++++++------------- accounts/abi/unpack_test.go | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/accounts/abi/unpack.go b/accounts/abi/unpack.go index 2a5db3b31..b2ce26cac 100644 --- a/accounts/abi/unpack.go +++ b/accounts/abi/unpack.go @@ -27,13 +27,9 @@ import ( var ( // MaxUint256 is the maximum value that can be represented by a uint256 - MaxUint256 = big.NewInt(0).Add( - big.NewInt(0).Exp(big.NewInt(2), big.NewInt(256), nil), - big.NewInt(-1)) + MaxUint256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1) // MaxInt256 is the maximum value that can be represented by a int256 - MaxInt256 = big.NewInt(0).Add( - big.NewInt(0).Exp(big.NewInt(2), big.NewInt(255), nil), - big.NewInt(-1)) + MaxInt256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 255), common.Big1) ) // ReadInteger reads the integer based on its kind and returns the appropriate value @@ -56,17 +52,17 @@ func ReadInteger(typ byte, kind reflect.Kind, b []byte) interface{} { case reflect.Int64: return int64(binary.BigEndian.Uint64(b[len(b)-8:])) default: - // the only case lefts for integer is int256/uint256. - // big.SetBytes can't tell if a number is negative, positive on itself. - // On EVM, if the returned number > max int256, it is negative. + // the only case left for integer is int256/uint256. ret := new(big.Int).SetBytes(b) if typ == UintTy { return ret } - - if ret.Cmp(MaxInt256) > 0 { - ret.Add(MaxUint256, big.NewInt(0).Neg(ret)) - ret.Add(ret, big.NewInt(1)) + // big.SetBytes can't tell if a number is negative or positive in itself. + // On EVM, if the returned number > max int256, it is negative. + // A number is > max int256 if the bit at position 255 is set. + if ret.Bit(255) == 1 { + ret.Add(MaxUint256, new(big.Int).Neg(ret)) + ret.Add(ret, common.Big1) ret.Neg(ret) } return ret diff --git a/accounts/abi/unpack_test.go b/accounts/abi/unpack_test.go index dfea8db67..ab343042b 100644 --- a/accounts/abi/unpack_test.go +++ b/accounts/abi/unpack_test.go @@ -1009,7 +1009,7 @@ func TestUnpackTuple(t *testing.T) { t.Errorf("unexpected value unpacked: want %x, got %x", 1, v.A) } if v.B.Cmp(big.NewInt(-1)) != 0 { - t.Errorf("unexpected value unpacked: want %x, got %x", v.B, -1) + t.Errorf("unexpected value unpacked: want %x, got %x", -1, v.B) } }