Skip to content

Add an independent Go runtime for the XIR execution layer - #2

Merged
lysrain21 merged 6 commits into
mainfrom
feat/go-runtime
Sep 22, 2026
Merged

lysrain21 merged 6 commits into
mainfrom
feat/go-runtime

Conversation

@lysrain21

@lysrain21 lysrain21 commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

本 PR 增加独立的 Go XIR 执行层:ABI/哈希与 Python 对齐、SQLite 持久化交易、部署与多跳执行、Hyperlane/LayerZero 本地协议投递、CLI 和 Go CI。规划、治理、分析和发布继续由 Python 承担。

此次在原 PR 分支 feat/go-runtime 上修复恢复缺陷,未新建重复 PR。旧发现和失败基线绑定 294db67dbe064bb98d3d2b23e2798f7b0f7f5949,修复快照为 53c25e3f1cea985c3b4ff321747646845323a547;base 为 main / 4966152ad92d572dbbe733cf09f2eb510f032d9f。发布前已重新核对原作者没有更新。

四项修复

  1. LayerZero 时长单位:直接使用 time.Duration,去除重复乘秒;实际异步投递测试确认首次未验证后仍能继续轮询并成功。
  2. LayerZero 重启身份漂移:从已有 DVN calldata 读取原期限,重建同一签名/计划,保留全部 durable identity 校验;DVN、commit verification、executor 各阶段中断后仅执行余下步骤。恢复 dispatch 复用已冻结费用,避免重新报价改变原交易。
  3. 根交易上链后最终确认超时:在签名前将 record_nonce 冻结到 action intent,并纳入 nonce 预留;旧版本账本缺少该字段时从原交易 RootCreated 事件恢复,保持 nonce/rid 一致。
  4. 早期 Hyperlane 消息恢复:按原 dispatch receipt 的区块哈希读取 checkpoint;同一区块多条插入时重放连续 Merkle hook 日志到原消息位置,核对消息、交易及区块身份,避免使用后续 checkpoint。

Go CI 修复

从 lock 中的官方 Hyperlane/LayerZero 提交安装依赖,构建 XIR 及两组真实协议产物;Foundry 固定 v1.5.1。CI 使用 XIR_REQUIRE_E2E=1,缺少 Anvil/产物直接失败。JSON gate 要求原 E2E、四个原复现及新增恢复测试实际 PASS,拒绝 skip、失败或缺少测试,上传测试日志。未修改 Python zero-write 流程。

本地验证与独立复审

  • 先失败后修复:原 head 上四个原始复现全部 FAIL;修复后不改动原始用例重新 overlay 执行,四项全部 PASS,失败日志保留在仓库外的审查证据目录。
  • 新鲜官方协议构建成功;全部 Go 测试、go vet ./... 通过。全量 JSON 为 160 个测试/子测试 PASS、零测试 skip;CLI 包无测试。
  • 严格真实协议 E2E:11 个顶层测试、3 个阶段子测试 PASS,无 skip。新增旧账本恢复、签名前 nonce 预留、三个 LZ 恢复阶段、外部异步投递、同区块两条 Hyperlane 消息恢复。
  • 对比重启前后 raw transaction、hash、calldata、nonce、value;已完成投递恢复时账户余额/nonce 不变;根记录、dispatch、最终 effect 和 deliveryCount 计数不重复,完成后重跑不再发交易/付费。
  • 定向 -race 检查 caller intent 和同区块并发 dispatch 恢复通过;缺少产物的真实负向检查按预期 FAIL,未计作成功 E2E。
  • 独立 reviewer 审查固定修复提交及证据,无阻塞问题;独立重跑旧根交易、LZ 三阶段、Hyperlane 同区块恢复通过。
  • tracked tree 发布检查通过;本次修复仅 17 个代码/文档/CI 文件,不含审查报告、缓存、构建产物、密钥或无关材料。

未测及边界

仅使用隔离本地 Anvil 和真实协议合约,不代表公共网络或生产就绪;没有远程部署或主网/测试网交易。历史恢复要求 RPC 提供原区块 state,必要时还需完整 hook logs;裁剪节点、远端限流及日志范围限制未验证。已冻结且在执行前过期的 DVN 指令不会自动更新签名,保持失败关闭。未改动 paper、数据或 Kaggle 材料。

CI 状态

已回读固定 head 53c25e3 的两次工作流:

  • PR Go CI:PASS;push Go CI:PASS。官方协议构建、vet、全量 Go、严格恢复 E2E 全部实际执行。两份上传的 E2E JSON 已下载复核:各 11 顶层 + 3 子测试 PASS,零 skip、零 fail。
  • Python zero-write:FAIL,uv sync --frozen 报 No interpreter found for Python 3.13.14 in managed installations or search path。该 pin 和流程已存在于 base,未作无关重写;后续 Python lint/type/tests 和该 job 的 Solidity 测试未执行,不算通过。
  • 因仍有上述基础环境失败,保留 Draft,未合并或关闭原 PR。

