github.com/ccm-chain/ccmchain@v1.0.0/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/ccm-chain/ccmchain/common" 24 "github.com/ccm-chain/ccmchain/common/math" 25 "github.com/ccm-chain/ccmchain/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.IsConstantinople: 103 jt = constantinopleInstructionSet 104 case evm.chainRules.IsByzantium: 105 jt = byzantiumInstructionSet 106 case evm.chainRules.IsEIP158: 107 jt = spuriousDragonInstructionSet 108 case evm.chainRules.IsEIP150: 109 jt = tangerineWhistleInstructionSet 110 case evm.chainRules.IsHomestead: 111 jt = homesteadInstructionSet 112 default: 113 jt = frontierInstructionSet 114 } 115 for i, eip := range cfg.ExtraEips { 116 if err := EnableEIP(eip, &jt); err != nil { 117 // Disable it, so caller can check if it's activated or not 118 cfg.ExtraEips = append(cfg.ExtraEips[:i], cfg.ExtraEips[i+1:]...) 119 log.Error("EIP activation failed", "eip", eip, "error", err) 120 } 121 } 122 cfg.JumpTable = jt 123 } 124 125 return &EVMInterpreter{ 126 evm: evm, 127 cfg: cfg, 128 } 129 } 130 131 // Run loops and evaluates the contract's code with the given input data and returns 132 // the return byte-slice and an error if one occurred. 133 // 134 // It's important to note that any errors returned by the interpreter should be 135 // considered a revert-and-consume-all-gas operation except for 136 // ErrExecutionReverted which means revert-and-keep-gas-left. 137 func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) { 138 139 // Increment the call depth which is restricted to 1024 140 in.evm.depth++ 141 defer func() { in.evm.depth-- }() 142 143 // Make sure the readOnly is only set if we aren't in readOnly yet. 144 // This makes also sure that the readOnly flag isn't removed for child calls. 145 if readOnly && !in.readOnly { 146 in.readOnly = true 147 defer func() { in.readOnly = false }() 148 } 149 150 // Reset the previous call's return data. It's unimportant to preserve the old buffer 151 // as every returning call will return new data anyway. 152 in.returnData = nil 153 154 // Don't bother with the execution if there's no code. 155 if len(contract.Code) == 0 { 156 return nil, nil 157 } 158 159 var ( 160 op OpCode // current opcode 161 mem = NewMemory() // bound memory 162 stack = newstack() // local stack 163 returns = newReturnStack() // local returns stack 164 callContext = &callCtx{ 165 memory: mem, 166 stack: stack, 167 rstack: returns, 168 contract: contract, 169 } 170 // For optimisation reason we're using uint64 as the program counter. 171 // It's theoretically possible to go above 2^64. The YP defines the PC 172 // to be uint256. Practically much less so feasible. 173 pc = uint64(0) // program counter 174 cost uint64 175 // copies used by tracer 176 pcCopy uint64 // needed for the deferred Tracer 177 gasCopy uint64 // for Tracer to log gas remaining before execution 178 logged bool // deferred Tracer should ignore already logged steps 179 res []byte // result of the opcode execution function 180 ) 181 // Don't move this deferrred function, it's placed before the capturestate-deferred method, 182 // so that it get's executed _after_: the capturestate needs the stacks before 183 // they are returned to the pools 184 defer func() { 185 returnStack(stack) 186 returnRStack(returns) 187 }() 188 contract.Input = input 189 190 if in.cfg.Debug { 191 defer func() { 192 if err != nil { 193 if !logged { 194 in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, returns, in.returnData, contract, in.evm.depth, err) 195 } else { 196 in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, returns, contract, in.evm.depth, err) 197 } 198 } 199 }() 200 } 201 // The Interpreter main run loop (contextual). This loop runs until either an 202 // explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during 203 // the execution of one of the operations or until the done flag is set by the 204 // parent context. 205 steps := 0 206 for { 207 steps++ 208 if steps%1000 == 0 && atomic.LoadInt32(&in.evm.abort) != 0 { 209 break 210 } 211 if in.cfg.Debug { 212 // Capture pre-execution values for tracing. 213 logged, pcCopy, gasCopy = false, pc, contract.Gas 214 } 215 216 // Get the operation from the jump table and validate the stack to ensure there are 217 // enough stack items available to perform the operation. 218 op = contract.GetOp(pc) 219 operation := in.cfg.JumpTable[op] 220 if operation == nil { 221 return nil, &ErrInvalidOpCode{opcode: op} 222 } 223 // Validate stack 224 if sLen := stack.len(); sLen < operation.minStack { 225 return nil, &ErrStackUnderflow{stackLen: sLen, required: operation.minStack} 226 } else if sLen > operation.maxStack { 227 return nil, &ErrStackOverflow{stackLen: sLen, limit: operation.maxStack} 228 } 229 // If the operation is valid, enforce and write restrictions 230 if in.readOnly && in.evm.chainRules.IsByzantium { 231 // If the interpreter is operating in readonly mode, make sure no 232 // state-modifying operation is performed. The 3rd stack item 233 // for a call operation is the value. Transferring value from one 234 // account to the others means the state is modified and should also 235 // return with an error. 236 if operation.writes || (op == CALL && stack.Back(2).Sign() != 0) { 237 return nil, ErrWriteProtection 238 } 239 } 240 // Static portion of gas 241 cost = operation.constantGas // For tracing 242 if !contract.UseGas(operation.constantGas) { 243 return nil, ErrOutOfGas 244 } 245 246 var memorySize uint64 247 // calculate the new memory size and expand the memory to fit 248 // the operation 249 // Memory check needs to be done prior to evaluating the dynamic gas portion, 250 // to detect calculation overflows 251 if operation.memorySize != nil { 252 memSize, overflow := operation.memorySize(stack) 253 if overflow { 254 return nil, ErrGasUintOverflow 255 } 256 // memory is expanded in words of 32 bytes. Gas 257 // is also calculated in words. 258 if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { 259 return nil, ErrGasUintOverflow 260 } 261 } 262 // Dynamic portion of gas 263 // consume the gas and return an error if not enough gas is available. 264 // cost is explicitly set so that the capture state defer method can get the proper cost 265 if operation.dynamicGas != nil { 266 var dynamicCost uint64 267 dynamicCost, err = operation.dynamicGas(in.evm, contract, stack, mem, memorySize) 268 cost += dynamicCost // total cost, for debug tracing 269 if err != nil || !contract.UseGas(dynamicCost) { 270 return nil, ErrOutOfGas 271 } 272 } 273 if memorySize > 0 { 274 mem.Resize(memorySize) 275 } 276 277 if in.cfg.Debug { 278 in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, returns, in.returnData, contract, in.evm.depth, err) 279 logged = true 280 } 281 282 // execute the operation 283 res, err = operation.execute(&pc, in, callContext) 284 // if the operation clears the return data (e.g. it has returning data) 285 // set the last return to the result of the operation. 286 if operation.returns { 287 in.returnData = common.CopyBytes(res) 288 } 289 290 switch { 291 case err != nil: 292 return nil, err 293 case operation.reverts: 294 return res, ErrExecutionReverted 295 case operation.halts: 296 return res, nil 297 case !operation.jumps: 298 pc++ 299 } 300 } 301 return nil, nil 302 } 303 304 // CanRun tells if the contract, passed as an argument, can be 305 // run by the current interpreter. 306 func (in *EVMInterpreter) CanRun(code []byte) bool { 307 return true 308 }