Polygon zkEVM 如何运作?

本文深入探讨了Polygon zkEVM交易的生命周期,从交易提交到以太坊L1上通过零知识证明进行验证的全过程。文章详细解释了交易如何被提交、执行、批量处理、排序并最终在L1上实现最终确认,以及Polygon zkEVM如何继承以太坊的安全性。

在我的前一篇文章中,我们讨论了 ZK 证明的工作原理,以及不同的非交互式 ZK 证明如何在 ZK-EVM(如 Polygon zkEVM)中使用。

但这是如何运作的呢? 有哪些信息会被发送回以太坊?这又是如何使 Polygon zkEVM 能够继承以太坊的安全性的?

在这篇文章中,我们将更仔细地 بررسی 到底层发生了什么,包括交易如何:

  1. 提交到 Polygon zkEVM。

  2. 几乎立即执行。

  3. 使用数据加密方法批量处理。

  4. 排序并发送到以太坊 L1。

  5. 在 L1 上利用 ZK 证明的力量实现整合的最终性。

让我们开始吧!

提交交易

正如我们在前一篇文章中探讨的那样,用户不断地通过 JSON-RPC 接口 (通常通过像 MetaMask 这样的钱包) 向受信任的排序器的节点提交他们的 L2 交易。

这使得 Polygon zkEVM 在与 dApp 交互时,从用户的角度来看,与以太坊完全一样。示例如下:

https://twitter.com/jarrodWattsDev/status/1686304245539274753

从用户的角度来看,交易几乎立即完成,允许他们在提交交易后立即继续使用 dApp。这种强大的用户体验优势之所以成为可能,是因为 zkEVM 的状态更新无需首先向以太坊 (L1) 发送任何信息。

但是,如果用户想要从 L2 (zkEVM) 桥接资金 到 L1 (以太坊),本质上是执行提款,那么完整的交易生命周期需要完成。这需要 PolygonZkEVM 智能合约:

  1. 接收来自排序器的批次(知道要证明哪些交易)。

  2. 接收来自聚合器的有效性证明(证明交易)。

查看 zkEVM 图中的数据流

从用户角度来看,此时简化的流程如下所示:

执行交易

提交后,交易将存储在待处理交易池中,等待排序器选择执行或丢弃。

排序器会做一些检查,看看是否可以基于以下内容丢弃交易:

  1. 发送者是否有足够的资金来支付交易。

  2. 调用的智能合约是否存在并且具有有效的/正确的字节码。

  3. 该交易是否不是重复的。

  4. 该交易是否不是“双重支付”,以确保发送者的资金尚未在另一笔交易中支出。

一旦该交易被认为是有效的,排序器就会更新 Polygon zkEVM 的状态,此时用户会体验到交易几乎立即完成。

如果我们修改我们的图表以探索底层,那么它是这样的:

此时,用户继续与 L2 的状态进行交互。此之后的每一步都与将交易数据发布回以太坊 L1 相关;这仅与想要将资金返回到以太坊的用户相关。

批量处理交易

添加到 L2 状态后,交易将广播到网络上的所有其他 zkEVM 节点,并准备好与其他交易进行批量处理

要将交易批量处理在一起,它们会以二进制形式连接成一组字节。在 PolygonZkEVM 智能合约上,定义了一个 Solidity struct,名为BatchData

在这个结构体中,定义了一个类型为 bytestransactions 字段,其中包含连接在一起的编码交易批次。

/**
 * @notice 将用于调用 sequenceBatches 的结构体
 * @param transactions L2 以太坊交易 EIP-155 或带有签名的 pre-EIP-155:
 * EIP-155: rlp(nonce, gasprice, gasLimit, to, value, data, chainid, 0, 0,) || v || r || s
 * pre-EIP-155: rlp(nonce, gasprice, gasLimit, to, value, data) || v || r || s
 * @param globalExitRoot 批次的全局退出根
 * @param timestamp 批次的排序时间戳
 * @param minForcedTimestamp 强制批处理数据的最小时间戳,非强制批处理时为空
 */
