分类 Ethereum-新手教程 下的文章

forkchoiceUpdatedV3 must only be called for cancun payloads


启动eth2.0 一段时间后,报如下错误

WARN [05-24|11:39:02.090] Served engine_forkchoiceUpdatedV3        conn=127.0.0.1:53124 reqid=355251 duration="74.273µs" err="Unsupported fork" errdata="{Error:forkchoiceUpdatedV3 must only be called for cancun payloads}"

查看代码
https://github.com/ethereum/go-ethereum/blob/b6474e9f90c88003de7d7eb993ddb5f60133172e/eth/catalyst/api.go#L213-L224

// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root
// in the payload attributes. It supports only PayloadAttributesV3.
func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) {
    if params != nil {
        if params.Withdrawals == nil {
            return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing withdrawals"))
        }
        if params.BeaconRoot == nil {
            return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root"))
        }
        if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { // 关键代码
            return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads"))
        }
    }

跟踪下代码,
https://github.com/ethereum/go-ethereum/blob/b6474e9f90c88003de7d7eb993ddb5f60133172e/params/config.go#L763-L778

// LatestFork returns the latest time-based fork that would be active for the given time.
func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
    // Assume last non-time-based fork has passed.
    london := c.LondonBlock

    switch {
    case c.IsPrague(london, time):
        return forks.Prague
    case c.IsCancun(london, time):
        return forks.Cancun
    case c.IsShanghai(london, time):
        return forks.Shanghai
    default:
        return forks.Paris
    }
}

当前genesis配置如下

