github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/core/vm/environment.go (about)

     1  // Copyright 2014 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package vm
    18  
    19  import (
    20  	"fmt"
    21  	"math/big"
    22  	"sync/atomic"
    23  
    24  	"github.com/atheioschain/go-atheios/common"
    25  	"github.com/atheioschain/go-atheios/crypto"
    26  	"github.com/atheioschain/go-atheios/params"
    27  )
    28  
    29  type (
    30  	CanTransferFunc func(StateDB, common.Address, *big.Int) bool
    31  	TransferFunc    func(StateDB, common.Address, common.Address, *big.Int)
    32  	// GetHashFunc returns the nth block hash in the blockchain
    33  	// and is used by the BLOCKHASH EVM op code.
    34  	GetHashFunc func(uint64) common.Hash
    35  )
    36  
    37  // Context provides the EVM with auxiliary information. Once provided it shouldn't be modified.
    38  type Context struct {
    39  	// CanTransfer returns whether the account contains
    40  	// sufficient ether to transfer the value
    41  	CanTransfer CanTransferFunc
    42  	// Transfer transfers ether from one account to the other
    43  	Transfer TransferFunc
    44  	// GetHash returns the hash corresponding to n
    45  	GetHash GetHashFunc
    46  
    47  	// Message information
    48  	Origin   common.Address // Provides information for ORIGIN
    49  	GasPrice *big.Int       // Provides information for GASPRICE
    50  
    51  	// Block information
    52  	Coinbase    common.Address // Provides information for COINBASE
    53  	GasLimit    *big.Int       // Provides information for GASLIMIT
    54  	BlockNumber *big.Int       // Provides information for NUMBER
    55  	Time        *big.Int       // Provides information for TIME
    56  	Difficulty  *big.Int       // Provides information for DIFFICULTY
    57  }
    58  
    59  // EVM provides information about external sources for the EVM
    60  //
    61  // The EVM should never be reused and is not thread safe.
    62  type EVM struct {
    63  	// Context provides auxiliary blockchain related information
    64  	Context
    65  	// StateDB gives access to the underlying state
    66  	StateDB StateDB
    67  	// Depth is the current call stack
    68  	depth int
    69  
    70  	// chainConfig contains information about the current chain
    71  	chainConfig *params.ChainConfig
    72  	// virtual machine configuration options used to initialise the
    73  	// evm.
    74  	vmConfig Config
    75  	// global (to this context) ethereum virtual machine
    76  	// used throughout the execution of the tx.
    77  	interpreter *Interpreter
    78  	// abort is used to abort the EVM calling operations
    79  	// NOTE: must be set atomically
    80  	abort int32
    81  }
    82  
    83  // NewEVM retutrns a new EVM evmironment.
    84  func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM {
    85  	evm := &EVM{
    86  		Context:     ctx,
    87  		StateDB:     statedb,
    88  		vmConfig:    vmConfig,
    89  		chainConfig: chainConfig,
    90  	}
    91  
    92  	evm.interpreter = NewInterpreter(evm, vmConfig)
    93  	return evm
    94  }
    95  
    96  // Cancel cancels any running EVM operation. This may be called concurrently and it's safe to be
    97  // called multiple times.
    98  func (evm *EVM) Cancel() {
    99  	atomic.StoreInt32(&evm.abort, 1)
   100  }
   101  
   102  // Call executes the contract associated with the addr with the given input as parameters. It also handles any
   103  // necessary value transfer required and takes the necessary steps to create accounts and reverses the state in
   104  // case of an execution error or failed value transfer.
   105  func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) (ret []byte, err error) {
   106  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   107  		caller.ReturnGas(gas)
   108  
   109  		return nil, nil
   110  	}
   111  
   112  	// Depth check execution. Fail if we're trying to execute above the
   113  	// limit.
   114  	if evm.depth > int(params.CallCreateDepth.Int64()) {
   115  		caller.ReturnGas(gas)
   116  
   117  		return nil, ErrDepth
   118  	}
   119  	if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
   120  		caller.ReturnGas(gas)
   121  
   122  		return nil, ErrInsufficientBalance
   123  	}
   124  
   125  	var (
   126  		to       Account
   127  		snapshot = evm.StateDB.Snapshot()
   128  	)
   129  	if !evm.StateDB.Exist(addr) {
   130  		if PrecompiledContracts[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.BitLen() == 0 {
   131  			caller.ReturnGas(gas)
   132  			return nil, nil
   133  		}
   134  
   135  		to = evm.StateDB.CreateAccount(addr)
   136  	} else {
   137  		to = evm.StateDB.GetAccount(addr)
   138  	}
   139  	evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
   140  
   141  	// initialise a new contract and set the code that is to be used by the
   142  	// E The contract is a scoped evmironment for this execution context
   143  	// only.
   144  	contract := NewContract(caller, to, value, gas)
   145  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   146  	defer contract.Finalise()
   147  
   148  	ret, err = evm.interpreter.Run(contract, input)
   149  	// When an error was returned by the EVM or when setting the creation code
   150  	// above we revert to the snapshot and consume any gas remaining. Additionally
   151  	// when we're in homestead this also counts for code storage gas errors.
   152  	if err != nil {
   153  		contract.UseGas(contract.Gas)
   154  
   155  		evm.StateDB.RevertToSnapshot(snapshot)
   156  	}
   157  	return ret, err
   158  }
   159  
   160  // CallCode executes the contract associated with the addr with the given input as parameters. It also handles any
   161  // necessary value transfer required and takes the necessary steps to create accounts and reverses the state in
   162  // case of an execution error or failed value transfer.
   163  //
   164  // CallCode differs from Call in the sense that it executes the given address' code with the caller as context.
   165  func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas, value *big.Int) (ret []byte, err error) {
   166  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   167  		caller.ReturnGas(gas)
   168  
   169  		return nil, nil
   170  	}
   171  
   172  	// Depth check execution. Fail if we're trying to execute above the
   173  	// limit.
   174  	if evm.depth > int(params.CallCreateDepth.Int64()) {
   175  		caller.ReturnGas(gas)
   176  
   177  		return nil, ErrDepth
   178  	}
   179  	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
   180  		caller.ReturnGas(gas)
   181  
   182  		return nil, fmt.Errorf("insufficient funds to transfer value. Req %v, has %v", value, evm.StateDB.GetBalance(caller.Address()))
   183  	}
   184  
   185  	var (
   186  		snapshot = evm.StateDB.Snapshot()
   187  		to       = evm.StateDB.GetAccount(caller.Address())
   188  	)
   189  	// initialise a new contract and set the code that is to be used by the
   190  	// E The contract is a scoped evmironment for this execution context
   191  	// only.
   192  	contract := NewContract(caller, to, value, gas)
   193  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   194  	defer contract.Finalise()
   195  
   196  	ret, err = evm.interpreter.Run(contract, input)
   197  	if err != nil {
   198  		contract.UseGas(contract.Gas)
   199  
   200  		evm.StateDB.RevertToSnapshot(snapshot)
   201  	}
   202  
   203  	return ret, err
   204  }
   205  
   206  // DelegateCall executes the contract associated with the addr with the given input as parameters.
   207  // It reverses the state in case of an execution error.
   208  //
   209  // DelegateCall differs from CallCode in the sense that it executes the given address' code with the caller as context
   210  // and the caller is set to the caller of the caller.
   211  func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas *big.Int) (ret []byte, err error) {
   212  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   213  		caller.ReturnGas(gas)
   214  
   215  		return nil, nil
   216  	}
   217  
   218  	// Depth check execution. Fail if we're trying to execute above the
   219  	// limit.
   220  	if evm.depth > int(params.CallCreateDepth.Int64()) {
   221  		caller.ReturnGas(gas)
   222  		return nil, ErrDepth
   223  	}
   224  
   225  	var (
   226  		snapshot = evm.StateDB.Snapshot()
   227  		to       = evm.StateDB.GetAccount(caller.Address())
   228  	)
   229  
   230  	// Iinitialise a new contract and make initialise the delegate values
   231  	contract := NewContract(caller, to, caller.Value(), gas).AsDelegate()
   232  	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr))
   233  	defer contract.Finalise()
   234  
   235  	ret, err = evm.interpreter.Run(contract, input)
   236  	if err != nil {
   237  		contract.UseGas(contract.Gas)
   238  
   239  		evm.StateDB.RevertToSnapshot(snapshot)
   240  	}
   241  
   242  	return ret, err
   243  }
   244  
   245  // Create creates a new contract using code as deployment code.
   246  func (evm *EVM) Create(caller ContractRef, code []byte, gas, value *big.Int) (ret []byte, contractAddr common.Address, err error) {
   247  	if evm.vmConfig.NoRecursion && evm.depth > 0 {
   248  		caller.ReturnGas(gas)
   249  
   250  		return nil, common.Address{}, nil
   251  	}
   252  
   253  	// Depth check execution. Fail if we're trying to execute above the
   254  	// limit.
   255  	if evm.depth > int(params.CallCreateDepth.Int64()) {
   256  		caller.ReturnGas(gas)
   257  
   258  		return nil, common.Address{}, ErrDepth
   259  	}
   260  	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) {
   261  		caller.ReturnGas(gas)
   262  
   263  		return nil, common.Address{}, ErrInsufficientBalance
   264  	}
   265  
   266  	// Create a new account on the state
   267  	nonce := evm.StateDB.GetNonce(caller.Address())
   268  	evm.StateDB.SetNonce(caller.Address(), nonce+1)
   269  
   270  	snapshot := evm.StateDB.Snapshot()
   271  	contractAddr = crypto.CreateAddress(caller.Address(), nonce)
   272  	to := evm.StateDB.CreateAccount(contractAddr)
   273  	if evm.ChainConfig().IsEIP158(evm.BlockNumber) {
   274  		evm.StateDB.SetNonce(contractAddr, 1)
   275  	}
   276  	evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value)
   277  
   278  	// initialise a new contract and set the code that is to be used by the
   279  	// E The contract is a scoped evmironment for this execution context
   280  	// only.
   281  	contract := NewContract(caller, to, value, gas)
   282  	contract.SetCallCode(&contractAddr, crypto.Keccak256Hash(code), code)
   283  	defer contract.Finalise()
   284  
   285  	ret, err = evm.interpreter.Run(contract, nil)
   286  
   287  	// check whether the max code size has been exceeded
   288  	maxCodeSizeExceeded := len(ret) > params.MaxCodeSize
   289  	// if the contract creation ran successfully and no errors were returned
   290  	// calculate the gas required to store the code. If the code could not
   291  	// be stored due to not enough gas set an error and let it be handled
   292  	// by the error checking condition below.
   293  	if err == nil && !maxCodeSizeExceeded {
   294  		dataGas := big.NewInt(int64(len(ret)))
   295  		dataGas.Mul(dataGas, params.CreateDataGas)
   296  		if contract.UseGas(dataGas) {
   297  			evm.StateDB.SetCode(contractAddr, ret)
   298  		} else {
   299  			err = ErrCodeStoreOutOfGas
   300  		}
   301  	}
   302  
   303  	// When an error was returned by the EVM or when setting the creation code
   304  	// above we revert to the snapshot and consume any gas remaining. Additionally
   305  	// when we're in homestead this also counts for code storage gas errors.
   306  	if maxCodeSizeExceeded ||
   307  		(err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) {
   308  		contract.UseGas(contract.Gas)
   309  		evm.StateDB.RevertToSnapshot(snapshot)
   310  
   311  		// Nothing should be returned when an error is thrown.
   312  		return nil, contractAddr, err
   313  	}
   314  	// If the vm returned with an error the return value should be set to nil.
   315  	// This isn't consensus critical but merely to for behaviour reasons such as
   316  	// tests, RPC calls, etc.
   317  	if err != nil {
   318  		ret = nil
   319  	}
   320  
   321  	return ret, contractAddr, err
   322  }
   323  
   324  // ChainConfig returns the evmironment's chain configuration
   325  func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig }
   326  
   327  // Interpreter returns the EVM interpreter
   328  func (evm *EVM) Interpreter() *Interpreter { return evm.interpreter }