common: move big integer operations to common/math

This commit consolidates all big integer operations into common/math and
adds tests and documentation.

There should be no change in semantics for BigPow, BigMin, BigMax, S256,
U256, Exp and their behaviour is now locked in by tests.

The BigD, BytesToBig and Bytes2Big functions don't provide additional
value, all uses are replaced by new(big.Int).SetBytes().

BigToBytes is now called PaddedBigBytes, its minimum output size
parameter is now specified as the number of bytes instead of bits. The
single use of this function is in the EVM's MSTORE instruction.

Big and String2Big are replaced by ParseBig, which is slightly stricter.
It previously accepted leading zeros for hexadecimal inputs but treated
decimal inputs as octal if a leading zero digit was present.

ParseUint64 is used in places where String2Big was used to decode a
uint64.

The new functions MustParseBig and MustParseUint64 are now used in many
places where parsing errors were previously ignored.
This commit is contained in:
Felix Lange 2017-02-21 15:18:32 +01:00
parent 5369616e16
commit 7061ab8d89
31 changed files with 575 additions and 529 deletions

View file

@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "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. // Set infinite balance to the fake caller account.
from := statedb.GetOrNewStateObject(call.From) from := statedb.GetOrNewStateObject(call.From)
from.SetBalance(common.MaxBig) from.SetBalance(math.MaxBig256)
// Execute the call. // Execute the call.
msg := callmsg{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 // Create a new environment which holds all relevant information
// about the transaction and calling mechanisms. // about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, chainConfig, vm.Config{}) 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() ret, gasUsed, _, err := core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
return ret, gasUsed, err return ret, gasUsed, err
} }

View file

@ -21,6 +21,7 @@ import (
"reflect" "reflect"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
) )
var ( var (
@ -58,7 +59,7 @@ var (
// U256 converts a big Int into a 256bit EVM number. // U256 converts a big Int into a 256bit EVM number.
func U256(n *big.Int) []byte { 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 // packNum packs the given number (using the reflect value) and will cast it to appropriate number representation

View file

@ -26,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common" "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/state"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/core/vm/runtime" "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{ ret, _, err = runtime.Create(input, &runtime.Config{
Origin: sender.Address(), Origin: sender.Address(),
State: statedb, State: statedb,
GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)).Uint64(), GasLimit: math.MustParseUint64(ctx.GlobalString(GasFlag.Name)),
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), GasPrice: math.MustParseBig(ctx.GlobalString(PriceFlag.Name)),
Value: common.Big(ctx.GlobalString(ValueFlag.Name)), Value: math.MustParseBig(ctx.GlobalString(ValueFlag.Name)),
EVMConfig: vm.Config{ EVMConfig: vm.Config{
Tracer: logger, Tracer: logger,
Debug: ctx.GlobalBool(DebugFlag.Name), 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{ ret, err = runtime.Call(receiverAddress, common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)), &runtime.Config{
Origin: sender.Address(), Origin: sender.Address(),
State: statedb, State: statedb,
GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)).Uint64(), GasLimit: math.MustParseUint64(ctx.GlobalString(GasFlag.Name)),
GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), GasPrice: math.MustParseBig(ctx.GlobalString(PriceFlag.Name)),
Value: common.Big(ctx.GlobalString(ValueFlag.Name)), Value: math.MustParseBig(ctx.GlobalString(ValueFlag.Name)),
EVMConfig: vm.Config{ EVMConfig: vm.Config{
Tracer: logger, Tracer: logger,
Debug: ctx.GlobalBool(DebugFlag.Name), Debug: ctx.GlobalBool(DebugFlag.Name),

View file

@ -32,125 +32,22 @@ var (
Big98 = big.NewInt(98) Big98 = big.NewInt(98)
Big256 = big.NewInt(0xff) Big256 = big.NewInt(0xff)
Big257 = big.NewInt(257) 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 // Bytes2Big
//
func BytesToBig(data []byte) *big.Int { func BytesToBig(data []byte) *big.Int {
n := new(big.Int) n := new(big.Int)
n.SetBytes(data) n.SetBytes(data)
return n 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 { func String2Big(num string) *big.Int {
n := new(big.Int) n := new(big.Int)
n.SetString(num, 0) n.SetString(num, 0)
return n 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
}

View file

@ -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 <http://www.gnu.org/licenses/>.
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)
}
}

136
common/math/big.go Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
// 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
}

194
common/math/big_test.go Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
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)
}
}
}

