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