github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/vm/interpreter.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:36</date> 10 //</624450082577584128> 11 12 13 package vm 14 15 import ( 16 "fmt" 17 "hash" 18 "sync/atomic" 19 20 "github.com/ethereum/go-ethereum/common" 21 "github.com/ethereum/go-ethereum/common/math" 22 "github.com/ethereum/go-ethereum/params" 23 ) 24 25 //config是解释器的配置选项 26 type Config struct { 27 //启用调试的调试解释器选项 28 Debug bool 29 //跟踪程序是操作代码记录器 30 Tracer Tracer 31 //无加密禁用的解释程序调用,调用代码, 32 //委派呼叫并创建。 33 NoRecursion bool 34 //启用sha3/keccak preimages的录制 35 EnablePreimageRecording bool 36 //JumpTable包含EVM指令表。这个 37 //可能未初始化,并将设置为默认值 38 //表。 39 JumpTable [256]operation 40 41 //ewasm解释器的类型 42 EWASMInterpreter string 43 //EVM解释器的类型 44 EVMInterpreter string 45 } 46 47 //解释器用于运行基于以太坊的合同,并将使用 48 //passed environment to query external sources for state information. 49 //解释器将根据传递的 50 //配置。 51 type Interpreter interface { 52 //运行循环并使用给定的输入数据评估契约的代码并返回 53 //返回字节切片,如果出现错误,则返回一个错误。 54 Run(contract *Contract, input []byte, static bool) ([]byte, error) 55 //canrun告诉作为参数传递的契约是否可以 56 //由当前解释器运行。这意味着 57 //呼叫方可以执行以下操作: 58 // 59 //'Gangang' 60 //对于u,解释器:=测距解释器 61 //if explorer.canrun(contract.code) 62 //解释器.run(contract.code,input) 63 //} 64 //} 65 //` ` 66 CanRun([]byte) bool 67 } 68 69 //keccakstate包裹sha3.state。除了通常的哈希方法外,它还支持 70 //读取以从哈希状态获取可变数量的数据。读取比求和快 71 //因为它不复制内部状态,而是修改内部状态。 72 type keccakState interface { 73 hash.Hash 74 Read([]byte) (int, error) 75 } 76 77 //evm interpreter表示evm解释器 78 type EVMInterpreter struct { 79 evm *EVM 80 cfg Config 81 gasTable params.GasTable 82 83 intPool *intPool 84 85 hasher keccakState //keccak256哈希实例跨操作码共享 86 hasherBuf common.Hash //keccak256哈希结果数组共享aross操作码 87 88 readOnly bool //是否进行状态修改 89 returnData []byte //最后一次调用的返回数据供后续重用 90 } 91 92 //NewEvminterPreter返回解释器的新实例。 93 func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { 94 //我们使用停止指令是否看到 95 //跳转表已初始化。如果不是 96 //我们将设置默认跳转表。 97 if !cfg.JumpTable[STOP].valid { 98 switch { 99 case evm.ChainConfig().IsConstantinople(evm.BlockNumber): 100 cfg.JumpTable = constantinopleInstructionSet 101 case evm.ChainConfig().IsByzantium(evm.BlockNumber): 102 cfg.JumpTable = byzantiumInstructionSet 103 case evm.ChainConfig().IsHomestead(evm.BlockNumber): 104 cfg.JumpTable = homesteadInstructionSet 105 default: 106 cfg.JumpTable = frontierInstructionSet 107 } 108 } 109 110 return &EVMInterpreter{ 111 evm: evm, 112 cfg: cfg, 113 gasTable: evm.ChainConfig().GasTable(evm.BlockNumber), 114 } 115 } 116 117 func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error { 118 if in.evm.chainRules.IsByzantium { 119 if in.readOnly { 120 //如果解释器在只读模式下工作,请确保否 121 //执行状态修改操作。第三个堆栈项 122 //对于一个调用操作来说是值。从一个转移价值 123 //对其他人的帐户意味着状态被修改,并且应该 124 //返回时出错。 125 if operation.writes || (op == CALL && stack.Back(2).BitLen() > 0) { 126 return errWriteProtection 127 } 128 } 129 } 130 return nil 131 } 132 133 //运行循环并使用给定的输入数据评估契约的代码并返回 134 //返回字节切片,如果出现错误,则返回一个错误。 135 // 136 //需要注意的是,解释程序返回的任何错误都应该 137 //被认为是一种还原和消耗除 138 //errExecutionReverted,这意味着还原并保留气体。 139 func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) { 140 if in.intPool == nil { 141 in.intPool = poolOfIntPools.get() 142 defer func() { 143 poolOfIntPools.put(in.intPool) 144 in.intPool = nil 145 }() 146 } 147 148 //增加限制为1024的调用深度 149 in.evm.depth++ 150 defer func() { in.evm.depth-- }() 151 152 //确保仅当我们还未处于只读状态时才设置只读。 153 //这还确保不会删除子调用的只读标志。 154 if readOnly && !in.readOnly { 155 in.readOnly = true 156 defer func() { in.readOnly = false }() 157 } 158 159 //重置上一个呼叫的返回数据。保留旧的缓冲区并不重要 160 //因为每次回电都会返回新的数据。 161 in.returnData = nil 162 163 //如果没有代码,就不必费心执行。 164 if len(contract.Code) == 0 { 165 return nil, nil 166 } 167 168 var ( 169 op OpCode //当前操作码 170 mem = NewMemory() //绑定内存 171 stack = newstack() //本地栈 172 //为了优化,我们使用uint64作为程序计数器。 173 //理论上可以超过2^64。YP定义PC 174 //为UIT2525。实际上不那么可行。 175 pc = uint64(0) //程序计数器 176 cost uint64 177 //追踪器使用的副本 178 pcCopy uint64 //延期追踪器需要 179 gasCopy uint64 //用于示踪剂记录执行前的剩余气体 180 logged bool //延迟跟踪程序应忽略已记录的步骤 181 ) 182 contract.Input = input 183 184 //在执行停止时将堆栈作为int池回收 185 defer func() { in.intPool.put(stack.data...) }() 186 187 if in.cfg.Debug { 188 defer func() { 189 if err != nil { 190 if !logged { 191 in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) 192 } else { 193 in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) 194 } 195 } 196 }() 197 } 198 //解释器主运行循环(上下文)。此循环运行到 199 //执行显式停止、返回或自毁函数,期间发生错误 200 //执行一个操作,或直到完成标志由 201 //父上下文。 202 for atomic.LoadInt32(&in.evm.abort) == 0 { 203 if in.cfg.Debug { 204 //捕获执行前的值以进行跟踪。 205 logged, pcCopy, gasCopy = false, pc, contract.Gas 206 } 207 208 //从跳转表中获取操作并验证堆栈以确保 209 //有足够的堆栈项可用于执行该操作。 210 op = contract.GetOp(pc) 211 operation := in.cfg.JumpTable[op] 212 if !operation.valid { 213 return nil, fmt.Errorf("invalid opcode 0x%x", int(op)) 214 } 215 if err := operation.validateStack(stack); err != nil { 216 return nil, err 217 } 218 //如果操作有效,则强制执行并写入限制 219 if err := in.enforceRestrictions(op, operation, stack); err != nil { 220 return nil, err 221 } 222 223 var memorySize uint64 224 //计算新内存大小并展开内存以适应 225 //手术 226 if operation.memorySize != nil { 227 memSize, overflow := bigUint64(operation.memorySize(stack)) 228 if overflow { 229 return nil, errGasUintOverflow 230 } 231 //内存以32字节的字扩展。气体 232 //也用文字计算。 233 if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { 234 return nil, errGasUintOverflow 235 } 236 } 237 //如果没有足够的气体可用,则消耗气体并返回错误。 238 //明确设置成本,以便捕获状态延迟方法可以获得适当的成本 239 cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize) 240 if err != nil || !contract.UseGas(cost) { 241 return nil, ErrOutOfGas 242 } 243 if memorySize > 0 { 244 mem.Resize(memorySize) 245 } 246 247 if in.cfg.Debug { 248 in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) 249 logged = true 250 } 251 252 //执行操作 253 res, err := operation.execute(&pc, in, contract, mem, stack) 254 //VerifyPool是一个生成标志。池验证确保完整性 255 //通过将值与默认值进行比较来获得整数池的值。 256 if verifyPool { 257 verifyIntegerPool(in.intPool) 258 } 259 //如果操作清除返回数据(例如,它有返回数据) 260 //将最后一个返回设置为操作结果。 261 if operation.returns { 262 in.returnData = 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告诉作为参数传递的契约是否可以 280 //由当前解释器运行。 281 func (in *EVMInterpreter) CanRun(code []byte) bool { 282 return true 283 } 284