{
  "config": {
    "chainId": ....,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "istanbulBlock": 0,
    "berlinBlock": 0,
    "londonBlock": 0,
    "mergeNetsplitBlock": 0,
    "terminalTotalDifficulty": 0,
    "terminalTotalDifficultyPassed": true,
    "shanghaiTime": 0,
    "cancunTime": 0,
    "pragueTime": 1716532255
  },
  ....
  "coinbase": "0x0000000000000000000000000000000000000000",
  "difficulty": "0x01",
  "extraData": "",
  "gasLimit": "0x17d7840",
  "nonce": "0x1234",
  "mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp": "1715760655"

由于设置了pragueTime,所以LatestFork会返回Prague fork,不会是Cancun,所以ForkchoiceUpdatedV3会报错,至于Prague为什么不支持ForkchoiceUpdatedV3,留个TODO

目前要做的是把最新的fork改为Cancun

  1. 将genesis.json中的pragueTime删掉
  2. 停止geth服务
  3. 重新初始化
    ./geth --config ./config/config.toml init ./config/genesis.json
  4. 重启geth服务

invalid opcode: opcode 0x5f not defined


问题

在低版本geth(quorum)上使用高版本solidity合约和编译(0.8.20及以上),部署时报以下错误

Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
Returned error: invalid opcode: opcode 0x5f not defined
OR the EVM version used by the selected environment is not compatible with the compiler EVM version.

分析

原因是因为当前版本Evm未支持eip-3855

查看代码,代码未支持 PUSH0 0x5f
https://github.com/Consensys/quorum/blob/643b5dcb8e2f0c68a8c78dc01c778a11f0ed14ba/core/vm/opcodes.go#L109-L121

const (
    POP      OpCode = 0x50
    MLOAD    OpCode = 0x51
    MSTORE   OpCode = 0x52
    MSTORE8  OpCode = 0x53
    SLOAD    OpCode = 0x54
    SSTORE   OpCode = 0x55
    JUMP     OpCode = 0x56
    JUMPI    OpCode = 0x57
    PC       OpCode = 0x58
    MSIZE    OpCode = 0x59
    GAS      OpCode = 0x5a
    JUMPDEST OpCode = 0x5b
)

对标以太坊,https://github.com/ethereum/go-ethereum/pull/24039/files
添加了对eip-3855的支持

后续

将EIP合并,并测试


梳理Polygon zkEVM node 本地启动测试环境及配置


测试硬件环境

OS: Mac Pro {cpu intel} v11.7.5
注意:目前,Executor/Prover 不能在 ARM 驱动的 Mac 上运行。对于 Windows 用户,不建议使用 WSL/WSL2。

测试环境搭建

先按官方的测试环境进行部署,熟悉下部署细节,然后再做针对性补充
主要参考文章如下

官方是已Docker环境进行演示介绍的,我们精简下,主要说下关键操作

安装基础环境

自行安装go,dockerdocker-compose
可以参考以下官方文档,查看对应平台的安装方法:
https://go.dev/doc/install
https://www.docker.com/get-started
https://docs.docker.com/compose/install/

克隆代码

git clone https://github.com/0xPolygonHermez/zkevm-node.git

构建Docker镜像

cd zkevm-node/
make build-docker

运行 zkNode 环境

cd test/
make run

其他操作

make stop // 停止 zkNode
make restart // 重启整个 zkNode 环境

执行后,会创建和启动如下容器

  • zkevm-state-db
  • zkevm-pool-db
  • zkevm-mock-l1-network
  • zkevm-prover
  • zkevm-approve
  • zkevm-sync
  • zkevm-eth-tx-manager
  • zkevm-sequencer
  • zkevm-l2gaspricer
  • zkevm-aggregator
  • zkevm-json-rpc

根据Docker环境抽离各个模块配置

//TODO

L1网络配置

L2网络配置

访问环境

关键地址私钥

L1 Addresses

Address Description
0xa513E6E4b8f2a923D98304ec87F64353C4D5C853 Proof of Efficiency
0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9 Bridge
0x5FbDB2315678afecb367f032d93F642f64180aa3 Matic token
0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0 GlobalExitRootManager

Deployer Account

Address Private Key
0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Sequencer Account

Address Private Key
0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D 0x28b2b0318721be8c8339199172cd7cc8f5e273800a35616ec893083a4b32c02e

Accounts

Address Private Key
0x70997970C51812dc3A010C7d01b50e0d17dc79C8 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a
0x90F79bf6EB2c4f870365E785982E1f101E93b906 0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6
0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a
0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc 0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba
0x976EA74026E726554dB657fA54763abd0C3a0aa9 0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e
0x14dC79964da2C08b23698B3D3cc7Ca32193d9955 0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356
0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f 0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97
0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6
0xBcd4042DE499D14e55001CcbB24a551F3b954096 0xf214f2b2cd398c806f84e317254e0f0b801d0643303237d97a22a48e01628897
0x71bE63f3384f5fb98995898A86B02Fb2426c5788 0x701b615bbdfb9de65240bc28bd21bbc0d996645a3dd57e7b12bc2bdf6f192c82
0xFABB0ac9d68B0B445fB7357272Ff202C5651694a 0xa267530f49f8280200edf313ee7af6b827f2a8bce2897751d06a843f644967b1
0x1CBd3b2770909D4e10f157cABC84C7264073C9Ec 0x47c99abed3324a2707c28affff1267e45918ec8c3f20b8aa892e8b065d2942dd
0xdF3e18d64BC6A983f673Ab319CCaE4f1a57C7097 0xc526ee95bf44d8fc405a158bb884d9d1238d99f0612e9f33d006bb0789009aaa
0xcd3B766CCDd6AE721141F452C550Ca635964ce71 0x8166f546bab6da521a8369cab06c5d2b9e46670292d85c875ee9ec20e84ffb61
0x2546BcD3c84621e976D8185a91A922aE77ECEc30 0xea6c44ac03bff858b476bba40716402b03e41b8e97e276d1baec7c37d42484a0
0xbDA5747bFD65F08deb54cb465eB87D40e51B197E 0x689af8efa8c651a91ad287602527f3af2fe9f6501a7ac4b061667b5a93e037fd
0xdD2FD4581271e230360230F9337D5c0430Bf44C0 0xde9be858da4a475276426320d5e9262ecfc3ba460bfac56360bfa6c4c28b4ee0
0x8626f6940E2eb28930eFb4CeF49B2d1F2C9C1199 0xdf57089febbacf7ba0bc227dafbffa9fc08a93fdc68e1e42411a14efcf23656e

Polygon zkEVM架构组成-思路梳理


Polygon zkEVM架构组成-思路梳理

  • zkNode

    • Synchronizer
      • 获取Sequencers提交的transactions
      • 获取Aggregators提交的validity proofs
      • 监听以太坊链上事件,包括new batches{events中读取的信息->存储database}
      • 处理可能的reorgs {检查last ethBlockNum 和 last ethBlockHash 是否已同步}
    • State子模块
      • 实现了Merkle Tree并连接到DB后台
        • 在block level检查integrity(即,关于gas、block size等相关信息)
        • 检查某些交易相关信息(如签名、足够的balance等)
        • 将smart contract(SC)代码存储到Merkle tree中,并使用EVM来处理交易
    • Sequencer
      • 支持模式:Trusted/Permissionless
      • 处理流程:接收L2交易+L2用户支付的交易手续费 -> 对L2交易进行排序 ->生成batches -> send tx{sequences形式}(为Aggregator验证支付费用) -> L1合约 {PolygonZkEVM.sol} -> 存储storage slots
      • 经济模型:向L1提交有效交易,以获利
        • 根据利润对pool中交易排序
        • 向L1提交batches,支付L1系统代币
    • Aggregator
      • 处理流程:L1合约 {PolygonZkEVM.sol} -> 获取Sequencer提交的L2 batches -> zkProver{特殊链下EVM解析器} -> 生成ZK proof{证明该batch的完整性}-> send tx -> L1合约 {PolygonZkEVM.sol} -> 更新 L2 State root
      • 经济模型:Sequencers提交L1 batch时支付的手续费
      • 开支
        • 向L1提交validity proof交易成本
        • 运行aggregator和zkProver服务器成本
  • Consensus Contract(PolygonZkEVM.sol)

    • 存储Sequencers提交的L2 batches
    • 对Aggregator新提交的L2 State root进行validity proof验证
  • zkProver

    • 本质:zk virtual machine来仿真EVM
    • 功能:为Aggregator使用,来验证batches并提供validity proofs
    • 生成proof:以多项式和汇编语言形式
    • 功能包含如下
      • Main State Machine Executor:处理zkEVM的执行
        • 使用zkASM解析EVM Bytecodes
        • 为每个transaction batch设置多项式约束
        • 对多项式约束使用PIL进行编码
      • secondary State Machines : zkEVM中证明交易正确性的每一步计算
        • zkProver是整个项目中最复杂的部分,包含了多个state machines:
          • 一些执行bitwise function的state machines(如XOR/Padding等等)
          • 执行哈希运算的的state machines(如Keccak、Poseidon等等)
          • 执行验签的state machines(如ECDSA等等)
        • 二级状态机有:
          • Binary SM
          • Memory SM
          • Storage SM
          • Poseidon SM
          • Keccak SM
          • Arithmetic SM
      • STARK-proof builder
        • State machines负责生成多项式约束,zk-STARKs用于证明batches满足这些多项式约束条件
        • zkProver使用FRI对zk-STARK证明加速
      • SNARK-proof builder
        • size: STARK-proof > SNARK-proof
          • SNARK-proof来证明STARK-proof的正确性
          • SNARK-proof做为validity proof
          • 更便宜地在L1上验证该validity proof
  • L1-to-L2 Bridge

    • L1 Contract:部署在以太坊,管理rollups之间的资产转移

      负责2个操作

      • bridge:将资产由一个rollup转移到另一个rollup

      • claim:当合约从任意rollup claim时,使用claim操作

      需要有2棵Merkle tree

      • globalExitTree:包括了所有rollups的exit trees的所有信息

      • mainnet exit tree:包含了用户与主网交互的交易信息

      global exit root manager L1的合约负责管理跨越多个网络的exit roots

    • L2 Contract:部署在某特定的rollup上,负责主网与该rollup之间的资产转移

      • 处理rollup端的bridge和claim操作
      • 与globalExitTree和rollup exit tree交互以更新exit roots

共识算法PoE

Hermez 1.0 PoD共识缺点

  • 特定时间,网络由单一actor控制,可能作弊
  • 竞价协议,预测复杂性高
  • 参与竞争运营门槛高,导致运营集中,抗审查

Proof-of-Efficiency(PoE)实现

  • Sequencer:负责将L2的交易打包为batches并添加到L1的PoE智能合约
  • Aggregator:之间竞争,负责检查transaction batches的有效性,并提供validity proofs

PoE智能合约基本接口

  • sendBatch:用于接收Sequencer的batches
  • validateBatch:用于接收Aggregator的validity proof,进行validate batches

batch fee

根据网络负载情况,batch fee将是可变的,可根据protocol合约中的某个参数来计算

PoE的经济模型

  • Sequencer赚L2的交易手续费{相应的validity proof提交后}
  • Aggregator赚取Sequencer支付的batch MATIC手续费