diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index fd69538d53..7f3feed2fc 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -283,9 +283,12 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM msg := callmsg{call} evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil) + // Ignore error, we're past header validation + beneficiary, _ := b.blockchain.Engine().Author(block.Header()) + blockContext := core.NewBlockContext(block.Header(), beneficiary, b.config) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. - vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{}) + vmenv := vm.NewEVM(evmContext, statedb, b.config, &vm.Config{}, blockContext) gaspool := new(core.GasPool).AddGas(math.MaxUint64) return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb() diff --git a/core/chain_makers.go b/core/chain_makers.go index d2590bcf8c..bb0434f184 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -53,8 +53,7 @@ type BlockGen struct { config *params.ChainConfig engine consensus.Engine - - } +} // SetCoinbase sets the coinbase of the generated block. // It can be called at most once. @@ -100,18 +99,8 @@ func (b *BlockGen) AddTxWithChain(bc *BlockChain, tx *types.Transaction) { } b.statedb.Prepare(tx.Hash(), common.Hash{}, len(b.txs)) - blockContext := &vm.BlockContext{ - BlockNumber: b.header.Number, - Coinbase: b.header.Coinbase, - GasLimit: b.header.GasLimit, - Signer: types.MakeSigner(b.config, b.header.Number), - Precompiles: vm.PrecompiledContractsByzantium, // TODO fix - Intpool: vm.NewIntpool(), - Time: b.header.Time, - Difficulty: b.header.Difficulty, - } - - receipt, _, err := ApplyTransaction(b.config, bc, &b.header.Coinbase, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, &vm.Config{}, blockContext) + blockContext := NewBlockContext(b.header, b.header.Coinbase, b.config) + receipt, _, err := ApplyTransaction(b.config, bc, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed, &vm.Config{}, blockContext) if err != nil { panic(err) } diff --git a/core/evm.go b/core/evm.go index 2cb219b98d..3ef01ba5da 100644 --- a/core/evm.go +++ b/core/evm.go @@ -23,6 +23,7 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/params" ) // ChainContext supports retrieving headers and consensus parameters from the @@ -36,7 +37,7 @@ type ChainContext interface { } // NewEVMContext creates a new context for use in the EVM. -func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author *common.Address) *vm.Context { +func NewEVMContext(msg Message, header *types.Header, chain ChainContext) *vm.Context { return &vm.Context{ CanTransfer: CanTransfer, Transfer: Transfer, @@ -46,6 +47,20 @@ func NewEVMContext(msg Message, header *types.Header, chain ChainContext, author } } +// NewBlockContext creates a block-specific context for use in the EVM +func NewBlockContext(header *types.Header, beneficiary common.Address, chainConfig *params.ChainConfig) *vm.BlockContext { + return &vm.BlockContext{ + Intpool: vm.NewIntpool(), + Coinbase: beneficiary, + BlockNumber: new(big.Int).Set(header.Number), + Time: new(big.Int).Set(header.Time), + Difficulty: new(big.Int).Set(header.Difficulty), + GasLimit: header.GasLimit, + Signer: types.MakeSigner(chainConfig, header.Number), + Precompiles: vm.PrecompilesAt(chainConfig, header.Number), + } +} + // GetHashFn returns a GetHashFunc which retrieves header hashes by number func GetHashFn(ref *types.Header, chain ChainContext) func(n uint64) common.Hash { var cache map[uint64]common.Hash diff --git a/core/state_processor.go b/core/state_processor.go index 28b3f61eaa..e12d246f7a 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -17,7 +17,6 @@ package core import ( - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" "github.com/ethereum/go-ethereum/core/state" @@ -25,7 +24,6 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" - "math/big" ) // StateProcessor is a basic Processor, which takes care of transitioning @@ -66,29 +64,15 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { misc.ApplyDAOHardFork(statedb) } - - precompiles := vm.PrecompiledContractsHomestead - if p.config.ByzantiumBlock.Cmp(block.Number()) <= 0 { - precompiles = vm.PrecompiledContractsByzantium - } + // Ignore error, we're past header validation beneficiary, _ := p.engine.Author(block.Header()) + blockContext := NewBlockContext(block.Header(), beneficiary, p.config) - blockContext := &vm.BlockContext{ - Intpool: vm.NewIntpool(), - Precompiles: precompiles, - - BlockNumber: new(big.Int).Set(block.Header().Number), - Time: new(big.Int).Set(block.Header().Time), - Difficulty: new(big.Int).Set(block.Header().Difficulty), - GasLimit: block.Header().GasLimit, - Coinbase: beneficiary, - Signer: types.MakeSigner(p.config, block.Header().Number), - } // Iterate over and process the individual transactions receipts = make([]*types.Receipt, len(block.Transactions())) for i, tx := range block.Transactions() { statedb.Prepare(tx.Hash(), block.Hash(), i) - receipt, _, err := ApplyTransaction(p.config, p.bc, nil, gp, statedb, header, tx, usedGas, &cfg, blockContext) + receipt, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, usedGas, &cfg, blockContext) if err != nil { return nil, nil, 0, err } @@ -105,13 +89,13 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg // and uses the input parameters for its environment. It returns the receipt // for the transaction, gas used and an error if the transaction failed, // indicating the block was invalid. -func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg *vm.Config, blockContext *vm.BlockContext) (*types.Receipt, uint64, error) { +func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg *vm.Config, blockContext *vm.BlockContext) (*types.Receipt, uint64, error) { msg, err := tx.AsMessage(blockContext.Signer) if err != nil { return nil, 0, err } // Create a new context to be used in the EVM environment - context := NewEVMContext(msg, header, bc, author) + context := NewEVMContext(msg, header, bc) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. vmenv := vm.NewEVM(context, statedb, config, cfg, blockContext) diff --git a/core/vm/contract.go b/core/vm/contract.go index 63c39e4b94..e3346073a9 100644 --- a/core/vm/contract.go +++ b/core/vm/contract.go @@ -64,6 +64,7 @@ type Contract struct { DelegateCall bool } +// NewPrecompiledContract returns a new contract environment for the execution of a precompiled contract func NewPrecompiledContract( caller ContractRef, object ContractRef,value *big.Int, gas uint64) *Contract{ c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil} diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 237450ea96..6c3c6f5202 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -59,6 +59,14 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{ common.BytesToAddress([]byte{8}): &bn256Pairing{}, } +// PrecompilesAt returns the map of active precompiled contracts at the given blocknumber and config +func PrecompilesAt(c *params.ChainConfig, blockNumber *big.Int) map[common.Address]PrecompiledContract { + if c.ByzantiumBlock.Cmp(blockNumber) <= 0 { + return PrecompiledContractsByzantium + } + return PrecompiledContractsHomestead +} + // RunPrecompiledContract runs and evaluates the output of a precompiled contract. func RunPrecompiledContract(p PrecompiledContract, input []byte, contract *Contract) (ret []byte, err error) { gas := p.RequiredGas(input) diff --git a/core/vm/evm.go b/core/vm/evm.go index 82002c71b7..c989b951a0 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -22,9 +22,9 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/core/types" ) // emptyCodeHash is used by create to ensure deployment is disallowed to already @@ -63,18 +63,11 @@ type Context struct { // Message information Origin common.Address // Provides information for ORIGIN GasPrice *big.Int // Provides information for GASPRICE - - //// Block information - //Coinbase common.Address // Provides information for COINBASE - //GasLimit uint64 // Provides information for GASLIMIT - //BlockNumber *big.Int // Provides information for NUMBER - //Time *big.Int // Provides information for TIME - //Difficulty *big.Int // Provides information for DIFFICULTY } // Blockcontext provides block-constant auxiliary information. Should never be modified after // creation -type BlockContext struct{ +type BlockContext struct { Precompiles map[common.Address]PrecompiledContract Signer types.Signer Intpool *IntPool @@ -125,7 +118,7 @@ type EVM struct { // NewEVM returns a new EVM. The returned EVM is not thread safe and should // only ever be used *once*. -func NewEVM(ctx *Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig *Config,blockContext *BlockContext) *EVM { +func NewEVM(ctx *Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig *Config, blockContext *BlockContext) *EVM { evm := &EVM{ Context: ctx, StateDB: statedb, @@ -170,7 +163,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas exists := evm.StateDB.Exist(addr) precompile, isPrecompile := evm.BlockContext.Precompiles[addr] - if !exists{ + if !exists { if !isPrecompile && evm.ChainConfig().IsEIP158(evm.BlockContext.BlockNumber) && value.Sign() == 0 { // Calling a non existing account, don't do anything, but ping the tracer if evm.vmConfig.Debug && evm.depth == 0 { @@ -184,7 +177,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value) var contract *Contract - if isPrecompile{ + if isPrecompile { // A 'contract' is needed for gas accounting contract = NewPrecompiledContract(caller, to, value, gas) ret, err = RunPrecompiledContract(precompile, input, contract) @@ -196,8 +189,8 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) }() } - }else{ - if !exists{ + } else { + if !exists { // Shortcut execution -- account didn't exist, // so no need to lookup the code // but make sure to set returndata to nil diff --git a/eth/api.go b/eth/api.go index d89871fe0f..82e13fac92 100644 --- a/eth/api.go +++ b/eth/api.go @@ -369,10 +369,10 @@ type storageEntry struct { Key *common.Hash `json:"key"` Value common.Hash `json:"value"` } -/* + // StorageRangeAt returns the storage at the given block height and transaction index. func (api *PrivateDebugAPI) StorageRangeAt(ctx context.Context, blockHash common.Hash, txIndex int, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int) (StorageRangeResult, error) { - _, _, statedb, err := api.computeTxEnv(blockHash, txIndex, 0) + _, _, _, statedb, err := api.computeTxEnv(blockHash, txIndex, 0) if err != nil { return StorageRangeResult{}, err } @@ -405,7 +405,7 @@ func storageRangeAt(st state.Trie, start []byte, maxResult int) (StorageRangeRes } return result, nil } -*/ + // GetModifiedAccountsByumber returns all accounts that have changed between the // two blocks specified. A change is defined as a difference in nonce, balance, // code hash, or storage hash. diff --git a/eth/api_backend.go b/eth/api_backend.go index c7ceaeb99f..58ec9da359 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -22,19 +22,19 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/bloombits" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/common/math" ) // EthAPIBackend implements ethapi.Backend for full nodes @@ -132,8 +132,11 @@ func (b *EthAPIBackend) GetEVM(ctx context.Context, msg core.Message, state *sta state.SetBalance(msg.From(), math.MaxBig256) vmError := func() error { return nil } - context := core.NewEVMContext(msg, header, b.eth.BlockChain(), nil) - return vm.NewEVM(context, state, b.eth.chainConfig, &vmCfg, &vm.BlockContext{} ), vmError, nil + context := core.NewEVMContext(msg, header, b.eth.BlockChain()) + beneficiary, _ := b.eth.BlockChain().Engine().Author(header) + blockContext := core.NewBlockContext(header, beneficiary, b.ChainConfig()) + + return vm.NewEVM(context, state, b.eth.chainConfig, &vmCfg, blockContext), vmError, nil } func (b *EthAPIBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription { diff --git a/eth/api_tracer.go b/eth/api_tracer.go index 8b1fd9ec98..ca03dd6a2e 100644 --- a/eth/api_tracer.go +++ b/eth/api_tracer.go @@ -24,12 +24,22 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - + "bytes" + "context" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/eth/tracers" + "github.com/ethereum/go-ethereum/internal/ethapi" "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/trie" + "io/ioutil" + "runtime" + "sync" ) const ( @@ -80,7 +90,7 @@ type txTraceTask struct { statedb *state.StateDB // Intermediate state prepped for tracing index int // Transaction offset in the block } -/* + // TraceChain returns the structured logs created during the execution of EVM // between two blocks (excluding start) and returns them as a JSON object. func (api *PrivateDebugAPI) TraceChain(ctx context.Context, start, end rpc.BlockNumber, config *TraceConfig) (*rpc.Subscription, error) { @@ -186,9 +196,10 @@ func (api *PrivateDebugAPI) traceChain(ctx context.Context, start, end *types.Bl // Trace all the transactions contained within for i, tx := range task.block.Transactions() { msg, _ := tx.AsMessage(signer) - vmctx := core.NewEVMContext(msg, task.block.Header(), api.eth.blockchain, nil) - - res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config) + vmctx := core.NewEVMContext(msg, task.block.Header(), api.eth.blockchain) + beneficiary, _ := api.eth.blockchain.Engine().Author(task.block.Header()) + blockCtx := core.NewBlockContext(task.block.Header(), beneficiary, api.eth.chainConfig) + res, err := api.traceTx(ctx, msg, vmctx, blockCtx, task.statedb, config) if err != nil { task.results[i] = &txTraceResult{Error: err.Error()} log.Warn("Tracing failed", "hash", tx.Hash(), "block", task.block.NumberU64(), "err", err) @@ -378,7 +389,7 @@ func (api *PrivateDebugAPI) TraceBlockFromFile(ctx context.Context, file string, // traceBlock configures a new tracer according to the provided configuration, and // executes all the transactions contained within. The return value will be one item // per transaction, dependent on the requestd tracer. -/* + func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, config *TraceConfig) ([]*txTraceResult, error) { // Create the parent state database if err := api.eth.engine.VerifyHeader(api.eth.blockchain, block.Header(), true); err != nil { @@ -418,9 +429,10 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, // Fetch and execute the next transaction trace tasks for task := range jobs { msg, _ := txs[task.index].AsMessage(signer) - vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) - - res, err := api.traceTx(ctx, msg, vmctx, task.statedb, config) + vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain) + beneficiary, _ := api.eth.blockchain.Engine().Author(block.Header()) + blockCtx := core.NewBlockContext(block.Header(), beneficiary, api.eth.chainConfig) + res, err := api.traceTx(ctx, msg, vmctx, blockCtx, task.statedb, config) if err != nil { results[task.index] = &txTraceResult{Error: err.Error()} continue @@ -437,9 +449,11 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, // Generate the next state snapshot fast without tracing msg, _ := tx.AsMessage(signer) - vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) + vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain) + beneficiary, _ := api.eth.blockchain.Engine().Author(block.Header()) + blockCtx := core.NewBlockContext(block.Header(), beneficiary, api.eth.chainConfig) - vmenv := vm.NewEVM(vmctx, statedb, api.config, vm.Config{}) + vmenv := vm.NewEVM(vmctx, statedb, api.config, &vm.Config{}, blockCtx) if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil { failed = err break @@ -456,7 +470,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block, } return results, nil } -*/ + // computeStateDB retrieves the state database associated with a certain block. // If no state is locally available for the given block, a number of blocks are // attempted to be reexecuted to generate the desired state. @@ -522,7 +536,7 @@ func (api *PrivateDebugAPI) computeStateDB(block *types.Block, reexec uint64) (* log.Info("Historical state regenerated", "block", block.NumberU64(), "elapsed", time.Since(start), "size", database.TrieDB().Size()) return statedb, nil } -/* + // TraceTransaction returns the structured logs created during the execution of EVM // and returns them as a JSON object. func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Hash, config *TraceConfig) (interface{}, error) { @@ -535,18 +549,18 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, hash common.Ha if config != nil && config.Reexec != nil { reexec = *config.Reexec } - msg, vmctx, statedb, err := api.computeTxEnv(blockHash, int(index), reexec) + msg, vmctx, blockCtx, statedb, err := api.computeTxEnv(blockHash, int(index), reexec) if err != nil { return nil, err } // Trace the transaction and return - return api.traceTx(ctx, msg, vmctx, statedb, config) + return api.traceTx(ctx, msg, vmctx, blockCtx, statedb, config) } // traceTx configures a new tracer according to the provided configuration, and // executes the given message in the provided environment. The return value will // be tracer dependent. -func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx vm.Context, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { +func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, vmctx *vm.Context, blockCtx *vm.BlockContext, statedb *state.StateDB, config *TraceConfig) (interface{}, error) { // Assemble the structured logger or the JavaScript tracer var ( tracer vm.Tracer @@ -580,7 +594,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v tracer = vm.NewStructLogger(config.LogConfig) } // Run the transaction with tracing enabled. - vmenv := vm.NewEVM(vmctx, statedb, api.config, vm.Config{Debug: true, Tracer: tracer}) + vmenv := vm.NewEVM(vmctx, statedb, api.config, &vm.Config{Debug: true, Tracer: tracer}, blockCtx) ret, gas, failed, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas())) if err != nil { @@ -605,19 +619,19 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v } // computeTxEnv returns the execution environment of a certain transaction. -func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, vm.Context, *state.StateDB, error) { +func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, reexec uint64) (core.Message, *vm.Context, *vm.BlockContext, *state.StateDB, error) { // Create the parent state database block := api.eth.blockchain.GetBlockByHash(blockHash) if block == nil { - return nil, vm.Context{}, nil, fmt.Errorf("block %x not found", blockHash) + return nil, nil, nil, nil, fmt.Errorf("block %x not found", blockHash) } parent := api.eth.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1) if parent == nil { - return nil, vm.Context{}, nil, fmt.Errorf("parent %x not found", block.ParentHash()) + return nil, nil, nil, nil, fmt.Errorf("parent %x not found", block.ParentHash()) } statedb, err := api.computeStateDB(parent, reexec) if err != nil { - return nil, vm.Context{}, nil, err + return nil, nil, nil, nil, err } // Recompute transactions up to the target index. signer := types.MakeSigner(api.config, block.Number()) @@ -625,18 +639,19 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree for idx, tx := range block.Transactions() { // Assemble the transaction call message and return if the requested offset msg, _ := tx.AsMessage(signer) - context := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil) + context := core.NewEVMContext(msg, block.Header(), api.eth.blockchain) + beneficiary, _ := api.eth.blockchain.Engine().Author(block.Header()) + blockCtx := core.NewBlockContext(block.Header(), beneficiary, api.eth.chainConfig) if idx == txIndex { - return msg, context, statedb, nil + return msg, context, blockCtx, statedb, nil } // Not yet the searched for transaction, execute on top of the current state - vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{}) + vmenv := vm.NewEVM(context, statedb, api.config, &vm.Config{}, blockCtx) if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil { - return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err) + return nil, nil, nil, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err) } // Ensure any modifications are committed to the state statedb.Finalise(true) } - return nil, vm.Context{}, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash) + return nil, nil, nil, nil, fmt.Errorf("tx index %d out of range for block %x", txIndex, blockHash) } -*/ diff --git a/les/api_backend.go b/les/api_backend.go index dba9632553..9c2271d97d 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -104,8 +104,10 @@ func (b *LesApiBackend) GetTd(hash common.Hash) *big.Int { func (b *LesApiBackend) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmCfg vm.Config) (*vm.EVM, func() error, error) { state.SetBalance(msg.From(), math.MaxBig256) - context := core.NewEVMContext(msg, header, b.eth.blockchain, nil) - return vm.NewEVM(context, state, b.eth.chainConfig, &vmCfg, &vm.BlockContext{}), state.Error, nil + context := core.NewEVMContext(msg, header, b.eth.blockchain) + beneficiary, _ := b.eth.BlockChain().Engine().Author(header) + blockContext := core.NewBlockContext(header, beneficiary, b.ChainConfig()) + return vm.NewEVM(context, state, b.eth.chainConfig, &vmCfg, blockContext), state.Error, nil } func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error { diff --git a/les/odr_test.go b/les/odr_test.go index 983f7262b0..f02612a890 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -135,8 +135,11 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)} - context := core.NewEVMContext(msg, header, bc, nil) - vmenv := vm.NewEVM(context, statedb, config, vm.Config{}) + context := core.NewEVMContext(msg, header, bc) + beneficiary, _ := bc.Engine().Author(header) + blockContext := core.NewBlockContext(header, beneficiary, bc.Config()) + + vmenv := vm.NewEVM(context, statedb, config, &vm.Config{}, blockContext) //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) gp := new(core.GasPool).AddGas(math.MaxUint64) @@ -148,8 +151,10 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai state := light.NewState(ctx, header, lc.Odr()) state.SetBalance(testBankAddress, math.MaxBig256) msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 100000, new(big.Int), data, false)} - context := core.NewEVMContext(msg, header, lc, nil) - vmenv := vm.NewEVM(context, state, config, vm.Config{}) + context := core.NewEVMContext(msg, header, lc) + beneficiary, _ := bc.Engine().Author(header) + blockContext := core.NewBlockContext(header, beneficiary, bc.Config()) + vmenv := vm.NewEVM(context, state, config, &vm.Config{}, blockContext) gp := new(core.GasPool).AddGas(math.MaxUint64) ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) if state.Error() == nil { diff --git a/light/odr_test.go b/light/odr_test.go index 3e7ac10118..de78674ed1 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -190,8 +190,10 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain // Perform read-only call. st.SetBalance(testBankAddress, math.MaxBig256) msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, new(big.Int), data, false)} - context := core.NewEVMContext(msg, header, chain, nil) - vmenv := vm.NewEVM(context, st, config, vm.Config{}) + context := core.NewEVMContext(msg, header, chain) + beneficiary, _ := bc.Engine().Author(header) + blockContext := core.NewBlockContext(header, beneficiary, bc.Config()) + vmenv := vm.NewEVM(context, st, config, &vm.Config{}, blockContext) gp := new(core.GasPool).AddGas(math.MaxUint64) ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp) res = append(res, ret...) diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 84581fae18..6cdbd1bb0b 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -133,9 +133,12 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD if err != nil { return nil, err } - context := core.NewEVMContext(msg, block.Header(), nil, &t.json.Env.Coinbase) + context := core.NewEVMContext(msg, block.Header(), nil) + beneficiary := t.json.Env.Coinbase + blockContext := core.NewBlockContext(block.Header(), beneficiary, config) + context.GetHash = vmTestBlockHash - evm := vm.NewEVM(context, statedb, config, vmconfig) + evm := vm.NewEVM(context, statedb, config, &vmconfig, blockContext) gaspool := new(core.GasPool) gaspool.AddGas(block.GasLimit())