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 }