View file

@ -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 <http://www.gnu.org/licenses/>.
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()
}

View file

@ -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 <http://www.gnu.org/licenses/>.
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)
}

View file

@ -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 <http://www.gnu.org/licenses/>.
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
}

View file

@ -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 <http://www.gnu.org/licenses/>.
package math package math
import gmath "math" import "strconv"
/* const (
* NOTE: The following methods need to be optimised using either bit checking or asm // 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. // SafeSub returns subtraction result and whether overflow occurred.
func SafeSub(x, y uint64) (uint64, bool) { 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. // SafeAdd returns the result and whether overflow occurred.
func SafeAdd(x, y uint64) (uint64, bool) { 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. // SafeMul returns multiplication result and whether overflow occurred.
@ -21,5 +74,5 @@ func SafeMul(x, y uint64) (uint64, bool) {
if x == 0 || y == 0 { if x == 0 || y == 0 {
return 0, false return 0, false
} }
return x * y, y > gmath.MaxUint64/x return x * y, y > MaxUint64/x
} }

View file

@ -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 <http://www.gnu.org/licenses/>.
package math package math
import ( import (
gmath "math"
"testing" "testing"
) )
@ -21,17 +36,18 @@ func TestOverflow(t *testing.T) {
op operation op operation
}{ }{
// add operations // add operations
{gmath.MaxUint64, 1, true, add}, {MaxUint64, 1, true, add},
{gmath.MaxUint64 - 1, 1, false, add}, {MaxUint64 - 1, 1, false, add},
// sub operations // sub operations
{0, 1, true, sub}, {0, 1, true, sub},
{0, 0, false, sub}, {0, 0, false, sub},
// mul operations // mul operations
{0, 0, false, mul},
{10, 10, false, mul}, {10, 10, false, mul},
{gmath.MaxUint64, 2, true, mul}, {MaxUint64, 2, true, mul},
{gmath.MaxUint64, 1, false, mul}, {MaxUint64, 1, false, mul},
} { } {
var overflows bool var overflows bool
switch test.op { 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")
}

View file

@ -24,6 +24,7 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "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/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
@ -73,7 +74,7 @@ var (
// This is the content of the genesis block used by the benchmarks. // This is the content of the genesis block used by the benchmarks.
benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") benchRootKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
benchRootAddr = crypto.PubkeyToAddress(benchRootKey.PublicKey) benchRootAddr = crypto.PubkeyToAddress(benchRootKey.PublicKey)
benchRootFunds = common.BigPow(2, 100) benchRootFunds = math.BigPow(2, 100)
) )
// genValueTx returns a block generator that includes a single // genValueTx returns a block generator that includes a single

View file

@ -22,6 +22,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "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/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
@ -209,7 +210,7 @@ func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Heade
} }
if uncle { if uncle {
if header.Time.Cmp(common.MaxBig) == 1 { if header.Time.Cmp(math.MaxBig256) == 1 {
return BlockTSTooBigErr return BlockTSTooBigErr
} }
} else { } else {
@ -344,7 +345,7 @@ func calcDifficultyFrontier(time, parentTime uint64, parentNumber, parentDiff *b
expDiff := periodCount.Sub(periodCount, common.Big2) expDiff := periodCount.Sub(periodCount, common.Big2)
expDiff.Exp(common.Big2, expDiff, nil) expDiff.Exp(common.Big2, expDiff, nil)
diff.Add(diff, expDiff) diff.Add(diff, expDiff)
diff = common.BigMax(diff, params.MinimumDifficulty) diff = math.BigMax(diff, params.MinimumDifficulty)
} }
return diff return diff
@ -372,13 +373,13 @@ func CalcGasLimit(parent *types.Block) *big.Int {
*/ */
gl := new(big.Int).Sub(parent.GasLimit(), decay) gl := new(big.Int).Sub(parent.GasLimit(), decay)
gl = gl.Add(gl, contrib) 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 // however, if we're now below the target (TargetGasLimit) we increase the
// limit as much as we can (parentGasLimit / 1024 -1) // limit as much as we can (parentGasLimit / 1024 -1)
if gl.Cmp(params.TargetGasLimit) < 0 { if gl.Cmp(params.TargetGasLimit) < 0 {
gl.Add(parent.GasLimit(), decay) gl.Add(parent.GasLimit(), decay)
gl.Set(common.BigMin(gl, params.TargetGasLimit)) gl.Set(math.BigMin(gl, params.TargetGasLimit))
} }
return gl return gl
} }

