Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
网络与协议指南阅读约 11 分钟

ZKsync Era:zkEVM Rollup 如何运作以及如何在其上构建

面向以太坊开发者的实用指南,涵盖 ZKsync Era 的 zkEVM 架构、交易生命周期、RPC 集成、Gas 处理与验证工作流。

TL;DR

ZKsync Era 是一个 Layer 2 zk-rollup,在以太坊之外执行 EVM 兼容交易,并将压缩后的状态承诺提交回以太坊,由零知识证明而非欺诈证明挑战窗口来保障安全。对开发者而言,实际影响是大多数以太坊工具可通过熟悉的 JSON-RPC 调用工作,但 Gas 计算、最终性阶段以及少数 Era 特有方法的行为与 L1 或 optimistic rollup 不同。本指南先解释思维模型,然后使用你自己的 RPC 端点,逐步演示可复现的集成与验证流程。它将文档化的协议行为、建议以及你应在自己基础设施上运行的测量区分开来。

ZKsync Era 是什么以及本指南涵盖什么

ZKsync Era 是构建在以太坊上的 Layer 2 rollup,围绕零知识 EVM(zkEVM)设计。交易由链下排序器执行、批量打包,并连同有效性证明一起提交到以太坊。由于正确性由证明以密码学方式强制执行,而非依赖挑战期,因此提款和状态转换不依赖于诚实的观察者在线守候争议窗口。

这个名称有两种重叠的用法。它指开发者今天交互的 Era 主网链,也指开源代码库 matter-labs/zksync-era,该代码库后来被泛化为 ZK Stack 框架,用于启动自定义链。阅读文档时,请检查页面描述的是 Era 链本身还是更广泛的堆栈。

本文涵盖作为集成目标的 Era 链:执行模型、JSON-RPC 接口、可运行的读写流程、如何验证结果以及常见故障模式所在。它不涵盖代币经济学或价格,也不推荐特定的公共端点 URL;端点选择是另一个由 RPC Assistant 覆盖的独立决策。

  • 执行:EVM 兼容字节码在链下排序器上运行。
  • 安全:向以太坊提交有效性证明,而非欺诈证明。
  • 数据:交易数据和状态差异被压缩并发布到以太坊。
  • 工具:标准以太坊 JSON-RPC 加上少量 Era 特有方法。

先决条件与假设

以下流程假设你拥有 Node.js 18 或更新版本、curl,并且如果你打算发送交易,还需要一个在 ZKsync Era 上有资金的账户。你需要一个服务于 Era 链的 RPC 端点;将其保存在名为 RPC_URL 的环境变量中,以便相同的脚本可在任何提供商上运行。对于写操作,将密钥保存在 PRIVATE_KEY 中,切勿提交。

你应当已经熟悉以太坊概念:账户、nonce、Gas,以及交易哈希与收据之间的区别。如果你对节点访问模式不熟悉,区块链节点托管指南解释了专用节点相比共享端点能提供什么。

本文中的所有数值输出均为占位符。链状态不断变化,因此你看到的任何值都是你自己调用的快照,而非基准。

思维模型:执行、批处理与证明

将 ZKsync Era 视为三个层次的活动。首先,排序器对交易进行排序和执行,产生新状态。其次,证明者生成零知识证明,证明状态转换遵循规则。第三,以太坊上的提交交易发布压缩数据和证明,以便任何人都能在不重新执行的情况下验证转换。

这与 optimistic rollup 的差异在操作上很重要。在 optimistic rollup 上,交易被乐观接受,并可在窗口期内被挑战;在 Era 上,安全论证依赖于证明。在实践中,两者对应用开发者来说感觉相似,但状态根在以太坊上被视为最终的时间不同,你不应将排序器已包含的交易视为以太坊最终确定。

Era 还会在发布前压缩 calldata。这就是为什么 Era 上的费用通常远低于 L1,以及为什么 Gas 估算可能看起来不熟悉:发布数据的成本占很大一部分,其定价方式反映的是字节级压缩而非原始 calldata 长度。

