feat(gnode): difftx 封装 + 参数化 7702 模板 + 同块有序批量 (D2)#795
Conversation
把「机制驱动攻击工具链」的 gnode 侧接上 D1 的 Rust 差分预言机,并把内置死 场景升级成可搜索的参数化模板: - gnode difftx / difftx-exec:shell out 到兄弟 gravity-reth worktree 的 difftx / difftx_exec 二进制(cargo run,GRAVITY_RETH_DIR 可配),透传输出 + 退出码(3=停链缺口/执行背离,0=干净),命中时指向 difftx-repro/*.json 复现 工件。纯静态、无需集群;worktree/cargo 缺失给干净错误(exit 2)。 - 7702-race 参数化场景(halt_7702_param.py,原 7702-halt 保留为稳定默认): 暴露旋钮 cross_sender_action(cross_sender|self_sponsored)/nonce_offset/ auth_count/chain_id(correct|zero|mismatched)/delegate_chain/attempts/ window,供红队 agent 搜索停链变体;不可构造的组合返回结构化 inconclusive/error 而非伪造 halt。旋钮走 PARAMS 类型校验(坏值→干净 exit 2)。 - gnode send-batch:同块有序批量发送——先全签名再按数组序背靠背 --no-wait 广播,回报 same_block/ordered_in_block/逐笔块+序。诚实标注排序边界(同发送者 连续 nonce=确定序;跨发送者=尽力而为的 fee-priority,无更强 RPC 原语)。 离线验证:gnode scenarios 列出 7702-race;difftx-exec 对 worktree 跑通(9 例 0 背离,exit 0);difftx 命中 7702 自检(exit 3);各错误路径 exit 2 无 traceback。 未跑 live 集群注入(7702-race/send-batch 的真链 halt/broadcast 未验证)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4f64dfabf3
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| for i, spec in enumerate(specs): | ||
| if not isinstance(spec, dict): | ||
| raise ValueError(f"batch[{i}] 需为对象(tx 规格),得到 {type(spec).__name__}") | ||
| raw, sender, to = _build_signed_from_spec(w3, spec) |
There was a problem hiding this comment.
Allocate pending nonces while preparing a batch
In gnode send-batch with two specs from the same account that omit nonce (allowed because each item is a normal gnode send spec and the default signer is the faucet), the pre-sign loop calls _build_signed_from_spec before any broadcast, so each call reads the same on-chain nonce via get_transaction_count. The batch then submits duplicate-nonce raw transactions; the second one is rejected or treated as an underpriced replacement instead of producing the advertised same-sender ordered batch. Minimal validation is a two-entry batch to different to addresses without explicit nonces; assign local per-sender nonces while preparing, or reject missing nonces for multi-tx senders.
AGENTS.md reference: AGENTS.md:L8-L8
Useful? React with 👍 / 👎.
| "顺序保证:同发送者连续 nonce = 块内序确定;跨发送者 = 靠 maxPriorityFeePerGas\n" | ||
| "小费定序(best-effort,非 100%)。示例:\n" |
There was a problem hiding this comment.
Accept the advertised fee-priority fields
For cross-sender batches, this help text tells operators to set maxPriorityFeePerGas, but those batch entries are still validated by _build_signed_from_spec, whose allowed field set does not include maxPriorityFeePerGas or maxFeePerGas; a batch that uses the documented ordering knob fails immediately as an unknown field before broadcasting. The cross-sender ordering mode therefore cannot be configured from gnode send-batch; either pass these EIP-1559 fields through for type 2/4 transactions or remove this documented mechanism.
AGENTS.md reference: AGENTS.md:L8-L8
Useful? React with 👍 / 👎.
| race = _inject_self_sponsored(w3, faucet, A, node_chain_id, nonce_offset=nonce_offset) | ||
| tx0_key, tx1_key = "tx0_self_create", "tx1_from_A_stale" | ||
| else: | ||
| race = _inject_race(w3, faucet, A, node_chain_id) |
There was a problem hiding this comment.
Apply nonce_offset to cross-sender races
With the default cross_sender_action=cross_sender, gnode attack 7702-race --param nonce_offset=... records the requested offset in params_used but still calls the old _inject_race, which always signs tx1 at nonce N. That makes all cross-sender nonce-offset search variants execute the same transaction shape, so an audit agent can report coverage for offsets that were never tested; pass the offset into a parameterized cross-sender injector or reject nonce_offset unless self_sponsored is selected.
AGENTS.md reference: AGENTS.md:L8-L8
Useful? React with 👍 / 👎.
review nit 修复: - difftx.py:非零退出码不再一律报「发现停链缺口/背离」——仅 rc==3 才是 gap; cargo 编译失败(101)/运行错误另给中性提示,避免 agent 把编译失败当停链。 - halt_7702_param.py:cross_sender 模式下 _inject_race 不吃 nonce_offset,过去 静默忽略却仍记进 params_used(误导)。现显式拒绝该组合(usage_error),提示改用 self_sponsored 或去掉 nonce_offset。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b10c0650fe
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| result.update({"verdict": Verdict.ERROR.value, "usage_error": True, | ||
| "detail": f"attempts 需 ≥1,得到 {attempts}"}) | ||
| return result | ||
| window = float(params.get("window", 20)) |
There was a problem hiding this comment.
Reject non-positive liveness windows
When 7702-race is run with --param window=0 or a negative value, this accepts the value and later passes it to probe_liveness, whose deadline is already expired so it skips polling and returns HALT; _evaluate then treats that as decisive before requiring the race to have formed. That can make a healthy node look like a successful halt finding from a bad parameter, so reject window <= 0 as a usage error before probing.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cca217c78c
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| from pathlib import Path | ||
|
|
||
| # 兄弟 gravity-reth worktree 默认位置;可用环境变量 GRAVITY_RETH_DIR 覆盖。 | ||
| DEFAULT_RETH_DIR = "/mnt/data2/kenji/galxe/gravity-reth-difftx" |
There was a problem hiding this comment.
Avoid defaulting difftx to a developer-local path
When GRAVITY_RETH_DIR is unset in a fresh checkout or CI job, gnode difftx follows _dispatch -> cmd_difftx -> _reth_dir() to this hard-coded /mnt/data2/... location and returns the worktree-missing usage error before invoking cargo, so the new static oracle is unusable unless operators already know to set a private environment variable. Minimal validation is unset GRAVITY_RETH_DIR; gnode difftx; derive a repo-relative sibling/default or require an explicit path instead.
AGENTS.md reference: AGENTS.md:L8-L9
Useful? React with 👍 / 👎.
移除 tools/gnode。集群攻击/PoC 工具(端到端攻击场景 + PoC 复现 harness)不宜 留在公开仓库,现迁往私有的审计工具库,与既有审计工具链并列归属。 Supersedes #795(其内容并入私有库)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
关闭:gnode 攻击/PoC 工具已整体迁往私有的审计工具库(集群攻击工具不再进公开链仓库),本 PR 的 D2 改动(difftx 封装 + 参数化 7702 模板 + 同块有序批量)一并并入私有库版本。
故本 PR 不再合入公开仓库。 |
Removes `tools/gnode`. The cluster attack / PoC tooling (end-to-end attack scenarios + a PoC reproduction harness) does not belong in a public repository. It has been relocated to a private audit-tooling repo, alongside the existing audit toolchain; future attack capabilities will land there as well, not in the public chain repo. - Deletes `tools/gnode/` only; no other code is touched. Verified there are no remaining references anywhere in the repo (`tools/` becomes empty as a result). - Supersedes #795 (the gnode changes are folded into the private-repo version). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
背景
「机制驱动攻击工具链」的 D2:把 gnode 攻击 CLI 接上 D1 的 Rust 差分预言机(见 Galxe/gravity-reth#399),并把内置的死场景升级成审计 agent 可搜索的参数化模板 —— 让红队从「只会发动内置 7702-halt」变成「能 craft 新变体」。
改了什么(仅
tools/gnode/,不碰其它)1.
gnode difftx/gnode difftx-exec—— D1 差分预言机的 gnode 封装新
gnodelib/difftx.py:shell out 到兄弟 gravity-reth worktree 的difftx/difftx_exec二进制(cargo run --features …,路径由GRAVITY_RETH_DIR配),实时透传子进程输出、原样传播退出码(3=停链缺口/执行背离,0=干净),命中时指向difftx-repro/*.json复现工件。纯静态、无需集群;worktree/manifest/cargo 缺失都给一行干净错误(exit 2),绝不抛 traceback。2.
7702-race—— 参数化的 7702 停链模板新
scenarios/halt_7702_param.py(原7702-halt保留为稳定默认)。旋钮(全走PARAMS类型校验,坏值→干净 exit 2):cross_sender_action(cross_sender|self_sponsored)、nonce_offset、auth_count、chain_id(correct|zero|mismatched)、delegate_chain、attempts、window。不可构造的组合(如delegate_chain=aba、chain_id=mismatched负对照)返回结构化inconclusive/error,不伪造 halt。3.
gnode send-batch—— 同块有序批量原语ops.py抽出_build_signed_from_spec共享给send,新增cmd_send_batch:先全签名,再按数组序背靠背--no-wait广播,回报same_block/ordered_in_block/逐笔块+序。诚实标注排序边界:同发送者连续 nonce=确定序;跨发送者=尽力而为的 fee-priority(无更强 RPC 原语)。验证
gnode scenarios列出7702-race;gnode difftx-exec对 worktree 跑通(9 例 0 背离,exit 0);gnode difftx命中 7702 自检(NonceTooLow{tx:1,state:2},写 repro,exit 3);各参数/环境错误路径 exit 2 无 traceback。7702-race真链注入与send-batch真链广播的 halt/alive 判决未验证 —— 无 live repro 声明。依赖
gnode difftx*封装依赖 Galxe/gravity-reth#399 的 difftx 二进制(通过GRAVITY_RETH_DIR指向该 worktree/仓库)。🤖 Generated with Claude Code