以太坊源码解读(6)以太坊VM源码解读之指令集与操作码解释器

以太坊指令集与操作码解释器

EVM事实是个堆栈机器。指令可能会使用栈上的数值作为参数,也会将值作为结果压入栈中,而指令的构成是由我们所编写的合约的ABI文件所生产,大致结构为

编写合约 > 生成ABI > 解析ABI得出指令集 > eth会将指令通过core/vm/opcodes.go文件中的操作码映射,映射成操作码集 > 生成一个operation[256] >

type operation struct {
   
    //下列函数在core/vm/jump_table.go文件中定义了模板
   //操作函数
   execute executionFunc 
   // gas函数,返回执行所需的gas
   gasCost gasFunc
   // 验证操作的堆栈(大小)
   validateStack stackValidationFunc
   // 返回操作所需的内存大小
   memorySize memorySizeFunc

   halts   bool // 指示操作是否应停止进一步执行
   jumps   bool // 指示程序计数器是否不应递增
   writes  bool // 确定此操作是否为状态修改操作
   valid   bool // 指示检索的操作是否有效和已知
   reverts bool // 确定操作是否恢复状态(隐式停止)
   returns bool // 确定操作是否设置返回的数据内容
}
type (
   executionFunc       func(pc *uint64, interpreter *EVMInterpreter, contract *Contract, 							memory *Memory, stack *Stack) ([]byte, error)
   gasFunc             func(params.GasTable, *EVM, *Contract, *Stack, *Memory, uint64) 							(uint64, error) 
   stackValidationFunc func(*Stack) error
   memorySizeFunc      func(*Stack) *big.Int
)

根据当前的版本选择对应的操作码生成函数

var (
	frontierInstructionSet       = newFrontierInstructionSet()
	homesteadInstructionSet      = newHomesteadInstructionSet()
	byzantiumInstructionSet      = newByzantiumInstructionSet()
	constantinopleInstructionSet = newConstantinopleInstructionSet()
)

例如:家园版本

//家园阶段可以执行的指令。
func newHomesteadInstructionSet() [256]operation {
   
   instructionSet := newFrontierInstructionSet()
   instructionSet[DELEGATECALL] = operation{
   
      execute:       opDelegateCall,
      gasCost:       gasDelegateCall,
      validateStack: makeStackFunc(6, 1),
      memorySize:    memoryDelegateCall,
      valid:         true,
      returns:       true,
   }
   return instructionSet
}

这样,对evm的操作实际上是操作码对程序的操作。

core/vm/opcodes.go:部分代码,实际上就是一堆的常量操作符,这些操作符会在core/vm/jump_table.go这个文件中映射成对应的操作函数,用于执行

const (
   STOP OpCode = iota
   ADD
   MUL
   SUB
   DIV
   SDIV
   MOD
   SMOD
   ADDMOD
   MULMOD
   EXP
   SIGNEXTEND
)

// 0x10 range - comparison ops.
const (
   LT OpCode = iota + 0x10
   GT
   SLT
   SGT
   EQ
   ISZERO
   AND
   OR
   XOR
   NOT
   BYTE
   SHL
   SHR
   SAR

   SHA3 = 0x20
)

// 0x30 range - closure state.
const (
   ADDRESS OpCode = 0x30 + iota
   BALANCE
   ORIGIN
   CALLER
   CALLVALUE
   CALLDATALOAD
   CALLDATASIZE
   CALLDATACOPY
   CODESIZE
   CODECOPY
   GASPRICE
   EXTCODESIZE
   EXTCODECOPY
   RETURNDATASIZE
   RETURNDATACOPY
   EXTCODEHASH
)

// 0x40 range - block operations.
const (
   BLOCKHASH OpCode = 0x40 + iota
   COINBASE
   TIMESTAMP
   NUMBER
   DIFFICULTY
   GASLIMIT
)

// 0x50 range - 'storage' and execution.
const (
   POP OpCode = 0x50 + iota
   MLOAD
   MSTORE
   MSTORE8
   SLOAD
   SSTORE
   JUMP
   JUMPI
   PC
   MSIZE
   GAS
   JUMPDEST
)

