Genesis 部署 — 实现

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: 用全部 44 个系统合约(含 OracleHub 0x8016 + DID 0x8017-0x8019)重新部署 genesis,验证 Oracle operator tx 注入和 DID 系统合约功能的端到端流程。

Architecture: 清理旧环境 → 修改 OracleHub.initialize() 权限 → 编译系统合约 + bootloader → zkstack ecosystem init 部署 L1 + genesis → 启动节点 + Oracle 后台 → post-genesis 合约初始化 → E2E 验证全部功能。

Tech Stack: Rust (nightly-2025-03-19), Solidity (0.8.20), Docker (reth + postgres), zkstack CLI, Foundry (foundry-zksync), cast


Task 1: OracleHub.initialize() 修饰符修改 + 编译验证

目标:initialize()onlyCallFromBootloader 改为 onlySystemCall,使 genesis 后可通过交易调用初始化。

Files:

  • Modify: era-contracts-l1/system-contracts/contracts/OracleHub.sol:66

Step 1: 修改 initialize() 修饰符

OracleHub.sol 第 66 行的 onlyCallFromBootloader 改为 onlySystemCall

// 修改前 (line 66):
) external onlyCallFromBootloader {

// 修改后:
) external onlySystemCall {

同时更新注释(第 60 行):

// 修改前 (line 60):
/// @dev Uses onlyCallFromBootloader since genesis deploys run as bootloader.

// 修改后:
/// @dev Uses onlySystemCall to allow post-genesis initialization via system call.

Step 2: 编译系统合约验证

Expected: 编译成功,无 error。

Step 3: 运行 Foundry 测试回归

Expected: 所有 OracleHub 测试通过(19 tests in OracleHubLocal 不受影响,因为 OracleHubLocal 使用独立的 admin 访问控制)。

Step 4: Commit


Task 2: 环境清理 (Docker + PostgreSQL)

目标: 停止旧容器、清理旧数据库,为全新 genesis 做准备。

Step 1: 停止所有 Docker 容器

确认容器已停止:

Expected: 无 reth/postgres 相关容器运行。

Step 2: 清理 PostgreSQL 数据库

查看当前数据库列表:

删除旧数据库并重建:

Expected: DROP DATABASE 成功(或 "does not exist")。

Step 3: 清理 era-core 生成的配置文件

Step 4: 重新启动 Docker 容器

验证容器运行:

Expected: reth (port 8545) 和 postgres (port 5432) 运行中。

Step 5: 验证 L1 reth 节点

Expected: 0x9 (chain_id = 9)

Step 6: 验证 PostgreSQL 连接

Expected: 返回 1


Task 3: 编译系统合约 + Bootloader

目标: 编译包含 OracleHub (onlySystemCall) + DID 合约的完整系统合约集和 bootloader。

前提: Task 1 已修改 OracleHub.sol,Task 2 环境已就绪。

Step 1: 确认 Node.js 版本

Expected: v20.x.x(v24 会导致 hardhat-zksync-solc 错误)

Step 2: 预处理 + 编译系统合约

Expected: 编译 44 个系统合约成功(包括 OracleHub 0x8016, DIDRegistry 0x8017, CredentialRegistry 0x8018, IdentityVerifier 0x8019)。

Step 3: 预处理 + 编译 Bootloader

Expected: 7 个 bootloader 变体编译成功。新的 bootloader 不含 Oracle memory slot 代码(已在 Phase 2.5b 移除),SCRATCH_SPACE_BEGIN_SLOT = 8。

Step 4: 编译 L1 合约

Expected: L1 合约编译成功。

Step 5: 验证 bootloader hash 已更新

bootloader hash 会在编译后自动更新到 artifacts。zkstack ecosystem init 会读取这些 artifacts 生成 genesis config。

Expected: 存在 proved_batch.yul.zbin 等 artifact 文件。


Task 4: zkstack ecosystem init (L1 合约 + Genesis)

目标: 使用 zkstack 部署 L1 合约到本地 reth,生成包含 44 个系统合约的 genesis block。

前提: Task 2(环境就绪)+ Task 3(合约已编译)。

⚠️ 重要:关闭系统代理再执行!

Step 1: 运行 zkstack ecosystem init

按照交互提示选择:

  • 部署 L1 合约到 http://127.0.0.1:8545(本地 reth)

  • Chain name: era

  • Chain ID: 271

  • Prover mode: NoProofs

  • VM type: EraVM

  • L1 batch commit data generator mode: Rollup

  • 数据库 URL: postgres://judybaby@localhost:5432/postgres(⚠️ 必须指定 /postgres

Expected:

  • 生态系统合约部署(Bridgehub, Diamond Proxy, Verifier, Governance)

  • ERC20 测试代币部署

  • Chain "era" 注册 (chain_id: 271)

  • Genesis block 生成(包含 44 个系统合约)

  • 数据库初始化

Step 2: 验证 genesis 配置生成

Expected: 新的 GENESIS_ROOTGENESIS_BATCH_COMMITMENT 等值已更新。

Step 3: 验证数据库已初始化

Expected: 存在新创建的 zksync 数据库。

故障排除:

  • 如果出现代理错误:确保 http_proxy 已 unset

  • 如果出现数据库错误:确保 DB URL 以 /postgres 结尾

  • 如果出现 forge build 错误:确保使用 foundry-zksync 而非标准 foundry


Task 5: 启动 zksync_server + 验证 API

目标: 启动节点,验证 API 正常工作,确认 genesis 包含正确的系统合约。

Step 1: 启动 zksync_server

等待日志显示 State Keeper 和 API Server 启动完成:

  • State Keeper: processing L1 batch...

  • API Server: JSON-RPC on http://127.0.0.1:3050

Step 2: 验证链 ID

Expected: 0x10f (271)

Step 3: 验证 L1 chain ID

Expected: 0x9 (9)

Step 4: 验证区块持续增长

Expected: 区块号持续增长。

Step 5: 验证 OracleHub 系统合约已部署

Expected: 返回非空 bytecode(0x... 大量数据)。

Step 6: 验证 DID 系统合约已部署

Expected: 三个地址均返回非空 bytecode。


Task 6: 合约初始化 (OracleHub + setOperator)

目标: 通过 cast 交易调用 OracleHub.initialize() 和 setOperator(),完成 post-genesis 初始化。

前提: Task 5(节点运行中)。

Step 1: 确认 fee_account (operator) 地址

查看配置中的 fee_account 地址:

Expected: 0xde03a0B5963f75f1C8485B355fF6D30f3093BDE7 或当前配置的地址。

同时需要确认 operator 的私钥(zkstack 生成的 rich wallet):

Step 2: 准备 symbol hashes

Step 3: 调用 OracleHub.initialize()

⚠️ 需要使用 isSystem: true 标志发送系统调用交易。由于 cast send 不直接支持 isSystem flag,使用 zkSync 的 EIP-712 交易格式:

Expected: 交易成功 (status: 1)。

⚠️ 如果 cast --zksync 不支持 isSystem flag:

  • 可能需要编写简短的 Node.js/TypeScript 脚本使用 zksync-ethers SDK 发送系统调用

  • 或者在 OracleHub.sol 中将 initialize() 改为无权限修饰符(只保留 require(stalenessThreshold == 0) 防重入)

Step 4: 验证初始化成功

Expected:

  • stalenessThreshold = 60

  • operator = fee_account 地址

Step 5: 调用 setOperator() (如需更新 operator)

Expected: 交易成功 (status: 1)。

Step 6: 验证 symbol 支持

Expected: true


Task 7: E2E 验证 (Oracle + DID + Bridge)

目标: 端到端验证 Oracle 价格注入、DID 系统、L1→L2 Bridge 所有功能。

前提: Task 6(合约初始化完成)、节点+Oracle后台运行中。

Step 1: 启动 Oracle 后台服务

如果 Oracle 后台未自动启动(取决于 zkstack 配置),手动启动:

⚠️ 注意: Oracle 服务是通过 OracleWiringLayer 集成到 zksync_server 的。如果 zksync_server 没有加载 Oracle 配置,可能需要单独的 Oracle 服务进程,或确认 MempoolIO 已连接 SharedOracleService。

Step 2: 验证 Oracle 价格查询

等待 Oracle 后台至少运行一个 fetch 周期(12 秒)后:

Expected: 返回非零价格和时间戳(price > 0, timestamp > 0)。

如果返回 0/0,说明 Oracle operator tx 尚未注入价格。检查:

  • zksync_server 日志中是否有 Oracle tx injected 日志

  • SharedOracleService 是否有价格数据

Step 3: 验证 DID 创建

Expected: 交易成功 (status: 1)。

Step 4: 验证 DID 查询

Expected: 返回非空 DID 文档数据(包含 publicKeys 和 authMethod)。

Step 5: L1→L2 Deposit

Expected: L1 交易成功。

Step 6: 验证 L2 余额增加

等待约 10 秒让 deposit 被处理:

Expected: 余额 > 0(如果 wallet 之前没有余额)。

Step 7: 验证 Batch 提交到 L1

检查 zksync_server 日志中是否有 CommitBlocks 交易。

Step 8: 综合验证清单

#
验证项
命令
期望结果
状态

1

链 ID

cast rpc eth_chainId --rpc-url localhost:3050

0x10f (271)

2

OracleHub 已部署

cast code 0x...8016 --rpc-url localhost:3050

非空

3

OracleHub 已初始化

cast call 0x...8016 "stalenessThreshold()"

60

4

Oracle 价格

cast call 0x...8016 "getLatestPrice(bytes32)" $ETH_HASH

非零

5

DID 创建

cast send 0x...8017 "createDID(...)"

status=1

6

DID 查询

cast call 0x...8017 "getDocument(address)"

非空

7

L1→L2 Deposit

cast send bridgehub ... --value 1ether

status=1

8

L2 余额

cast balance $ADDR --rpc-url localhost:3050

> 0

9

DIDRegistry 已部署

cast code 0x...8017

非空

10

CredentialRegistry 已部署

cast code 0x...8018

非空

11

IdentityVerifier 已部署

cast code 0x...8019

非空


Task 8: dev-log 更新

目标: 记录 genesis 重部署的完整过程、结果和踩坑记录。

Files:

  • Modify: docs/dev-log.md

Step 1: 在 dev-log 末尾追加 Genesis 重部署条目

docs/dev-log.md 末尾添加:

Step 2: Commit

Last updated