提交 64af2aaf 编写于 作者: J Jeffrey Wilcke 提交者: Jeffrey Wilcke

core, core/vm: added gas price variance table

This implements 1b & 1c of EIP150 by adding a new GasTable which must be
returned from the RuleSet config method. This table is used to determine
the gas prices for the current epoch.

Please note that when the CreateBySuicide gas price is set it is assumed
that we're in the new epoch phase.

In addition this PR will serve as temporary basis while refactorisation
in being done in the EVM64 PR, which will substentially overhaul the gas
price code.
上级 eeb2a1a6
/Users/jeffrey/dotfiles/zsh/zshrc
\ No newline at end of file
...@@ -74,7 +74,7 @@ func runTestWithReader(test string, r io.Reader) error { ...@@ -74,7 +74,7 @@ func runTestWithReader(test string, r io.Reader) error {
var err error var err error
switch strings.ToLower(test) { switch strings.ToLower(test) {
case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests": case "bk", "block", "blocktest", "blockchaintest", "blocktests", "blockchaintests":
err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, r, skipTests) err = tests.RunBlockTestWithReader(params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, params.MainNetHomesteadGasRepriceBlock, r, skipTests)
case "st", "state", "statetest", "statetests": case "st", "state", "statetest", "statetests":
rs := tests.RuleSet{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true} rs := tests.RuleSet{HomesteadBlock: params.MainNetHomesteadBlock, DAOForkBlock: params.MainNetDAOForkBlock, DAOForkSupport: true}
err = tests.RunStateTestWithReader(rs, r, skipTests) err = tests.RunStateTestWithReader(rs, r, skipTests)
......
...@@ -33,6 +33,7 @@ import ( ...@@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger/glog" "github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/params"
"gopkg.in/urfave/cli.v1" "gopkg.in/urfave/cli.v1"
) )
...@@ -226,6 +227,9 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg ...@@ -226,6 +227,9 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int, cfg
type ruleSet struct{} type ruleSet struct{}
func (ruleSet) IsHomestead(*big.Int) bool { return true } func (ruleSet) IsHomestead(*big.Int) bool { return true }
func (ruleSet) GasTable(*big.Int) params.GasTable {
return params.GasTableHomesteadGasRepriceFork
}
func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} } func (self *VMEnv) RuleSet() vm.RuleSet { return ruleSet{} }
func (self *VMEnv) Vm() vm.Vm { return self.evm } func (self *VMEnv) Vm() vm.Vm { return self.evm }
......
...@@ -792,6 +792,13 @@ func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfi ...@@ -792,6 +792,13 @@ func MakeChainConfigFromDb(ctx *cli.Context, db ethdb.Database) *core.ChainConfi
} }
config.DAOForkSupport = true config.DAOForkSupport = true
} }
if config.HomesteadGasRepriceBlock == nil {
if ctx.GlobalBool(TestNetFlag.Name) {
config.HomesteadGasRepriceBlock = params.TestNetHomesteadGasRepriceBlock
} else {
config.HomesteadGasRepriceBlock = params.MainNetHomesteadGasRepriceBlock
}
}
// Force override any existing configs if explicitly requested // Force override any existing configs if explicitly requested
switch { switch {
case ctx.GlobalBool(SupportDAOFork.Name): case ctx.GlobalBool(SupportDAOFork.Name):
......
...@@ -21,6 +21,7 @@ import ( ...@@ -21,6 +21,7 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/params"
) )
var ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error var ChainConfigNotFoundErr = errors.New("ChainConfig not found") // general config not found error
...@@ -35,6 +36,8 @@ type ChainConfig struct { ...@@ -35,6 +36,8 @@ type ChainConfig struct {
DAOForkBlock *big.Int `json:"daoForkBlock"` // TheDAO hard-fork switch block (nil = no fork) DAOForkBlock *big.Int `json:"daoForkBlock"` // TheDAO hard-fork switch block (nil = no fork)
DAOForkSupport bool `json:"daoForkSupport"` // Whether the nodes supports or opposes the DAO hard-fork DAOForkSupport bool `json:"daoForkSupport"` // Whether the nodes supports or opposes the DAO hard-fork
HomesteadGasRepriceBlock *big.Int `json:"homesteadGasRepriceBlock"` // Homestead gas reprice switch block (nil = no fork)
VmConfig vm.Config `json:"-"` VmConfig vm.Config `json:"-"`
} }
...@@ -45,3 +48,14 @@ func (c *ChainConfig) IsHomestead(num *big.Int) bool { ...@@ -45,3 +48,14 @@ func (c *ChainConfig) IsHomestead(num *big.Int) bool {
} }
return num.Cmp(c.HomesteadBlock) >= 0 return num.Cmp(c.HomesteadBlock) >= 0
} }
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).
//
// The returned GasTable's fields shouldn't, under any circumstances, be changed.
func (c *ChainConfig) GasTable(num *big.Int) params.GasTable {
if c.HomesteadGasRepriceBlock == nil || num == nil || num.Cmp(c.HomesteadGasRepriceBlock) < 0 {
return params.GasTableHomestead
}
return params.GasTableHomesteadGasRepriceFork
}
...@@ -20,12 +20,16 @@ import ( ...@@ -20,12 +20,16 @@ import (
"math/big" "math/big"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
) )
// RuleSet is an interface that defines the current rule set during the // RuleSet is an interface that defines the current rule set during the
// execution of the EVM instructions (e.g. whether it's homestead) // execution of the EVM instructions (e.g. whether it's homestead)
type RuleSet interface { type RuleSet interface {
IsHomestead(*big.Int) bool IsHomestead(*big.Int) bool
// GasTable returns the gas prices for this phase, which is based on
// block number passed in.
GasTable(*big.Int) params.GasTable
} }
// Environment is an EVM requirement and helper which allows access to outside // Environment is an EVM requirement and helper which allows access to outside
......
...@@ -35,8 +35,27 @@ var ( ...@@ -35,8 +35,27 @@ var (
GasStop = big.NewInt(0) GasStop = big.NewInt(0)
GasContractByte = big.NewInt(200) GasContractByte = big.NewInt(200)
n64 = big.NewInt(64)
) )
// calcGas returns the actual gas cost of the call.
//
// The cost of gas was changed during the homestead price change HF. To allow for EIP150
// to be implemented. The returned gas is gas - base * 63 / 64.
func callGas(gasTable params.GasTable, availableGas, base, callCost *big.Int) *big.Int {
if gasTable.CreateBySuicide != nil {
availableGas = new(big.Int).Sub(availableGas, base)
g := new(big.Int).Div(availableGas, n64)
g.Sub(availableGas, g)
if g.Cmp(callCost) < 0 {
return g
}
}
return callCost
}
// baseCheck checks for any stack error underflows // baseCheck checks for any stack error underflows
func baseCheck(op OpCode, stack *Stack, gas *big.Int) error { func baseCheck(op OpCode, stack *Stack, gas *big.Int) error {
// PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit // PUSH and DUP are a bit special. They all cost the same but we do want to have checking on stack push limit
...@@ -127,18 +146,19 @@ var _baseCheck = map[OpCode]req{ ...@@ -127,18 +146,19 @@ var _baseCheck = map[OpCode]req{
MSIZE: {0, GasQuickStep, 1}, MSIZE: {0, GasQuickStep, 1},
GAS: {0, GasQuickStep, 1}, GAS: {0, GasQuickStep, 1},
BLOCKHASH: {1, GasExtStep, 1}, BLOCKHASH: {1, GasExtStep, 1},
BALANCE: {1, GasExtStep, 1}, BALANCE: {1, Zero, 1},
EXTCODESIZE: {1, GasExtStep, 1}, EXTCODESIZE: {1, Zero, 1},
EXTCODECOPY: {4, GasExtStep, 0}, EXTCODECOPY: {4, Zero, 0},
SLOAD: {1, params.SloadGas, 1}, SLOAD: {1, params.SloadGas, 1},
SSTORE: {2, Zero, 0}, SSTORE: {2, Zero, 0},
SHA3: {2, params.Sha3Gas, 1}, SHA3: {2, params.Sha3Gas, 1},
CREATE: {3, params.CreateGas, 1}, CREATE: {3, params.CreateGas, 1},
CALL: {7, params.CallGas, 1}, // Zero is calculated in the gasSwitch
CALLCODE: {7, params.CallGas, 1}, CALL: {7, Zero, 1},
DELEGATECALL: {6, params.CallGas, 1}, CALLCODE: {7, Zero, 1},
JUMPDEST: {0, params.JumpdestGas, 0}, DELEGATECALL: {6, Zero, 1},
SUICIDE: {1, Zero, 0}, SUICIDE: {1, Zero, 0},
JUMPDEST: {0, params.JumpdestGas, 0},
RETURN: {2, Zero, 0}, RETURN: {2, Zero, 0},
PUSH1: {0, GasFastestStep, 1}, PUSH1: {0, GasFastestStep, 1},
DUP1: {0, Zero, 1}, DUP1: {0, Zero, 1},
......
...@@ -514,7 +514,12 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract ...@@ -514,7 +514,12 @@ func opCreate(instr instruction, pc *uint64, env Environment, contract *Contract
input = memory.Get(offset.Int64(), size.Int64()) input = memory.Get(offset.Int64(), size.Int64())
gas = new(big.Int).Set(contract.Gas) gas = new(big.Int).Set(contract.Gas)
) )
contract.UseGas(contract.Gas) if env.RuleSet().GasTable(env.BlockNumber()).CreateBySuicide != nil {
gas.Div(gas, n64)
gas = gas.Sub(contract.Gas, gas)
}
contract.UseGas(gas)
_, addr, suberr := env.Create(contract, input, gas, contract.Price, value) _, addr, suberr := env.Create(contract, input, gas, contract.Price, value)
// Push item on the stack based on the returned error. If the ruleset is // Push item on the stack based on the returned error. If the ruleset is
// homestead we must check for CodeStoreOutOfGasError (homestead only // homestead we must check for CodeStoreOutOfGasError (homestead only
......
...@@ -25,12 +25,16 @@ import ( ...@@ -25,12 +25,16 @@ import (
"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"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/params"
) )
// The default, always homestead, rule set for the vm env // The default, always homestead, rule set for the vm env
type ruleSet struct{} type ruleSet struct{}
func (ruleSet) IsHomestead(*big.Int) bool { return true } func (ruleSet) IsHomestead(*big.Int) bool { return true }
func (ruleSet) GasTable(*big.Int) params.GasTable {
return params.GasTableHomesteadGasRepriceFork
}
// Config is a basic type specifying certain configuration flags for running // Config is a basic type specifying certain configuration flags for running
// the EVM. // the EVM.
......
...@@ -16,10 +16,17 @@ ...@@ -16,10 +16,17 @@
package vm package vm
import "math/big" import (
"math/big"
"github.com/ethereum/go-ethereum/params"
)
type ruleSet struct { type ruleSet struct {
hs *big.Int hs *big.Int
} }
func (r ruleSet) IsHomestead(n *big.Int) bool { return n.Cmp(r.hs) >= 0 } func (r ruleSet) IsHomestead(n *big.Int) bool { return n.Cmp(r.hs) >= 0 }
func (r ruleSet) GasTable(*big.Int) params.GasTable {
return params.GasTableHomestead
}
...@@ -44,6 +44,7 @@ type EVM struct { ...@@ -44,6 +44,7 @@ type EVM struct {
env Environment env Environment
jumpTable vmJumpTable jumpTable vmJumpTable
cfg Config cfg Config
gasTable params.GasTable
} }
// New returns a new instance of the EVM. // New returns a new instance of the EVM.
...@@ -52,6 +53,7 @@ func New(env Environment, cfg Config) *EVM { ...@@ -52,6 +53,7 @@ func New(env Environment, cfg Config) *EVM {
env: env, env: env,
jumpTable: newJumpTable(env.RuleSet(), env.BlockNumber()), jumpTable: newJumpTable(env.RuleSet(), env.BlockNumber()),
cfg: cfg, cfg: cfg,
gasTable: env.RuleSet().GasTable(env.BlockNumber()),
} }
} }
...@@ -169,7 +171,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) { ...@@ -169,7 +171,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
// Get the memory location of pc // Get the memory location of pc
op = contract.GetOp(pc) op = contract.GetOp(pc)
// calculate the new memory size and gas price for the current executing opcode // calculate the new memory size and gas price for the current executing opcode
newMemSize, cost, err = calculateGasAndSize(evm.env, contract, caller, op, statedb, mem, stack) newMemSize, cost, err = calculateGasAndSize(evm.gasTable, evm.env, contract, caller, op, statedb, mem, stack)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -234,7 +236,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) { ...@@ -234,7 +236,7 @@ func (evm *EVM) Run(contract *Contract, input []byte) (ret []byte, err error) {
// calculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for // calculateGasAndSize calculates the required given the opcode and stack items calculates the new memorysize for
// the operation. This does not reduce gas or resizes the memory. // the operation. This does not reduce gas or resizes the memory.
func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef, op OpCode, statedb Database, mem *Memory, stack *Stack) (*big.Int, *big.Int, error) { func calculateGasAndSize(gasTable params.GasTable, env Environment, contract *Contract, caller ContractRef, op OpCode, statedb Database, mem *Memory, stack *Stack) (*big.Int, *big.Int, error) {
var ( var (
gas = new(big.Int) gas = new(big.Int)
newMemSize *big.Int = new(big.Int) newMemSize *big.Int = new(big.Int)
...@@ -246,6 +248,24 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef ...@@ -246,6 +248,24 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
// stack Check, memory resize & gas phase // stack Check, memory resize & gas phase
switch op { switch op {
case SUICIDE:
// if suicide is not nil: homestead gas fork
if gasTable.CreateBySuicide != nil {
gas.Set(gasTable.Suicide)
if !env.Db().Exist(common.BigToAddress(stack.data[len(stack.data)-1])) {
gas.Add(gas, gasTable.CreateBySuicide)
}
}
if !statedb.HasSuicided(contract.Address()) {
statedb.AddRefund(params.SuicideRefundGas)
}
case EXTCODESIZE:
gas.Set(gasTable.ExtcodeSize)
case BALANCE:
gas.Set(gasTable.Balance)
case SLOAD:
gas.Set(gasTable.SLoad)
case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16: case SWAP1, SWAP2, SWAP3, SWAP4, SWAP5, SWAP6, SWAP7, SWAP8, SWAP9, SWAP10, SWAP11, SWAP12, SWAP13, SWAP14, SWAP15, SWAP16:
n := int(op - SWAP1 + 2) n := int(op - SWAP1 + 2)
err := stack.require(n) err := stack.require(n)
...@@ -274,6 +294,8 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef ...@@ -274,6 +294,8 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas)) gas.Add(gas, new(big.Int).Mul(mSize, params.LogDataGas))
newMemSize = calcMemSize(mStart, mSize) newMemSize = calcMemSize(mStart, mSize)
quadMemGas(mem, newMemSize, gas)
case EXP: case EXP:
gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas)) gas.Add(gas, new(big.Int).Mul(big.NewInt(int64(len(stack.data[stack.len()-2].Bytes()))), params.ExpByteGas))
case SSTORE: case SSTORE:
...@@ -302,67 +324,100 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef ...@@ -302,67 +324,100 @@ func calculateGasAndSize(env Environment, contract *Contract, caller ContractRef
g = params.SstoreResetGas g = params.SstoreResetGas
} }
gas.Set(g) gas.Set(g)
case SUICIDE:
if !statedb.HasSuicided(contract.Address()) {
statedb.AddRefund(params.SuicideRefundGas)
}
case MLOAD: case MLOAD:
newMemSize = calcMemSize(stack.peek(), u256(32)) newMemSize = calcMemSize(stack.peek(), u256(32))
quadMemGas(mem, newMemSize, gas)
case MSTORE8: case MSTORE8:
newMemSize = calcMemSize(stack.peek(), u256(1)) newMemSize = calcMemSize(stack.peek(), u256(1))
quadMemGas(mem, newMemSize, gas)
case MSTORE: case MSTORE:
newMemSize = calcMemSize(stack.peek(), u256(32)) newMemSize = calcMemSize(stack.peek(), u256(32))
quadMemGas(mem, newMemSize, gas)
case RETURN: case RETURN:
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
quadMemGas(mem, newMemSize, gas)
case SHA3: case SHA3:
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2]) newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-2])
words := toWordSize(stack.data[stack.len()-2]) words := toWordSize(stack.data[stack.len()-2])
gas.Add(gas, words.Mul(words, params.Sha3WordGas)) gas.Add(gas, words.Mul(words, params.Sha3WordGas))
quadMemGas(mem, newMemSize, gas)
case CALLDATACOPY: case CALLDATACOPY:
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
words := toWordSize(stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3])
gas.Add(gas, words.Mul(words, params.CopyGas)) gas.Add(gas, words.Mul(words, params.CopyGas))
quadMemGas(mem, newMemSize, gas)
case CODECOPY: case CODECOPY:
newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3]) newMemSize = calcMemSize(stack.peek(), stack.data[stack.len()-3])
words := toWordSize(stack.data[stack.len()-3]) words := toWordSize(stack.data[stack.len()-3])
gas.Add(gas, words.Mul(words, params.CopyGas)) gas.Add(gas, words.Mul(words, params.CopyGas))
quadMemGas(mem, newMemSize, gas)
case EXTCODECOPY: case EXTCODECOPY:
gas.Set(gasTable.ExtcodeCopy)
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4]) newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-4])
words := toWordSize(stack.data[stack.len()-4]) words := toWordSize(stack.data[stack.len()-4])
gas.Add(gas, words.Mul(words, params.CopyGas)) gas.Add(gas, words.Mul(words, params.CopyGas))
quadMemGas(mem, newMemSize, gas)
case CREATE: case CREATE:
newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3]) newMemSize = calcMemSize(stack.data[stack.len()-2], stack.data[stack.len()-3])
quadMemGas(mem, newMemSize, gas)
case CALL, CALLCODE: case CALL, CALLCODE:
gas.Add(gas, stack.data[stack.len()-1]) gas.Set(gasTable.Calls)
if op == CALL { if op == CALL {
if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) { if !env.Db().Exist(common.BigToAddress(stack.data[stack.len()-2])) {
gas.Add(gas, params.CallNewAccountGas) gas.Add(gas, params.CallNewAccountGas)
} }
} }
if len(stack.data[stack.len()-3].Bytes()) > 0 { if len(stack.data[stack.len()-3].Bytes()) > 0 {
gas.Add(gas, params.CallValueTransferGas) gas.Add(gas, params.CallValueTransferGas)
} }
x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7]) x := calcMemSize(stack.data[stack.len()-6], stack.data[stack.len()-7])
y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5]) y := calcMemSize(stack.data[stack.len()-4], stack.data[stack.len()-5])
newMemSize = common.BigMax(x, y) newMemSize = common.BigMax(x, y)
quadMemGas(mem, newMemSize, gas)
cg := callGas(gasTable, contract.Gas, gas, stack.data[stack.len()-1])
// Replace the stack item with the new gas calculation. This means that
// either the original item is left on the stack or the item is replaced by:
// (availableGas - gas) * 63 / 64
// We replace the stack item so that it's available when the opCall instruction is
// called. This information is otherwise lost due to the dependency on *current*
// available gas.
stack.data[stack.len()-1] = cg
gas.Add(gas, cg)
case DELEGATECALL: case DELEGATECALL:
gas.Add(gas, stack.data[stack.len()-1]) gas.Set(gasTable.Calls)
x := calcMemSize(stack.data[stack.len()-5], stack.data[stack.len()-6]) x := calcMemSize(stack.data[stack.len()-5], stack.data[stack.len()-6])
y := calcMemSize(stack.data[stack.len()-3], stack.data[stack.len()-4]) y := calcMemSize(stack.data[stack.len()-3], stack.data[stack.len()-4])
newMemSize = common.BigMax(x, y) newMemSize = common.BigMax(x, y)
quadMemGas(mem, newMemSize, gas)
cg := callGas(gasTable, contract.Gas, gas, stack.data[stack.len()-1])
// Replace the stack item with the new gas calculation. This means that
// either the original item is left on the stack or the item is replaced by:
// (availableGas - gas) * 63 / 64
// We replace the stack item so that it's available when the opCall instruction is
// called.
stack.data[stack.len()-1] = cg
gas.Add(gas, cg)
} }
quadMemGas(mem, newMemSize, gas)
return newMemSize, gas, nil return newMemSize, gas, nil
} }
......
...@@ -26,11 +26,13 @@ import ( ...@@ -26,11 +26,13 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"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"
"github.com/ethereum/go-ethereum/params"
) )
type ruleSet struct{} type ruleSet struct{}
func (self *ruleSet) IsHomestead(*big.Int) bool { return true } func (self *ruleSet) IsHomestead(*big.Int) bool { return true }
func (*ruleSet) GasTable(*big.Int) params.GasTable { return params.GasTableHomesteadGasRepriceFork }
type Env struct { type Env struct {
gasLimit *big.Int gasLimit *big.Int
......
// 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 params
import "math/big"
type GasTable struct {
ExtcodeSize *big.Int
ExtcodeCopy *big.Int
Balance *big.Int
SLoad *big.Int
Calls *big.Int
Suicide *big.Int
// CreateBySuicide occurs when the
// refunded account is one that does
// not exist. This logic is similar
// to call. May be left nil. Nil means
// not charged.
CreateBySuicide *big.Int
}
var (
// GasTableHomestead contain the gas prices for
// the homestead phase.
GasTableHomestead = GasTable{
ExtcodeSize: big.NewInt(20),
ExtcodeCopy: big.NewInt(20),
Balance: big.NewInt(20),
SLoad: big.NewInt(50),
Calls: big.NewInt(40),
Suicide: big.NewInt(0),
// explicitly set to nil to indicate
// this rule does not apply to homestead.
CreateBySuicide: nil,
}
// GasTableHomestead contain the gas re-prices for
// the homestead phase.
GasTableHomesteadGasRepriceFork = GasTable{
ExtcodeSize: big.NewInt(700),
ExtcodeCopy: big.NewInt(700),
Balance: big.NewInt(400),
SLoad: big.NewInt(200),
Calls: big.NewInt(700),
Suicide: big.NewInt(5000),
CreateBySuicide: big.NewInt(25000),
}
)
...@@ -71,4 +71,5 @@ var ( ...@@ -71,4 +71,5 @@ var (
SuicideRefundGas = big.NewInt(24000) // Refunded following a suicide operation. SuicideRefundGas = big.NewInt(24000) // Refunded following a suicide operation.
MemoryGas = big.NewInt(3) // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL. MemoryGas = big.NewInt(3) // Times the address of the (highest referenced byte in memory + 1). NOTE: referencing happens on read, write and in instructions such as RETURN and CALL.
TxDataNonZeroGas = big.NewInt(68) // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions. TxDataNonZeroGas = big.NewInt(68) // Per byte of data attached to a transaction that is not equal to zero. NOTE: Not payable on data of calls between transactions.
) )
...@@ -19,6 +19,8 @@ package params ...@@ -19,6 +19,8 @@ package params
import "math/big" import "math/big"
var ( var (
TestNetHomesteadBlock = big.NewInt(494000) // Testnet homestead block TestNetHomesteadBlock = big.NewInt(494000) // Testnet homestead block
MainNetHomesteadBlock = big.NewInt(1150000) // Mainnet homestead block MainNetHomesteadBlock = big.NewInt(1150000) // Mainnet homestead block
TestNetHomesteadGasRepriceBlock = big.NewInt(1783000) // Test net gas reprice block
MainNetHomesteadGasRepriceBlock = big.NewInt(2457000) // Main net gas reprice block
) )
...@@ -6,4 +6,4 @@ h1 { ...@@ -6,4 +6,4 @@ h1 {
} }
body { body {
background-color: orange background-color: orange
} }
\ No newline at end of file
...@@ -23,63 +23,63 @@ import ( ...@@ -23,63 +23,63 @@ import (
) )
func TestBcValidBlockTests(t *testing.T) { func TestBcValidBlockTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcValidBlockTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcUncleHeaderValidityTests(t *testing.T) { func TestBcUncleHeaderValidityTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcUncleHeaderValiditiy.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcUncleTests(t *testing.T) { func TestBcUncleTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcForkUncleTests(t *testing.T) { func TestBcForkUncleTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcForkUncle.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcInvalidHeaderTests(t *testing.T) { func TestBcInvalidHeaderTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcInvalidRLPTests(t *testing.T) { func TestBcInvalidRLPTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcInvalidRLPTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcRPCAPITests(t *testing.T) { func TestBcRPCAPITests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcRPC_API_Test.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcForkBlockTests(t *testing.T) { func TestBcForkBlockTests(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcForkBlockTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcForkStress(t *testing.T) { func TestBcForkStress(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcForkStressTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -89,21 +89,21 @@ func TestBcTotalDifficulty(t *testing.T) { ...@@ -89,21 +89,21 @@ func TestBcTotalDifficulty(t *testing.T) {
// skip because these will fail due to selfish mining fix // skip because these will fail due to selfish mining fix
t.Skip() t.Skip()
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcTotalDifficultyTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcWallet(t *testing.T) { func TestBcWallet(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcWalletTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcGasPricer(t *testing.T) { func TestBcGasPricer(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, nil, filepath.Join(blockTestDir, "bcGasPricerTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -111,7 +111,7 @@ func TestBcGasPricer(t *testing.T) { ...@@ -111,7 +111,7 @@ func TestBcGasPricer(t *testing.T) {
// TODO: iterate over files once we got more than a few // TODO: iterate over files once we got more than a few
func TestBcRandom(t *testing.T) { func TestBcRandom(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, big.NewInt(10), filepath.Join(blockTestDir, "RandomTests/bl201507071825GO.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -121,14 +121,14 @@ func TestBcMultiChain(t *testing.T) { ...@@ -121,14 +121,14 @@ func TestBcMultiChain(t *testing.T) {
// skip due to selfish mining // skip due to selfish mining
t.Skip() t.Skip()
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, big.NewInt(10), filepath.Join(blockTestDir, "bcMultiChainTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestBcState(t *testing.T) { func TestBcState(t *testing.T) {
err := RunBlockTest(big.NewInt(1000000), nil, filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(1000000), nil, big.NewInt(10), filepath.Join(blockTestDir, "bcStateTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -136,77 +136,77 @@ func TestBcState(t *testing.T) { ...@@ -136,77 +136,77 @@ func TestBcState(t *testing.T) {
// Homestead tests // Homestead tests
func TestHomesteadBcValidBlockTests(t *testing.T) { func TestHomesteadBcValidBlockTests(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcValidBlockTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcUncleHeaderValidityTests(t *testing.T) { func TestHomesteadBcUncleHeaderValidityTests(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcUncleHeaderValiditiy.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcUncleTests(t *testing.T) { func TestHomesteadBcUncleTests(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcUncleTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcInvalidHeaderTests(t *testing.T) { func TestHomesteadBcInvalidHeaderTests(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcInvalidHeaderTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcRPCAPITests(t *testing.T) { func TestHomesteadBcRPCAPITests(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcRPC_API_Test.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcForkStress(t *testing.T) { func TestHomesteadBcForkStress(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcForkStressTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcTotalDifficulty(t *testing.T) { func TestHomesteadBcTotalDifficulty(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcTotalDifficultyTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcWallet(t *testing.T) { func TestHomesteadBcWallet(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcWalletTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcGasPricer(t *testing.T) { func TestHomesteadBcGasPricer(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcGasPricerTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcMultiChain(t *testing.T) { func TestHomesteadBcMultiChain(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcMultiChainTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcState(t *testing.T) { func TestHomesteadBcState(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcStateTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
...@@ -214,26 +214,33 @@ func TestHomesteadBcState(t *testing.T) { ...@@ -214,26 +214,33 @@ func TestHomesteadBcState(t *testing.T) {
// DAO hard-fork tests // DAO hard-fork tests
func TestDAOBcTheDao(t *testing.T) { func TestDAOBcTheDao(t *testing.T) {
err := RunBlockTest(big.NewInt(5), big.NewInt(8), filepath.Join(blockTestDir, "TestNetwork", "bcTheDaoTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(5), big.NewInt(8), nil, filepath.Join(blockTestDir, "TestNetwork", "bcTheDaoTest.json"), BlockSkipTests)
if err != nil {
t.Fatal(err)
}
}
func TestEIP150Bc(t *testing.T) {
err := RunBlockTest(big.NewInt(0), big.NewInt(8), big.NewInt(10), filepath.Join(blockTestDir, "TestNetwork", "bcEIP150Test.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcExploit(t *testing.T) { func TestHomesteadBcExploit(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcExploitTest.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcExploitTest.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcShanghaiLove(t *testing.T) { func TestHomesteadBcShanghaiLove(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcShanghaiLove.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcShanghaiLove.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
func TestHomesteadBcSuicideIssue(t *testing.T) { func TestHomesteadBcSuicideIssue(t *testing.T) {
err := RunBlockTest(big.NewInt(0), nil, filepath.Join(blockTestDir, "Homestead", "bcSuicideIssue.json"), BlockSkipTests) err := RunBlockTest(big.NewInt(0), nil, nil, filepath.Join(blockTestDir, "Homestead", "bcSuicideIssue.json"), BlockSkipTests)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -104,7 +104,7 @@ type btTransaction struct { ...@@ -104,7 +104,7 @@ type btTransaction struct {
Value string Value string
} }
func RunBlockTestWithReader(homesteadBlock, daoForkBlock *big.Int, r io.Reader, skipTests []string) error { func RunBlockTestWithReader(homesteadBlock, daoForkBlock, gasPriceFork *big.Int, r io.Reader, skipTests []string) error {
btjs := make(map[string]*btJSON) btjs := make(map[string]*btJSON)
if err := readJson(r, &btjs); err != nil { if err := readJson(r, &btjs); err != nil {
return err return err
...@@ -115,13 +115,13 @@ func RunBlockTestWithReader(homesteadBlock, daoForkBlock *big.Int, r io.Reader, ...@@ -115,13 +115,13 @@ func RunBlockTestWithReader(homesteadBlock, daoForkBlock *big.Int, r io.Reader,
return err return err
} }
if err := runBlockTests(homesteadBlock, daoForkBlock, bt, skipTests); err != nil { if err := runBlockTests(homesteadBlock, daoForkBlock, gasPriceFork, bt, skipTests); err != nil {
return err return err
} }
return nil return nil
} }
func RunBlockTest(homesteadBlock, daoForkBlock *big.Int, file string, skipTests []string) error { func RunBlockTest(homesteadBlock, daoForkBlock, gasPriceFork *big.Int, file string, skipTests []string) error {
btjs := make(map[string]*btJSON) btjs := make(map[string]*btJSON)
if err := readJsonFile(file, &btjs); err != nil { if err := readJsonFile(file, &btjs); err != nil {
return err return err
...@@ -131,13 +131,13 @@ func RunBlockTest(homesteadBlock, daoForkBlock *big.Int, file string, skipTests ...@@ -131,13 +131,13 @@ func RunBlockTest(homesteadBlock, daoForkBlock *big.Int, file string, skipTests
if err != nil { if err != nil {
return err return err
} }
if err := runBlockTests(homesteadBlock, daoForkBlock, bt, skipTests); err != nil { if err := runBlockTests(homesteadBlock, daoForkBlock, gasPriceFork, bt, skipTests); err != nil {
return err return err
} }
return nil return nil
} }
func runBlockTests(homesteadBlock, daoForkBlock *big.Int, bt map[string]*BlockTest, skipTests []string) error { func runBlockTests(homesteadBlock, daoForkBlock, gasPriceFork *big.Int, bt map[string]*BlockTest, skipTests []string) error {
skipTest := make(map[string]bool, len(skipTests)) skipTest := make(map[string]bool, len(skipTests))
for _, name := range skipTests { for _, name := range skipTests {
skipTest[name] = true skipTest[name] = true
...@@ -149,7 +149,7 @@ func runBlockTests(homesteadBlock, daoForkBlock *big.Int, bt map[string]*BlockTe ...@@ -149,7 +149,7 @@ func runBlockTests(homesteadBlock, daoForkBlock *big.Int, bt map[string]*BlockTe
continue continue
} }
// test the block // test the block
if err := runBlockTest(homesteadBlock, daoForkBlock, test); err != nil { if err := runBlockTest(homesteadBlock, daoForkBlock, gasPriceFork, test); err != nil {
return fmt.Errorf("%s: %v", name, err) return fmt.Errorf("%s: %v", name, err)
} }
glog.Infoln("Block test passed: ", name) glog.Infoln("Block test passed: ", name)
...@@ -158,7 +158,7 @@ func runBlockTests(homesteadBlock, daoForkBlock *big.Int, bt map[string]*BlockTe ...@@ -158,7 +158,7 @@ func runBlockTests(homesteadBlock, daoForkBlock *big.Int, bt map[string]*BlockTe
return nil return nil
} }
func runBlockTest(homesteadBlock, daoForkBlock *big.Int, test *BlockTest) error { func runBlockTest(homesteadBlock, daoForkBlock, gasPriceFork *big.Int, test *BlockTest) error {
// import pre accounts & construct test genesis block & state root // import pre accounts & construct test genesis block & state root
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
if _, err := test.InsertPreState(db); err != nil { if _, err := test.InsertPreState(db); err != nil {
...@@ -170,7 +170,7 @@ func runBlockTest(homesteadBlock, daoForkBlock *big.Int, test *BlockTest) error ...@@ -170,7 +170,7 @@ func runBlockTest(homesteadBlock, daoForkBlock *big.Int, test *BlockTest) error
core.WriteCanonicalHash(db, test.Genesis.Hash(), test.Genesis.NumberU64()) core.WriteCanonicalHash(db, test.Genesis.Hash(), test.Genesis.NumberU64())
core.WriteHeadBlockHash(db, test.Genesis.Hash()) core.WriteHeadBlockHash(db, test.Genesis.Hash())
evmux := new(event.TypeMux) evmux := new(event.TypeMux)
config := &core.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true} config := &core.ChainConfig{HomesteadBlock: homesteadBlock, DAOForkBlock: daoForkBlock, DAOForkSupport: true, HomesteadGasRepriceBlock: gasPriceFork}
chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux) chain, err := core.NewBlockChain(db, config, ethash.NewShared(), evmux)
if err != nil { if err != nil {
return err return err
......
{
"contractCreationOOGdontLeaveEmptyContract" : {
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x02b8feb0",
"currentGasLimit" : "0x0f4240",
"currentNumber" : "0x257da8",
"currentTimestamp" : "0x01",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"1000000000000000000000000000000000000001" : {
"balance" : "0x00",
"code" : "0x60106001557f6001600155601080600c6000396000f3006000355415600957005b6020356000600052602060006000f0",
"nonce" : "0x01",
"storage" : {
"0x01" : "0x10"
}
},
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
"balance" : "0x016a48",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x1c58",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
}
},
"postStateRoot" : "35df33d2a146ff660bb837914781857715d1b8752371b2f3e0768f29dd484775",
"pre" : {
"1000000000000000000000000000000000000001" : {
"balance" : "0x00",
"code" : "0x60106001557f6001600155601080600c6000396000f3006000355415600957005b6020356000600052602060006000f0",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0186a0",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"transaction" : {
"data" : "",
"gasLimit" : "0x016b80",
"gasPrice" : "0x01",
"nonce" : "0x00",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "1000000000000000000000000000000000000001",
"value" : "0x00"
}
},
"contractCreationOOGdontLeaveEmptyContractViaTransaction" : {
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x02b8feb0",
"currentGasLimit" : "0x0f4240",
"currentNumber" : "0x257da8",
"currentTimestamp" : "0x01",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"1000000000000000000000000000000000000001" : {
"balance" : "0x0186a0",
"code" : "0x6001600155",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x10c8e0",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0186a0",
"code" : "0x6040600060406000600073100000000000000000000000000000000000000161c350f1",
"nonce" : "0x00",
"storage" : {
}
}
},
"postStateRoot" : "e83fc77d3037af4447bc5e67db8c646240473cd77125129d085d4ffeddbb5e4f",
"pre" : {
"1000000000000000000000000000000000000001" : {
"balance" : "0x0186a0",
"code" : "0x6001600155",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x10c8e0",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"b94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0186a0",
"code" : "0x6040600060406000600073100000000000000000000000000000000000000161c350f1",
"nonce" : "0x00",
"storage" : {
}
}
},
"transaction" : {
"data" : "0x6040600060406000600073100000000000000000000000000000000000000161c350f1",
"gasLimit" : "0xcf08",
"gasPrice" : "0x01",
"nonce" : "0x00",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "",
"value" : "0x00"
}
},
"createContractViaContract" : {
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x02b8feb0",
"currentGasLimit" : "0x0f4240",
"currentNumber" : "0x257da8",
"currentTimestamp" : "0x01",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"1000000000000000000000000000000000000001" : {
"balance" : "0x00",
"code" : "0x600060006000f0",
"nonce" : "0x01",
"storage" : {
}
},
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
"balance" : "0xcf11",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"5dddfce53ee040d9eb21afbc0ae1bb4dbb0ba643" : {
"balance" : "0x00",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0xb78f",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
}
},
"postStateRoot" : "373942284112628b5c8cfd0f36d8058934fe6861cd7224feb3ac2d03739da305",
"pre" : {
"1000000000000000000000000000000000000001" : {
"balance" : "0x00",
"code" : "0x600060006000f0",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0186a0",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"transaction" : {
"data" : "",
"gasLimit" : "0x0186a0",
"gasPrice" : "0x01",
"nonce" : "0x00",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "1000000000000000000000000000000000000001",
"value" : "0x00"
}
},
"createContractViaContractOOGInitCode" : {
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x02b8feb0",
"currentGasLimit" : "0x0f4240",
"currentNumber" : "0x257da8",
"currentTimestamp" : "0x01",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"1000000000000000000000000000000000000001" : {
"balance" : "0x00",
"code" : "0x6b602060406000f0600c600055600052600c60146000f0",
"nonce" : "0x01",
"storage" : {
}
},
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
"balance" : "0x019728",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0f31b8",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
}
},
"postStateRoot" : "f079b93388a39a4c343c66a917a044fb0d91de079786366d0c6c3b01bee07e7b",
"pre" : {
"1000000000000000000000000000000000000001" : {
"balance" : "0x00",
"code" : "0x6b602060406000f0600c600055600052600c60146000f0",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x10c8e0",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"transaction" : {
"data" : "",
"gasLimit" : "0x019a54",
"gasPrice" : "0x01",
"nonce" : "0x00",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "1000000000000000000000000000000000000001",
"value" : "0x00"
}
},
"createContractViaTransactionCost53000" : {
"env" : {
"currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba",
"currentDifficulty" : "0x02b8feb0",
"currentGasLimit" : "0x0f4240",
"currentNumber" : "0x257da8",
"currentTimestamp" : "0x01",
"previousHash" : "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6"
},
"logs" : [
],
"out" : "0x",
"post" : {
"2adc25665018aa1fe0e6bc666dac8fc2697ff9ba" : {
"balance" : "0xcf08",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"6295ee1b4f6dd65047762f924ecd367c17eabf8f" : {
"balance" : "0x00",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
},
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0xb798",
"code" : "0x",
"nonce" : "0x01",
"storage" : {
}
}
},
"postStateRoot" : "53f5b84edd82703a225e53e9ae3639729eb8e337098531456998af602b0ded0a",
"pre" : {
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
"balance" : "0x0186a0",
"code" : "0x",
"nonce" : "0x00",
"storage" : {
}
}
},
"transaction" : {
"data" : "",
"gasLimit" : "0x0186a0",
"gasPrice" : "0x01",
"nonce" : "0x00",
"secretKey" : "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8",
"to" : "",
"value" : "0x00"
}
}
}
\ No newline at end of file
此差异已折叠。
此差异已折叠。
...@@ -440,3 +440,238 @@ func TestHomesteadBounds(t *testing.T) { ...@@ -440,3 +440,238 @@ func TestHomesteadBounds(t *testing.T) {
t.Error(err) t.Error(err)
} }
} }
// EIP150 tests
func TestEIP150Specific(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "stEIPSpecificTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150SingleCodeGasPrice(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "stEIPSingleCodeGasPrices.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150MemExpandingCalls(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "stMemExpandingEIPCalls.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadStateSystemOperations(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stSystemOperationsTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadStatePreCompiledContracts(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stPreCompiledContracts.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadStateRecursiveCreate(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stSpecialTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadStateRefund(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stRefundTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadStateInitCode(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stInitCodeTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadStateLog(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stLogTests.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadStateTransaction(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stTransactionTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadCallCreateCallCode(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stCallCreateCallCodeTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadCallCodes(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stCallCodes.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadMemory(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stMemoryTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadMemoryStress(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
if os.Getenv("TEST_VM_COMPLEX") == "" {
t.Skip()
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stMemoryStressTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadQuadraticComplexity(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
if os.Getenv("TEST_VM_COMPLEX") == "" {
t.Skip()
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stQuadraticComplexityTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadWallet(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stWalletTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadDelegateCodes(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stCallDelegateCodes.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadDelegateCodesCallCode(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stCallDelegateCodesCallCode.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
func TestEIP150HomesteadBounds(t *testing.T) {
ruleSet := RuleSet{
HomesteadBlock: new(big.Int),
HomesteadGasRepriceBlock: big.NewInt(2457000),
}
fn := filepath.Join(stateTestDir, "EIP150", "Homestead", "stBoundsTest.json")
if err := RunStateTest(ruleSet, fn, StateSkipTests); err != nil {
t.Error(err)
}
}
此差异已折叠。
...@@ -225,7 +225,7 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, vm.Logs, ...@@ -225,7 +225,7 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, vm.Logs,
caller := state.GetOrNewStateObject(from) caller := state.GetOrNewStateObject(from)
vmenv := NewEnvFromMap(RuleSet{params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, true}, state, env, exec) vmenv := NewEnvFromMap(RuleSet{params.MainNetHomesteadBlock, params.MainNetDAOForkBlock, true, nil}, state, env, exec)
vmenv.vmTest = true vmenv.vmTest = true
vmenv.skipTransfer = true vmenv.skipTransfer = true
vmenv.initial = true vmenv.initial = true
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册