| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2014 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // 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. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-10-18 13:31:20 +02:00
										 |  |  | package vm | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	"sync/atomic" | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:27:38 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							| 
									
										
										
										
											2016-10-08 00:23:45 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/params" | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-25 12:30:51 +03:00
										 |  |  | // emptyCodeHash is used by create to ensure deployment is disallowed to already | 
					
						
							|  |  |  | // deployed contract addresses (relevant after the account abstraction). | 
					
						
							|  |  |  | var emptyCodeHash = crypto.Keccak256Hash(nil) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | type ( | 
					
						
							| 
									
										
										
										
											2018-06-26 08:56:25 -04:00
										 |  |  | 	// CanTransferFunc is the signature of a transfer guard function | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	CanTransferFunc func(StateDB, common.Address, *big.Int) bool | 
					
						
							| 
									
										
										
										
											2018-06-26 08:56:25 -04:00
										 |  |  | 	// TransferFunc is the signature of a transfer function | 
					
						
							|  |  |  | 	TransferFunc func(StateDB, common.Address, common.Address, *big.Int) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// GetHashFunc returns the nth block hash in the blockchain | 
					
						
							|  |  |  | 	// and is used by the BLOCKHASH EVM op code. | 
					
						
							|  |  |  | 	GetHashFunc func(uint64) common.Hash | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | // run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter. | 
					
						
							| 
									
										
										
										
											2018-09-07 18:13:25 +02:00
										 |  |  | func run(evm *EVM, contract *Contract, input []byte, readOnly bool) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 	if contract.CodeAddr != nil { | 
					
						
							| 
									
										
										
										
											2017-08-10 16:39:43 +03:00
										 |  |  | 		precompiles := PrecompiledContractsHomestead | 
					
						
							| 
									
										
										
										
											2017-09-14 10:07:31 +03:00
										 |  |  | 		if evm.ChainConfig().IsByzantium(evm.BlockNumber) { | 
					
						
							|  |  |  | 			precompiles = PrecompiledContractsByzantium | 
					
						
							| 
									
										
										
										
											2017-08-10 14:07:11 +03:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-08-10 16:39:43 +03:00
										 |  |  | 		if p := precompiles[*contract.CodeAddr]; p != nil { | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 			return RunPrecompiledContract(p, input, contract) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-25 08:56:39 -04:00
										 |  |  | 	for _, interpreter := range evm.interpreters { | 
					
						
							|  |  |  | 		if interpreter.CanRun(contract.Code) { | 
					
						
							|  |  |  | 			if evm.interpreter != interpreter { | 
					
						
							|  |  |  | 				// Ensure that the interpreter pointer is set back | 
					
						
							|  |  |  | 				// to its current value upon return. | 
					
						
							|  |  |  | 				defer func(i Interpreter) { | 
					
						
							|  |  |  | 					evm.interpreter = i | 
					
						
							|  |  |  | 				}(evm.interpreter) | 
					
						
							|  |  |  | 				evm.interpreter = interpreter | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-09-07 18:13:25 +02:00
										 |  |  | 			return interpreter.Run(contract, input, readOnly) | 
					
						
							| 
									
										
										
										
											2018-07-25 08:56:39 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil, ErrNoCompatibleInterpreter | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Context provides the EVM with auxiliary information. Once provided | 
					
						
							|  |  |  | // it shouldn't be modified. | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | type Context struct { | 
					
						
							|  |  |  | 	// 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 | 
					
						
							|  |  |  | 	GasPrice *big.Int       // Provides information for GASPRICE | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Block information | 
					
						
							|  |  |  | 	Coinbase    common.Address // Provides information for COINBASE | 
					
						
							| 
									
										
										
										
											2017-11-13 13:47:27 +02:00
										 |  |  | 	GasLimit    uint64         // Provides information for GASLIMIT | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	BlockNumber *big.Int       // Provides information for NUMBER | 
					
						
							|  |  |  | 	Time        *big.Int       // Provides information for TIME | 
					
						
							|  |  |  | 	Difficulty  *big.Int       // Provides information for DIFFICULTY | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | // EVM is the Ethereum Virtual Machine base object and provides | 
					
						
							|  |  |  | // the necessary tools to run a contract on the given state with | 
					
						
							|  |  |  | // the provided context. It should be noted that any error | 
					
						
							|  |  |  | // generated through any of the calls should be considered a | 
					
						
							|  |  |  | // revert-state-and-consume-all-gas operation, no checks on | 
					
						
							|  |  |  | // specific errors should ever be performed. The interpreter makes | 
					
						
							|  |  |  | // sure that any errors generated are to be considered faulty code. | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | // The EVM should never be reused and is not thread safe. | 
					
						
							|  |  |  | type EVM struct { | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// Context provides auxiliary blockchain related information | 
					
						
							|  |  |  | 	Context | 
					
						
							|  |  |  | 	// StateDB gives access to the underlying state | 
					
						
							|  |  |  | 	StateDB StateDB | 
					
						
							|  |  |  | 	// Depth is the current call stack | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	depth int | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// chainConfig contains information about the current chain | 
					
						
							|  |  |  | 	chainConfig *params.ChainConfig | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | 	// chain rules contains the chain rules for the current epoch | 
					
						
							|  |  |  | 	chainRules params.Rules | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	// virtual machine configuration options used to initialise the | 
					
						
							|  |  |  | 	// evm. | 
					
						
							|  |  |  | 	vmConfig Config | 
					
						
							|  |  |  | 	// global (to this context) ethereum virtual machine | 
					
						
							|  |  |  | 	// used throughout the execution of the tx. | 
					
						
							| 
									
										
										
										
											2018-07-25 08:56:39 -04:00
										 |  |  | 	interpreters []Interpreter | 
					
						
							|  |  |  | 	interpreter  Interpreter | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	// abort is used to abort the EVM calling operations | 
					
						
							|  |  |  | 	// NOTE: must be set atomically | 
					
						
							|  |  |  | 	abort int32 | 
					
						
							| 
									
										
										
										
											2017-11-28 20:05:49 +01:00
										 |  |  | 	// callGasTemp holds the gas available for the current call. This is needed because the | 
					
						
							|  |  |  | 	// available gas is calculated in gasCall* according to the 63/64 rule and later | 
					
						
							|  |  |  | 	// applied in opCall*. | 
					
						
							|  |  |  | 	callGasTemp uint64 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-26 21:40:00 +08:00
										 |  |  | // NewEVM returns a new EVM. The returned EVM is not thread safe and should | 
					
						
							| 
									
										
										
										
											2017-08-10 14:07:11 +03:00
										 |  |  | // only ever be used *once*. | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmConfig Config) *EVM { | 
					
						
							|  |  |  | 	evm := &EVM{ | 
					
						
							| 
									
										
										
										
											2018-07-25 08:56:39 -04:00
										 |  |  | 		Context:      ctx, | 
					
						
							|  |  |  | 		StateDB:      statedb, | 
					
						
							|  |  |  | 		vmConfig:     vmConfig, | 
					
						
							|  |  |  | 		chainConfig:  chainConfig, | 
					
						
							|  |  |  | 		chainRules:   chainConfig.Rules(ctx.BlockNumber), | 
					
						
							| 
									
										
										
										
											2018-09-20 09:44:35 +02:00
										 |  |  | 		interpreters: make([]Interpreter, 0, 1), | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-20 09:44:35 +02:00
										 |  |  | 	if chainConfig.IsEWASM(ctx.BlockNumber) { | 
					
						
							|  |  |  | 		// to be implemented by EVM-C and Wagon PRs. | 
					
						
							|  |  |  | 		// if vmConfig.EWASMInterpreter != "" { | 
					
						
							|  |  |  | 		//  extIntOpts := strings.Split(vmConfig.EWASMInterpreter, ":") | 
					
						
							|  |  |  | 		//  path := extIntOpts[0] | 
					
						
							|  |  |  | 		//  options := []string{} | 
					
						
							|  |  |  | 		//  if len(extIntOpts) > 1 { | 
					
						
							|  |  |  | 		//    options = extIntOpts[1..] | 
					
						
							|  |  |  | 		//  } | 
					
						
							|  |  |  | 		//  evm.interpreters = append(evm.interpreters, NewEVMVCInterpreter(evm, vmConfig, options)) | 
					
						
							|  |  |  | 		// } else { | 
					
						
							|  |  |  | 		// 	evm.interpreters = append(evm.interpreters, NewEWASMInterpreter(evm, vmConfig)) | 
					
						
							|  |  |  | 		// } | 
					
						
							|  |  |  | 		panic("No supported ewasm interpreter yet.") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// vmConfig.EVMInterpreter will be used by EVM-C, it won't be checked here | 
					
						
							|  |  |  | 	// as we always want to have the built-in EVM as the failover option. | 
					
						
							|  |  |  | 	evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig)) | 
					
						
							| 
									
										
										
										
											2018-07-25 08:56:39 -04:00
										 |  |  | 	evm.interpreter = evm.interpreters[0] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	return evm | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-01 22:36:51 +01:00
										 |  |  | // Cancel cancels any running EVM operation. This may be called concurrently and | 
					
						
							|  |  |  | // it's safe to be called multiple times. | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | func (evm *EVM) Cancel() { | 
					
						
							|  |  |  | 	atomic.StoreInt32(&evm.abort, 1) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-25 08:56:39 -04:00
										 |  |  | // Interpreter returns the current interpreter | 
					
						
							|  |  |  | func (evm *EVM) Interpreter() Interpreter { | 
					
						
							|  |  |  | 	return evm.interpreter | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | // Call executes the contract associated with the addr with the given input as | 
					
						
							|  |  |  | // parameters. 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. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if evm.vmConfig.NoRecursion && evm.depth > 0 { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, nil | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | 	// Fail if we're trying to execute above the call depth limit | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	if evm.depth > int(params.CallCreateDepth) { | 
					
						
							|  |  |  | 		return nil, gas, ErrDepth | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | 	// Fail if we're trying to transfer more than the available balance | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, ErrInsufficientBalance | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 		to       = AccountRef(addr) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		snapshot = evm.StateDB.Snapshot() | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if !evm.StateDB.Exist(addr) { | 
					
						
							| 
									
										
										
										
											2017-08-10 16:39:43 +03:00
										 |  |  | 		precompiles := PrecompiledContractsHomestead | 
					
						
							| 
									
										
										
										
											2017-09-14 10:07:31 +03:00
										 |  |  | 		if evm.ChainConfig().IsByzantium(evm.BlockNumber) { | 
					
						
							|  |  |  | 			precompiles = PrecompiledContractsByzantium | 
					
						
							| 
									
										
										
										
											2017-08-10 16:39:43 +03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 { | 
					
						
							| 
									
										
										
										
											2018-08-06 16:42:49 +08:00
										 |  |  | 			// Calling a non existing account, don't do anything, but ping the tracer | 
					
						
							| 
									
										
										
										
											2018-04-27 14:27:33 +03:00
										 |  |  | 			if evm.vmConfig.Debug && evm.depth == 0 { | 
					
						
							|  |  |  | 				evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) | 
					
						
							|  |  |  | 				evm.vmConfig.Tracer.CaptureEnd(ret, 0, 0, nil) | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 			return nil, gas, nil | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 		evm.StateDB.CreateAccount(addr) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	evm.Transfer(evm.StateDB, caller.Address(), to.Address(), value) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	// 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. | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	contract := NewContract(caller, to, value, gas) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-04 17:15:37 +02:00
										 |  |  | 	// Even if the account has no code, we need to continue because it might be a precompile | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	start := time.Now() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Capture the tracer start/end events in debug mode | 
					
						
							|  |  |  | 	if evm.vmConfig.Debug && evm.depth == 0 { | 
					
						
							|  |  |  | 		evm.vmConfig.Tracer.CaptureStart(caller.Address(), addr, false, input, gas, value) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		defer func() { // Lazy evaluation of the parameters | 
					
						
							|  |  |  | 			evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) | 
					
						
							|  |  |  | 		}() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-09-07 18:13:25 +02:00
										 |  |  | 	ret, err = run(evm, contract, input, false) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// 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 { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		evm.StateDB.RevertToSnapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2017-08-16 17:09:29 +03:00
										 |  |  | 		if err != errExecutionReverted { | 
					
						
							|  |  |  | 			contract.UseGas(contract.Gas) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	return ret, contract.Gas, err | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | // CallCode executes the contract associated with the addr with the given input | 
					
						
							|  |  |  | // as parameters. 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. | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | // CallCode differs from Call in the sense that it executes the given address' | 
					
						
							|  |  |  | // code with the caller as context. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func (evm *EVM) CallCode(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if evm.vmConfig.NoRecursion && evm.depth > 0 { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, nil | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | 	// Fail if we're trying to execute above the call depth limit | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	if evm.depth > int(params.CallCreateDepth) { | 
					
						
							|  |  |  | 		return nil, gas, ErrDepth | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | 	// Fail if we're trying to transfer more than the available balance | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, ErrInsufficientBalance | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		snapshot = evm.StateDB.Snapshot() | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 		to       = AccountRef(caller.Address()) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	) | 
					
						
							|  |  |  | 	// initialise a new contract and set the code that is to be used by the | 
					
						
							| 
									
										
										
										
											2018-03-26 21:40:00 +08:00
										 |  |  | 	// EVM. The contract is a scoped environment for this execution context | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// only. | 
					
						
							|  |  |  | 	contract := NewContract(caller, to, value, gas) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-07 18:13:25 +02:00
										 |  |  | 	ret, err = run(evm, contract, input, false) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		evm.StateDB.RevertToSnapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2017-08-16 17:09:29 +03:00
										 |  |  | 		if err != errExecutionReverted { | 
					
						
							|  |  |  | 			contract.UseGas(contract.Gas) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	return ret, contract.Gas, err | 
					
						
							| 
									
										
										
										
											2016-02-03 23:46:27 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | // DelegateCall executes the contract associated with the addr with the given input | 
					
						
							|  |  |  | // as parameters. It reverses the state in case of an execution error. | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | // 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. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | func (evm *EVM) DelegateCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if evm.vmConfig.NoRecursion && evm.depth > 0 { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, gas, nil | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | 	// Fail if we're trying to execute above the call depth limit | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	if evm.depth > int(params.CallCreateDepth) { | 
					
						
							|  |  |  | 		return nil, gas, ErrDepth | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	var ( | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		snapshot = evm.StateDB.Snapshot() | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 		to       = AccountRef(caller.Address()) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | 	// Initialise a new contract and make initialise the delegate values | 
					
						
							| 
									
										
										
										
											2017-02-22 23:29:59 +01:00
										 |  |  | 	contract := NewContract(caller, to, nil, gas).AsDelegate() | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) | 
					
						
							| 
									
										
										
										
											2015-08-30 10:19:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-07 18:13:25 +02:00
										 |  |  | 	ret, err = run(evm, contract, input, false) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		evm.StateDB.RevertToSnapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2017-08-16 17:09:29 +03:00
										 |  |  | 		if err != errExecutionReverted { | 
					
						
							|  |  |  | 			contract.UseGas(contract.Gas) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	return ret, contract.Gas, err | 
					
						
							| 
									
										
										
										
											2014-10-14 11:48:52 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | // StaticCall executes the contract associated with the addr with the given input | 
					
						
							|  |  |  | // as parameters while disallowing any modifications to the state during the call. | 
					
						
							|  |  |  | // Opcodes that attempt to perform such modifications will result in exceptions | 
					
						
							|  |  |  | // instead of performing the modifications. | 
					
						
							| 
									
										
										
										
											2017-08-15 11:23:23 +03:00
										 |  |  | func (evm *EVM) StaticCall(caller ContractRef, addr common.Address, input []byte, gas uint64) (ret []byte, leftOverGas uint64, err error) { | 
					
						
							|  |  |  | 	if evm.vmConfig.NoRecursion && evm.depth > 0 { | 
					
						
							|  |  |  | 		return nil, gas, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | 	// Fail if we're trying to execute above the call depth limit | 
					
						
							| 
									
										
										
										
											2017-08-15 11:23:23 +03:00
										 |  |  | 	if evm.depth > int(params.CallCreateDepth) { | 
					
						
							|  |  |  | 		return nil, gas, ErrDepth | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var ( | 
					
						
							|  |  |  | 		to       = AccountRef(addr) | 
					
						
							|  |  |  | 		snapshot = evm.StateDB.Snapshot() | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | 	// 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 | 
					
						
							| 
									
										
										
										
											2017-08-15 11:23:23 +03:00
										 |  |  | 	// only. | 
					
						
							|  |  |  | 	contract := NewContract(caller, to, new(big.Int), gas) | 
					
						
							|  |  |  | 	contract.SetCallCode(&addr, evm.StateDB.GetCodeHash(addr), evm.StateDB.GetCode(addr)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-29 09:51:57 +01:00
										 |  |  | 	// We do an AddBalance of zero here, just in order to trigger a touch. | 
					
						
							|  |  |  | 	// This doesn't matter on Mainnet, where all empties are gone at the time of Byzantium, | 
					
						
							|  |  |  | 	// but is the correct thing to do and matters on other networks, in tests, and potential | 
					
						
							|  |  |  | 	// future scenarios | 
					
						
							|  |  |  | 	evm.StateDB.AddBalance(addr, bigZero) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-15 11:23:23 +03:00
										 |  |  | 	// 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 | 
					
						
							| 
									
										
										
										
											2017-08-15 12:56:09 +03:00
										 |  |  | 	// when we're in Homestead this also counts for code storage gas errors. | 
					
						
							| 
									
										
										
										
											2018-09-07 18:13:25 +02:00
										 |  |  | 	ret, err = run(evm, contract, input, true) | 
					
						
							| 
									
										
										
										
											2017-08-15 11:23:23 +03:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		evm.StateDB.RevertToSnapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2017-08-16 17:09:29 +03:00
										 |  |  | 		if err != errExecutionReverted { | 
					
						
							|  |  |  | 			contract.UseGas(contract.Gas) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-08-15 11:23:23 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return ret, contract.Gas, err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-04 17:15:37 +02:00
										 |  |  | type codeAndHash struct { | 
					
						
							|  |  |  | 	code []byte | 
					
						
							|  |  |  | 	hash common.Hash | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *codeAndHash) Hash() common.Hash { | 
					
						
							|  |  |  | 	if c.hash == (common.Hash{}) { | 
					
						
							|  |  |  | 		c.hash = crypto.Keccak256Hash(c.code) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return c.hash | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | // create creates a new contract using code as deployment code. | 
					
						
							| 
									
										
										
										
											2018-10-04 17:15:37 +02:00
										 |  |  | func (evm *EVM) create(caller ContractRef, codeAndHash *codeAndHash, gas uint64, value *big.Int, address common.Address) ([]byte, common.Address, uint64, error) { | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// Depth check execution. Fail if we're trying to execute above the | 
					
						
							|  |  |  | 	// limit. | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 	if evm.depth > int(params.CallCreateDepth) { | 
					
						
							|  |  |  | 		return nil, common.Address{}, gas, ErrDepth | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if !evm.CanTransfer(evm.StateDB, caller.Address(), value) { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		return nil, common.Address{}, gas, ErrInsufficientBalance | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	nonce := evm.StateDB.GetNonce(caller.Address()) | 
					
						
							|  |  |  | 	evm.StateDB.SetNonce(caller.Address(), nonce+1) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | 	// Ensure there's no existing contract already at the designated address | 
					
						
							|  |  |  | 	contractHash := evm.StateDB.GetCodeHash(address) | 
					
						
							|  |  |  | 	if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != emptyCodeHash) { | 
					
						
							| 
									
										
										
										
											2017-08-25 12:30:51 +03:00
										 |  |  | 		return nil, common.Address{}, 0, ErrContractAddressCollision | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Create a new account on the state | 
					
						
							|  |  |  | 	snapshot := evm.StateDB.Snapshot() | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | 	evm.StateDB.CreateAccount(address) | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 	if evm.ChainConfig().IsEIP158(evm.BlockNumber) { | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | 		evm.StateDB.SetNonce(address, 1) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | 	evm.Transfer(evm.StateDB, caller.Address(), address, value) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// initialise a new contract and set the code that is to be used by the | 
					
						
							| 
									
										
										
										
											2018-03-26 21:40:00 +08:00
										 |  |  | 	// EVM. The contract is a scoped environment for this execution context | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// only. | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | 	contract := NewContract(caller, AccountRef(address), value, gas) | 
					
						
							| 
									
										
										
										
											2018-10-04 17:15:37 +02:00
										 |  |  | 	contract.SetCodeOptionalHash(&address, codeAndHash) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:35:54 +02:00
										 |  |  | 	if evm.vmConfig.NoRecursion && evm.depth > 0 { | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | 		return nil, address, gas, nil | 
					
						
							| 
									
										
										
										
											2017-09-14 09:35:54 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if evm.vmConfig.Debug && evm.depth == 0 { | 
					
						
							| 
									
										
										
										
											2018-10-04 17:15:37 +02:00
										 |  |  | 		evm.vmConfig.Tracer.CaptureStart(caller.Address(), address, true, codeAndHash.code, gas, value) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	start := time.Now() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-07 18:13:25 +02:00
										 |  |  | 	ret, err := run(evm, contract, nil, false) | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// check whether the max code size has been exceeded | 
					
						
							| 
									
										
										
										
											2017-09-04 11:53:25 +02:00
										 |  |  | 	maxCodeSizeExceeded := evm.ChainConfig().IsEIP158(evm.BlockNumber) && len(ret) > params.MaxCodeSize | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	// 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 { | 
					
						
							| 
									
										
										
										
											2017-01-04 20:17:24 +01:00
										 |  |  | 		createDataGas := uint64(len(ret)) * params.CreateDataGas | 
					
						
							|  |  |  | 		if contract.UseGas(createDataGas) { | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | 			evm.StateDB.SetCode(address, ret) | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 			err = ErrCodeStoreOutOfGas | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 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. | 
					
						
							| 
									
										
										
										
											2017-08-16 17:09:29 +03:00
										 |  |  | 	if maxCodeSizeExceeded || (err != nil && (evm.ChainConfig().IsHomestead(evm.BlockNumber) || err != ErrCodeStoreOutOfGas)) { | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | 		evm.StateDB.RevertToSnapshot(snapshot) | 
					
						
							| 
									
										
										
										
											2017-08-16 17:09:29 +03:00
										 |  |  | 		if err != errExecutionReverted { | 
					
						
							|  |  |  | 			contract.UseGas(contract.Gas) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-21 08:47:15 +08:00
										 |  |  | 	// Assign err if contract code size exceeds the max while the err is still empty. | 
					
						
							|  |  |  | 	if maxCodeSizeExceeded && err == nil { | 
					
						
							|  |  |  | 		err = errMaxCodeSizeExceeded | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
											
												cmd, core, eth/tracers: support fancier js tracing (#15516)
* cmd, core, eth/tracers: support fancier js tracing
* eth, internal/web3ext: rework trace API, concurrency, chain tracing
* eth/tracers: add three more JavaScript tracers
* eth/tracers, vendor: swap ottovm to duktape for tracing
* core, eth, internal: finalize call tracer and needed extras
* eth, tests: prestate tracer, call test suite, rewinding
* vendor: fix windows builds for tracer js engine
* vendor: temporary duktape fix
* eth/tracers: fix up 4byte and evmdis tracer
* vendor: pull in latest duktape with my upstream fixes
* eth: fix some review comments
* eth: rename rewind to reexec to make it more obvious
* core/vm: terminate tracing using defers
											
										 
											2017-12-21 13:56:11 +02:00
										 |  |  | 	if evm.vmConfig.Debug && evm.depth == 0 { | 
					
						
							|  |  |  | 		evm.vmConfig.Tracer.CaptureEnd(ret, gas-contract.Gas, time.Since(start), err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | 	return ret, address, contract.Gas, err | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Create creates a new contract using code as deployment code. | 
					
						
							|  |  |  | func (evm *EVM) Create(caller ContractRef, code []byte, gas uint64, value *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { | 
					
						
							|  |  |  | 	contractAddr = crypto.CreateAddress(caller.Address(), evm.StateDB.GetNonce(caller.Address())) | 
					
						
							| 
									
										
										
										
											2018-10-04 17:15:37 +02:00
										 |  |  | 	return evm.create(caller, &codeAndHash{code: code}, gas, value, contractAddr) | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Create2 creates a new contract using code as deployment code. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2018-08-14 23:30:42 +08:00
										 |  |  | // The different between Create2 with Create is Create2 uses sha3(0xff ++ msg.sender ++ salt ++ sha3(init_code))[12:] | 
					
						
							| 
									
										
										
										
											2018-07-24 22:22:03 +08:00
										 |  |  | // instead of the usual sender-and-nonce-hash as the address where the contract is initialized at. | 
					
						
							|  |  |  | func (evm *EVM) Create2(caller ContractRef, code []byte, gas uint64, endowment *big.Int, salt *big.Int) (ret []byte, contractAddr common.Address, leftOverGas uint64, err error) { | 
					
						
							| 
									
										
										
										
											2018-10-04 17:15:37 +02:00
										 |  |  | 	codeAndHash := &codeAndHash{code: code} | 
					
						
							|  |  |  | 	contractAddr = crypto.CreateAddress2(caller.Address(), common.BigToHash(salt), codeAndHash.Hash().Bytes()) | 
					
						
							|  |  |  | 	return evm.create(caller, codeAndHash, gas, endowment, contractAddr) | 
					
						
							| 
									
										
										
										
											2014-10-22 15:22:21 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2016-12-06 02:16:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-16 15:45:13 +00:00
										 |  |  | // ChainConfig returns the environment's chain configuration | 
					
						
							| 
									
										
										
										
											2017-01-05 11:52:10 +01:00
										 |  |  | func (evm *EVM) ChainConfig() *params.ChainConfig { return evm.chainConfig } |