go-runtime/ implements the delivery, confirmation, and recovery paths of the
XIR runtime independently of the Python campaign machinery:

- internal/xir, internal/abiutil: byte-exact wire encoding and ABI packing.
- internal/state, internal/evm: durable SQLite ledger, JSON-RPC client,
  signer, and a transactor whose intent/frozen-calldata/signed/submitted
  sequence survives a restart without rebroadcasting or reusing a nonce.
- internal/artifacts, internal/deploy: Forge artifact loading, the Hyperlane
  and LayerZero stack bootstrap, the XIR application deployment, and the
  registry/adapter configuration.
- internal/layerzero, internal/hyperlane: packet/checkpoint codecs and the
  DVN/Executor and validator/relayer roles the local lab needs.
- internal/runner: attempt loop, carriers, transitions, delivery, effect
  checks, and an injected-fault hook for recovery tests.
- internal/lab: disposable anvil chains for integration tests.
- cmd/xirlab-go: CLI; keys come from environment variables only.
- scripts/generate_go_parity_vectors.py and testdata/vectors.json pin every
  derivation against the Python reference.

Verification: go vet and go test are green across the module, including an
anvil integration test that deploys both protocol stacks plus one XIR
application on three chains, executes an HL route end to end, and a recovery
test that injects a fault after the first dispatch and resumes from the same
ledger with the dispatch count unchanged.

Planning, governance gates, analysis, and publication remain Python-side; a Go
run is not a campaign result.
The GitHub runner image does not carry Python 3.13.14, so `uv sync --frozen`
aborted with "No interpreter found" before any check ran in either job.
The runner image cannot provide Python 3.13.14, so the Go job no longer runs
uv: the parity vectors are committed and regenerated locally when the Python
runtime changes, and the integration tests skip when the protocol artifacts are
absent. The pre-existing zero-write job is left exactly as it was.
The repository ignores artifacts/ because release evidence must not be
committed; that rule also swallowed go-runtime/internal/artifacts, so the Go
module did not build from a fresh checkout.
CI builds the XIR contracts but cannot build the pinned Hyperlane and LayerZero
sources, so the tests that read protocol-projects artifacts now skip with the
reason instead of failing. The deploy request validation also runs before any
artifact lookup, so a caller who mixes up routes or role addresses is told that
rather than "protocol artifacts are missing".
@lysrain21

Copy link
Copy Markdown
Owner Author

Verification summary for this branch.

Go module (cd go-runtime && go vet ./... && go test ./...) — green, 11 packages:

ok internal/abiutil   ok internal/artifacts   ok internal/deploy   ok internal/evm
ok internal/hyperlane ok internal/lab         ok internal/layerzero ok internal/runner
ok internal/state     ok internal/xir

internal/runner (43s) contains the live route proof: three disposable anvil chains with the frozen chain ids, the real Hyperlane and LayerZero stacks plus one XIR application deployed from Forge artifacts, one HL attempt executed end to end. It asserts the destination NativeMultihopEffectApplied event, deliveryCount == 1, and exactly one dispatch per carrier. TestAnvilRestartResumesWithoutDuplicateDispatch injects a fault after the first dispatch, restarts the runtime over the same ledger, and asserts the attempt completes while the dispatch count stays at one.

Parity — go-runtime/testdata/vectors.json is generated by scripts/generate_go_parity_vectors.py from the Python runtime and pins typed ids, record/context/root/message/transition/receipt hashes, prefix chains, bundle commitments, profile hashes, gateway ids, adapter keys, application payloads, the full XIRTypes.Envelope ABI encoding, the EIP-191 root signature, the LayerZero packet and DVN instruction, and the Hyperlane evidence hash. internal/xir, internal/layerzero, and internal/hyperlane compare byte for byte.

Python suite — unchanged by this branch. pytest -q reports 22 failures here and 28 on a pristine HEAD checkout of the same commit in a clean worktree; the difference is that this worktree has the Forge outputs copied in. Every failure in both runs references the same missing openspec/changes/measure-multihop-switching-scalability tree, i.e. they are pre-existing and unrelated.

CI — the new go-runtime job passes (vet + tests in a clean checkout). The zero-write job fails, but it fails on every recent main push for the same reason: the runner image cannot provide the pinned Python 3.13.14 (error: No interpreter found for Python 3.13.14), so uv sync --frozen aborts before any check runs. I left that job untouched; fixing it means revisiting the setup-uv pin, which is your call.

Boundaries — planning, governance gates, analysis, and publication stay Python-side; a Go run is not a campaign result. The integration tests use anvil because the frozen five-chain Besu QBFT topology needs at least 8 CPUs and 20 GB. No mainnet or public-testnet write path.

@lysrain21
lysrain21 marked this pull request as draft September 22, 2026 13:57
@lysrain21
lysrain21 marked this pull request as ready for review September 22, 2026 15:17
@lysrain21
lysrain21 merged commit 5f53520 into main Sep 22, 2026
2 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant