test(#18): relayer message enumeration + MessageIdMultisig metadata parity - #35
Merged
Merged
Conversation
…arity Verify the relayer's outbound half for Midnight-origin messages against committed offline fixtures (no node/prover), following #17's methodology. - indexer.rs: dispatch_enumerates_committed_fixture_in_sequence drives the real decode_dispatch_snapshot + fetch_dispatch_logs range logic over the #16 fixture, asserting enumeration with sequence == nonce. - metadata_tests.rs (new): assert the assembled MessageIdMultisig metadata blob (merkleTreeHook || root || index(BE) || sigs) matches the byte layout a standard destination ISM reads, and run the exact forward-only two-pointer verification recovering an ascending M-of-N signer subset. - hyperlane-metadata-vector.json: offline 2-of-3 metadata reference vector.
Address REVIEW-18 gaps #5 and #6: - The signing subset is now descending by address while ascending by set index, so the forward-only two-pointer verification adversarially proves ordering is enforced by set index, not by address (the old {0,2} subset was ascending under both orderings). Adds an explicit descending-address assert. - Assert digest parity (signing_hash == inner, eth_signed_message_hash == digest) against the independent @hyperlane-xyz/utils oracle, consuming the previously-dead vector fields and localising a digest regression to a clear failure instead of a confusing signer-not-in-set.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
#18 — Relayer: message + metadata indexer for Midnight
Verification + test coverage for the relayer's outbound half (Midnight as ORIGIN). Research confirmed the relayer's message enumeration and
MessageIdMultisigMetadataBuilderare entirely chain-agnostic — once the Midnight crate supplies the dispatch indexer (#16), merkle indexer (#15), chain-sourced ISM (#14), and ValidatorAnnounce (#33), and the validator signs standard checkpoints (#17), the relayer lists Midnight-origin messages and builds standard metadata with zero per-chain code. So #18 is verification + tests, same shape as #17 (no new production code).What's here (offline, no node/prover)
indexer.rs::dispatch_enumerates_committed_fixture_in_sequence— decodes the real fix(cardano): prevent consumption of ref script UTXOs #16 fixture (night-state-dispatched.hex) through the productiondecode_dispatch_snapshotand drives the actualfetch_dispatch_logsrange logic, asserting the relayer enumerates both dispatches withIndexed.sequence == nonceand that the messages are the fixture's decoded messages (same keccak ids the merkle indexer / validator anchor on). Covers AC 1 ("lists pending Midnight-origin messages").metadata_tests.rs(new module) — asserts the assembled MessageIdMultisig metadata blob (merkleTreeHook || root || index(BE) || sigs) matches the68 + 65*thresholdbyte layout a standard destination ISM reads, then runs the exact destination-side verification: recovers every signature and matches the validator set with a forward-only two-pointer, proving the signers are the ascending{0, 2}subset (index 1 skipped) and the blob is consumable unchanged by a stock EVMMessageIdMultisigIsm. Covers AC 2 ("consumable by standard ISM verifiers"). Drift-guards the committedhyperlane-metadata-vector.jsonagainst the fixture (root/index/messageId), same as fix(cardano): fix minted amount #17.The metadata vector is generated offline by
generate-metadata-vector.tsin the contracts repo (equilibriumco/hyperlane-midnight#78), using the same two-dispatch Compact-simulator scenario as the #17 checkpoint vector and the independent@hyperlane-xyz/utilsdigest oracle. Itsrootand validator-0 signature match #17's checkpoint vector byte-for-byte.Caveats investigated and cleared (not on the relay path, no fix)
MidnightMailbox::count()returnsOk(0)— confirmed no production caller chain-wide; the relayer's origin sequence comes from the dispatch indexer'snonce_count.Large-host live outbound relayer run deferred to the outbound E2E (#26).
Tests
cargo test -p hyperlane-midnight: 70 passed, 0 failed. Clippy clean.Closes #18.