// 0x60 range.
const (
   PUSH1 OpCode = 0x60 + iota
   PUSH2
   PUSH3
   PUSH4
   PUSH5
   PUSH6
   PUSH7
   PUSH8
   PUSH9
   PUSH10
   PUSH11
   PUSH12
   PUSH13
   PUSH14
   PUSH15
   PUSH16
   PUSH17
   PUSH18
   PUSH19
   PUSH20
   PUSH21
   PUSH22
   PUSH23
   PUSH24
   PUSH25
   PUSH26
   PUSH27
   PUSH28
   PUSH29
   PUSH30
   PUSH31
   PUSH32
   DUP1
   DUP2
   DUP3
   DUP4
   DUP5
   DUP6
   DUP7
   DUP8
   DUP9
   DUP10
   DUP11
   DUP12
   DUP13
   DUP14
   DUP15
   DUP16
   SWAP1
   SWAP2
   SWAP3
   SWAP4
   SWAP5
   SWAP6
   SWAP7
   SWAP8
   SWAP9
   SWAP10
   SWAP11
   SWAP12
   SWAP13
   SWAP14
   SWAP15
   SWAP16
)

// 0xa0 range - logging ops.
const (
   LOG0 OpCode = 0xa0 + iota
   LOG1
   LOG2
   LOG3
   LOG4
)

// unofficial opcodes used for parsing.
const (
   PUSH OpCode = 0xb0 + iota
   DUP
   SWAP
)

core/vm/jump_table.go:都是对操作码的映射解释,可以将jump理解为操作码解释器,将opcodes理解为指令解释器

func newFrontierInstructionSet() [256]operation {
   
   return [256]operation{
   
      STOP: {
   
         execute:       opStop,
         gasCost:       constGasFunc(0),
         validateStack: makeStackFunc(0, 0),
         halts:         true,
         valid:         true,
      },
      ADD: {
   
         execute:       opAdd,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      MUL: {
   
         execute:       opMul,
         gasCost:       constGasFunc(GasFastStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      SUB: {
   
         execute:       opSub,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      DIV: {
   
         execute:       opDiv,
         gasCost:       constGasFunc(GasFastStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      SDIV: {
   
         execute:       opSdiv,
         gasCost:       constGasFunc(GasFastStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      MOD: {
   
         execute:       opMod,
         gasCost:       constGasFunc(GasFastStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      SMOD: {
   
         execute:       opSmod,
         gasCost:       constGasFunc(GasFastStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      ADDMOD: {
   
         execute:       opAddmod,
         gasCost:       constGasFunc(GasMidStep),
         validateStack: makeStackFunc(3, 1),
         valid:         true,
      },
      MULMOD: {
   
         execute:       opMulmod,
         gasCost:       constGasFunc(GasMidStep),
         validateStack: makeStackFunc(3, 1),
         valid:         true,
      },
      EXP: {
   
         execute:       opExp,
         gasCost:       gasExp,
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      SIGNEXTEND: {
   
         execute:       opSignExtend,
         gasCost:       constGasFunc(GasFastStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      LT: {
   
         execute:       opLt,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      GT: {
   
         execute:       opGt,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      SLT: {
   
         execute:       opSlt,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      SGT: {
   
         execute:       opSgt,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      EQ: {
   
         execute:       opEq,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      ISZERO: {
   
         execute:       opIszero,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(1, 1),
         valid:         true,
      },
      AND: {
   
         execute:       opAnd,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      XOR: {
   
         execute:       opXor,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      OR: {
   
         execute:       opOr,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      NOT: {
   
         execute:       opNot,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(1, 1),
         valid:         true,
      },
      BYTE: {
   
         execute:       opByte,
         gasCost:       constGasFunc(GasFastestStep),
         validateStack: makeStackFunc(2, 1),
         valid:         true,
      },
      SHA3: {
   
         execute:       opSha3,
         gasCost:       gasSha3,
         validateStack: makeStackFunc(2, 1),
         memorySize:    memorySha3,
         valid:         true,
      },
      ADDRESS: {
   
         execute:       opAddress,
         gasCost:       constGasFunc(GasQuickStep),
         validateStack: makeStackFunc(0, 1),
         valid:         true,
      },
      BALANCE: {
   
         execute:       opBalance,
         gasCost:       gasBalance,
         validateStack: makeStackFunc(1
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值