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