View file

@ -25,6 +25,7 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "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/types"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/sha3" "github.com/ethereum/go-ethereum/crypto/sha3"
@ -53,11 +54,11 @@ func (d *diffTest) UnmarshalJSON(b []byte) (err error) {
return err return err
} }
d.ParentTimestamp = common.String2Big(ext.ParentTimestamp).Uint64() d.ParentTimestamp = math.MustParseUint64(ext.ParentTimestamp)
d.ParentDifficulty = common.String2Big(ext.ParentDifficulty) d.ParentDifficulty = math.MustParseBig(ext.ParentDifficulty)
d.CurrentTimestamp = common.String2Big(ext.CurrentTimestamp).Uint64() d.CurrentTimestamp = math.MustParseUint64(ext.CurrentTimestamp)
d.CurrentBlocknumber = common.String2Big(ext.CurrentBlocknumber) d.CurrentBlocknumber = math.MustParseBig(ext.CurrentBlocknumber)
d.CurrentDifficulty = common.String2Big(ext.CurrentDifficulty) d.CurrentDifficulty = math.MustParseBig(ext.CurrentDifficulty)
return nil return nil
} }

View file

@ -22,6 +22,7 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "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/core/vm"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -281,7 +282,7 @@ func (self *StateTransition) refundGas() {
// Apply refund counter, capped to half of the used gas. // Apply refund counter, capped to half of the used gas.
uhalf := remaining.Div(self.gasUsed(), common.Big2) 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.gas += refund.Uint64()
self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice)) self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice))

View file

@ -17,15 +17,10 @@
package vm package vm
import ( import (
"math"
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) "github.com/ethereum/go-ethereum/common/math"
var (
U256 = common.U256 // Shortcut to common.U256
S256 = common.S256 // Shortcut to common.S256
) )
// calculates the memory size required for a step // 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 { func getData(data []byte, start, size *big.Int) []byte {
dlen := big.NewInt(int64(len(data))) dlen := big.NewInt(int64(len(data)))
s := common.BigMin(start, dlen) s := math.BigMin(start, dlen)
e := common.BigMin(new(big.Int).Add(s, size), dlen) e := math.BigMin(new(big.Int).Add(s, size), dlen)
return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64())) return common.RightPadBytes(data[s.Uint64():e.Uint64()], int(size.Uint64()))
} }

View file