struct BatchData {
    bytes transactions;
    bytes32 globalExitRoot;
    uint64 timestamp;
    uint64 minForcedTimestamp;
}

正如你在上面的注释中看到的,交易是使用 "RLP" 进行编码的,可以是 EIP-155 或 pre-EIP-155 交易。

  • EIP-155 是 Vitalik 于 2016 年提出的一个提案,旨在防止重放攻击。它添加了 chainId 值,以避免用于一个链的交易也可以在其他链上工作。

  • rlp 代表 Recursive-Length Prefix Serialization。这是一种数据序列化方法,以太坊使用它将任意嵌套的数据数组的结构编码为二进制。

至于其他三个字段:

  1. globalExitRoot:全局退出 (Merkle) 树的根,该树存储有关 L1 和 L2 之间资产转移的信息。了解更多

  2. timestamp:创建批次的时间。

  3. minForcedTimestamp:仅当用户不使用受信任的排序器时才相关(有助于审查抗性)。通常设置为 0了解更多

要更新我们的图表,让我们缩小范围,看看排序器在做什么:

根据我们将在下一節中定义的,在 L1 智能合约上定义的一些大小规则,创建了多个此类批次。因此,让我们看看接下来这些批次会发生什么。

对交易批次进行排序

一旦我们有了交易批次,它们就可以被“排序”了。为此,排序器调用 PolygonZkEVM 智能合约的 sequenceBatches 函数(在 L1 上)并为其提供多个交易批次。

此交易 是以太坊主网上 sequenceBatch 交易的一个示例。通过检查输入数据,我们可以看到在此特定函数调用中包含的 52 个交易批次:

每个批次还包含我们之前看到的 transactions 字段(连接的字节),该字段连接了尽可能多的 RLP 编码交易:

PolygonZkEVM 智能合约具有一个名为 _MAX_TRANSACTIONS_BYTE_LENGTH 的常量值,该值确定可以在该字段中连接多少个交易。源代码

// 可以在单个批次中添加的最大交易字节数
// 最大 keccaks 电路 = (2**23 / 155286) * 44 = 2376
// 每个 keccak 的字节数 = 136
// 最小静态 keccaks 批次 = 2
// 允许的最大字节数 = (2376 - 2) * 136 = 322864 字节 - 1 字节填充
// 四舍五入为 300000 字节
// 为了处理交易,数据大约哈希两次用于 ecrecover:
// 300000 字节 / 2 = 150000 字节
// 由于 geth 池当前最多只接受 128kb 交易:
// https://github.com/ethereum/go-ethereum/blob/master/core/txpool/txpool.go#L54
// 我们将限制此长度以符合 geth 限制,因为我们的节点将使用它
// 我们保留 8kb 作为安全裕度
uint256 internal constant _MAX_TRANSACTIONS_BYTE_LENGTH = 120000;

同样,可以作为一个交易发送的批次数量也有限制,在一个名为 _MAX_VERIFY_BATCHES 的常量变量中。源代码

// 一次调用中可以验证的最大批次数量。这取决于我们当前的指标
// 这应该是防止有人试图生成大量无效批次的保护措施,我们在挂起超时到期之前无法证明
uint64 internal constant _MAX_VERIFY_BATCHES = 1000;

这些批次被提供给一个名为 sequenceBatches 的函数,该函数接受:

  1. 一个名为 batchesBatchData 结构体数组。

  2. 一个地址,用于发送排序批次的费用,称为l2Coinbase

function sequenceBatches(
    BatchData[] calldata batches,
    address l2Coinbase
) external ifNotEmergencyState onlyTrustedSequencer {
  ...
}

这个函数遍历每个批次,确保它们有效,然后在 L1 智能合约的一个名为 sequencedBatchesmapping 中更新虚拟状态

// 定义虚拟状态的批次队列
// SequenceBatchNum --> SequencedBatchData
mapping(uint64 => SequencedBatchData) public sequencedBatches;

在我们的图表中,这是我们所处的位置:

三种最终状态

