diff --git a/core/call_context.go b/core/call_context.go deleted file mode 100644 index d9a9a029b1..0000000000 --- a/core/call_context.go +++ /dev/null @@ -1,227 +0,0 @@ -// Copyright 2014 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package core - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/crypto" - "github.com/ethereum/go-ethereum/params" -) - -// EVMCallContext is the backbone of the Ethereum Virtual Machine allowing -// Subcalls, creation and delegate calls. It limits the EVM call depth and -// takes care of all value transfers during the transations. -// -// EVMCallContext implements the CallContext interface. -type EVMCallContext struct { - // CanTransfer returns whether the address has enough ether to make the transfer happen - CanTransfer func(db vm.StateDB, addr common.Address, amount *big.Int) bool - // Transfer transfers amount of ether from sender to recipient. - Transfer func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) - // Get Hash returns the nth hash in the blockchain. - GetHashFn func(n uint64) common.Hash -} - -func (c EVMCallContext) GetHash(n uint64) common.Hash { - return c.GetHashFn(n) -} - -// Call executes within the given contract -func (c EVMCallContext) Call(env *vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, value *big.Int) (ret []byte, err error) { - // Depth check execution. Fail if we're trying to execute above the - // limit. - if env.Depth > int(params.CallCreateDepth.Int64()) { - caller.ReturnGas(gas) - - return nil, vm.DepthError - } - if !c.CanTransfer(env.StateDB, caller.Address(), value) { - caller.ReturnGas(gas) - - return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.StateDB.GetBalance(caller.Address())) - } - - var ( - to vm.Account - snapshotPreTransfer = env.StateDB.Snapshot() - ) - if !env.StateDB.Exist(addr) { - if vm.Precompiled[addr.Str()] == nil && env.ChainConfig().IsEIP158(env.BlockNumber) && value.BitLen() == 0 { - caller.ReturnGas(gas) - return nil, nil - } - - to = env.StateDB.CreateAccount(addr) - } else { - to = env.StateDB.GetAccount(addr) - } - c.Transfer(env.StateDB, caller.Address(), to.Address(), value) - - // initialise a new contract and set the code that is to be used by the - // EVM. The contract is a scoped environment for this execution context - // only. - contract := vm.NewContract(caller, to, value, gas) - contract.SetCallCode(&addr, env.StateDB.GetCodeHash(addr), env.StateDB.GetCode(addr)) - defer contract.Finalise() - - ret, err = env.EVM().Run(contract, input) - // When an error was returned by the EVM or when setting the creation code - // above we revert to the snapshot and consume any gas remaining. Additionally - // when we're in homestead this also counts for code storage gas errors. - if err != nil { - contract.UseGas(contract.Gas) - - env.StateDB.RevertToSnapshot(snapshotPreTransfer) - } - return ret, err -} - -// CallCode executes the given address' code as the given contract address -func (c EVMCallContext) CallCode(env *vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, value *big.Int) (ret []byte, err error) { - // Depth check execution. Fail if we're trying to execute above the - // limit. - if env.Depth > int(params.CallCreateDepth.Int64()) { - caller.ReturnGas(gas) - - return nil, vm.DepthError - } - if !c.CanTransfer(env.StateDB, caller.Address(), value) { - caller.ReturnGas(gas) - - return nil, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.StateDB.GetBalance(caller.Address())) - } - - var ( - snapshotPreTransfer = env.StateDB.Snapshot() - to = env.StateDB.GetAccount(caller.Address()) - ) - // initialise a new contract and set the code that is to be used by the - // EVM. The contract is a scoped environment for this execution context - // only. - contract := vm.NewContract(caller, to, value, gas) - contract.SetCallCode(&addr, env.StateDB.GetCodeHash(addr), env.StateDB.GetCode(addr)) - defer contract.Finalise() - - ret, err = env.EVM().Run(contract, input) - if err != nil { - contract.UseGas(contract.Gas) - - env.StateDB.RevertToSnapshot(snapshotPreTransfer) - } - - return ret, err -} - -// Create creates a new contract with the given code -func (c EVMCallContext) Create(env *vm.Environment, caller vm.ContractRef, code []byte, gas, value *big.Int) (ret []byte, address common.Address, err error) { - // Depth check execution. Fail if we're trying to execute above the - // limit. - if env.Depth > int(params.CallCreateDepth.Int64()) { - caller.ReturnGas(gas) - - return nil, common.Address{}, vm.DepthError - } - if !c.CanTransfer(env.StateDB, caller.Address(), value) { - caller.ReturnGas(gas) - - return nil, common.Address{}, ValueTransferErr("insufficient funds to transfer value. Req %v, has %v", value, env.StateDB.GetBalance(caller.Address())) - } - - // Create a new account on the state - nonce := env.StateDB.GetNonce(caller.Address()) - env.StateDB.SetNonce(caller.Address(), nonce+1) - - snapshotPreTransfer := env.StateDB.Snapshot() - var ( - addr = crypto.CreateAddress(caller.Address(), nonce) - to = env.StateDB.CreateAccount(addr) - ) - if env.ChainConfig().IsEIP158(env.BlockNumber) { - env.StateDB.SetNonce(addr, 1) - } - c.Transfer(env.StateDB, caller.Address(), to.Address(), value) - - // initialise a new contract and set the code that is to be used by the - // EVM. The contract is a scoped environment for this execution context - // only. - contract := vm.NewContract(caller, to, value, gas) - contract.SetCallCode(&addr, crypto.Keccak256Hash(code), code) - defer contract.Finalise() - - ret, err = env.EVM().Run(contract, nil) - // check whether the max code size has been exceeded - maxCodeSizeExceeded := len(ret) > params.MaxCodeSize - // if the contract creation ran successfully and no errors were returned - // calculate the gas required to store the code. If the code could not - // be stored due to not enough gas set an error and let it be handled - // by the error checking condition below. - if err == nil && !maxCodeSizeExceeded { - dataGas := big.NewInt(int64(len(ret))) - dataGas.Mul(dataGas, params.CreateDataGas) - if contract.UseGas(dataGas) { - env.StateDB.SetCode(addr, ret) - } else { - err = vm.CodeStoreOutOfGasError - } - } - - // When an error was returned by the EVM or when setting the creation code - // above we revert to the snapshot and consume any gas remaining. Additionally - // when we're in homestead this also counts for code storage gas errors. - if maxCodeSizeExceeded || - (err != nil && (env.ChainConfig().IsHomestead(env.BlockNumber) || err != vm.CodeStoreOutOfGasError)) { - contract.UseGas(contract.Gas) - env.StateDB.RevertToSnapshot(snapshotPreTransfer) - - // Nothing should be returned when an error is thrown. - return nil, addr, err - } - - return ret, addr, err -} - -// DelegateCall is equivalent to CallCode except that sender and value propagates from parent scope to child scope -func (c EVMCallContext) DelegateCall(env *vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas *big.Int) (ret []byte, err error) { - // Depth check execution. Fail if we're trying to execute above the - // limit. - if env.Depth > int(params.CallCreateDepth.Int64()) { - caller.ReturnGas(gas) - return nil, vm.DepthError - } - - var ( - snapshot = env.StateDB.Snapshot() - to = env.StateDB.GetAccount(caller.Address()) - ) - - // Iinitialise a new contract and make initialise the delegate values - contract := vm.NewContract(caller, to, caller.Value(), gas).AsDelegate() - contract.SetCallCode(&addr, env.StateDB.GetCodeHash(addr), env.StateDB.GetCode(addr)) - defer contract.Finalise() - - ret, err = env.EVM().Run(contract, input) - if err != nil { - contract.UseGas(contract.Gas) - - env.StateDB.RevertToSnapshot(snapshot) - } - - return ret, err -} diff --git a/core/evm.go b/core/evm.go index c30c878de5..5630a43c24 100644 --- a/core/evm.go +++ b/core/evm.go @@ -34,11 +34,10 @@ type BlockFetcher interface { // ToEVMContext creates a new context for use in the EVM. func ToEVMContext(msg Message, header *types.Header, chain BlockFetcher) vm.Context { return vm.Context{ - CallContext: EVMCallContext{ - CanTransfer: CanTransfer, - Transfer: Transfer, - GetHashFn: GetHashFn(header, chain), - }, + CanTransfer: CanTransfer, + Transfer: Transfer, + GetHash: GetHashFn(header, chain), + Origin: msg.From(), Coinbase: header.Coinbase, BlockNumber: new(big.Int).Set(header.Number), diff --git a/core/state_transition.go b/core/state_transition.go index f9bebbc13e..6829f7d276 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -244,8 +244,7 @@ func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *b glog.V(logger.Core).Infoln("VM call err:", err) } } - - if err != nil && IsValueTransferErr(err) { + if err == vm.ErrInsufficientBalance { return nil, nil, nil, InvalidTxError(err) } diff --git a/core/vm/environment.go b/core/vm/environment.go index cb6bc36632..795a653713 100644 --- a/core/vm/environment.go +++ b/core/vm/environment.go @@ -17,29 +17,47 @@ package vm import ( + "fmt" "math/big" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/params" ) +type ( + CanTransferFunc func(StateDB, common.Address, *big.Int) bool + TransferFunc func(StateDB, common.Address, common.Address, *big.Int) + // GetHashFunc returns the nth block hash in the blockchain + // and is used by the BLOCKHASH EVM op code. + GetHashFunc func(uint64) common.Hash +) + // Context provides the EVM with auxilary information. Once provided it shouldn't be modified. type Context struct { - CallContext + // CanTransfer returns whether the account contains + // sufficient ether to transfer the value + CanTransfer CanTransferFunc + // Transfer transfers ether from one account to the other + Transfer TransferFunc + // GetHash returns the hash corresponding to n + GetHash GetHashFunc // Message information Origin common.Address // Provides information for ORIGIN - Coinbase common.Address // Provides information for COINBASE GasPrice *big.Int // Provides information for GASPRICE // Block information - GasLimit *big.Int // 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 + Coinbase common.Address // Provides information for COINBASE + GasLimit *big.Int // 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 } -// Environment provides information about external sources for the EVM. +// Environment provides information about external sources for the EVM +// +// The Environment should never be reused and is not thread safe. type Environment struct { // Context provides auxiliary blockchain related information Context @@ -67,47 +85,210 @@ func NewEnvironment(context Context, statedb StateDB, chainConfig *params.ChainC return env } -func (env *Environment) Call(caller ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error) { - if env.vmConfig.Test && env.Depth > 0 { +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) return nil, nil } - return env.CallContext.Call(env, caller, addr, data, gas, value) + // Depth check execution. Fail if we're trying to execute above the + // limit. + if env.Depth > int(params.CallCreateDepth.Int64()) { + caller.ReturnGas(gas) + + return nil, DepthError + } + if !env.Context.CanTransfer(env.StateDB, caller.Address(), value) { + caller.ReturnGas(gas) + + return nil, ErrInsufficientBalance + } + + var ( + to Account + snapshotPreTransfer = env.StateDB.Snapshot() + ) + if !env.StateDB.Exist(addr) { + if Precompiled[addr.Str()] == nil && env.ChainConfig().IsEIP158(env.BlockNumber) && value.BitLen() == 0 { + caller.ReturnGas(gas) + return nil, nil + } + + to = env.StateDB.CreateAccount(addr) + } else { + to = env.StateDB.GetAccount(addr) + } + env.Transfer(env.StateDB, caller.Address(), to.Address(), value) + + // initialise a new contract and set the code that is to be used by the + // E The contract is a scoped environment for this execution context + // only. + contract := NewContract(caller, to, value, gas) + contract.SetCallCode(&addr, env.StateDB.GetCodeHash(addr), env.StateDB.GetCode(addr)) + defer contract.Finalise() + + ret, err := env.EVM().Run(contract, input) + // When an error was returned by the EVM or when setting the creation code + // above we revert to the snapshot and consume any gas remaining. Additionally + // when we're in homestead this also counts for code storage gas errors. + if err != nil { + contract.UseGas(contract.Gas) + + env.StateDB.RevertToSnapshot(snapshotPreTransfer) + } + return ret, err } // Take another's contract code and execute within our own context -func (env *Environment) CallCode(caller ContractRef, addr common.Address, data []byte, gas, value *big.Int) ([]byte, error) { - if env.vmConfig.Test && env.Depth > 0 { +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) return nil, nil } - return env.CallContext.CallCode(env, caller, addr, data, gas, value) + // Depth check execution. Fail if we're trying to execute above the + // limit. + if env.Depth > int(params.CallCreateDepth.Int64()) { + caller.ReturnGas(gas) + + return nil, DepthError + } + if !env.CanTransfer(env.StateDB, caller.Address(), value) { + caller.ReturnGas(gas) + + return nil, fmt.Errorf("insufficient funds to transfer value. Req %v, has %v", value, env.StateDB.GetBalance(caller.Address())) + } + + var ( + snapshotPreTransfer = env.StateDB.Snapshot() + to = env.StateDB.GetAccount(caller.Address()) + ) + // initialise a new contract and set the code that is to be used by the + // E The contract is a scoped environment for this execution context + // only. + contract := NewContract(caller, to, value, gas) + contract.SetCallCode(&addr, env.StateDB.GetCodeHash(addr), env.StateDB.GetCode(addr)) + defer contract.Finalise() + + ret, err := env.EVM().Run(contract, input) + if err != nil { + contract.UseGas(contract.Gas) + + env.StateDB.RevertToSnapshot(snapshotPreTransfer) + } + + return ret, err } // Same as CallCode except sender and value is propagated from parent to child scope -func (env *Environment) DelegateCall(caller ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error) { - if env.vmConfig.Test && env.Depth > 0 { +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) return nil, nil } - return env.CallContext.DelegateCall(env, caller, addr, data, gas) + // Depth check execution. Fail if we're trying to execute above the + // limit. + if env.Depth > int(params.CallCreateDepth.Int64()) { + caller.ReturnGas(gas) + return nil, DepthError + } + + var ( + snapshot = env.StateDB.Snapshot() + to = env.StateDB.GetAccount(caller.Address()) + ) + + // Iinitialise a new contract and make initialise the delegate values + contract := NewContract(caller, to, caller.Value(), gas).AsDelegate() + contract.SetCallCode(&addr, env.StateDB.GetCodeHash(addr), env.StateDB.GetCode(addr)) + defer contract.Finalise() + + ret, err := env.EVM().Run(contract, input) + if err != nil { + contract.UseGas(contract.Gas) + + env.StateDB.RevertToSnapshot(snapshot) + } + + return ret, err } // Create a new contract -func (env *Environment) Create(caller ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error) { - if env.vmConfig.Test && env.Depth > 0 { +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) return nil, common.Address{}, nil } - return env.CallContext.Create(env, caller, data, gas, value) + // Depth check execution. Fail if we're trying to execute above the + // limit. + if env.Depth > int(params.CallCreateDepth.Int64()) { + caller.ReturnGas(gas) + + return nil, common.Address{}, DepthError + } + if !env.CanTransfer(env.StateDB, caller.Address(), value) { + caller.ReturnGas(gas) + + return nil, common.Address{}, ErrInsufficientBalance + } + + // Create a new account on the state + nonce := env.StateDB.GetNonce(caller.Address()) + env.StateDB.SetNonce(caller.Address(), nonce+1) + + snapshotPreTransfer := env.StateDB.Snapshot() + var ( + addr = crypto.CreateAddress(caller.Address(), nonce) + to = env.StateDB.CreateAccount(addr) + ) + if env.ChainConfig().IsEIP158(env.BlockNumber) { + env.StateDB.SetNonce(addr, 1) + } + env.Transfer(env.StateDB, caller.Address(), to.Address(), value) + + // initialise a new contract and set the code that is to be used by the + // E The contract is a scoped environment for this execution context + // only. + contract := NewContract(caller, to, value, gas) + contract.SetCallCode(&addr, crypto.Keccak256Hash(code), code) + defer contract.Finalise() + + ret, err := env.EVM().Run(contract, nil) + // check whether the max code size has been exceeded + maxCodeSizeExceeded := len(ret) > params.MaxCodeSize + // if the contract creation ran successfully and no errors were returned + // calculate the gas required to store the code. If the code could not + // be stored due to not enough gas set an error and let it be handled + // by the error checking condition below. + if err == nil && !maxCodeSizeExceeded { + dataGas := big.NewInt(int64(len(ret))) + dataGas.Mul(dataGas, params.CreateDataGas) + if contract.UseGas(dataGas) { + env.StateDB.SetCode(addr, ret) + } else { + err = CodeStoreOutOfGasError + } + } + + // When an error was returned by the EVM or when setting the creation code + // above we revert to the snapshot and consume any gas remaining. Additionally + // when we're in homestead this also counts for code storage gas errors. + if maxCodeSizeExceeded || + (err != nil && (env.ChainConfig().IsHomestead(env.BlockNumber) || err != CodeStoreOutOfGasError)) { + contract.UseGas(contract.Gas) + env.StateDB.RevertToSnapshot(snapshotPreTransfer) + + // Nothing should be returned when an error is thrown. + return nil, addr, err + } + + return ret, addr, err } // ChainConfig returns the environment's chain configuration diff --git a/core/vm/errors.go b/core/vm/errors.go index 1766bf9fbb..f8d26b1f0a 100644 --- a/core/vm/errors.go +++ b/core/vm/errors.go @@ -23,7 +23,10 @@ import ( "github.com/ethereum/go-ethereum/params" ) -var OutOfGasError = errors.New("Out of gas") -var CodeStoreOutOfGasError = errors.New("Contract creation code storage out of gas") -var DepthError = fmt.Errorf("Max call depth exceeded (%d)", params.CallCreateDepth) -var TraceLimitReachedError = errors.New("The number of logs reached the specified limit") +var ( + OutOfGasError = errors.New("Out of gas") + CodeStoreOutOfGasError = errors.New("Contract creation code storage out of gas") + DepthError = fmt.Errorf("Max call depth exceeded (%d)", params.CallCreateDepth) + TraceLimitReachedError = errors.New("The number of logs reached the specified limit") + ErrInsufficientBalance = errors.New("insufficient balance for transfer") +) diff --git a/core/vm/interface.go b/core/vm/interface.go index 9354c68d08..918fde85fb 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -94,6 +94,4 @@ type CallContext interface { DelegateCall(env *Environment, me ContractRef, addr common.Address, data []byte, gas *big.Int) ([]byte, error) // Create a new contract Create(env *Environment, me ContractRef, data []byte, gas, value *big.Int) ([]byte, common.Address, error) - // GetHash returns the hash corresponding to n - GetHash(n uint64) common.Hash } diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go index 49ed5dfd6e..3cf0dd024a 100644 --- a/core/vm/runtime/env.go +++ b/core/vm/runtime/env.go @@ -27,11 +27,10 @@ import ( func NewEnv(cfg *Config, state *state.StateDB) *vm.Environment { context := vm.Context{ - CallContext: core.EVMCallContext{ - CanTransfer: core.CanTransfer, - Transfer: core.Transfer, - GetHashFn: func(uint64) common.Hash { return common.Hash{} }, - }, + CanTransfer: core.CanTransfer, + Transfer: core.Transfer, + GetHash: func(uint64) common.Hash { return common.Hash{} }, + Origin: cfg.Origin, Coinbase: cfg.Coinbase, BlockNumber: cfg.BlockNumber, @@ -43,92 +42,3 @@ func NewEnv(cfg *Config, state *state.StateDB) *vm.Environment { return vm.NewEnvironment(context, cfg.State, cfg.ChainConfig, cfg.EVMConfig) } - -/* -// Env is a basic runtime environment required for running the EVM. -type Env struct { - chainConfig *params.ChainConfig - depth int - state *state.StateDB - - origin common.Address - coinbase common.Address - - number *big.Int - time *big.Int - difficulty *big.Int - gasLimit *big.Int - - getHashFn func(uint64) common.Hash - - evm *vm.EVM -} - -// NewEnv returns a new vm.Environment -func NewEnv(cfg *Config, state *state.StateDB) vm.Environment { - env := &Env{ - chainConfig: cfg.ChainConfig, - state: state, - origin: cfg.Origin, - coinbase: cfg.Coinbase, - number: cfg.BlockNumber, - time: cfg.Time, - difficulty: cfg.Difficulty, - gasLimit: cfg.GasLimit, - } - env.evm = vm.New(env, vm.Config{ - Debug: cfg.Debug, - EnableJit: !cfg.DisableJit, - ForceJit: !cfg.DisableJit, - }) - - return env -} - -func (self *Env) ChainConfig() *params.ChainConfig { return self.chainConfig } -func (self *Env) Vm() vm.Vm { return self.evm } -func (self *Env) Origin() common.Address { return self.origin } -func (self *Env) BlockNumber() *big.Int { return self.number } -func (self *Env) Coinbase() common.Address { return self.coinbase } -func (self *Env) Time() *big.Int { return self.time } -func (self *Env) Difficulty() *big.Int { return self.difficulty } -func (self *Env) Db() vm.Database { return self.state } -func (self *Env) GasLimit() *big.Int { return self.gasLimit } -func (self *Env) VmType() vm.Type { return vm.StdVmTy } -func (self *Env) GetHash(n uint64) common.Hash { - return self.getHashFn(n) -} -func (self *Env) AddLog(log *vm.Log) { - self.state.AddLog(log) -} -func (self *Env) Depth() int { return self.depth } -func (self *Env) SetDepth(i int) { self.depth = i } -func (self *Env) CanTransfer(from common.Address, balance *big.Int) bool { - return self.state.GetBalance(from).Cmp(balance) >= 0 -} -func (self *Env) SnapshotDatabase() int { - return self.state.Snapshot() -} -func (self *Env) RevertToSnapshot(snapshot int) { - self.state.RevertToSnapshot(snapshot) -} - -func (self *Env) Transfer(from, to vm.Account, amount *big.Int) { - core.Transfer(from, to, amount) -} - -func (self *Env) Call(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - return core.Call(self, caller, addr, data, gas, price, value) -} -func (self *Env) CallCode(caller vm.ContractRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) { - return core.CallCode(self, caller, addr, data, gas, price, value) -} - -func (self *Env) DelegateCall(me vm.ContractRef, addr common.Address, data []byte, gas, price *big.Int) ([]byte, error) { - return core.DelegateCall(self, me, addr, data, gas, price) -} - -func (self *Env) Create(caller vm.ContractRef, data []byte, gas, price, value *big.Int) ([]byte, common.Address, error) { - return core.Create(self, caller, data, gas, price, value) -} -*/ diff --git a/core/vm/vm.go b/core/vm/vm.go index f2e368a9c3..3521839df5 100644 --- a/core/vm/vm.go +++ b/core/vm/vm.go @@ -38,9 +38,9 @@ type Config struct { ForceJit bool // Tracer is the op code logger Tracer Tracer - // Test enforces certain (generic) JSON test rules - // see core/vm/environment.go - Test bool + // NoRecursion disabled EVM call, callcode, + // delegate call and create. + NoRecursion bool } // EVM is used to run Ethereum based contracts and will utilise the diff --git a/tests/util.go b/tests/util.go index 03e7396eaf..b545a0cc8c 100644 --- a/tests/util.go +++ b/tests/util.go @@ -180,7 +180,7 @@ func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *st return true } } - return db.GetBalance(address).Cmp(amount) >= 0 + return core.CanTransfer(db, address, amount) } transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) { if vmTest { @@ -190,13 +190,12 @@ func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *st } context := vm.Context{ - CallContext: core.EVMCallContext{ - CanTransfer: canTransfer, - Transfer: transfer, - GetHashFn: func(n uint64) common.Hash { - return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String()))) - }, + CanTransfer: canTransfer, + Transfer: transfer, + GetHash: func(n uint64) common.Hash { + return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String()))) }, + Origin: origin, Coinbase: common.HexToAddress(envValues["currentCoinbase"]), BlockNumber: common.Big(envValues["currentNumber"]), @@ -208,5 +207,5 @@ func NewEVMEnvironment(vmTest bool, chainConfig *params.ChainConfig, statedb *st if context.GasPrice == nil { context.GasPrice = new(big.Int) } - return vm.NewEnvironment(context, statedb, chainConfig, vm.Config{Test: vmTest}), msg + return vm.NewEnvironment(context, statedb, chainConfig, vm.Config{NoRecursion: vmTest}), msg }