Skip to content

feat(relay): support relaying all bundles from a tx with --all#27

Open
vibelyova wants to merge 3 commits intomm-zk-codex:mainfrom
vibelyova:feature/multi-bundle-relay
Open

feat(relay): support relaying all bundles from a tx with --all#27
vibelyova wants to merge 3 commits intomm-zk-codex:mainfrom
vibelyova:feature/multi-bundle-relay

Conversation

@vibelyova
Copy link
Copy Markdown

@vibelyova vibelyova commented Mar 4, 2026

Problem

bundle relay only ever processed the first InteropBundleSent event in a transaction. Any transaction that emits multiple bundles (e.g. a batched operation sending to several destination chains) would have all bundles after the first one permanently stranded — with no error or warning.

The --msg-index flag existed to pick a specific bundle, but the bundle-selection code always selected the first InteropBundleSent regardless of the flag's value, so it had no real effect.

Solution

  • Add --all flag to bundle relay. When set, every InteropBundleSent in the receipt is relayed in sequence (proof → root → execute/verify for each).
  • Fix --msg-index to actually select the bundle with that index. If no bundle matches, a clear error suggests using --all.
  • Extract find_bundle_log_positions — the core function that scans logs in order, counts L1MessageSent events from 0x8008, and derives the correct msg_index for each bundle. This matches the logic already used by auto-relay but was missing from the relay command.

Usage

Relay all bundles from a tx (new):

cast-interop bundle relay \
  --chain-src era --chain-dest test \
  --tx 0xSOURCE_TX_HASH \
  --all \
  --private-key $PRIVATE_KEY

Relay a specific bundle by index (fixed):

cast-interop bundle relay \
  --chain-src era --chain-dest test \
  --tx 0xSOURCE_TX_HASH \
  --msg-index 1 \
  --private-key $PRIVATE_KEY

When using --all with --out-dir, each bundle's artifacts are written with a _{msg_index} suffix (bundle_0.hex, proof_0.json, etc.) to avoid overwrites.

Tests

9 unit tests added for find_bundle_log_positions covering:

  • Empty log list
  • Single bundle
  • Two sequential bundles with correct msg_index values
  • Unrelated L1MessageSent events before the first bundle shifting indices
  • L1MessageSent events from wrong addresses (not counted)
  • Bundles from wrong InteropCenter address (not returned)
  • Bundle appearing before any L1MessageSent (saturating_sub edge case)
  • Mixed centers in same receipt

Additional fixes (code review follow-up)

Critical

  • Fix panics on user input: root_wait called .unwrap() on parse_b256 from --expected-root (panics on bad hex); abi.rs called .unwrap() on U256→u64 conversion in decode_bundle_status/decode_call_status. Both now use ? error propagation.
  • Fix tx show ignoring --center overrides: was hardcoded to INTEROP_CENTER_ADDRESS constant instead of using the resolved AddressBook, so config and CLI overrides had no effect.
  • Fix relay not waiting for destination tx receipt: sent the handler tx and reported success without checking if it reverted on-chain. Now waits for receipt and bails on revert, matching send and token commands.

Important

  • Fix bundle extract only extracting the first bundle: silently ignored multi-bundle transactions. Added --all and --msg-index flags reusing the same extract_bundles logic from relay.
  • Fix dead require_signer_or_dry_run in send.rs: the check was called after the dry_run branch had already returned, making it unreachable. Moved before the branch so it actually validates.
  • Add --private-key-env to auto-relay: was the only command without it, forcing users to pass keys on the command line (visible in ps and shell history).

Minor

  • Fix debug println! corrupting --json output: tx_show printed "Decoding L1MessageSent event..." to stdout; bundle_action printed debug messages to stdout. Moved to eprintln or removed.
  • Remove write_relay_outputs unnecessary async: function did only synchronous fs::write calls.
  • Remove unnecessary calldata.clone() in relay dry-run branch.
  • Remove unused INTEROP_CENTER_ADDRESS constant from types.rs.
  • Fixed all pre-existing cargo clippy -- -D warnings errors (redundant closures, clone on Copy types, dead code branch in doctor.rs, import hygiene, etc.).

🤖 Generated with Claude Code

vibelyova and others added 3 commits March 4, 2026 17:49
Previously `bundle relay` only processed the first InteropBundleSent
event in a tx, silently ignoring any additional bundles. Transactions
that emit multiple bundles (batched operations) would have all but
the first bundle stranded on the source chain.

Changes:
- Add `--all` flag to `bundle relay`; when set, every InteropBundleSent
  event in the receipt is relayed in sequence.
- Extract `find_bundle_log_positions` to compute the correct msg_index
  for each bundle by counting L1MessageSent events from 0x8008 in log
  order — matching the logic already used by `auto-relay`.
- Extract `extract_bundles` which pairs ABI decoding with the index
  computation; used by the relay command.
- Without `--all`, the existing `--msg-index` flag (default 0) selects
  a specific bundle; an actionable error is emitted if not found.
- Output artifacts (bundle.hex, proof.json, relay_summary.json) are
  written with a `_{msg_index}` suffix when multiple bundles are relayed
  so the files don't overwrite each other.
- Add 9 unit tests covering `find_bundle_log_positions` edge cases.

Also fix pre-existing clippy warnings across the codebase so the
project passes `cargo clippy -- -D warnings`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Make write_relay_outputs a sync fn (it does no async work)
- Remove unnecessary calldata.clone() in dry-run branch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace unwrap/expect on user input with proper error propagation
  (root_wait parse_b256, abi decode_bundle_status/decode_call_status)
- Fix tx_show using hardcoded INTEROP_CENTER_ADDRESS instead of
  resolved AddressBook (--center override and config had no effect)
- Fix relay not waiting for destination tx receipt (tx could revert
  silently; now waits and checks receipt status like send/token do)
- Fix bundle extract only extracting first bundle; add --all and
  --msg-index flags to match relay command behavior
- Fix send.rs require_signer_or_dry_run being dead code (called
  after dry_run branch already returned); move check before branch
- Add --private-key-env to auto-relay (was the only command without
  it, forcing users to pass keys on the command line)
- Move debug println in tx_show and bundle_action to eprintln to
  avoid corrupting --json output
- Remove unused INTEROP_CENTER_ADDRESS constant

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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