Skip to content

Commit afeb18a

Browse files
committed
accounts/abi faster unpacking of int256 (ethereum#20850)
1 parent 7965385 commit afeb18a

File tree

2 files changed

+10
-14
lines changed

2 files changed

+10
-14
lines changed

accounts/abi/unpack.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,9 @@ import (
2828

2929
var (
3030
// MaxUint256 is the maximum value that can be represented by a uint256
31-
MaxUint256 = big.NewInt(0).Add(
32-
big.NewInt(0).Exp(big.NewInt(2), big.NewInt(256), nil),
33-
big.NewInt(-1))
31+
MaxUint256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 256), common.Big1)
3432
// MaxInt256 is the maximum value that can be represented by a int256
35-
MaxInt256 = big.NewInt(0).Add(
36-
big.NewInt(0).Exp(big.NewInt(2), big.NewInt(255), nil),
37-
big.NewInt(-1))
33+
MaxInt256 = new(big.Int).Sub(new(big.Int).Lsh(common.Big1, 255), common.Big1)
3834
)
3935

4036
// ReadInteger reads the integer based on its kind and returns the appropriate value
@@ -57,17 +53,17 @@ func ReadInteger(typ byte, kind reflect.Kind, b []byte) interface{} {
5753
case reflect.Int64:
5854
return int64(binary.BigEndian.Uint64(b[len(b)-8:]))
5955
default:
60-
// the only case lefts for integer is int256/uint256.
61-
// big.SetBytes can't tell if a number is negative, positive on itself.
62-
// On EVM, if the returned number > max int256, it is negative.
56+
// the only case left for integer is int256/uint256.
6357
ret := new(big.Int).SetBytes(b)
6458
if typ == UintTy {
6559
return ret
6660
}
67-
68-
if ret.Cmp(MaxInt256) > 0 {
69-
ret.Add(MaxUint256, big.NewInt(0).Neg(ret))
70-
ret.Add(ret, big.NewInt(1))
61+
// big.SetBytes can't tell if a number is negative or positive in itself.
62+
// On EVM, if the returned number > max int256, it is negative.
63+
// A number is > max int256 if the bit at position 255 is set.
64+
if ret.Bit(255) == 1 {
65+
ret.Add(MaxUint256, new(big.Int).Neg(ret))
66+
ret.Add(ret, common.Big1)
7167
ret.Neg(ret)
7268
}
7369
return ret

accounts/abi/unpack_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,7 +1009,7 @@ func TestUnpackTuple(t *testing.T) {
10091009
t.Errorf("unexpected value unpacked: want %x, got %x", 1, v.A)
10101010
}
10111011
if v.B.Cmp(big.NewInt(-1)) != 0 {
1012-
t.Errorf("unexpected value unpacked: want %x, got %x", v.B, -1)
1012+
t.Errorf("unexpected value unpacked: want %x, got %x", -1, v.B)
10131013
}
10141014
}
10151015

0 commit comments

Comments
 (0)