diff --git a/cmd/utils/customflags.go b/cmd/utils/customflags.go index 7d6732838a..00f28f2ecf 100644 --- a/cmd/utils/customflags.go +++ b/cmd/utils/customflags.go @@ -78,8 +78,8 @@ func (self DirectoryFlag) Apply(set *flag.FlagSet) { }) } -// BigFlag is a command line flag that accepts big integers in decimal -// or hexadecimal syntax. +// BigFlag is a command line flag that accepts 256 bit big integers in decimal or +// hexadecimal syntax. type BigFlag struct { Name string Value *big.Int @@ -97,7 +97,7 @@ func (b *bigValue) String() string { } func (b *bigValue) Set(s string) error { - int, ok := math.ParseBig(s) + int, ok := math.ParseBig256(s) if !ok { return errors.New("invalid integer syntax") } diff --git a/common/math/big.go b/common/math/big.go index 130a0615c9..c0508c102d 100644 --- a/common/math/big.go +++ b/common/math/big.go @@ -28,23 +28,30 @@ var ( MaxBig256 = new(big.Int).Set(tt256m1) ) -// ParseBig parses s as a big integer in decimal or hexadecimal syntax. +// ParseBig256 parses s as a 256 bit integer in decimal or hexadecimal syntax. // Leading zeros are accepted. The empty string parses as zero. -func ParseBig(s string) (*big.Int, bool) { +func ParseBig256(s string) (*big.Int, bool) { if s == "" { return new(big.Int), true } + var bigint *big.Int + var ok bool if len(s) >= 2 && (s[:2] == "0x" || s[:2] == "0X") { - return new(big.Int).SetString(s[2:], 16) + bigint, ok = new(big.Int).SetString(s[2:], 16) + } else { + bigint, ok = new(big.Int).SetString(s, 10) } - return new(big.Int).SetString(s, 10) + if ok && bigint.BitLen() > 256 { + bigint, ok = nil, false + } + return bigint, ok } -// MustParseBig parses s as a big integer and panics if the string is invalid. -func MustParseBig(s string) *big.Int { - v, ok := ParseBig(s) +// MustParseBig parses s as a 256 bit big integer and panics if the string is invalid. +func MustParseBig256(s string) *big.Int { + v, ok := ParseBig256(s) if !ok { - panic("invalid integer: " + s) + panic("invalid 256 bit integer: " + s) } return v } diff --git a/common/math/big_test.go b/common/math/big_test.go index 29727ce192..a0f48a8ebf 100644 --- a/common/math/big_test.go +++ b/common/math/big_test.go @@ -22,7 +22,7 @@ import ( "testing" ) -func TestParseBig(t *testing.T) { +func TestParseBig256(t *testing.T) { tests := []struct { input string num *big.Int @@ -42,9 +42,11 @@ func TestParseBig(t *testing.T) { // Invalid syntax: {"abcdef", nil, false}, {"0xgg", nil, false}, + // Larger than 256 bits: + {"115792089237316195423570985008687907853269984665640564039457584007913129639936", nil, false}, } for _, test := range tests { - num, ok := ParseBig(test.input) + num, ok := ParseBig256(test.input) if ok != test.ok { t.Errorf("ParseBig(%q) -> ok = %t, want %t", test.input, ok, test.ok) continue @@ -55,13 +57,13 @@ func TestParseBig(t *testing.T) { } } -func TestMustParseBig(t *testing.T) { +func TestMustParseBig256(t *testing.T) { defer func() { if recover() == nil { t.Error("MustParseBig should've panicked") } }() - MustParseBig("ggg") + MustParseBig256("ggg") } func TestBigMax(t *testing.T) { @@ -183,8 +185,8 @@ func TestExp(t *testing.T) { {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")}, + {base: big.NewInt(3), exponent: big.NewInt(144), result: MustParseBig256("507528786056415600719754159741696356908742250191663887263627442114881")}, + {base: big.NewInt(2), exponent: big.NewInt(255), result: MustParseBig256("57896044618658097711785492504343953926634992332820282019728792003956564819968")}, } for _, test := range tests { if result := Exp(test.base, test.exponent); result.Cmp(test.result) != 0 { diff --git a/core/database_util_test.go b/core/database_util_test.go index 8628fa483f..0af4e49206 100644 --- a/core/database_util_test.go +++ b/core/database_util_test.go @@ -55,10 +55,10 @@ func (d *diffTest) UnmarshalJSON(b []byte) (err error) { } d.ParentTimestamp = math.MustParseUint64(ext.ParentTimestamp) - d.ParentDifficulty = math.MustParseBig(ext.ParentDifficulty) + d.ParentDifficulty = math.MustParseBig256(ext.ParentDifficulty) d.CurrentTimestamp = math.MustParseUint64(ext.CurrentTimestamp) - d.CurrentBlocknumber = math.MustParseBig(ext.CurrentBlocknumber) - d.CurrentDifficulty = math.MustParseBig(ext.CurrentDifficulty) + d.CurrentBlocknumber = math.MustParseBig256(ext.CurrentBlocknumber) + d.CurrentDifficulty = math.MustParseBig256(ext.CurrentDifficulty) return nil } diff --git a/core/genesis.go b/core/genesis.go index 964a903df8..58d3440d62 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -68,7 +68,7 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, // creating with empty hash always works statedb, _ := state.New(common.Hash{}, chainDb) for addr, account := range genesis.Alloc { - balance, ok := math.ParseBig(account.Balance) + balance, ok := math.ParseBig256(account.Balance) if !ok { return nil, fmt.Errorf("invalid balance for account %s: %q", addr, account.Balance) } @@ -87,7 +87,7 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, } root, stateBatch := statedb.CommitBatch(false) - difficulty, ok := math.ParseBig(genesis.Difficulty) + difficulty, ok := math.ParseBig256(genesis.Difficulty) if !ok { return nil, fmt.Errorf("invalid difficulty: %q", genesis.Difficulty) } @@ -99,7 +99,7 @@ func WriteGenesisBlock(chainDb ethdb.Database, reader io.Reader) (*types.Block, if !ok { return nil, fmt.Errorf("invalid nonce: %q", genesis.Nonce) } - timestamp, ok := math.ParseBig(genesis.Timestamp) + timestamp, ok := math.ParseBig256(genesis.Timestamp) if !ok { return nil, fmt.Errorf("invalid timestamp: %q", genesis.Timestamp) } diff --git a/tests/state_test_util.go b/tests/state_test_util.go index a5963ed89a..81f49efa5b 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -171,8 +171,8 @@ 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(math.MustParseBig(account.Balance)) != 0 { - return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", address[:4], math.MustParseBig(account.Balance), balance) + if balance := statedb.GetBalance(address); balance.Cmp(math.MustParseBig256(account.Balance)) != 0 { + return fmt.Errorf("(%x) balance failed. Expected: %v have: %v\n", address[:4], math.MustParseBig256(account.Balance), balance) } if nonce := statedb.GetNonce(address); nonce != math.MustParseUint64(account.Nonce) { @@ -206,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(math.MustParseBig(env["currentGasLimit"])) + gaspool := new(core.GasPool).AddGas(math.MustParseBig256(env["currentGasLimit"])) root, _ := statedb.Commit(false) statedb.Reset(root) diff --git a/tests/transaction_test_util.go b/tests/transaction_test_util.go index 854971b0f3..1ecc73a67c 100644 --- a/tests/transaction_test_util.go +++ b/tests/transaction_test_util.go @@ -162,7 +162,7 @@ func verifyTxFields(chainConfig *params.ChainConfig, txTest TransactionTest, dec var decodedSender common.Address - signer := types.MakeSigner(chainConfig, math.MustParseBig(txTest.Blocknumber)) + signer := types.MakeSigner(chainConfig, math.MustParseBig256(txTest.Blocknumber)) decodedSender, err = types.Sender(signer, decodedTx) if err != nil { return err diff --git a/tests/util.go b/tests/util.go index 887adadd7d..ce5b02fed8 100644 --- a/tests/util.go +++ b/tests/util.go @@ -121,7 +121,7 @@ func insertAccount(state *state.StateDB, saddr string, account Account) { addr := common.HexToAddress(saddr) state.SetCode(addr, common.Hex2Bytes(account.Code)) state.SetNonce(addr, math.MustParseUint64(account.Nonce)) - state.SetBalance(addr, math.MustParseBig(account.Balance)) + state.SetBalance(addr, math.MustParseBig256(account.Balance)) for a, v := range account.Storage { state.SetState(addr, common.HexToHash(a), common.HexToHash(v)) } @@ -153,9 +153,9 @@ 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 = math.MustParseBig(tx["gasLimit"]) - price = math.MustParseBig(tx["gasPrice"]) - value = math.MustParseBig(tx["value"]) + gas = math.MustParseBig256(tx["gasLimit"]) + price = math.MustParseBig256(tx["gasPrice"]) + value = math.MustParseBig256(tx["value"]) nonce = math.MustParseUint64(tx["nonce"]) ) @@ -199,10 +199,10 @@ func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *st Origin: origin, Coinbase: common.HexToAddress(envValues["currentCoinbase"]), - BlockNumber: math.MustParseBig(envValues["currentNumber"]), - Time: math.MustParseBig(envValues["currentTimestamp"]), - GasLimit: math.MustParseBig(envValues["currentGasLimit"]), - Difficulty: math.MustParseBig(envValues["currentDifficulty"]), + BlockNumber: math.MustParseBig256(envValues["currentNumber"]), + Time: math.MustParseBig256(envValues["currentTimestamp"]), + GasLimit: math.MustParseBig256(envValues["currentGasLimit"]), + Difficulty: math.MustParseBig256(envValues["currentDifficulty"]), GasPrice: price, } if context.GasPrice == nil { diff --git a/tests/vm_test_util.go b/tests/vm_test_util.go index 9c72221510..d2ddee039e 100644 --- a/tests/vm_test_util.go +++ b/tests/vm_test_util.go @@ -181,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 := math.MustParseBig(test.Gas) + gexp := math.MustParseBig256(test.Gas) if gexp.Cmp(gas) != 0 { return fmt.Errorf("gas failed. Expected %v, got %v\n", gexp, gas) } @@ -223,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 = math.MustParseBig(exec["gas"]) - value = math.MustParseBig(exec["value"]) + gas = math.MustParseBig256(exec["gas"]) + value = math.MustParseBig256(exec["value"]) ) caller := statedb.GetOrNewStateObject(from) vm.PrecompiledContracts = make(map[common.Address]vm.PrecompiledContract)