github.com/snowblossomcoin/go-ethereum@v1.9.25/core/vm/interpreter.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 "hash" 21 "sync/atomic" 22 23 "github.com/ethereum/go-ethereum/common" 24 "github.com/ethereum/go-ethereum/common/math" 25 "github.com/ethereum/go-ethereum/log" 26 ) 27 28 // Config are the configuration options for the Interpreter 29 type Config struct { 30 Debug bool // Enables debugging 31 Tracer Tracer // Opcode logger 32 NoRecursion bool // Disables call, callcode, delegate call and create 33 EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages 34 35 JumpTable [256]*operation // EVM instruction table, automatically populated if unset 36 37 EWASMInterpreter string // External EWASM interpreter options 38 EVMInterpreter string // External EVM interpreter options 39 40 ExtraEips []int // Additional EIPS that are to be enabled 41 } 42 43 // Interpreter is used to run Ethereum based contracts and will utilise the 44 // passed environment to query external sources for state information. 45 // The Interpreter will run the byte code VM based on the passed 46 // configuration. 47 type Interpreter interface { 48 // Run loops and evaluates the contract's code with the given input data and returns 49 // the return byte-slice and an error if one occurred. 50 Run(contract *Contract, input []byte, static bool) ([]byte, error) 51 // CanRun tells if the contract, passed as an argument, can be 52 // run by the current interpreter. This is meant so that the 53 // caller can do something like: 54 // 55 // ```golang 56 // for _, interpreter := range interpreters { 57 // if interpreter.CanRun(contract.code) { 58 // interpreter.Run(contract.code, input) 59 // } 60 // } 61 // ``` 62 CanRun([]byte) bool 63 } 64 65 // callCtx contains the things that are per-call, such as stack and memory, 66 // but not transients like pc and gas 67 type callCtx struct { 68 memory *Memory 69 stack *Stack 70 rstack *ReturnStack 71 contract *Contract 72 } 73 74 // keccakState wraps sha3.state. In addition to the usual hash methods, it also supports 75 // Read to get a variable amount of data from the hash state. Read is faster than Sum 76 // because it doesn't copy the internal state, but also modifies the internal state. 77 type keccakState interface { 78 hash.Hash 79 Read([]byte) (int, error) 80 } 81 82 // EVMInterpreter represents an EVM interpreter 83 type EVMInterpreter struct { 84 evm *EVM 85 cfg Config 86 87 hasher keccakState // Keccak256 hasher instance shared across opcodes 88 hasherBuf common.Hash // Keccak256 hasher result array shared aross opcodes 89 90 readOnly bool // Whether to throw on stateful modifications 91 returnData []byte // Last CALL's return data for subsequent reuse 92 } 93 94 // NewEVMInterpreter returns a new instance of the Interpreter. 95 func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { 96 // We use the STOP instruction whether to see 97 // the jump table was initialised. If it was not 98 // we'll set the default jump table. 99 if cfg.JumpTable[STOP] == nil { 100 var jt JumpTable 101 switch { 102 case evm.chainRules.IsYoloV2: 103 jt = yoloV2InstructionSet 104 case evm.chainRules.IsIstanbul: 105 jt = istanbulInstructionSet 106 case evm.chainRules.IsConstantinople: 107 jt = constantinopleInstructionSet 108 case evm.chainRules.IsByzantium: 109 jt = byzantiumInstructionSet 110 case evm.chainRules.IsEIP158: 111 jt = spuriousDragonInstructionSet 112 case evm.chainRules.IsEIP150: 113 jt = tangerineWhistleInstructionSet 114 case evm.chainRules.IsHomestead: 115 jt = homesteadInstructionSet 116 default: 117 jt = frontierInstructionSet 118 } 119 for i, eip := range cfg.ExtraEips { 120 if err := EnableEIP(eip, &jt); err != nil { 121 // Disable it, so caller can check if it's activated or not 122 cfg.ExtraEips = append(cfg.ExtraEips[:i], cfg.ExtraEips[i+1:]...) 123 log.Error("EIP activation failed", "eip", eip, "error", err) 124 } 125 } 126 cfg.JumpTable = jt 127 } 128 129 return &EVMInterpreter{ 130 evm: evm, 131 cfg: cfg, 132 } 133 } 134 135 // Run loops and evaluates the contract's code with the given input data and returns 136 // the return byte-slice and an error if one occurred. 137 // 138 // It's important to note that any errors returned by the interpreter should be 139 // considered a revert-and-consume-all-gas operation except for 140 // ErrExecutionReverted which means revert-and-keep-gas-left. 141 func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) { 142 143 // Increment the call depth which is restricted to 1024 144 in.evm.depth++ 145 defer func() { in.evm.depth-- }() 146 147 // Make sure the readOnly is only set if we aren't in readOnly yet. 148 // This makes also sure that the readOnly flag isn't removed for child calls. 149 if readOnly && !in.readOnly { 150 in.readOnly = true 151 defer func() { in.readOnly = false }() 152 } 153 154 // Reset the previous call's return data. It's unimportant to preserve the old buffer 155 // as every returning call will return new data anyway. 156 in.returnData = nil 157 158 // Don't bother with the execution if there's no code. 159 if len(contract.Code) == 0 { 160 return nil, nil 161 } 162 163 var ( 164 op OpCode // current opcode 165 mem = NewMemory() // bound memory 166 stack = newstack() // local stack 167 returns = newReturnStack() // local returns stack 168 callContext = &callCtx{ 169 memory: mem, 170 stack: stack, 171 rstack: returns, 172 contract: contract, 173 } 174 // For optimisation reason we're using uint64 as the program counter. 175 // It's theoretically possible to go above 2^64. The YP defines the PC 176 // to be uint256. Practically much less so feasible. 177 pc = uint64(0) // program counter 178 cost uint64 179 // copies used by tracer 180 pcCopy uint64 // needed for the deferred Tracer 181 gasCopy uint64 // for Tracer to log gas remaining before execution 182 logged bool // deferred Tracer should ignore already logged steps 183 res []byte // result of the opcode execution function 184 ) 185 // Don't move this deferrred function, it's placed before the capturestate-deferred method, 186 // so that it get's executed _after_: the capturestate needs the stacks before 187 // they are returned to the pools 188 defer func() { 189 returnStack(stack) 190 returnRStack(returns) 191 }() 192 contract.Input = input 193 194 if in.cfg.Debug { 195 defer func() { 196 if err != nil { 197 if !logged { 198 in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, returns, in.returnData, contract, in.evm.depth, err) 199 } else { 200 in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, returns, contract, in.evm.depth, err) 201 } 202 } 203 }() 204 } 205 // The Interpreter main run loop (contextual). This loop runs until either an 206 // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during 207 // the execution of one of the operations or until the done flag is set by the 208 // parent context. 209 steps := 0 210 for { 211 steps++ 212 if steps%1000 == 0 && atomic.LoadInt32(&in.evm.abort) != 0 { 213 break 214 } 215 if in.cfg.Debug { 216 // Capture pre-execution values for tracing. 217 logged, pcCopy, gasCopy = false, pc, contract.Gas 218 } 219 220 // Get the operation from the jump table and validate the stack to ensure there are 221 // enough stack items available to perform the operation. 222 op = contract.GetOp(pc) 223 operation := in.cfg.JumpTable[op] 224 if operation == nil { 225 return nil, &ErrInvalidOpCode{opcode: op} 226 } 227 // Validate stack 228 if sLen := stack.len(); sLen < operation.minStack { 229 return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack} 230 } else if sLen > operation.maxStack { 231 return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack} 232 } 233 // If the operation is valid, enforce and write restrictions 234 if in.readOnly && in.evm.chainRules.IsByzantium { 235 // If the interpreter is operating in readonly mode, make sure no 236 // state-modifying operation is performed. The 3rd stack item 237 // for a call operation is the value. Transferring value from one 238 // account to the others means the state is modified and should also 239 // return with an error. 240 if operation.writes || (op == CALL && stack.Back(2).Sign() != 0) { 241 return nil, ErrWriteProtection 242 } 243 } 244 // Static portion of gas 245 cost = operation.constantGas // For tracing 246 if !contract.UseGas(operation.constantGas) { 247 return nil, ErrOutOfGas 248 } 249 250 var memorySize uint64 251 // calculate the new memory size and expand the memory to fit 252 // the operation 253 // Memory check needs to be done prior to evaluating the dynamic gas portion, 254 // to detect calculation overflows 255 if operation.memorySize != nil { 256 memSize, overflow := operation.memorySize(stack) 257 if overflow { 258 return nil, ErrGasUintOverflow 259 } 260 // memory is expanded in words of 32 bytes. Gas 261 // is also calculated in words. 262 if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { 263 return nil, ErrGasUintOverflow 264 } 265 } 266 // Dynamic portion of gas 267 // consume the gas and return an error if not enough gas is available. 268 // cost is explicitly set so that the capture state defer method can get the proper cost 269 if operation.dynamicGas != nil { 270 var dynamicCost uint64 271 dynamicCost, err = operation.dynamicGas(in.evm, contract, stack, mem, memorySize) 272 cost += dynamicCost // total cost, for debug tracing 273 if err != nil || !contract.UseGas(dynamicCost) { 274 return nil, ErrOutOfGas 275 } 276 } 277 if memorySize > 0 { 278 mem.Resize(memorySize) 279 } 280 281 if in.cfg.Debug { 282 in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, returns, in.returnData, contract, in.evm.depth, err) 283 logged = true 284 } 285 286 // execute the operation 287 res, err = operation.execute(&pc, in, callContext) 288 // if the operation clears the return data (e.g. it has returning data) 289 // set the last return to the result of the operation. 290 if operation.returns { 291 in.returnData = common.CopyBytes(res) 292 } 293 294 switch { 295 case err != nil: 296 return nil, err 297 case operation.reverts: 298 return res, ErrExecutionReverted 299 case operation.halts: 300 return res, nil 301 case !operation.jumps: 302 pc++ 303 } 304 } 305 return nil, nil 306 } 307 308 // CanRun tells if the contract, passed as an argument, can be 309 // run by the current interpreter. 310 func (in *EVMInterpreter) CanRun(code []byte) bool { 311 return true 312 }