ZKsync Era 与普通 EVM 链的区别

大多数合约无需修改即可部署和运行,但少数行为是 Era 特有的,在调试前值得了解。Gas 分为计算和 pubdata 两部分,gasPerPubdataByte 字段出现在交易类型中。某些预编译和操作码行为不同或不可用,账户抽象是原生支持的而非外挂的,因此账户可以用 ERC-20 代币支付费用,并可以携带自定义验证逻辑。

对于集成工作,最重要的后果是你不应假设以太坊主网 Gas 估算器会产生正确的限制。使用节点自身的估算并添加余量。同样,不要假设 eth_getTransactionReceipt 返回收据就意味着批次已在以太坊上证明;它意味着排序器已包含该交易。

  • 原生账户抽象:智能账户和 paymaster 是一等公民。
  • 两部分 Gas:计算加 pubdata,通过 Era 特有字段暴露。
  • 基于证明的最终性:包含、批次提交和证明验证是不同的阶段。
  • Era 特有 RPC 方法补充标准以太坊方法集。

通过 JSON-RPC 读取链状态

从只读调用开始,确认你的端点服务于 Era 链,并且标准方法按预期工作。下面的脚本使用 curl,打印链 ID、最新区块号以及你提供的地址的余额。运行前替换 RPC_URL 和 ADDRESS。

正确运行会返回与你预期 Era 网络匹配的链 ID、单调递增的区块号,以及以十六进制字符串表示的 wei 余额。如果链 ID 不匹配,说明你指向了错误的网络,后续所有结果都值得怀疑。

export RPC_URL="https://your-era-endpoint.example"
export ADDRESS="0xYourAddress"

curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}'

curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"eth_blockNumber","params":[]}'

curl -s -X POST "$RPC_URL" \
  -H 'Content-Type: application/json' \
  -d "{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"eth_getBalance\",\"params\":[\"$ADDRESS\",\"latest\"]}"

发送交易并跟踪其阶段

下面的 JavaScript 示例使用 ethers 发送一笔小额转账,然后轮询收据。它从环境变量读取端点和密钥,使用节点估算 Gas,并应用余量。它还打印收据出现的区块号,以便你之后与批次活动关联。

先在测试账户上运行。预期的验证结果是收据的 status 等于 1,且 blockNumber 大于发送前记录的区块号。如果收据始终不出现,交易可能仍在排序器的内存池中待处理;在重新发送前用 eth_getTransactionByHash 检查哈希。

import { JsonRpcProvider, Wallet, parseEther } from "ethers";

const provider = new JsonRpcProvider(process.env.RPC_URL);
const wallet = new Wallet(process.env.PRIVATE_KEY, provider);

const before = await provider.getBlockNumber();
const fee = await provider.getFeeData();
const gas = await provider.estimateGas({
  from: wallet.address,
  to: process.env.ADDRESS,
  value: parseEther("0.0001"),
});

const tx = await wallet.sendTransaction({
  to: process.env.ADDRESS,
  value: parseEther("0.0001"),
  gasLimit: (gas * 120n) / 100n,
  maxFeePerGas: fee.maxFeePerGas,
  maxPriorityFeePerGas: fee.maxPriorityFeePerGas,
});

console.log("sent", tx.hash, "from block", before);
const receipt = await tx.wait();
console.log("status", receipt.status, "in block", receipt.blockNumber);

可复现的测量流程

如果你需要比较端点或确认自己应用的延迟,请运行受控流程,而不是信任单次调用。下面的方法设计为让另一位工程师可以重复并获得可比的结构,即使绝对数值不同。

为你测试的每个端点记录下表,每次调用至少 100 次迭代,并报告中位数和第 95 百分位数。不要填入本文中的数字;该表是你自己运行的模板。

  • 用 10 次调用预热并丢弃。
  • 分别计时 eth_blockNumber 和 eth_getBalance。
  • 对每个端点从同一机器和网络路径运行。
  • 将失败和超时记录为独立类别,而非缓慢的成功。
  • 在不同时间段重复,以暴露负载相关的方差。

