diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index 1c34ba0e79..5e2fcbae76 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -244,7 +245,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM } // Set infinite balance to the fake caller account. from := statedb.GetOrNewStateObject(call.From) - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) // Execute the call. msg := callmsg{call} @@ -252,7 +253,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. vmenv := vm.NewEVM(evmContext, statedb, chainConfig, vm.Config{}) - gaspool := new(core.GasPool).AddGas(common.MaxBig) + gaspool := new(core.GasPool).AddGas(math.MaxBig256) ret, gasUsed, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() return ret, gasUsed, err } diff --git a/accounts/abi/numbers.go b/accounts/abi/numbers.go index 3d58422925..36fb6705e6 100644 --- a/accounts/abi/numbers.go +++ b/accounts/abi/numbers.go @@ -21,6 +21,7 @@ import ( "reflect" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" ) var ( @@ -58,7 +59,7 @@ var ( // U256 converts a big Int into a 256bit EVM number. func U256(n *big.Int) []byte { - return common.LeftPadBytes(common.U256(n).Bytes(), 32) + return common.LeftPadBytes(math.U256(n).Bytes(), 32) } // packNum packs the given number (using the reflect value) and will cast it to appropriate number representation diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 86e2493ca1..6c4b44220c 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm/runtime" @@ -160,9 +161,9 @@ func run(ctx *cli.Context) error { ret, _, err = runtime.Create(input, &runtime.Config{ Origin: sender.Address(), State: statedb, - GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)).Uint64(), - GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), - Value: common.Big(ctx.GlobalString(ValueFlag.Name)), + GasLimit: math.MustParseUint64(ctx.GlobalString(GasFlag.Name)), + GasPrice: math.MustParseBig(ctx.GlobalString(PriceFlag.Name)), + Value: math.MustParseBig(ctx.GlobalString(ValueFlag.Name)), EVMConfig: vm.Config{ Tracer: logger, Debug: ctx.GlobalBool(DebugFlag.Name), @@ -177,9 +178,9 @@ func run(ctx *cli.Context) error { ret, err = runtime.Call(receiverAddress, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtime.Config{ Origin: sender.Address(), State: statedb, - GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)).Uint64(), - GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), - Value: common.Big(ctx.GlobalString(ValueFlag.Name)), + GasLimit: math.MustParseUint64(ctx.GlobalString(GasFlag.Name)), + GasPrice: math.MustParseBig(ctx.GlobalString(PriceFlag.Name)), + Value: math.MustParseBig(ctx.GlobalString(ValueFlag.Name)), EVMConfig: vm.Config{ Tracer: logger, Debug: ctx.GlobalBool(DebugFlag.Name), diff --git a/common/big.go b/common/big.go index 4ce87ee0c6..fb5a1da130 100644 --- a/common/big.go +++ b/common/big.go @@ -32,125 +32,22 @@ var ( Big98 = big.NewInt(98) Big256 = big.NewInt(0xff) Big257 = big.NewInt(257) - MaxBig = String2Big("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") ) -// Big pow -// -// Returns the power of two big integers -func BigPow(a, b int) *big.Int { - c := new(big.Int) - c.Exp(big.NewInt(int64(a)), big.NewInt(int64(b)), big.NewInt(0)) - - return c -} - -// Big -// -// Shortcut for new(big.Int).SetString(..., 0) -func Big(num string) *big.Int { - n := new(big.Int) - n.SetString(num, 0) - - return n -} - // Bytes2Big -// func BytesToBig(data []byte) *big.Int { n := new(big.Int) n.SetBytes(data) return n } -func Bytes2Big(data []byte) *big.Int { return BytesToBig(data) } -func BigD(data []byte) *big.Int { return BytesToBig(data) } + +func Bytes2Big(data []byte) *big.Int { + return BytesToBig(data) +} func String2Big(num string) *big.Int { n := new(big.Int) n.SetString(num, 0) return n } - -func BitTest(num *big.Int, i int) bool { - return num.Bit(i) > 0 -} - -// To256 -// -// "cast" the big int to a 256 big int (i.e., limit to) -var tt256 = new(big.Int).Lsh(big.NewInt(1), 256) -var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1)) -var tt255 = new(big.Int).Lsh(big.NewInt(1), 255) - -func U256(x *big.Int) *big.Int { - //if x.Cmp(Big0) < 0 { - // return new(big.Int).Add(tt256, x) - // } - - x.And(x, tt256m1) - - return x -} - -func S256(x *big.Int) *big.Int { - if x.Cmp(tt255) < 0 { - return x - } else { - // We don't want to modify x, ever - return new(big.Int).Sub(x, tt256) - } -} - -func FirstBitSet(v *big.Int) int { - for i := 0; i < v.BitLen(); i++ { - if v.Bit(i) > 0 { - return i - } - } - - return v.BitLen() -} - -// Big to bytes -// -// Returns the bytes of a big integer with the size specified by **base** -// Attempts to pad the byte array with zeros. -func BigToBytes(num *big.Int, base int) []byte { - ret := make([]byte, base/8) - - if len(num.Bytes()) > base/8 { - return num.Bytes() - } - - return append(ret[:len(ret)-len(num.Bytes())], num.Bytes()...) -} - -// Big copy -// -// Creates a copy of the given big integer -func BigCopy(src *big.Int) *big.Int { - return new(big.Int).Set(src) -} - -// Big max -// -// Returns the maximum size big integer -func BigMax(x, y *big.Int) *big.Int { - if x.Cmp(y) < 0 { - return y - } - - return x -} - -// Big min -// -// Returns the minimum size big integer -func BigMin(x, y *big.Int) *big.Int { - if x.Cmp(y) > 0 { - return y - } - - return x -} diff --git a/common/big_test.go b/common/big_test.go deleted file mode 100644 index 4d04a8db36..0000000000 --- a/common/big_test.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package common - -import ( - "bytes" - "testing" -) - -func TestMisc(t *testing.T) { - a := Big("10") - b := Big("57896044618658097711785492504343953926634992332820282019728792003956564819968") - c := []byte{1, 2, 3, 4} - z := BitTest(a, 1) - - if !z { - t.Error("Expected true got", z) - } - - U256(a) - S256(a) - - U256(b) - S256(b) - - BigD(c) -} - -func TestBigMax(t *testing.T) { - a := Big("10") - b := Big("5") - - max1 := BigMax(a, b) - if max1 != a { - t.Errorf("Expected %d got %d", a, max1) - } - - max2 := BigMax(b, a) - if max2 != a { - t.Errorf("Expected %d got %d", a, max2) - } -} - -func TestBigMin(t *testing.T) { - a := Big("10") - b := Big("5") - - min1 := BigMin(a, b) - if min1 != b { - t.Errorf("Expected %d got %d", b, min1) - } - - min2 := BigMin(b, a) - if min2 != b { - t.Errorf("Expected %d got %d", b, min2) - } -} - -func TestBigCopy(t *testing.T) { - a := Big("10") - b := BigCopy(a) - c := Big("1000000000000") - y := BigToBytes(b, 16) - ybytes := []byte{0, 10} - z := BigToBytes(c, 16) - zbytes := []byte{232, 212, 165, 16, 0} - - if !bytes.Equal(y, ybytes) { - t.Error("Got", ybytes) - } - - if !bytes.Equal(z, zbytes) { - t.Error("Got", zbytes) - } -} diff --git a/common/math/big.go b/common/math/big.go new file mode 100644 index 0000000000..130a0615c9 --- /dev/null +++ b/common/math/big.go @@ -0,0 +1,136 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// Package math provides integer math utilities. +package math + +import ( + "math/big" +) + +var ( + tt255 = BigPow(2, 255) + tt256 = BigPow(2, 256) + tt256m1 = new(big.Int).Sub(tt256, big.NewInt(1)) + MaxBig256 = new(big.Int).Set(tt256m1) +) + +// ParseBig parses s as a big integer in decimal or hexadecimal syntax. +// Leading zeros are accepted. The empty string parses as zero. +func ParseBig(s string) (*big.Int, bool) { + if s == "" { + return new(big.Int), true + } + if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { + return new(big.Int).SetString(s[2:], 16) + } + return new(big.Int).SetString(s, 10) +} + +// MustParseBig parses s as a big integer and panics if the string is invalid. +func MustParseBig(s string) *big.Int { + v, ok := ParseBig(s) + if !ok { + panic("invalid integer: " + s) + } + return v +} + +// BigPow returns a ** b as a big integer. +func BigPow(a, b int64) *big.Int { + r := big.NewInt(a) + return r.Exp(r, big.NewInt(b), nil) +} + +// BigMax returns the larger of x or y. +func BigMax(x, y *big.Int) *big.Int { + if x.Cmp(y) < 0 { + return y + } + return x +} + +// BigMin returns the smaller of x or y. +func BigMin(x, y *big.Int) *big.Int { + if x.Cmp(y) > 0 { + return y + } + return x +} + +// FirstBitSet returns the index of the first 1 bit in v, counting from LSB. +func FirstBitSet(v *big.Int) int { + for i := 0; i < v.BitLen(); i++ { + if v.Bit(i) > 0 { + return i + } + } + return v.BitLen() +} + +// PaddedBigBytes encodes a big integer as a big-endian byte slice. The length +// of the slice is at least n bytes. +func PaddedBigBytes(bigint *big.Int, n int) []byte { + bytes := bigint.Bytes() + if len(bytes) >= n { + return bytes + } + ret := make([]byte, n) + return append(ret[:len(ret)-len(bytes)], bytes...) +} + +// U256 encodes as a 256 bit two's complement number. This operation is destructive. +func U256(x *big.Int) *big.Int { + return x.And(x, tt256m1) +} + +// S256 interprets x as a two's complement number. +// x must not exceed 256 bits (the result is undefined if it does) and is not modified. +// +// S256(0) = 0 +// S256(1) = 1 +// S256(2**255) = -2**255 +// S256(2**256-1) = -1 +func S256(x *big.Int) *big.Int { + if x.Cmp(tt255) < 0 { + return x + } else { + return new(big.Int).Sub(x, tt256) + } +} + +// wordSize is the size number of bits in a big.Word. +const wordSize = 32 << (uint64(^big.Word(0)) >> 63) + +// Exp implements exponentiation by squaring. +// Exp returns a newly-allocated big integer and does not change +// base or exponent. The result is truncated to 256 bits. +// +// Courtesy @karalabe and @chfast +func Exp(base, exponent *big.Int) *big.Int { + result := big.NewInt(1) + + for _, word := range exponent.Bits() { + for i := 0; i < wordSize; i++ { + if word&1 == 1 { + U256(result.Mul(result, base)) + } + U256(base.Mul(base, base)) + word >>= 1 + } + } + return result +} diff --git a/common/math/big_test.go b/common/math/big_test.go new file mode 100644 index 0000000000..29727ce192 --- /dev/null +++ b/common/math/big_test.go @@ -0,0 +1,194 @@ +// Copyright 2014 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package math + +import ( + "bytes" + "math/big" + "testing" +) + +func TestParseBig(t *testing.T) { + tests := []struct { + input string + num *big.Int + ok bool + }{ + {"", big.NewInt(0), true}, + {"0", big.NewInt(0), true}, + {"0x0", big.NewInt(0), true}, + {"12345678", big.NewInt(12345678), true}, + {"0x12345678", big.NewInt(0x12345678), true}, + {"0X12345678", big.NewInt(0x12345678), true}, + // Tests for leading zero behaviour: + {"0123456789", big.NewInt(123456789), true}, // note: not octal + {"00", big.NewInt(0), true}, + {"0x00", big.NewInt(0), true}, + {"0x012345678abc", big.NewInt(0x12345678abc), true}, + // Invalid syntax: + {"abcdef", nil, false}, + {"0xgg", nil, false}, + } + for _, test := range tests { + num, ok := ParseBig(test.input) + if ok != test.ok { + t.Errorf("ParseBig(%q) -> ok = %t, want %t", test.input, ok, test.ok) + continue + } + if num != nil && test.num != nil && num.Cmp(test.num) != 0 { + t.Errorf("ParseBig(%q) -> %d, want %d", test.input, num, test.num) + } + } +} + +func TestMustParseBig(t *testing.T) { + defer func() { + if recover() == nil { + t.Error("MustParseBig should've panicked") + } + }() + MustParseBig("ggg") +} + +func TestBigMax(t *testing.T) { + a := big.NewInt(10) + b := big.NewInt(5) + + max1 := BigMax(a, b) + if max1 != a { + t.Errorf("Expected %d got %d", a, max1) + } + + max2 := BigMax(b, a) + if max2 != a { + t.Errorf("Expected %d got %d", a, max2) + } +} + +func TestBigMin(t *testing.T) { + a := big.NewInt(10) + b := big.NewInt(5) + + min1 := BigMin(a, b) + if min1 != b { + t.Errorf("Expected %d got %d", b, min1) + } + + min2 := BigMin(b, a) + if min2 != b { + t.Errorf("Expected %d got %d", b, min2) + } +} + +func TestFirstBigSet(t *testing.T) { + tests := []struct { + num *big.Int + ix int + }{ + {big.NewInt(0), 0}, + {big.NewInt(1), 0}, + {big.NewInt(2), 1}, + {big.NewInt(0x100), 8}, + } + for _, test := range tests { + if ix := FirstBitSet(test.num); ix != test.ix { + t.Errorf("FirstBitSet(b%b) = %d, want %d", test.num, ix, test.ix) + } + } +} + +func TestPaddedBigBytes(t *testing.T) { + tests := []struct { + num *big.Int + n int + result []byte + }{ + {num: big.NewInt(0), n: 4, result: []byte{0, 0, 0, 0}}, + {num: big.NewInt(1), n: 4, result: []byte{0, 0, 0, 1}}, + {num: big.NewInt(512), n: 4, result: []byte{0, 0, 2, 0}}, + {num: BigPow(2, 32), n: 4, result: []byte{1, 0, 0, 0, 0}}, + } + for _, test := range tests { + if result := PaddedBigBytes(test.num, test.n); !bytes.Equal(result, test.result) { + t.Errorf("PaddedBigBytes(%d, %d) = %v, want %v", test.num, test.n, result, test.result) + } + } +} + +func TestU256(t *testing.T) { + tests := []struct{ x, y *big.Int }{ + {x: big.NewInt(0), y: big.NewInt(0)}, + {x: big.NewInt(1), y: big.NewInt(1)}, + {x: BigPow(2, 255), y: BigPow(2, 255)}, + {x: BigPow(2, 256), y: big.NewInt(0)}, + {x: new(big.Int).Add(BigPow(2, 256), big.NewInt(1)), y: big.NewInt(1)}, + // negative values + {x: big.NewInt(-1), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1))}, + {x: big.NewInt(-2), y: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2))}, + {x: BigPow(2, -255), y: big.NewInt(1)}, + } + for _, test := range tests { + if y := U256(new(big.Int).Set(test.x)); y.Cmp(test.y) != 0 { + t.Errorf("U256(%x) = %x, want %x", test.x, y, test.y) + } + } +} + +func TestS256(t *testing.T) { + tests := []struct{ x, y *big.Int }{ + {x: big.NewInt(0), y: big.NewInt(0)}, + {x: big.NewInt(1), y: big.NewInt(1)}, + {x: big.NewInt(2), y: big.NewInt(2)}, + { + x: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), + y: new(big.Int).Sub(BigPow(2, 255), big.NewInt(1)), + }, + { + x: BigPow(2, 255), + y: new(big.Int).Neg(BigPow(2, 255)), + }, + { + x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(1)), + y: big.NewInt(-1), + }, + { + x: new(big.Int).Sub(BigPow(2, 256), big.NewInt(2)), + y: big.NewInt(-2), + }, + } + for _, test := range tests { + if y := S256(test.x); y.Cmp(test.y) != 0 { + t.Errorf("S256(%x) = %x, want %x", test.x, y, test.y) + } + } +} + +func TestExp(t *testing.T) { + tests := []struct{ base, exponent, result *big.Int }{ + {base: big.NewInt(0), exponent: big.NewInt(0), result: big.NewInt(1)}, + {base: big.NewInt(1), exponent: big.NewInt(0), result: big.NewInt(1)}, + {base: big.NewInt(1), exponent: big.NewInt(1), result: big.NewInt(1)}, + {base: big.NewInt(1), exponent: big.NewInt(2), result: big.NewInt(1)}, + {base: big.NewInt(3), exponent: big.NewInt(144), result: MustParseBig("507528786056415600719754159741696356908742250191663887263627442114881")}, + {base: big.NewInt(2), exponent: big.NewInt(255), result: MustParseBig("57896044618658097711785492504343953926634992332820282019728792003956564819968")}, + } + for _, test := range tests { + if result := Exp(test.base, test.exponent); result.Cmp(test.result) != 0 { + t.Errorf("Exp(%d, %d) = %d, want %d", test.base, test.exponent, result, test.result) + } + } +} diff --git a/common/math/dist.go b/common/math/dist.go deleted file mode 100644 index 913fbfbd47..0000000000 --- a/common/math/dist.go +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package math - -import ( - "math/big" - "sort" - - "github.com/ethereum/go-ethereum/common" -) - -type Summer interface { - Sum(i int) *big.Int - Len() int -} - -func Sum(slice Summer) (sum *big.Int) { - sum = new(big.Int) - - for i := 0; i < slice.Len(); i++ { - sum.Add(sum, slice.Sum(i)) - } - return -} - -type Vector struct { - Gas, Price *big.Int -} - -type VectorsBy func(v1, v2 Vector) bool - -func (self VectorsBy) Sort(vectors []Vector) { - bs := vectorSorter{ - vectors: vectors, - by: self, - } - sort.Sort(bs) -} - -type vectorSorter struct { - vectors []Vector - by func(v1, v2 Vector) bool -} - -func (v vectorSorter) Len() int { return len(v.vectors) } -func (v vectorSorter) Less(i, j int) bool { return v.by(v.vectors[i], v.vectors[j]) } -func (v vectorSorter) Swap(i, j int) { v.vectors[i], v.vectors[j] = v.vectors[j], v.vectors[i] } - -func PriceSort(v1, v2 Vector) bool { return v1.Price.Cmp(v2.Price) < 0 } -func GasSort(v1, v2 Vector) bool { return v1.Gas.Cmp(v2.Gas) < 0 } - -type vectorSummer struct { - vectors []Vector - by func(v Vector) *big.Int -} - -type VectorSum func(v Vector) *big.Int - -func (v VectorSum) Sum(vectors []Vector) *big.Int { - vs := vectorSummer{ - vectors: vectors, - by: v, - } - return Sum(vs) -} - -func (v vectorSummer) Len() int { return len(v.vectors) } -func (v vectorSummer) Sum(i int) *big.Int { return v.by(v.vectors[i]) } - -func GasSum(v Vector) *big.Int { return v.Gas } - -var etherInWei = new(big.Rat).SetInt(common.String2Big("1000000000000000000")) - -func GasPrice(bp, gl, ep *big.Int) *big.Int { - BP := new(big.Rat).SetInt(bp) - GL := new(big.Rat).SetInt(gl) - EP := new(big.Rat).SetInt(ep) - GP := new(big.Rat).Quo(BP, GL) - GP = GP.Quo(GP, EP) - - return GP.Mul(GP, etherInWei).Num() -} diff --git a/common/math/dist_test.go b/common/math/dist_test.go deleted file mode 100644 index f5857b6f80..0000000000 --- a/common/math/dist_test.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright 2015 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package math - -import ( - "fmt" - "math/big" - "testing" -) - -type summer struct { - numbers []*big.Int -} - -func (s summer) Len() int { return len(s.numbers) } -func (s summer) Sum(i int) *big.Int { - return s.numbers[i] -} - -func TestSum(t *testing.T) { - summer := summer{numbers: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}} - sum := Sum(summer) - if sum.Cmp(big.NewInt(6)) != 0 { - t.Errorf("got sum = %d, want 6", sum) - } -} - -func TestDist(t *testing.T) { - var vectors = []Vector{ - {big.NewInt(1000), big.NewInt(1234)}, - {big.NewInt(500), big.NewInt(10023)}, - {big.NewInt(1034), big.NewInt(1987)}, - {big.NewInt(1034), big.NewInt(1987)}, - {big.NewInt(8983), big.NewInt(1977)}, - {big.NewInt(98382), big.NewInt(1887)}, - {big.NewInt(12398), big.NewInt(1287)}, - {big.NewInt(12398), big.NewInt(1487)}, - {big.NewInt(12398), big.NewInt(1987)}, - {big.NewInt(12398), big.NewInt(128)}, - {big.NewInt(12398), big.NewInt(1987)}, - {big.NewInt(1398), big.NewInt(187)}, - {big.NewInt(12328), big.NewInt(1927)}, - {big.NewInt(12398), big.NewInt(1987)}, - {big.NewInt(22398), big.NewInt(1287)}, - {big.NewInt(1370), big.NewInt(1981)}, - {big.NewInt(12398), big.NewInt(1957)}, - {big.NewInt(42198), big.NewInt(1987)}, - } - - VectorsBy(GasSort).Sort(vectors) - fmt.Println(vectors) - - BP := big.NewInt(15) - GL := big.NewInt(1000000) - EP := big.NewInt(100) - fmt.Println("BP", BP, "GL", GL, "EP", EP) - GP := GasPrice(BP, GL, EP) - fmt.Println("GP =", GP, "Wei per GU") - - S := len(vectors) / 4 - fmt.Println("L", len(vectors), "S", S) - for i := 1; i <= S*4; i += S { - fmt.Printf("T%d = %v\n", i, vectors[i]) - } - - g := VectorSum(GasSum).Sum(vectors) - fmt.Printf("G = ∑g* (%v)\n", g) -} diff --git a/common/math/exp.go b/common/math/exp.go deleted file mode 100644 index 113b76b39b..0000000000 --- a/common/math/exp.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2016 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package math - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" -) - -// wordSize is the size number of bits in a big.Int Word. -const wordSize = 32 << (uint64(^big.Word(0)) >> 63) - -// Exp implement exponentiation by squaring algorithm. -// -// Exp return a new variable; base and exponent must -// not be changed under any circumstance. -// -// Courtesy @karalabe and @chfast -func Exp(base, exponent *big.Int) *big.Int { - result := big.NewInt(1) - - for _, word := range exponent.Bits() { - for i := 0; i < wordSize; i++ { - if word&1 == 1 { - common.U256(result.Mul(result, base)) - } - common.U256(base.Mul(base, base)) - word >>= 1 - } - } - return result -} diff --git a/common/math/integer.go b/common/math/integer.go index 1689b65864..a3eeee27e7 100644 --- a/common/math/integer.go +++ b/common/math/integer.go @@ -1,10 +1,63 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package math -import gmath "math" +import "strconv" -/* - * NOTE: The following methods need to be optimised using either bit checking or asm - */ +const ( + // Integer limit values. + MaxInt8 = 1<<7 - 1 + MinInt8 = -1 << 7 + MaxInt16 = 1<<15 - 1 + MinInt16 = -1 << 15 + MaxInt32 = 1<<31 - 1 + MinInt32 = -1 << 31 + MaxInt64 = 1<<63 - 1 + MinInt64 = -1 << 63 + MaxUint8 = 1<<8 - 1 + MaxUint16 = 1<<16 - 1 + MaxUint32 = 1<<32 - 1 + MaxUint64 = 1<<64 - 1 +) + +// ParseUint64 parses s as an integer in decimal or hexadecimal syntax. +// Leading zeros are accepted. The empty string parses as zero. +func ParseUint64(s string) (uint64, bool) { + if s == "" { + return 0, true + } + if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { + v, err := strconv.ParseUint(s[2:], 16, 64) + return v, err == nil + } + v, err := strconv.ParseUint(s, 10, 64) + return v, err == nil +} + +// MustParseUint64 parses s as an integer and panics if the string is invalid. +func MustParseUint64(s string) uint64 { + v, ok := ParseUint64(s) + if !ok { + panic("invalid unsigned 64 bit integer: " + s) + } + return v +} + +// NOTE: The following methods need to be optimised using either bit checking or asm // SafeSub returns subtraction result and whether overflow occurred. func SafeSub(x, y uint64) (uint64, bool) { @@ -13,7 +66,7 @@ func SafeSub(x, y uint64) (uint64, bool) { // SafeAdd returns the result and whether overflow occurred. func SafeAdd(x, y uint64) (uint64, bool) { - return x + y, y > gmath.MaxUint64-x + return x + y, y > MaxUint64-x } // SafeMul returns multiplication result and whether overflow occurred. @@ -21,5 +74,5 @@ func SafeMul(x, y uint64) (uint64, bool) { if x == 0 || y == 0 { return 0, false } - return x * y, y > gmath.MaxUint64/x + return x * y, y > MaxUint64/x } diff --git a/common/math/integer_test.go b/common/math/integer_test.go index 198114e5e1..05bba221f9 100644 --- a/common/math/integer_test.go +++ b/common/math/integer_test.go @@ -1,7 +1,22 @@ +// Copyright 2017 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + package math import ( - gmath "math" "testing" ) @@ -21,17 +36,18 @@ func TestOverflow(t *testing.T) { op operation }{ // add operations - {gmath.MaxUint64, 1, true, add}, - {gmath.MaxUint64 - 1, 1, false, add}, + {MaxUint64, 1, true, add}, + {MaxUint64 - 1, 1, false, add}, // sub operations {0, 1, true, sub}, {0, 0, false, sub}, // mul operations + {0, 0, false, mul}, {10, 10, false, mul}, - {gmath.MaxUint64, 2, true, mul}, - {gmath.MaxUint64, 1, false, mul}, + {MaxUint64, 2, true, mul}, + {MaxUint64, 1, false, mul}, } { var overflows bool switch test.op { @@ -48,3 +64,52 @@ func TestOverflow(t *testing.T) { } } } + +func TestParseUint64(t *testing.T) { + tests := []struct { + input string + num uint64 + ok bool + }{ + {"", 0, true}, + {"0", 0, true}, + {"0x0", 0, true}, + {"12345678", 12345678, true}, + {"0x12345678", 0x12345678, true}, + {"0X12345678", 0x12345678, true}, + // Tests for leading zero behaviour: + {"0123456789", 123456789, true}, // note: not octal + {"0x00", 0, true}, + {"0x012345678abc", 0x12345678abc, true}, + // Invalid syntax: + {"abcdef", 0, false}, + {"0xgg", 0, false}, + // Doesn't fit into 64 bits: + {"18446744073709551617", 0, false}, + } + for _, test := range tests { + num, ok := ParseUint64(test.input) + if ok != test.ok { + t.Errorf("ParseUint64(%q) -> ok = %t, want %t", test.input, ok, test.ok) + continue + } + if ok && num != test.num { + t.Errorf("ParseUint64(%q) -> %d, want %d", test.input, num, test.num) + } + } +} + +func TestMustParseUint64(t *testing.T) { + if v := MustParseUint64("12345"); v != 12345 { + t.Errorf(`MustParseUint64("12345") = %d, want 12345`, v) + } +} + +func TestMustParseUint64Panic(t *testing.T) { + defer func() { + if recover() == nil { + t.Error("MustParseBig should've panicked") + } + }() + MustParseUint64("ggg") +} diff --git a/core/bench_test.go b/core/bench_test.go index 59b5ad7589..8a16005579 100644 --- a/core/bench_test.go +++ b/core/bench_test.go @@ -24,6 +24,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" @@ -73,7 +74,7 @@ var ( // This is the content of the genesis block used by the benchmarks. benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") benchRootAddr = crypto.PubkeyToAddress(benchRootKey.PublicKey) - benchRootFunds = common.BigPow(2, 100) + benchRootFunds = math.BigPow(2, 100) ) // genValueTx returns a block generator that includes a single diff --git a/core/block_validator.go b/core/block_validator.go index a23a4134b1..117974ee66 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -22,6 +22,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" @@ -209,7 +210,7 @@ func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Heade } if uncle { - if header.Time.Cmp(common.MaxBig) == 1 { + if header.Time.Cmp(math.MaxBig256) == 1 { return BlockTSTooBigErr } } else { @@ -344,7 +345,7 @@ func calcDifficultyFrontier(time, parentTime uint64, parentNumber, parentDiff *b expDiff := periodCount.Sub(periodCount, common.Big2) expDiff.Exp(common.Big2, expDiff, nil) diff.Add(diff, expDiff) - diff = common.BigMax(diff, params.MinimumDifficulty) + diff = math.BigMax(diff, params.MinimumDifficulty) } return diff @@ -372,13 +373,13 @@ func CalcGasLimit(parent *types.Block) *big.Int { */ gl := new(big.Int).Sub(parent.GasLimit(), decay) gl = gl.Add(gl, contrib) - gl.Set(common.BigMax(gl, params.MinGasLimit)) + gl.Set(math.BigMax(gl, params.MinGasLimit)) // however, if we're now below the target (TargetGasLimit) we increase the // limit as much as we can (parentGasLimit / 1024 -1) if gl.Cmp(params.TargetGasLimit) < 0 { gl.Add(parent.GasLimit(), decay) - gl.Set(common.BigMin(gl, params.TargetGasLimit)) + gl.Set(math.BigMin(gl, params.TargetGasLimit)) } return gl } diff --git a/core/database_util_test.go b/core/database_util_test.go index d96aa71ba8..8628fa483f 100644 --- a/core/database_util_test.go +++ b/core/database_util_test.go @@ -25,6 +25,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/sha3" @@ -53,11 +54,11 @@ func (d *diffTest) UnmarshalJSON(b []byte) (err error) { return err } - d.ParentTimestamp = common.String2Big(ext.ParentTimestamp).Uint64() - d.ParentDifficulty = common.String2Big(ext.ParentDifficulty) - d.CurrentTimestamp = common.String2Big(ext.CurrentTimestamp).Uint64() - d.CurrentBlocknumber = common.String2Big(ext.CurrentBlocknumber) - d.CurrentDifficulty = common.String2Big(ext.CurrentDifficulty) + d.ParentTimestamp = math.MustParseUint64(ext.ParentTimestamp) + d.ParentDifficulty = math.MustParseBig(ext.ParentDifficulty) + d.CurrentTimestamp = math.MustParseUint64(ext.CurrentTimestamp) + d.CurrentBlocknumber = math.MustParseBig(ext.CurrentBlocknumber) + d.CurrentDifficulty = math.MustParseBig(ext.CurrentDifficulty) return nil } diff --git a/core/state_transition.go b/core/state_transition.go index 8e7891b965..98a24af2b2 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -22,6 +22,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -281,7 +282,7 @@ func (self *StateTransition) refundGas() { // Apply refund counter, capped to half of the used gas. uhalf := remaining.Div(self.gasUsed(), common.Big2) - refund := common.BigMin(uhalf, self.state.GetRefund()) + refund := math.BigMin(uhalf, self.state.GetRefund()) self.gas += refund.Uint64() self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice)) diff --git a/core/vm/common.go b/core/vm/common.go index b7b9a6a9c7..f6a30bd15e 100644 --- a/core/vm/common.go +++ b/core/vm/common.go @@ -17,15 +17,10 @@ package vm import ( - "math" "math/big" "github.com/ethereum/go-ethereum/common" -) - -var ( - U256 = common.U256 // Shortcut to common.U256 - S256 = common.S256 // Shortcut to common.S256 + "github.com/ethereum/go-ethereum/common/math" ) // calculates the memory size required for a step @@ -42,8 +37,8 @@ func calcMemSize(off, l *big.Int) *big.Int { func getData(data []byte, start, size *big.Int) []byte { dlen := big.NewInt(int64(len(data))) - s := common.BigMin(start, dlen) - e := common.BigMin(new(big.Int).Add(s, size), dlen) + s := math.BigMin(start, dlen) + e := math.BigMin(new(big.Int).Add(s, size), dlen) return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64())) } diff --git a/core/vm/instructions.go b/core/vm/instructions.go index 39e5c05870..fb49b5130a 100644 --- a/core/vm/instructions.go +++ b/core/vm/instructions.go @@ -31,7 +31,7 @@ var bigZero = new(big.Int) func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := stack.pop(), stack.pop() - stack.push(U256(x.Add(x, y))) + stack.push(math.U256(x.Add(x, y))) evm.interpreter.intPool.put(y) @@ -40,7 +40,7 @@ func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := stack.pop(), stack.pop() - stack.push(U256(x.Sub(x, y))) + stack.push(math.U256(x.Sub(x, y))) evm.interpreter.intPool.put(y) @@ -49,7 +49,7 @@ func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := stack.pop(), stack.pop() - stack.push(U256(x.Mul(x, y))) + stack.push(math.U256(x.Mul(x, y))) evm.interpreter.intPool.put(y) @@ -59,7 +59,7 @@ func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x, y := stack.pop(), stack.pop() if y.Cmp(common.Big0) != 0 { - stack.push(U256(x.Div(x, y))) + stack.push(math.U256(x.Div(x, y))) } else { stack.push(new(big.Int)) } @@ -70,7 +70,7 @@ func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac } func opSdiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := S256(stack.pop()), S256(stack.pop()) + x, y := math.S256(stack.pop()), math.S256(stack.pop()) if y.Cmp(common.Big0) == 0 { stack.push(new(big.Int)) return nil, nil @@ -85,7 +85,7 @@ func opSdiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta res := x.Div(x.Abs(x), y.Abs(y)) res.Mul(res, n) - stack.push(U256(res)) + stack.push(math.U256(res)) } evm.interpreter.intPool.put(y) return nil, nil @@ -96,14 +96,14 @@ func opMod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac if y.Cmp(common.Big0) == 0 { stack.push(new(big.Int)) } else { - stack.push(U256(x.Mod(x, y))) + stack.push(math.U256(x.Mod(x, y))) } evm.interpreter.intPool.put(y) return nil, nil } func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := S256(stack.pop()), S256(stack.pop()) + x, y := math.S256(stack.pop()), math.S256(stack.pop()) if y.Cmp(common.Big0) == 0 { stack.push(new(big.Int)) @@ -118,7 +118,7 @@ func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta res := x.Mod(x.Abs(x), y.Abs(y)) res.Mul(res, n) - stack.push(U256(res)) + stack.push(math.U256(res)) } evm.interpreter.intPool.put(y) return nil, nil @@ -140,13 +140,13 @@ func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac num := stack.pop() mask := back.Lsh(common.Big1, bit) mask.Sub(mask, common.Big1) - if common.BitTest(num, int(bit)) { + if num.Bit(int(bit)) > 0 { num.Or(num, mask.Not(mask)) } else { num.And(num, mask) } - stack.push(U256(num)) + stack.push(math.U256(num)) } evm.interpreter.intPool.put(back) @@ -155,7 +155,7 @@ func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac func opNot(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { x := stack.pop() - stack.push(U256(x.Not(x))) + stack.push(math.U256(x.Not(x))) return nil, nil } @@ -184,8 +184,8 @@ func opGt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack } func opSlt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := S256(stack.pop()), S256(stack.pop()) - if x.Cmp(S256(y)) < 0 { + x, y := math.S256(stack.pop()), math.S256(stack.pop()) + if x.Cmp(math.S256(y)) < 0 { stack.push(evm.interpreter.intPool.get().SetUint64(1)) } else { stack.push(new(big.Int)) @@ -196,7 +196,7 @@ func opSlt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac } func opSgt(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - x, y := S256(stack.pop()), S256(stack.pop()) + x, y := math.S256(stack.pop()), math.S256(stack.pop()) if x.Cmp(y) > 0 { stack.push(evm.interpreter.intPool.get().SetUint64(1)) } else { @@ -269,7 +269,7 @@ func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S if z.Cmp(bigZero) > 0 { add := x.Add(x, y) add.Mod(add, z) - stack.push(U256(add)) + stack.push(math.U256(add)) } else { stack.push(new(big.Int)) } @@ -282,7 +282,7 @@ func opMulmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S if z.Cmp(bigZero) > 0 { mul := x.Mul(x, y) mul.Mod(mul, z) - stack.push(U256(mul)) + stack.push(math.U256(mul)) } else { stack.push(new(big.Int)) } @@ -427,22 +427,22 @@ func opCoinbase(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack } func opTimestamp(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(U256(new(big.Int).Set(evm.Time))) + stack.push(math.U256(new(big.Int).Set(evm.Time))) return nil, nil } func opNumber(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(U256(new(big.Int).Set(evm.BlockNumber))) + stack.push(math.U256(new(big.Int).Set(evm.BlockNumber))) return nil, nil } func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(U256(new(big.Int).Set(evm.Difficulty))) + stack.push(math.U256(new(big.Int).Set(evm.Difficulty))) return nil, nil } func opGasLimit(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { - stack.push(U256(new(big.Int).Set(evm.GasLimit))) + stack.push(math.U256(new(big.Int).Set(evm.GasLimit))) return nil, nil } @@ -453,7 +453,7 @@ func opPop(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stac func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { offset := stack.pop() - val := common.BigD(memory.Get(offset.Int64(), 32)) + val := new(big.Int).SetBytes(memory.Get(offset.Int64(), 32)) stack.push(val) evm.interpreter.intPool.put(offset) @@ -463,7 +463,7 @@ func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *St func opMstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { // pop value of the stack mStart, val := stack.pop(), stack.pop() - memory.Set(mStart.Uint64(), 32, common.BigToBytes(val, 256)) + memory.Set(mStart.Uint64(), 32, math.PaddedBigBytes(val, 32)) evm.interpreter.intPool.put(mStart, val) return nil, nil @@ -572,7 +572,7 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta gas := stack.pop().Uint64() // pop gas and value of the stack. addr, value := stack.pop(), stack.pop() - value = U256(value) + value = math.U256(value) // pop input size and offset inOffset, inSize := stack.pop(), stack.pop() // pop return size and offset @@ -605,7 +605,7 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack gas := stack.pop().Uint64() // pop gas and value of the stack. addr, value := stack.pop(), stack.pop() - value = U256(value) + value = math.U256(value) // pop input size and offset inOffset, inSize := stack.pop(), stack.pop() // pop return size and offset diff --git a/core/vm/memory_table.go b/core/vm/memory_table.go index 4db9948375..3141a2f61a 100644 --- a/core/vm/memory_table.go +++ b/core/vm/memory_table.go @@ -3,7 +3,7 @@ package vm import ( "math/big" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" ) func memorySha3(stack *Stack) *big.Int { @@ -42,20 +42,20 @@ func memoryCall(stack *Stack) *big.Int { x := calcMemSize(stack.Back(5), stack.Back(6)) y := calcMemSize(stack.Back(3), stack.Back(4)) - return common.BigMax(x, y) + return math.BigMax(x, y) } func memoryCallCode(stack *Stack) *big.Int { x := calcMemSize(stack.Back(5), stack.Back(6)) y := calcMemSize(stack.Back(3), stack.Back(4)) - return common.BigMax(x, y) + return math.BigMax(x, y) } func memoryDelegateCall(stack *Stack) *big.Int { x := calcMemSize(stack.Back(4), stack.Back(5)) y := calcMemSize(stack.Back(2), stack.Back(3)) - return common.BigMax(x, y) + return math.BigMax(x, y) } func memoryReturn(stack *Stack) *big.Int { diff --git a/crypto/crypto.go b/crypto/crypto.go index 9d67d82e1d..ecc3be3ce5 100644 --- a/crypto/crypto.go +++ b/crypto/crypto.go @@ -71,7 +71,7 @@ func ToECDSA(prv []byte) *ecdsa.PrivateKey { priv := new(ecdsa.PrivateKey) priv.PublicKey.Curve = S256() - priv.D = common.BigD(prv) + priv.D = new(big.Int).SetBytes(prv) priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(prv) return priv } diff --git a/eth/api_backend.go b/eth/api_backend.go index 72ed76cc4a..5a5c4c532e 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -109,7 +110,7 @@ func (b *EthApiBackend) GetTd(blockHash common.Hash) *big.Int { func (b *EthApiBackend) GetEVM(ctx context.Context, msg core.Message, state ethapi.State, header *types.Header, vmCfg vm.Config) (*vm.EVM, func() error, error) { statedb := state.(EthApiState).state from := statedb.GetOrNewStateObject(msg.From()) - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) vmError := func() error { return nil } context := core.NewEVMContext(msg, header, b.eth.BlockChain()) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index b3d606b5e4..8f4bde4719 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -21,7 +21,6 @@ import ( "encoding/hex" "errors" "fmt" - "math" "math/big" "strings" "time" @@ -31,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -634,7 +634,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr // Setup the gas pool (also for unmetered requests) // and apply the message. - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) res, gas, err := core.ApplyMessage(evm, msg, gp) if err := vmError(); err != nil { return nil, common.Big0, err diff --git a/les/api_backend.go b/les/api_backend.go index ed2a7cd13e..264b381f51 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -21,6 +21,7 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -95,7 +96,7 @@ func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state etha if err != nil { return nil, nil, err } - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) vmstate := light.NewVMState(ctx, stateDb) context := core.NewEVMContext(msg, header, b.eth.blockchain) diff --git a/les/odr_test.go b/les/odr_test.go index 622d89e5c7..4f1fccb248 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -118,7 +119,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai if err == nil { from := statedb.GetOrNewStateObject(testBankAddress) - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)} @@ -126,7 +127,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai vmenv := vm.NewEVM(context, statedb, config, vm.Config{}) //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) res = append(res, ret...) } @@ -136,7 +137,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai vmstate := light.NewVMState(ctx, state) from, err := state.GetOrNewStateObject(ctx, testBankAddress) if err == nil { - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)} @@ -144,7 +145,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai vmenv := vm.NewEVM(context, vmstate, config, vm.Config{}) //vmenv := light.NewEnv(ctx, state, config, lc, msg, header, vm.Config{}) - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) if vmstate.Error() == nil { res = append(res, ret...) diff --git a/light/odr_test.go b/light/odr_test.go index a76050a299..6987db6440 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -24,6 +24,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -169,14 +170,14 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain statedb, err := state.New(header.Root, db) if err == nil { from := statedb.GetOrNewStateObject(testBankAddress) - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} context := core.NewEVMContext(msg, header, bc) vmenv := vm.NewEVM(context, statedb, config, vm.Config{}) - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) res = append(res, ret...) } @@ -186,12 +187,12 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain vmstate := NewVMState(ctx, state) from, err := state.GetOrNewStateObject(ctx, testBankAddress) if err == nil { - from.SetBalance(common.MaxBig) + from.SetBalance(math.MaxBig256) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} context := core.NewEVMContext(msg, header, lc) vmenv := vm.NewEVM(context, vmstate, config, vm.Config{}) - gp := new(core.GasPool).AddGas(common.MaxBig) + gp := new(core.GasPool).AddGas(math.MaxBig256) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) if vmstate.Error() == nil { res = append(res, ret...) diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 064bf45886..a5963ed89a 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -26,6 +26,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -170,11 +171,11 @@ func runStateTest(chainConfig *params.ChainConfig, test VmTest) error { return fmt.Errorf("did not find expected post-state account: %s", addr) } - if balance := statedb.GetBalance(address); balance.Cmp(common.Big(account.Balance)) != 0 { - return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", address[:4], common.String2Big(account.Balance), balance) + if balance := statedb.GetBalance(address); balance.Cmp(math.MustParseBig(account.Balance)) != 0 { + return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", address[:4], math.MustParseBig(account.Balance), balance) } - if nonce := statedb.GetNonce(address); nonce != common.String2Big(account.Nonce).Uint64() { + if nonce := statedb.GetNonce(address); nonce != math.MustParseUint64(account.Nonce) { return fmt.Errorf("(%x) nonce failed. Expected: %v have: %v\n", address[:4], account.Nonce, nonce) } @@ -205,7 +206,7 @@ func runStateTest(chainConfig *params.ChainConfig, test VmTest) error { func RunState(chainConfig *params.ChainConfig, statedb *state.StateDB, env, tx map[string]string) ([]byte, []*types.Log, *big.Int, error) { environment, msg := NewEVMEnvironment(false, chainConfig, statedb, env, tx) - gaspool := new(core.GasPool).AddGas(common.Big(env["currentGasLimit"])) + gaspool := new(core.GasPool).AddGas(math.MustParseBig(env["currentGasLimit"])) root, _ := statedb.Commit(false) statedb.Reset(root) diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index d267258673..854971b0f3 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -24,6 +24,7 @@ import ( "runtime" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -161,7 +162,7 @@ func verifyTxFields(chainConfig *params.ChainConfig, txTest TransactionTest, dec var decodedSender common.Address - signer := types.MakeSigner(chainConfig, common.String2Big(txTest.Blocknumber)) + signer := types.MakeSigner(chainConfig, math.MustParseBig(txTest.Blocknumber)) decodedSender, err = types.Sender(signer, decodedTx) if err != nil { return err diff --git a/tests/util.go b/tests/util.go index c96c2e06dc..887adadd7d 100644 --- a/tests/util.go +++ b/tests/util.go @@ -24,6 +24,7 @@ import ( "os" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" @@ -119,8 +120,8 @@ func insertAccount(state *state.StateDB, saddr string, account Account) { } addr := common.HexToAddress(saddr) state.SetCode(addr, common.Hex2Bytes(account.Code)) - state.SetNonce(addr, common.Big(account.Nonce).Uint64()) - state.SetBalance(addr, common.Big(account.Balance)) + state.SetNonce(addr, math.MustParseUint64(account.Nonce)) + state.SetBalance(addr, math.MustParseBig(account.Balance)) for a, v := range account.Storage { state.SetState(addr, common.HexToHash(a), common.HexToHash(v)) } @@ -152,10 +153,10 @@ type VmTest struct { func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *state.StateDB, envValues map[string]string, tx map[string]string) (*vm.EVM, core.Message) { var ( data = common.FromHex(tx["data"]) - gas = common.Big(tx["gasLimit"]) - price = common.Big(tx["gasPrice"]) - value = common.Big(tx["value"]) - nonce = common.Big(tx["nonce"]).Uint64() + gas = math.MustParseBig(tx["gasLimit"]) + price = math.MustParseBig(tx["gasPrice"]) + value = math.MustParseBig(tx["value"]) + nonce = math.MustParseUint64(tx["nonce"]) ) origin := common.HexToAddress(tx["caller"]) @@ -198,10 +199,10 @@ func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *st Origin: origin, Coinbase: common.HexToAddress(envValues["currentCoinbase"]), - BlockNumber: common.Big(envValues["currentNumber"]), - Time: common.Big(envValues["currentTimestamp"]), - GasLimit: common.Big(envValues["currentGasLimit"]), - Difficulty: common.Big(envValues["currentDifficulty"]), + BlockNumber: math.MustParseBig(envValues["currentNumber"]), + Time: math.MustParseBig(envValues["currentTimestamp"]), + GasLimit: math.MustParseBig(envValues["currentGasLimit"]), + Difficulty: math.MustParseBig(envValues["currentDifficulty"]), GasPrice: price, } if context.GasPrice == nil { diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 4bf2dbfe98..9c72221510 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -25,6 +25,7 @@ import ( "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" @@ -180,7 +181,7 @@ func runVmTest(test VmTest) error { if len(test.Gas) == 0 && err == nil { return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successful") } else { - gexp := common.Big(test.Gas) + gexp := math.MustParseBig(test.Gas) if gexp.Cmp(gas) != 0 { return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas) } @@ -222,8 +223,8 @@ func RunVm(statedb *state.StateDB, env, exec map[string]string) ([]byte, []*type to = common.HexToAddress(exec["address"]) from = common.HexToAddress(exec["caller"]) data = common.FromHex(exec["data"]) - gas = common.Big(exec["gas"]) - value = common.Big(exec["value"]) + gas = math.MustParseBig(exec["gas"]) + value = math.MustParseBig(exec["value"]) ) caller := statedb.GetOrNewStateObject(from) vm.PrecompiledContracts = make(map[common.Address]vm.PrecompiledContract) diff --git a/whisper/whisperv2/envelope.go b/whisper/whisperv2/envelope.go index 7110ab4571..9f1c682040 100644 --- a/whisper/whisperv2/envelope.go +++ b/whisper/whisperv2/envelope.go @@ -23,9 +23,11 @@ import ( "crypto/ecdsa" "encoding/binary" "fmt" + "math/big" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/ecies" "github.com/ethereum/go-ethereum/rlp" @@ -66,7 +68,8 @@ func (self *Envelope) Seal(pow time.Duration) { for i := 0; i < 1024; i++ { binary.BigEndian.PutUint32(d[60:], nonce) - firstBit := common.FirstBitSet(common.BigD(crypto.Keccak256(d))) + d := new(big.Int).SetBytes(crypto.Keccak256(d)) + firstBit := math.FirstBitSet(d) if firstBit > bestBit { self.Nonce, bestBit = nonce, firstBit } diff --git a/whisper/whisperv5/envelope.go b/whisper/whisperv5/envelope.go index 8812ae207f..5d882d5dc2 100644 --- a/whisper/whisperv5/envelope.go +++ b/whisper/whisperv5/envelope.go @@ -23,10 +23,12 @@ import ( "encoding/binary" "errors" "fmt" - "math" + gmath "math" + "math/big" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/ecies" "github.com/ethereum/go-ethereum/rlp" @@ -103,8 +105,8 @@ func (e *Envelope) Seal(options *MessageParams) error { for nonce := uint64(0); time.Now().UnixNano() < finish; { for i := 0; i < 1024; i++ { binary.BigEndian.PutUint64(buf[56:], nonce) - h = crypto.Keccak256(buf) - firstBit := common.FirstBitSet(common.BigD(h)) + d := new(big.Int).SetBytes(crypto.Keccak256(buf)) + firstBit := math.FirstBitSet(d) if firstBit > bestBit { e.EnvNonce, bestBit = nonce, firstBit if target > 0 && bestBit >= target { @@ -138,9 +140,9 @@ func (e *Envelope) calculatePoW(diff uint32) { h := crypto.Keccak256(e.rlpWithoutNonce()) copy(buf[:32], h) binary.BigEndian.PutUint64(buf[56:], e.EnvNonce) - h = crypto.Keccak256(buf) - firstBit := common.FirstBitSet(common.BigD(h)) - x := math.Pow(2, float64(firstBit)) + d := new(big.Int).SetBytes(crypto.Keccak256(buf)) + firstBit := math.FirstBitSet(d) + x := gmath.Pow(2, float64(firstBit)) x /= float64(e.size()) x /= float64(e.TTL + diff) e.pow = x @@ -150,8 +152,8 @@ func (e *Envelope) powToFirstBit(pow float64) int { x := pow x *= float64(e.size()) x *= float64(e.TTL) - bits := math.Log2(x) - bits = math.Ceil(bits) + bits := gmath.Log2(x) + bits = gmath.Ceil(bits) return int(bits) }