• Polygon zkEVM zkASM 与 以太坊虚拟机opcode 对应集合


    1. 引言

    结合:

    Polygon zkEVM的虚拟机支持的opcode为:【基本与以太坊虚拟机opcode对应】

    opcodenamecnt_arithcnt_binarycnt_mem_aligncnt_keccak_fcnt_padding_pgcnt_poseidon_gis_dynamic
    0x00STOP000000false
    0x01ADD010000false
    0x02MUL100000false
    0x03SUB010000false
    0x04DIV120000false
    0x05SDIV180000false
    0x06MOD120000false
    0x07SMOD180000false
    0x08ADDMOD130000false
    0x09MULMOD220000false
    0x0aEXP51210250000true
    0x0bSIGNEXTEND060000false
    0x10LT010000false
    0x11GT010000false
    0x12SLT010000false
    0x13SGT010000false
    0x14EQ010000false
    0x15ISZERO010000false
    0x16AND010000false
    0x17OR010000false
    0x18XOR010000false
    0x19NOT010000false
    0x1aBYTE240000false
    0x1bSHL120000false
    0x1cSHR130000false
    0x1dSAR2100000false
    0x20SHA319219322010true
    0x30ADDRESS000000false
    0x31BALANCE000009false
    0x32ORIGIN000000false
    0x33CALLER000000false
    0x34CALLVALUE000000false
    0x35CALLDATALOAD64660000true
    0x36CALLDATASIZE000000false
    0x37CALLDATACOPY---000true
    0x38CODESIZE00000252true
    0x39CODECOPY0--00255true
    0x3aGASPRICE000000false
    0x3bEXTCODESIZE00000255true
    0x3cEXTCODECOPY0--011510true
    0x3dRETURNDATASIZE010000false
    0x3eRETURNDATACOPY--2000true
    0x3fEXTCODEHASH00000255true
    0x40BLOCKHASH000109false
    0x41COINBASE000000false
    0x42TIMESTAMP000000false
    0x43NUMBER000000false
    0x44DIFFICULTY000000false
    0x45GASLIMIT000000false
    0x46CHAINID000000false
    0x47SELFBALANCE00000255true
    0x50POP000000false
    0x51MLOAD3232100255true
    0x52MSTORE3232100255true
    0x53MSTORE8321100255false
    0x54SLOAD00000255true
    0x55SSTORE0-000255true
    0x56JUMP0-0000true
    0x57JUMPI0-0000true
    0x59MSIZE130000false
    0x5aGAS000000false
    0x5bJUMPDEST000000false
    0x60PUSH1030000true
    0x61PUSH2040000true
    0x62PUSH3050000false
    0x63PUSH4020000false
    0x64PUSH5040000false
    0x65PUSH6050000false
    0x66PUSH7060000false
    0x67PUSH8030000false
    0x68PUSH9050000false
    0x69PUSH10060000false
    0x6aPUSH11070000false
    0x6bPUSH12040000false
    0x6cPUSH13060000false
    0x6dPUSH14070000false
    0x6ePUSH15080000false
    0x6fPUSH16050000false
    0x70PUSH17070000false
    0x71PUSH18080000false
    0x72PUSH19090000false
    0x73PUSH20060000false
    0x74PUSH21080000false
    0x75PUSH22090000false
    0x76PUSH230100000false
    0x77PUSH24070000false
    0x78PUSH25090000false
    0x79PUSH260100000false
    0x7aPUSH270110000false
    0x7bPUSH28080000false
    0x7cPUSH290100000false
    0x7dPUSH300110000false
    0x7ePUSH310120000false
    0x7fPUSH32090000false
    0x80DUP1000000false
    0x81DUP2000000false
    0x82DUP3000000false
    0x83DUP4000000false
    0x84DUP5000000false
    0x85DUP6000000false
    0x86DUP7000000false
    0x87DUP8000000false
    0x88DUP9000000false
    0x90SWAP1000000false
    0x91SWAP2000000false
    0x92SWAP3000000false
    0x93SWAP4000000false
    0x94SWAP5000000false
    0x95SWAP6000000false
    0x96SWAP7000000false
    0xa0LOG00-0000true
    0xa1LOG10-0000true
    0xa2LOG20-0000true
    0xa3LOG30-0000true
    0xa4LOG40-0000true
    0xf0CREATE--0-0-true
    0xf1CALL--00--true
    0xf2CALLCODE--00--true
    0xf3RETURN000000false
    0xf4DELEGATECALL--00--true
    0xf5CREATE2--0-0-true
    0xfaSTATICCALL--00--true
    0xfdREVERT000000false
    0xfeINVALID010000false

    各opcode详细的zkASM实现参见zkevm-rom项目中的opcodes.zkasm文件。

    2. 0x01 ADD opcode

    在这里插入图片描述
    其中:

    • δ \delta δ为从stack中pop出来的value数,因ADD是对stack的top 2 values求和(除非明确说明,否则是对 2 256 2^{256} 2256取模)。
    • α \alpha α为向stack push进去的value数。ADD操作会将二值求和结果再push进stack中。

    在这里插入图片描述
    根据上图可知,0x01 ADD opcode所需最小gas为3。

    在Polygon zkEVM中,以太坊虚拟机的0x01 ADD opcode对应的zkASM表示为:【分别调用了Memory二级状态机、Binary二级状态机。】

    opADD:
    	; 检查当前stack中确实有至少2个元素,否则跳转到stackUnderflow。
        SP - 2          :JMPN(stackUnderflow)
        ; 将stack pointer值减一
        SP - 1 => SP
        ; 将stack pointer值加载到A寄存器中;再将stack pointer值减一
        $ => A          :MLOAD(SP--)
        ; 将stack pointer值加载到C寄存器中
        $ => C          :MLOAD(SP)
    
        ; Add operation with Arith
        ; 将A寄存器的值存储在Memory状态机中的`arithA`变量中
        A               :MSTORE(arithA)
        ; 将C寄存器的值存储在Memory状态机中的`arithB`变量中
        C               :MSTORE(arithB)
        ; 调用`addARITH`子程序,负责执行加法运算
                        :CALL(addARITH)
        ; 从Memory状态机中的`arithRes1`变量中读取加法运算结果 存入在 E寄存器中
        $ => E          :MLOAD(arithRes1)
        ; 将E寄存器的值存储在stack pointer位置,将stack pointer值加一
        E               :MSTORE(SP++)
        ; stack空间为1024,若当前stack pointer值大于1024,则跳转到stackOverflow
        1024 - SP       :JMPN(stackOverflow)
        ; ADD opcode所需最低gas为3,若执行为ADD操作后GAS为负数,则跳转到outOfGas
        GAS-3 => GAS    :JMPN(outOfGas)
        ; 最后但同样重要的是,以下表示继续处理下一指令。
                        :JMP(readCode)
    

    其中addARITH子程序负责执行加法运算,具体实现见:

    • zkEVM Rom项目中的utils.zkasm
      ; 其中tmpZkPC、storeTmp、arithA、arithB、arithRes1、loadTmp均为全局变量。
      addARITH:
      	; 将调用addARITH子程序之前的RR值存入tmpZkPC临时全局变量中。
          RR              :MSTORE(tmpZkPC)
          zkPC+1 => RR    :JMP(storeTmp) ; 等效为 CALL(storeTmp),将A/B/C/D/E寄存器的值存储在临时全局变量tmpVarA/B/C/D/E中。
      
          $ => A          :MLOAD(arithA)
          $ => B          :MLOAD(arithB)
          $ => E          :ADD ; 对应Binary状态机,为byte-wise加法运算。
      
          E               :MSTORE(arithRes1)
      
          zkPC+1 => RR    :JMP(loadTmp) ; 等效为 CALL(loadTmp),将临时全局变量tmpVarA/B/C/D/E中的值加载到A/B/C/D/E寄存器中。
          ; 重置RR值 为 调用addARITH子程序之前的RR值(从tmpZkPC临时全局变量中取出)
          $ => RR         :MLOAD(tmpZkPC)
                          :JMP(RR) ; 等效为 RETURN
      
      其中storeTmp子程序为将A/B/C/D/E寄存器的值存储在临时全局变量tmpVarA/B/C/D/E中,而loadTmp为将临时全局变量tmpVarA/B/C/D/E中的值加载到A/B/C/D/E寄存器中:
      storeTmp:
          A                   :MSTORE(tmpVarA)
          B                   :MSTORE(tmpVarB)
          C                   :MSTORE(tmpVarC)
          D                   :MSTORE(tmpVarD)
          E                   :MSTORE(tmpVarE)
                              :JMP(RR) ; 等效为 RETURN
      loadTmp:
          $ => A                  :MLOAD(tmpVarA)
          $ => B                  :MLOAD(tmpVarB)
          $ => C                  :MLOAD(tmpVarC)
          $ => D                  :MLOAD(tmpVarD)
          $ => E                  :MLOAD(tmpVarE)
                                  :JMP(RR) ; 等效为 RETURN
      

    不过,实际实现时,Polygon zkEVM中设定了一些常量上限值:

    ; COUNTERS
    CONST %MAX_CNT_STEPS = 2**21 ; 最大STEP数
    
    CONST %MAX_CNT_ARITH = %MAX_CNT_STEPS / 32 ; 最多ARITH计算数
    CONST %MAX_CNT_BINARY = %MAX_CNT_STEPS / 32 ; 最多BINARY计算数
    CONST %MAX_CNT_MEM_ALIGN = %MAX_CNT_STEPS / 32 ; 最多MemAlign计算数
    CONST %MAX_CNT_KECCAK_F = (%MAX_CNT_STEPS / 158418) * 9 ; 最多Keccakf计算数
    CONST %MAX_CNT_PADDING_PG = (%MAX_CNT_STEPS / 56) ; 最多padding pg计算数,针对Poseidon哈希
    CONST %MAX_CNT_POSEIDON_G = (%MAX_CNT_STEPS / 30) ; 最多PoseidonG计算数,针对Poseidon哈希
    CONST %MIN_CNT_KECCAK_BATCH = 2 ; 最少Keccak_batch数
    ; ETHEREUM CONSTANTS
    CONSTL %MAX_NONCE = 0xffffffffffffffffn ; 以太坊nonce最大值为2^{64}-1。
    

    因此,实际在zkevm-rom的opcodes.zkasm中对0x01 ADD opcode的实际实现为:【借助了Binary状态机默认是对A和B寄存器进行运算的,进行了优化,使代码更简洁;同时考虑实际应用场景,对相关计数器进行了约束。】

    opADD:
    
        %MAX_CNT_BINARY - CNT_BINARY - 1 :JMPN(outOfCounters) ; 对相关计算计数器进行了约束。
        %MAX_CNT_STEPS - STEP - 120 :JMPN(outOfCounters) ; 约束了计算复杂度。
    
        SP - 2          :JMPN(stackUnderflow)
        SP - 1 => SP
        $ => A          :MLOAD(SP--)
        $ => B          :MLOAD(SP)
    
        ; Add operation with Arith
        $ => E          :ADD
    
        E               :MSTORE(SP++)
        1024 - SP       :JMPN(stackOverflow)
        GAS-3 => GAS    :JMPN(outOfGas)
                        :JMP(readCode)
    

    参考资料

    [1] zkASM示例
    [2] 以太坊黄皮书 https://ethereum.github.io/yellowpaper/paper.pdf
    [3] 理解以太坊黄皮书
    [3] EVM.Codes

    附录:Polygon Hermez 2.0 zkEVM系列博客

  • 相关阅读:
    【Linux】Linux进程间通信(二)
    【基于Arduino的垃圾分类装置开发教程四超声波检测】
    124. 二叉树中的最大路径和
    论文《Sequential Recommendation with Graph Neural Networks》阅读
    allegro中怎样制作和添加logo
    【Linux学习笔记3】-【指定运行级别,Linux找回root密码,帮助指令(man,help),查看以.开头的隐藏文件】
    SQLite 学习笔记1 - 简介、下载、安装
    Java程序设计2023-第六次上机测试
    Android Kotlin 打开相册选择图片(多选)
    项目平台——项目首页设计(五)
  • 原文地址:https://blog.csdn.net/mutourend/article/details/126938909