验证结果并理解最终性

验证有两个层次。第一是包含:排序器已执行你的交易且收据存在。第二是以太坊级结算:包含你交易的批次已提交,其证明已在以太坊上验证。仅凭收据不能证明第二点。

要检查结算,使用 Era 特有方法(如 zks_getTransactionDetails)查找包含你交易的批次,该方法返回批次号和相关元数据,然后用 zks_getL1BatchDetails 查询批次。将批次的提交和执行交易哈希与以太坊对比。如果这些哈希不存在,则批次尚未结算。

对于大多数应用逻辑,包含已足够,你应围绕它设计。对于桥、托管以及任何必须在排序器故障后存活的操作,等待证明在以太坊上验证。权衡是延迟:结算比包含耗时更长,差距取决于证明者吞吐量和以太坊区块时间。

  • 包含:收据存在,状态为 1。
  • 提交:批次数据发布到以太坊。
  • 执行:有效性证明在以太坊上验证。
  • 应用规则:选择与你的风险承受能力匹配的阶段。

排查常见集成故障

大多数故障属于几类。错误的链 ID 意味着端点服务于不同的网络。Gas 估算回滚通常意味着交易在执行时会失败,而不是端点损坏;先用 eth_call 模拟。长时间等待后收据缺失通常意味着交易被丢弃或 nonce 过时。

如果在负载下出现重复超时,问题可能是端点的速率限制而非链本身。使用上述测量流程与第二个端点比较。对于持续的吞吐需求,专用节点可消除共享速率限制,RPC 定价页面解释了计划如何映射到请求量。

如果合约行为与以太坊主网不同,在假设节点错误之前,检查 Era 特有的操作码和预编译支持。针对已知良好的区块用 eth_call 复现调用,以隔离问题是否依赖于状态。

  • 链 ID 不匹配:在进一步调试前确认端点的网络。
  • 估算回滚:用 eth_call 模拟并检查回滚原因。
  • 过时 nonce:查询待处理 nonce 并替换交易。
  • 速率限制:比较端点并检查响应头。

限制与权衡

ZKsync Era 并非在所有方面都是以太坊的即插即用替代品。账户抽象改变了费用的支付方式和验证的工作方式,这影响钱包和 paymaster 集成。Pubdata 定价意味着 Gas 成本对 calldata 大小的敏感方式与 L1 不同。而且由于结算依赖于证明生成,达到以太坊最终性的时间并不固定。

访问链的方式也存在操作权衡。共享公共端点方便但受速率限制和延迟变化影响;专用基础设施成本更高但提供可预测的性能。两种选择都不改变协议,但都改变用户体验。

最后,生态系统比 Era 链本身更广泛。ZK Stack 允许团队启动与 Era 互操作的自定义链,因此你阅读的文档可能描述适用于堆栈而非 Era 本身的行为。始终确认页面针对的目标。

在 ZKsync Era 上构建的后续步骤

在读取、写入和验证正常工作后,下一步是加固你的集成。在 RPC 调用周围添加带退避的重试,缓存不可变数据(如链 ID),并在每笔交易旁记录批次号,以便日后轻松检查结算。如果你要部署合约,先在本地节点或测试网上测试,再上主网。

对于端点选择,使用 RPC Assistant 而不是硬编码教程中的 URL。它可以为你指向合适的 Era 端点并解释权衡。要查看支持哪些网络,浏览网络目录,对于托管访问选项,查看 API 服务。如果你仍在共享与专用访问之间做决定,多链 RPC 端点指南更深入地涵盖了该决策。

  • 在每个 RPC 调用周围添加重试和退避逻辑。
  • 为需要结算检查的交易记录批次号。
  • 在主网前于测试网测试合约部署。
  • 在任何基础设施变更后重新运行测量流程。

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始