github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/core/vm/interpreter.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2014 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package vm 26 27 import ( 28 "fmt" 29 "sync/atomic" 30 31 "github.com/ethereum/go-ethereum/common/math" 32 "github.com/ethereum/go-ethereum/params" 33 ) 34 35 //config是解释器的配置选项 36 type Config struct { 37 //启用调试的调试解释器选项 38 Debug bool 39 //跟踪程序是操作代码记录器 40 Tracer Tracer 41 //无加密禁用的解释程序调用,调用代码, 42 //委派呼叫并创建。 43 NoRecursion bool 44 //启用sha3/keccak preimages的录制 45 EnablePreimageRecording bool 46 //JumpTable包含EVM指令表。这个 47 //可能未初始化,并将设置为默认值 48 //表。 49 JumpTable [256]operation 50 } 51 52 //解释器用于运行基于以太坊的合同,并将使用 53 //已传递环境以查询外部源以获取状态信息。 54 //解释器将根据传递的 55 //配置。 56 type Interpreter interface { 57 //运行循环并使用给定的输入数据评估契约的代码并返回 58 //返回字节切片,如果出现错误,则返回一个错误。 59 Run(contract *Contract, input []byte) ([]byte, error) 60 //canrun告诉作为参数传递的契约是否可以 61 //由当前解释器运行。这意味着 62 //呼叫方可以执行以下操作: 63 // 64 //'Gangang' 65 //对于u,解释器:=测距解释器 66 //if explorer.canrun(contract.code) 67 //解释器.run(contract.code,input) 68 //} 69 //} 70 //` ` 71 CanRun([]byte) bool 72 //如果解释器处于只读模式,is read only将报告。 73 IsReadOnly() bool 74 //setreadonly在解释器中设置(或取消设置)只读模式。 75 SetReadOnly(bool) 76 } 77 78 //evm interpreter表示evm解释器 79 type EVMInterpreter struct { 80 evm *EVM 81 cfg Config 82 gasTable params.GasTable 83 intPool *intPool 84 85 readOnly bool //是否进行状态修改 86 returnData []byte //最后一次调用的返回数据供后续重用 87 } 88 89 //NewEvminterPreter返回解释器的新实例。 90 func NewEVMInterpreter(evm *EVM, cfg Config) *EVMInterpreter { 91 //我们使用停止指令是否看到 92 //跳转表已初始化。如果不是 93 //我们将设置默认跳转表。 94 if !cfg.JumpTable[STOP].valid { 95 switch { 96 case evm.ChainConfig().IsConstantinople(evm.BlockNumber): 97 cfg.JumpTable = constantinopleInstructionSet 98 case evm.ChainConfig().IsByzantium(evm.BlockNumber): 99 cfg.JumpTable = byzantiumInstructionSet 100 case evm.ChainConfig().IsHomestead(evm.BlockNumber): 101 cfg.JumpTable = homesteadInstructionSet 102 default: 103 cfg.JumpTable = frontierInstructionSet 104 } 105 } 106 107 return &EVMInterpreter{ 108 evm: evm, 109 cfg: cfg, 110 gasTable: evm.ChainConfig().GasTable(evm.BlockNumber), 111 } 112 } 113 114 func (in *EVMInterpreter) enforceRestrictions(op OpCode, operation operation, stack *Stack) error { 115 if in.evm.chainRules.IsByzantium { 116 if in.readOnly { 117 //如果解释器在只读模式下工作,请确保否 118 //执行状态修改操作。第三个堆栈项 119 //对于一个调用操作来说是值。从一个转移价值 120 //对其他人的帐户意味着状态被修改,并且应该 121 //返回时出错。 122 if operation.writes || (op == CALL && stack.Back(2).BitLen() > 0) { 123 return errWriteProtection 124 } 125 } 126 } 127 return nil 128 } 129 130 //运行循环并使用给定的输入数据评估契约的代码并返回 131 //返回字节切片,如果出现错误,则返回一个错误。 132 // 133 //需要注意的是,解释程序返回的任何错误都应该 134 //被认为是一种还原和消耗除 135 //errExecutionReverted,这意味着还原并保留气体。 136 func (in *EVMInterpreter) Run(contract *Contract, input []byte) (ret []byte, err error) { 137 if in.intPool == nil { 138 in.intPool = poolOfIntPools.get() 139 defer func() { 140 poolOfIntPools.put(in.intPool) 141 in.intPool = nil 142 }() 143 } 144 145 //增加限制为1024的调用深度 146 in.evm.depth++ 147 defer func() { in.evm.depth-- }() 148 149 //重置上一个呼叫的返回数据。保留旧的缓冲区并不重要 150 //因为每次回电都会返回新的数据。 151 in.returnData = nil 152 153 //如果没有代码,就不必费心执行。 154 if len(contract.Code) == 0 { 155 return nil, nil 156 } 157 158 var ( 159 op OpCode //当前操作码 160 mem = NewMemory() //绑定内存 161 stack = newstack() //本地栈 162 //为了优化,我们使用uint64作为程序计数器。 163 //理论上可以超过2^64。YP定义PC 164 //为UIT2525。实际上不那么可行。 165 pc = uint64(0) //程序计数器 166 cost uint64 167 //追踪器使用的副本 168 pcCopy uint64 //延期追踪器需要 169 gasCopy uint64 //用于示踪剂记录执行前的剩余气体 170 logged bool //延迟跟踪程序应忽略已记录的步骤 171 ) 172 contract.Input = input 173 174 //在执行停止时将堆栈作为int池回收 175 defer func() { in.intPool.put(stack.data...) }() 176 177 if in.cfg.Debug { 178 defer func() { 179 if err != nil { 180 if !logged { 181 in.cfg.Tracer.CaptureState(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) 182 } else { 183 in.cfg.Tracer.CaptureFault(in.evm, pcCopy, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) 184 } 185 } 186 }() 187 } 188 //解释器主运行循环(上下文)。此循环运行到 189 //执行显式停止、返回或自毁函数,期间发生错误 190 //执行一个操作,或直到完成标志由 191 //父上下文。 192 for atomic.LoadInt32(&in.evm.abort) == 0 { 193 if in.cfg.Debug { 194 //捕获执行前的值以进行跟踪。 195 logged, pcCopy, gasCopy = false, pc, contract.Gas 196 } 197 198 //从跳转表中获取操作并验证堆栈以确保 199 //有足够的堆栈项可用于执行该操作。 200 op = contract.GetOp(pc) 201 operation := in.cfg.JumpTable[op] 202 if !operation.valid { 203 return nil, fmt.Errorf("invalid opcode 0x%x", int(op)) 204 } 205 if err := operation.validateStack(stack); err != nil { 206 return nil, err 207 } 208 //如果操作有效,则强制执行并写入限制 209 if err := in.enforceRestrictions(op, operation, stack); err != nil { 210 return nil, err 211 } 212 213 var memorySize uint64 214 //计算新内存大小并展开内存以适应 215 //手术 216 if operation.memorySize != nil { 217 memSize, overflow := bigUint64(operation.memorySize(stack)) 218 if overflow { 219 return nil, errGasUintOverflow 220 } 221 //内存以32字节的字扩展。气体 222 //也用文字计算。 223 if memorySize, overflow = math.SafeMul(toWordSize(memSize), 32); overflow { 224 return nil, errGasUintOverflow 225 } 226 } 227 //如果没有足够的气体可用,则消耗气体并返回错误。 228 //明确设置成本,以便捕获状态延迟方法可以获得适当的成本 229 cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize) 230 if err != nil || !contract.UseGas(cost) { 231 return nil, ErrOutOfGas 232 } 233 if memorySize > 0 { 234 mem.Resize(memorySize) 235 } 236 237 if in.cfg.Debug { 238 in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err) 239 logged = true 240 } 241 242 //执行操作 243 res, err := operation.execute(&pc, in, contract, mem, stack) 244 //VerifyPool是一个生成标志。池验证确保完整性 245 //通过将值与默认值进行比较来获得整数池的值。 246 if verifyPool { 247 verifyIntegerPool(in.intPool) 248 } 249 //如果操作清除返回数据(例如,它有返回数据) 250 //将最后一个返回设置为操作结果。 251 if operation.returns { 252 in.returnData = res 253 } 254 255 switch { 256 case err != nil: 257 return nil, err 258 case operation.reverts: 259 return res, errExecutionReverted 260 case operation.halts: 261 return res, nil 262 case !operation.jumps: 263 pc++ 264 } 265 } 266 return nil, nil 267 } 268 269 //canrun告诉作为参数传递的契约是否可以 270 //由当前解释器运行。 271 func (in *EVMInterpreter) CanRun(code []byte) bool { 272 return true 273 } 274 275 //如果解释器处于只读模式,is read only将报告。 276 func (in *EVMInterpreter) IsReadOnly() bool { 277 return in.readOnly 278 } 279 280 //setreadonly在解释器中设置(或取消设置)只读模式。 281 func (in *EVMInterpreter) SetReadOnly(ro bool) { 282 in.readOnly = ro 283 }