@ -31,7 +31,7 @@ var bigZero = new(big.Int)
func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { func opAdd(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.pop() 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) 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) { func opSub(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.pop() 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) 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) { func opMul(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.pop() 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) 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) { func opDiv(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x, y := stack.pop(), stack.pop() x, y := stack.pop(), stack.pop()
if y.Cmp(common.Big0) != 0 { if y.Cmp(common.Big0) != 0 {
stack.push(U256(x.Div(x, y))) stack.push(math.U256(x.Div(x, y)))
} else { } else {
stack.push(new(big.Int)) 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) { 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 { if y.Cmp(common.Big0) == 0 {
stack.push(new(big.Int)) stack.push(new(big.Int))
return nil, nil 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 := x.Div(x.Abs(x), y.Abs(y))
res.Mul(res, n) res.Mul(res, n)
stack.push(U256(res)) stack.push(math.U256(res))
} }
evm.interpreter.intPool.put(y) evm.interpreter.intPool.put(y)
return nil, nil 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 { if y.Cmp(common.Big0) == 0 {
stack.push(new(big.Int)) stack.push(new(big.Int))
} else { } else {
stack.push(U256(x.Mod(x, y))) stack.push(math.U256(x.Mod(x, y)))
} }
evm.interpreter.intPool.put(y) evm.interpreter.intPool.put(y)
return nil, nil return nil, nil
} }
func opSmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 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 { if y.Cmp(common.Big0) == 0 {
stack.push(new(big.Int)) 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 := x.Mod(x.Abs(x), y.Abs(y))
res.Mul(res, n) res.Mul(res, n)
stack.push(U256(res)) stack.push(math.U256(res))
} }
evm.interpreter.intPool.put(y) evm.interpreter.intPool.put(y)
return nil, nil return nil, nil
@ -140,13 +140,13 @@ func opSignExtend(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stac
num := stack.pop() num := stack.pop()
mask := back.Lsh(common.Big1, bit) mask := back.Lsh(common.Big1, bit)
mask.Sub(mask, common.Big1) mask.Sub(mask, common.Big1)
if common.BitTest(num, int(bit)) { if num.Bit(int(bit)) > 0 {
num.Or(num, mask.Not(mask)) num.Or(num, mask.Not(mask))
} else { } else {
num.And(num, mask) num.And(num, mask)
} }
stack.push(U256(num)) stack.push(math.U256(num))
} }
evm.interpreter.intPool.put(back) 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) { func opNot(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
x := stack.pop() x := stack.pop()
stack.push(U256(x.Not(x))) stack.push(math.U256(x.Not(x)))
return nil, nil 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) { func opSlt(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(S256(y)) < 0 { if x.Cmp(math.S256(y)) < 0 {
stack.push(evm.interpreter.intPool.get().SetUint64(1)) stack.push(evm.interpreter.intPool.get().SetUint64(1))
} else { } else {
stack.push(new(big.Int)) 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) { 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 { if x.Cmp(y) > 0 {
stack.push(evm.interpreter.intPool.get().SetUint64(1)) stack.push(evm.interpreter.intPool.get().SetUint64(1))
} else { } else {
@ -269,7 +269,7 @@ func opAddmod(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *S
if z.Cmp(bigZero) > 0 { if z.Cmp(bigZero) > 0 {
add := x.Add(x, y) add := x.Add(x, y)
add.Mod(add, z) add.Mod(add, z)
stack.push(U256(add)) stack.push(math.U256(add))
} else { } else {
stack.push(new(big.Int)) 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 { if z.Cmp(bigZero) > 0 {
mul := x.Mul(x, y) mul := x.Mul(x, y)
mul.Mod(mul, z) mul.Mod(mul, z)
stack.push(U256(mul)) stack.push(math.U256(mul))
} else { } else {
stack.push(new(big.Int)) 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) { 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 return nil, nil
} }
func opNumber(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 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 return nil, nil
} }
func opDifficulty(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 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 return nil, nil
} }
func opGasLimit(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) { 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 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) { func opMload(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
offset := stack.pop() offset := stack.pop()
val := common.BigD(memory.Get(offset.Int64(), 32)) val := new(big.Int).SetBytes(memory.Get(offset.Int64(), 32))
stack.push(val) stack.push(val)
evm.interpreter.intPool.put(offset) 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) { func opMstore(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Stack) ([]byte, error) {
// pop value of the stack // pop value of the stack
mStart, val := stack.pop(), stack.pop() 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) evm.interpreter.intPool.put(mStart, val)
return nil, nil return nil, nil
@ -572,7 +572,7 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
gas := stack.pop().Uint64() gas := stack.pop().Uint64()
// pop gas and value of the stack. // pop gas and value of the stack.
addr, value := stack.pop(), stack.pop() addr, value := stack.pop(), stack.pop()
value = U256(value) value = math.U256(value)
// pop input size and offset // pop input size and offset
inOffset, inSize := stack.pop(), stack.pop() inOffset, inSize := stack.pop(), stack.pop()
// pop return size and offset // pop return size and offset
@ -605,7 +605,7 @@ func opCallCode(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack
gas := stack.pop().Uint64() gas := stack.pop().Uint64()
// pop gas and value of the stack. // pop gas and value of the stack.
addr, value := stack.pop(), stack.pop() addr, value := stack.pop(), stack.pop()
value = U256(value) value = math.U256(value)
// pop input size and offset // pop input size and offset
inOffset, inSize := stack.pop(), stack.pop() inOffset, inSize := stack.pop(), stack.pop()
// pop return size and offset // pop return size and offset

View file

@ -3,7 +3,7 @@ package vm
import ( import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/math"
) )
func memorySha3(stack *Stack) *big.Int { func memorySha3(stack *Stack) *big.Int {
@ -42,20 +42,20 @@ func memoryCall(stack *Stack) *big.Int {
x := calcMemSize(stack.Back(5), stack.Back(6)) x := calcMemSize(stack.Back(5), stack.Back(6))
y := calcMemSize(stack.Back(3), stack.Back(4)) y := calcMemSize(stack.Back(3), stack.Back(4))
return common.BigMax(x, y) return math.BigMax(x, y)
} }
func memoryCallCode(stack *Stack) *big.Int { func memoryCallCode(stack *Stack) *big.Int {
x := calcMemSize(stack.Back(5), stack.Back(6)) x := calcMemSize(stack.Back(5), stack.Back(6))
y := calcMemSize(stack.Back(3), stack.Back(4)) y := calcMemSize(stack.Back(3), stack.Back(4))
return common.BigMax(x, y) return math.BigMax(x, y)
} }
func memoryDelegateCall(stack *Stack) *big.Int { func memoryDelegateCall(stack *Stack) *big.Int {
x := calcMemSize(stack.Back(4), stack.Back(5)) x := calcMemSize(stack.Back(4), stack.Back(5))
y := calcMemSize(stack.Back(2), stack.Back(3)) y := calcMemSize(stack.Back(2), stack.Back(3))
return common.BigMax(x, y) return math.BigMax(x, y)
} }
func memoryReturn(stack *Stack) *big.Int { func memoryReturn(stack *Stack) *big.Int {

View file

@ -71,7 +71,7 @@ func ToECDSA(prv []byte) *ecdsa.PrivateKey {
priv := new(ecdsa.PrivateKey) priv := new(ecdsa.PrivateKey)
priv.PublicKey.Curve = S256() 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) priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(prv)
return priv return priv
} }

View file

@ -21,6 +21,7 @@ import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "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) { 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 statedb := state.(EthApiState).state
from := statedb.GetOrNewStateObject(msg.From()) from := statedb.GetOrNewStateObject(msg.From())
from.SetBalance(common.MaxBig) from.SetBalance(math.MaxBig256)
vmError := func() error { return nil } vmError := func() error { return nil }
context := core.NewEVMContext(msg, header, b.eth.BlockChain()) context := core.NewEVMContext(msg, header, b.eth.BlockChain())

View file

@ -21,7 +21,6 @@ import (
"encoding/hex" "encoding/hex"
"errors" "errors"
"fmt" "fmt"
"math"
"math/big" "math/big"
"strings" "strings"
"time" "time"
@ -31,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "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"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "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) // Setup the gas pool (also for unmetered requests)
// and apply the message. // 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) res, gas, err := core.ApplyMessage(evm, msg, gp)
if err := vmError(); err != nil { if err := vmError(); err != nil {
return nil, common.Big0, err return nil, common.Big0, err

View file

@ -21,6 +21,7 @@ import (
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "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 { if err != nil {
return nil, nil, err return nil, nil, err
} }
from.SetBalance(common.MaxBig) from.SetBalance(math.MaxBig256)
vmstate := light.NewVMState(ctx, stateDb) vmstate := light.NewVMState(ctx, stateDb)
context := core.NewEVMContext(msg, header, b.eth.blockchain) context := core.NewEVMContext(msg, header, b.eth.blockchain)

View file

@ -23,6 +23,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "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 { if err == nil {
from := statedb.GetOrNewStateObject(testBankAddress) 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)} 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 := vm.NewEVM(context, statedb, config, vm.Config{})
//vmenv := core.NewEnv(statedb, config, bc, msg, header, 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) ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...) res = append(res, ret...)
} }
@ -136,7 +137,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
vmstate := light.NewVMState(ctx, state) vmstate := light.NewVMState(ctx, state)
from, err := state.GetOrNewStateObject(ctx, testBankAddress) from, err := state.GetOrNewStateObject(ctx, testBankAddress)
if err == nil { 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)} 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 := vm.NewEVM(context, vmstate, config, vm.Config{})
//vmenv := light.NewEnv(ctx, state, config, lc, msg, header, 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) ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
if vmstate.Error() == nil { if vmstate.Error() == nil {
res = append(res, ret...) res = append(res, ret...)

View file

@ -24,6 +24,7 @@ import (
"time" "time"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "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) statedb, err := state.New(header.Root, db)
if err == nil { if err == nil {
from := statedb.GetOrNewStateObject(testBankAddress) 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)} 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) context := core.NewEVMContext(msg, header, bc)
vmenv := vm.NewEVM(context, statedb, config, vm.Config{}) 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) ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...) res = append(res, ret...)
} }
@ -186,12 +187,12 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
vmstate := NewVMState(ctx, state) vmstate := NewVMState(ctx, state)
from, err := state.GetOrNewStateObject(ctx, testBankAddress) from, err := state.GetOrNewStateObject(ctx, testBankAddress)
if err == nil { 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)} 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) context := core.NewEVMContext(msg, header, lc)
vmenv := vm.NewEVM(context, vmstate, config, vm.Config{}) 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) ret, _, _ := core.ApplyMessage(vmenv, msg, gp)
if vmstate.Error() == nil { if vmstate.Error() == nil {
res = append(res, ret...) res = append(res, ret...)

View file

@ -26,6 +26,7 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "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) return fmt.Errorf("did not find expected post-state account: %s", addr)
} }
if balance := statedb.GetBalance(address); balance.Cmp(common.Big(account.Balance)) != 0 { 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], common.String2Big(account.Balance), balance) 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) 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) { 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) 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) root, _ := statedb.Commit(false)
statedb.Reset(root) statedb.Reset(root)