现在是介绍交易在 Polygon zkEVM 中可以处于的不同状态的好时机。交易会经历不同的最终性阶段:

  1. 可信状态:L2 上的状态已更新。尚未到达 L1。

    • 大多数情况下,这是用户与之交互的状态。
  2. 虚拟状态:批次已排序,数据可在 L1 上获得。

    • 此时,数据可在 L1 上获得,供任何人证明,但尚未经过证明。
  3. 合并状态:一个 ZK 证明已发布在 L1 上。

    • 此时,数据已得到证明并继承了以太坊的安全性。

了解更多 ↗

到目前为止,我们已经讨论了可信和虚拟状态的过程所以,让我们现在跳到最后阶段,其中计算完整性的 ZK 证明被提交到 L1。

聚合排序批次

一旦所有排序的批次都到达 L1,最后一步是生成一个 ZK 证明,以验证这些交易的有效性。

聚合器节点获取排序的批次并将它们提供给 ZK prover,它使用 fflonk 协议生成最终的 SNARK。(下面是快速总结):

https://twitter.com/jbaylina/status/1624116186861404188

最终结果是聚合器收到一个 ZK 证明,该证明足够简洁,可以存储在以太坊 L1 上。此流程的简化图如下:

zkProver 的骨架概览

一旦聚合器节点有了证明,它就会调用 PolygonZkEVM 智能合约的 verifyBatchesTrustedAggregator 函数,并将它刚刚收到的证明提供给该函数,以及其他参数,源代码

/**
 * @notice 允许聚合器验证多个批次
 * @param pendingStateNum 初始挂起状态,如果使用合并状态则为 0
 * @param initNumBatch 聚合器开始验证的批次
 * @param finalNewBatch 聚合器打算验证的最后一个批次
 * @param newLocalExitRoot 一旦批次被处理,新的本地退出根
 * @param newStateRoot 一旦批次被处理,新的状态根
 * @param proof fflonk 证明
 */
function verifyBatchesTrustedAggregator(
    uint64 pendingStateNum,
    uint64 initNumBatch,
    uint64 finalNewBatch,
    bytes32 newLocalExitRoot,
    bytes32 newStateRoot,
    bytes calldata proof
) external onlyTrustedAggregator {
  ...
}

让我们再次检查一个示例交易,看看这在现实世界中是什么样子。

此交易 来自受信任的聚合器,并使用该证明在 PolygonZkEVM 智能合约上调用 verifyBatchesTrustedAggregator

有关其他参数的详细信息,请参见 此处 .

在这个函数中,另一个名为 rollupVerifier 的合约有一个函数 verifyProof 会被调用。这个函数被提供了该证明以及一个 inputSnark;这是一个特定的 L2 状态转换的所有 L2 交易的加密表示。

// 验证证明
if (!rollupVerifier.verifyProof(proof, [inputSnark])) {
    revert InvalidProof();
}

如果证明有效,各种状态会更新,例如全局退出根和包含合并的 L2 状态根的 batchNumToStateRoot 映射:

// 状态根映射
// BatchNum --> 状态根
mapping(uint64 => bytes32) public batchNumToStateRoot;

在这个例子中,在 L1 上发布和验证这个证明花费了大约 350K gas:

通过对我们的图表进行最后一次更新,我们在 L1 上实现了合并状态!

此时,交易批次处于最终的“合并”状态,这就是 Polygon zkEVM 如何继承以太坊的安全性的;通过将所有交易数据发布和证明回以太坊 L1。

总结

从用户的角度与 Polygon zkEVM 交互时,交易几乎可以立即确认,同时通过在底层发生的整个过程继承以太坊的安全性。

这种方法提供了两全其美的效果,用户既可以在几秒钟内获得低 gas 费和快速交易速度,也可以使用 ZK 证明的力量在大约 1 小时内将资金桥接回以太坊。

在这篇博客中,我们介绍了从 Polygon zkEVM 交易的完整生命周期,一直到使用以太坊 L1 上的零知识进行证明。

如果你喜欢这篇文章,请考虑在 Twitter 上关注我!

  • 原文链接: blog.jarrodwatts.com/how...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
JarrodWatts
JarrodWatts
江湖只有他的大名,没有他的介绍。