From bfade2679fb9973bc99453e60feb6bc8f87ca914 Mon Sep 17 00:00:00 2001 From: Jeffrey Wilcke Date: Mon, 5 Dec 2016 13:27:44 +0100 Subject: [PATCH] cmd/evm, core, tests: review changes --- accounts/abi/bind/backends/simulated.go | 2 +- cmd/evm/main.go | 2 ++ core/evm.go | 14 ++++----- core/state/statedb.go | 2 ++ core/state_processor.go | 2 +- core/vm/environment.go | 23 +++++++++++---- eth/api.go | 2 +- eth/api_backend.go | 2 +- les/api_backend.go | 2 +- les/odr_test.go | 4 +-- light/odr_test.go | 4 +-- tests/state_test_util.go | 39 ------------------------- 12 files changed, 36 insertions(+), 62 deletions(-) diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go index d031c13ed8..06bd13cae2 100644 --- a/accounts/abi/bind/backends/simulated.go +++ b/accounts/abi/bind/backends/simulated.go @@ -226,7 +226,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM // Execute the call. msg := callmsg{call} - evmContext := core.ToEVMContext(msg, block.Header(), b.blockchain) + evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. vmenv := vm.NewEnvironment(evmContext, statedb, chainConfig, vm.Config{}) diff --git a/cmd/evm/main.go b/cmd/evm/main.go index d0ca4cf300..993dd7659e 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -162,6 +162,7 @@ func run(ctx *cli.Context) error { Origin: sender.Address(), State: statedb, GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)), + GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), Value: common.Big(ctx.GlobalString(ValueFlag.Name)), EVMConfig: vm.Config{ Tracer: logger, @@ -175,6 +176,7 @@ func run(ctx *cli.Context) error { Origin: sender.Address(), State: statedb, GasLimit: common.Big(ctx.GlobalString(GasFlag.Name)), + GasPrice: common.Big(ctx.GlobalString(PriceFlag.Name)), Value: common.Big(ctx.GlobalString(ValueFlag.Name)), EVMConfig: vm.Config{ Tracer: logger, diff --git a/core/evm.go b/core/evm.go index 5630a43c24..6a5713075b 100644 --- a/core/evm.go +++ b/core/evm.go @@ -1,5 +1,4 @@ // Copyright 2014 The go-ethereum Authors - // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify @@ -26,13 +25,13 @@ import ( ) // BlockFetcher retrieves headers by their hash -type BlockFetcher interface { +type HeaderFetcher interface { // GetHeader returns the hash corresponding to their hash GetHeader(common.Hash, uint64) *types.Header } -// ToEVMContext creates a new context for use in the EVM. -func ToEVMContext(msg Message, header *types.Header, chain BlockFetcher) vm.Context { +// NewEVMContext creates a new context for use in the EVM. +func NewEVMContext(msg Message, header *types.Header, chain HeaderFetcher) vm.Context { return vm.Context{ CanTransfer: CanTransfer, Transfer: Transfer, @@ -48,10 +47,8 @@ func ToEVMContext(msg Message, header *types.Header, chain BlockFetcher) vm.Cont } } -// GetHashFn returns a function for which the VM env can query block hashes through -// up to the limit defined by the Yellow Paper and uses the given block chain -// to query for information. -func GetHashFn(ref *types.Header, chain BlockFetcher) func(n uint64) common.Hash { +// GetHashFn returns a GetHashFunc which retrieves header hashes by number +func GetHashFn(ref *types.Header, chain HeaderFetcher) func(n uint64) common.Hash { return func(n uint64) common.Hash { for header := chain.GetHeader(ref.ParentHash, ref.Number.Uint64()-1); header != nil; header = chain.GetHeader(header.ParentHash, header.Number.Uint64()-1) { if header.Number.Uint64() == n { @@ -64,6 +61,7 @@ func GetHashFn(ref *types.Header, chain BlockFetcher) func(n uint64) common.Hash } // CanTransfer checks wether there are enough funds in the address' account to make a transfer. +// This does not take the necessary gas in to account to make the transfer valid. func CanTransfer(db vm.StateDB, addr common.Address, amount *big.Int) bool { return db.GetBalance(addr).Cmp(amount) >= 0 } diff --git a/core/state/statedb.go b/core/state/statedb.go index 1017bb2b0d..82e2ec7c1f 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -293,6 +293,7 @@ func (self *StateDB) HasSuicided(addr common.Address) bool { * SETTERS */ +// AddBalance adds amount to the account associated with addr func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { @@ -300,6 +301,7 @@ func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) { } } +// SubBalance subtracts amount from the account associated with addr func (self *StateDB) SubBalance(addr common.Address, amount *big.Int) { stateObject := self.GetOrNewStateObject(addr) if stateObject != nil { diff --git a/core/state_processor.go b/core/state_processor.go index e3f84a33f6..67a7ad5a12 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -97,7 +97,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, gp *GasPool, s return nil, nil, nil, err } // Create a new context to be used in the EVM environment - context := ToEVMContext(msg, header, bc) + context := NewEVMContext(msg, header, bc) // Create a new environment which holds all relevant information // about the transaction and calling mechanisms. vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{}) diff --git a/core/vm/environment.go b/core/vm/environment.go index 3233aee068..50a09d4444 100644 --- a/core/vm/environment.go +++ b/core/vm/environment.go @@ -74,17 +74,20 @@ type Environment struct { } // NewEnvironment retutrns a new EVM environment. -func NewEnvironment(context Context, statedb StateDB, chainConfig *params.ChainConfig, vmCfg Config) *Environment { +func NewEnvironment(context Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *Environment { env := &Environment{ Context: context, StateDB: statedb, - vmConfig: vmCfg, + vmConfig: vmConfig, chainConfig: chainConfig, } - env.evm = New(env, vmCfg) + env.evm = New(env, vmConfig) return env } +// Call executes the contract associated with the addr with the given input as paramaters. It also handles any +// necessary value transfer required and takes the necessary steps to create accounts and reverses the state in +// case of an execution error or failed value transfer. func (env *Environment) Call(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) ([]byte, error) { if env.vmConfig.NoRecursion && env.Depth > 0 { caller.ReturnGas(gas) @@ -140,7 +143,11 @@ func (env *Environment) Call(caller ContractRef, addr common.Address, input []by return ret, err } -// Take another's contract code and execute within our own context +// CallCode executes the contract associated with the addr with the given input as paramaters. It also handles any +// necessary value transfer required and takes the necessary steps to create accounts and reverses the state in +// case of an execution error or failed value transfer. +// +// CallCode differs from Call in the sense that it executes the given address' code with the caller as context. func (env *Environment) CallCode(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) ([]byte, error) { if env.vmConfig.NoRecursion && env.Depth > 0 { caller.ReturnGas(gas) @@ -182,7 +189,11 @@ func (env *Environment) CallCode(caller ContractRef, addr common.Address, input return ret, err } -// Same as CallCode except sender and value is propagated from parent to child scope +// DelegateCall executes the contract associated with the addr with the given input as paramaters. +// It reverses the state in case of an execution error. +// +// DelegateCall differs from CallCode in the sense that it executes the given address' code with the caller as context +// and the caller is set to the caller of the caller. func (env *Environment) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas *big.Int) ([]byte, error) { if env.vmConfig.NoRecursion && env.Depth > 0 { caller.ReturnGas(gas) @@ -217,7 +228,7 @@ func (env *Environment) DelegateCall(caller ContractRef, addr common.Address, in return ret, err } -// Create a new contract +// Create creates a new contract using code as deployment code. func (env *Environment) Create(caller ContractRef, code []byte, gas, value *big.Int) ([]byte, common.Address, error) { if env.vmConfig.NoRecursion && env.Depth > 0 { caller.ReturnGas(gas) diff --git a/eth/api.go b/eth/api.go index 7d02b0f20d..a86ed95cfc 100644 --- a/eth/api.go +++ b/eth/api.go @@ -515,7 +515,7 @@ func (api *PrivateDebugAPI) TraceTransaction(ctx context.Context, txHash common. if err != nil { return nil, fmt.Errorf("sender retrieval failed: %v", err) } - context := core.ToEVMContext(msg, block.Header(), api.eth.BlockChain()) + context := core.NewEVMContext(msg, block.Header(), api.eth.BlockChain()) // Mutate the state if we haven't reached the tracing transaction yet if uint64(idx) < txIndex { diff --git a/eth/api_backend.go b/eth/api_backend.go index ea06217b12..b95ef79c5a 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -112,7 +112,7 @@ func (b *EthApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state et from.SetBalance(common.MaxBig) vmError := func() error { return nil } - context := core.ToEVMContext(msg, header, b.eth.BlockChain()) + context := core.NewEVMContext(msg, header, b.eth.BlockChain()) return vm.NewEnvironment(context, statedb, b.eth.chainConfig, vm.Config{}), vmError, nil } diff --git a/les/api_backend.go b/les/api_backend.go index eaacea6bf1..8df963f6e6 100644 --- a/les/api_backend.go +++ b/les/api_backend.go @@ -98,7 +98,7 @@ func (b *LesApiBackend) GetVMEnv(ctx context.Context, msg core.Message, state et from.SetBalance(common.MaxBig) vmstate := light.NewVMState(ctx, stateDb) - context := core.ToEVMContext(msg, header, b.eth.blockchain) + context := core.NewEVMContext(msg, header, b.eth.blockchain) return vm.NewEnvironment(context, vmstate, b.eth.chainConfig, vm.Config{}), vmstate.Error, nil } diff --git a/les/odr_test.go b/les/odr_test.go index 3a0b94d8da..27e3b283dc 100644 --- a/les/odr_test.go +++ b/les/odr_test.go @@ -122,7 +122,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)} - context := core.ToEVMContext(msg, header, bc) + context := core.NewEVMContext(msg, header, bc) vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{}) //vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{}) @@ -140,7 +140,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(100000), new(big.Int), data, false)} - context := core.ToEVMContext(msg, header, lc) + context := core.NewEVMContext(msg, header, lc) vmenv := vm.NewEnvironment(context, vmstate, config, vm.Config{}) //vmenv := light.NewEnv(ctx, state, config, lc, msg, header, vm.Config{}) diff --git a/light/odr_test.go b/light/odr_test.go index 3268e6c04d..2f60f32fd9 100644 --- a/light/odr_test.go +++ b/light/odr_test.go @@ -171,7 +171,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} - context := core.ToEVMContext(msg, header, bc) + context := core.NewEVMContext(msg, header, bc) vmenv := vm.NewEnvironment(context, statedb, config, vm.Config{}) gp := new(core.GasPool).AddGas(common.MaxBig) @@ -187,7 +187,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain from.SetBalance(common.MaxBig) msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), big.NewInt(1000000), new(big.Int), data, false)} - context := core.ToEVMContext(msg, header, lc) + context := core.NewEVMContext(msg, header, lc) vmenv := vm.NewEnvironment(context, vmstate, config, vm.Config{}) gp := new(core.GasPool).AddGas(common.MaxBig) ret, _, _ := core.ApplyMessage(vmenv, msg, gp) diff --git a/tests/state_test_util.go b/tests/state_test_util.go index 37a5ba9604..dc5872d98e 100644 --- a/tests/state_test_util.go +++ b/tests/state_test_util.go @@ -221,43 +221,4 @@ func RunState(chainConfig *params.ChainConfig, statedb *state.StateDB, env, tx m statedb.Commit(chainConfig.IsEIP158(environment.Context.BlockNumber)) return ret, statedb.Logs(), gasUsed, err - /* - - var ( - data = common.FromHex(tx["data"]) - gas = common.Big(tx["gasLimit"]) - price = common.Big(tx["gasPrice"]) - value = common.Big(tx["value"]) - nonce = common.Big(tx["nonce"]).Uint64() - ) - - var to *common.Address - if len(tx["to"]) > 2 { - t := common.HexToAddress(tx["to"]) - to = &t - } - // Set pre compiled contracts - vm.Precompiled = vm.PrecompiledContracts() - gaspool := new(core.GasPool).AddGas(common.Big(env["currentGasLimit"])) - - key, _ := hex.DecodeString(tx["secretKey"]) - addr := crypto.PubkeyToAddress(crypto.ToECDSA(key).PublicKey) - - message := types.NewMessage(addr, to, nonce, value, gas, price, data, true) - vmenv := NewEnvFromMap(chainConfig, statedb, env, tx) - vmenv.origin = addr - - root, _ := statedb.Commit(false) - statedb.Reset(root) - - snapshot := statedb.Snapshot() - - ret, _, err := core.ApplyMessage(vmenv, message, gaspool) - if core.IsNonceErr(err) || core.IsInvalidTxErr(err) || core.IsGasLimitErr(err) { - statedb.RevertToSnapshot(snapshot) - } - statedb.Commit(chainConfig.IsEIP158(vmenv.BlockNumber())) - - return ret, vmenv.state.Logs(), vmenv.Gas, err - */ }