View file

@ -24,6 +24,7 @@ import (
"runtime" "runtime"
"github.com/ethereum/go-ethereum/common" "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/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
@ -161,7 +162,7 @@ func verifyTxFields(chainConfig *params.ChainConfig, txTest TransactionTest, dec
var decodedSender common.Address 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) decodedSender, err = types.Sender(signer, decodedTx)
if err != nil { if err != nil {
return err return err

View file

@ -24,6 +24,7 @@ import (
"os" "os"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
@ -119,8 +120,8 @@ func insertAccount(state *state.StateDB, saddr string, account Account) {
} }
addr := common.HexToAddress(saddr) addr := common.HexToAddress(saddr)
state.SetCode(addr, common.Hex2Bytes(account.Code)) state.SetCode(addr, common.Hex2Bytes(account.Code))
state.SetNonce(addr, common.Big(account.Nonce).Uint64()) state.SetNonce(addr, math.MustParseUint64(account.Nonce))
state.SetBalance(addr, common.Big(account.Balance)) state.SetBalance(addr, math.MustParseBig(account.Balance))
for a, v := range account.Storage { for a, v := range account.Storage {
state.SetState(addr, common.HexToHash(a), common.HexToHash(v)) 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) { func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *state.StateDB, envValues map[string]string, tx map[string]string) (*vm.EVM, core.Message) {
var ( var (
data = common.FromHex(tx["data"]) data = common.FromHex(tx["data"])
gas = common.Big(tx["gasLimit"]) gas = math.MustParseBig(tx["gasLimit"])
price = common.Big(tx["gasPrice"]) price = math.MustParseBig(tx["gasPrice"])
value = common.Big(tx["value"]) value = math.MustParseBig(tx["value"])
nonce = common.Big(tx["nonce"]).Uint64() nonce = math.MustParseUint64(tx["nonce"])
) )
origin := common.HexToAddress(tx["caller"]) origin := common.HexToAddress(tx["caller"])
@ -198,10 +199,10 @@ func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *st
Origin: origin, Origin: origin,
Coinbase: common.HexToAddress(envValues["currentCoinbase"]), Coinbase: common.HexToAddress(envValues["currentCoinbase"]),
BlockNumber: common.Big(envValues["currentNumber"]), BlockNumber: math.MustParseBig(envValues["currentNumber"]),
Time: common.Big(envValues["currentTimestamp"]), Time: math.MustParseBig(envValues["currentTimestamp"]),
GasLimit: common.Big(envValues["currentGasLimit"]), GasLimit: math.MustParseBig(envValues["currentGasLimit"]),
Difficulty: common.Big(envValues["currentDifficulty"]), Difficulty: math.MustParseBig(envValues["currentDifficulty"]),
GasPrice: price, GasPrice: price,
} }
if context.GasPrice == nil { if context.GasPrice == nil {

View file

@ -25,6 +25,7 @@ import (
"testing" "testing"
"github.com/ethereum/go-ethereum/common" "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/state"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
@ -180,7 +181,7 @@ func runVmTest(test VmTest) error {
if len(test.Gas) == 0 && err == nil { if len(test.Gas) == 0 && err == nil {
return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successful") return fmt.Errorf("gas unspecified, indicating an error. VM returned (incorrectly) successful")
} else { } else {
gexp := common.Big(test.Gas) gexp := math.MustParseBig(test.Gas)
if gexp.Cmp(gas) != 0 { if gexp.Cmp(gas) != 0 {
return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas) 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"]) to = common.HexToAddress(exec["address"])
from = common.HexToAddress(exec["caller"]) from = common.HexToAddress(exec["caller"])
data = common.FromHex(exec["data"]) data = common.FromHex(exec["data"])
gas = common.Big(exec["gas"]) gas = math.MustParseBig(exec["gas"])
value = common.Big(exec["value"]) value = math.MustParseBig(exec["value"])
) )
caller := statedb.GetOrNewStateObject(from) caller := statedb.GetOrNewStateObject(from)
vm.PrecompiledContracts = make(map[common.Address]vm.PrecompiledContract) vm.PrecompiledContracts = make(map[common.Address]vm.PrecompiledContract)

View file

@ -23,9 +23,11 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math/big"
"time" "time"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/crypto/ecies" "github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
@ -66,7 +68,8 @@ func (self *Envelope) Seal(pow time.Duration) {
for i := 0; i < 1024; i++ { for i := 0; i < 1024; i++ {
binary.BigEndian.PutUint32(d[60:], nonce) 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 { if firstBit > bestBit {
self.Nonce, bestBit = nonce, firstBit self.Nonce, bestBit = nonce, firstBit
} }

View file

@ -23,10 +23,12 @@ import (
"encoding/binary" "encoding/binary"
"errors" "errors"
"fmt" "fmt"
"math" gmath "math"
"math/big"
"time" "time"
"github.com/ethereum/go-ethereum/common" "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"
"github.com/ethereum/go-ethereum/crypto/ecies" "github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/ethereum/go-ethereum/rlp" "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 nonce := uint64(0); time.Now().UnixNano() < finish; {
for i := 0; i < 1024; i++ { for i := 0; i < 1024; i++ {
binary.BigEndian.PutUint64(buf[56:], nonce) binary.BigEndian.PutUint64(buf[56:], nonce)
h = crypto.Keccak256(buf) d := new(big.Int).SetBytes(crypto.Keccak256(buf))
firstBit := common.FirstBitSet(common.BigD(h)) firstBit := math.FirstBitSet(d)
if firstBit > bestBit { if firstBit > bestBit {
e.EnvNonce, bestBit = nonce, firstBit e.EnvNonce, bestBit = nonce, firstBit
if target > 0 && bestBit >= target { if target > 0 && bestBit >= target {
@ -138,9 +140,9 @@ func (e *Envelope) calculatePoW(diff uint32) {
h := crypto.Keccak256(e.rlpWithoutNonce()) h := crypto.Keccak256(e.rlpWithoutNonce())
copy(buf[:32], h) copy(buf[:32], h)
binary.BigEndian.PutUint64(buf[56:], e.EnvNonce) binary.BigEndian.PutUint64(buf[56:], e.EnvNonce)
h = crypto.Keccak256(buf) d := new(big.Int).SetBytes(crypto.Keccak256(buf))
firstBit := common.FirstBitSet(common.BigD(h)) firstBit := math.FirstBitSet(d)
x := math.Pow(2, float64(firstBit)) x := gmath.Pow(2, float64(firstBit))
x /= float64(e.size()) x /= float64(e.size())
x /= float64(e.TTL + diff) x /= float64(e.TTL + diff)
e.pow = x e.pow = x
@ -150,8 +152,8 @@ func (e *Envelope) powToFirstBit(pow float64) int {
x := pow x := pow
x *= float64(e.size()) x *= float64(e.size())
x *= float64(e.TTL) x *= float64(e.TTL)
bits := math.Log2(x) bits := gmath.Log2(x)
bits = math.Ceil(bits) bits = gmath.Ceil(bits)
return int(bits) return int(bits)
} }