github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/core/vm/vm.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  	"time"
    24  
    25  	"github.com/atheioschain/go-atheios/common"
    26  	"github.com/atheioschain/go-atheios/crypto"
    27  	"github.com/atheioschain/go-atheios/logger"
    28  	"github.com/atheioschain/go-atheios/logger/glog"
    29  	"github.com/atheioschain/go-atheios/params"
    30  )
    31  
    32  // Config are the configuration options for the Interpreter
    33  type Config struct {
    34  	// Debug enabled debugging Interpreter options
    35  	Debug bool
    36  	// EnableJit enabled the JIT VM
    37  	EnableJit bool
    38  	// ForceJit forces the JIT VM
    39  	ForceJit bool
    40  	// Tracer is the op code logger
    41  	Tracer Tracer
    42  	// NoRecursion disabled Interpreter call, callcode,
    43  	// delegate call and create.
    44  	NoRecursion bool
    45  	// Disable gas metering
    46  	DisableGasMetering bool
    47  	// Enable recording of SHA3/keccak preimages
    48  	EnablePreimageRecording bool
    49  	// JumpTable contains the EVM instruction table. This
    50  	// may me left uninitialised and will be set the default
    51  	// table.
    52  	JumpTable [256]operation
    53  }
    54  
    55  // Interpreter is used to run Ethereum based contracts and will utilise the
    56  // passed environment to query external sources for state information.
    57  // The Interpreter will run the byte code VM or JIT VM based on the passed
    58  // configuration.
    59  type Interpreter struct {
    60  	env      *EVM
    61  	cfg      Config
    62  	gasTable params.GasTable
    63  }
    64  
    65  // NewInterpreter returns a new instance of the Interpreter.
    66  func NewInterpreter(env *EVM, cfg Config) *Interpreter {
    67  	// We use the STOP instruction whether to see
    68  	// the jump table was initialised. If it was not
    69  	// we'll set the default jump table.
    70  	if !cfg.JumpTable[STOP].valid {
    71  		cfg.JumpTable = defaultJumpTable
    72  	}
    73  
    74  	return &Interpreter{
    75  		env:      env,
    76  		cfg:      cfg,
    77  		gasTable: env.ChainConfig().GasTable(env.BlockNumber),
    78  	}
    79  }
    80  
    81  // Run loops and evaluates the contract's code with the given input data
    82  func (evm *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err error) {
    83  	evm.env.depth++
    84  	defer func() { evm.env.depth-- }()
    85  
    86  	if contract.CodeAddr != nil {
    87  		if p := PrecompiledContracts[*contract.CodeAddr]; p != nil {
    88  			return RunPrecompiledContract(p, input, contract)
    89  		}
    90  	}
    91  
    92  	// Don't bother with the execution if there's no code.
    93  	if len(contract.Code) == 0 {
    94  		return nil, nil
    95  	}
    96  
    97  	codehash := contract.CodeHash // codehash is used when doing jump dest caching
    98  	if codehash == (common.Hash{}) {
    99  		codehash = crypto.Keccak256Hash(contract.Code)
   100  	}
   101  
   102  	var (
   103  		op    OpCode        // current opcode
   104  		mem   = NewMemory() // bound memory
   105  		stack = newstack()  // local stack
   106  		// For optimisation reason we're using uint64 as the program counter.
   107  		// It's theoretically possible to go above 2^64. The YP defines the PC to be uint256. Practically much less so feasible.
   108  		pc   = uint64(0) // program counter
   109  		cost *big.Int
   110  	)
   111  	contract.Input = input
   112  
   113  	// User defer pattern to check for an error and, based on the error being nil or not, use all gas and return.
   114  	defer func() {
   115  		if err != nil && evm.cfg.Debug {
   116  			evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.depth, err)
   117  		}
   118  	}()
   119  
   120  	if glog.V(logger.Debug) {
   121  		glog.Infof("evm running: %x\n", codehash[:4])
   122  		tstart := time.Now()
   123  		defer func() {
   124  			glog.Infof("evm done: %x. time: %v\n", codehash[:4], time.Since(tstart))
   125  		}()
   126  	}
   127  
   128  	// The Interpreter main run loop (contextual). This loop runs until either an
   129  	// explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during
   130  	// the execution of one of the operations or until the evm.done is set by
   131  	// the parent context.Context.
   132  	for atomic.LoadInt32(&evm.env.abort) == 0 {
   133  		// Get the memory location of pc
   134  		op = contract.GetOp(pc)
   135  
   136  		// get the operation from the jump table matching the opcode
   137  		operation := evm.cfg.JumpTable[op]
   138  
   139  		// if the op is invalid abort the process and return an error
   140  		if !operation.valid {
   141  			return nil, fmt.Errorf("invalid opcode %x", op)
   142  		}
   143  
   144  		// validate the stack and make sure there enough stack items available
   145  		// to perform the operation
   146  		if err := operation.validateStack(stack); err != nil {
   147  			return nil, err
   148  		}
   149  
   150  		var memorySize *big.Int
   151  		// calculate the new memory size and expand the memory to fit
   152  		// the operation
   153  		if operation.memorySize != nil {
   154  			memorySize = operation.memorySize(stack)
   155  			// memory is expanded in words of 32 bytes. Gas
   156  			// is also calculated in words.
   157  			memorySize.Mul(toWordSize(memorySize), big.NewInt(32))
   158  		}
   159  
   160  		if !evm.cfg.DisableGasMetering {
   161  			// consume the gas and return an error if not enough gas is available.
   162  			// cost is explicitly set so that the capture state defer method cas get the proper cost
   163  			cost = operation.gasCost(evm.gasTable, evm.env, contract, stack, mem, memorySize)
   164  			if !contract.UseGas(cost) {
   165  				return nil, ErrOutOfGas
   166  			}
   167  		}
   168  		if memorySize != nil {
   169  			mem.Resize(memorySize.Uint64())
   170  		}
   171  
   172  		if evm.cfg.Debug {
   173  			evm.cfg.Tracer.CaptureState(evm.env, pc, op, contract.Gas, cost, mem, stack, contract, evm.env.depth, err)
   174  		}
   175  
   176  		// execute the operation
   177  		res, err := operation.execute(&pc, evm.env, contract, mem, stack)
   178  		switch {
   179  		case err != nil:
   180  			return nil, err
   181  		case operation.halts:
   182  			return res, nil
   183  		case !operation.jumps:
   184  			pc++
   185  		}
   186  	}
   187  	return nil, nil
   188  }