Skip to content

Snowbridge: drop outbound-queue-v2 message leaves from state#12211

Open
dimartiro wants to merge 3 commits into
paritytech:masterfrom
dimartiro:snowbridge/7971-drop-message-leaves
Open

Snowbridge: drop outbound-queue-v2 message leaves from state#12211
dimartiro wants to merge 3 commits into
paritytech:masterfrom
dimartiro:snowbridge/7971-drop-message-leaves

Conversation

@dimartiro
Copy link
Copy Markdown
Contributor

Description

The outbound-queue-v2 pallet stored the per-message merkle leaves in the MessageLeaves storage value and only
cleared them at the start of the next block. As a result the leaves persisted in state across blocks and were
needlessly included in the PoV, even though they are only required to build the commitment root and to generate proofs
off-chain.

This PR makes MessageLeaves truly transient: the leaves are still appended during block execution to build the merkle
root, but the value is now killed within the same block, right after the commitment is produced in commit(). The
committed root inserted into the header digest is unchanged.

Closes #7971

Integration

No integration steps are required for downstream runtimes. The change is internal to the outbound-queue-v2 pallet:

  • The on-chain commitment (merkle root in the header digest) is computed exactly as before, so relayers and the
    Ethereum-side verification are unaffected.
  • The prove_message runtime API keeps the same signature and return value; it now recomputes the leaves from
    Messages instead of reading MessageLeaves.
  • MessageLeaves is no longer expected to be present in state after a block; any tooling that read it directly (there
    should be none, as it was transient by design) must recompute leaves from Messages instead.

Review Notes

  • commit() now calls MessageLeaves::kill() immediately after building the root, so the value never persists beyond
    the block in which it is produced and never enters the PoV.
  • Because the leaves are no longer stored, the prove_message runtime API reconstructs them from the Messages
    storage, in the same order they were appended during block execution, so leaf_index stays valid. This API is read
    off-chain only, so reading Messages here does not enter any block's PoV.
  • Leaf computation (Keccak256 of the ABI-encoded message) was extracted into a single Pallet::message_leaf helper,
    shared by message processing and proof generation, so both always produce identical leaves.
  • The MessageLeaves::kill() in on_initialize is kept as a defensive cleanup that also removes any value left
    persisted by a pre-upgrade runtime.
  • New test prove_message_recomputes_committed_leaves_after_commit asserts that, after commit drops the leaves,
    proofs recomputed from Messages still verify against the very same root committed on-chain.

Checklist

  • My PR includes a detailed description as outlined in the "Description" and its two subsections above.
  • My PR follows the labeling requirements of this project (at minimum one label for T required)
  • I have made corresponding changes to the documentation (if applicable)
  • I have added tests that prove my fix is effective or that my feature works (if applicable)

@dimartiro dimartiro force-pushed the snowbridge/7971-drop-message-leaves branch from 0340bb0 to e8988a0 Compare May 27, 2026 01:21
@paritytech-review-bot paritytech-review-bot Bot requested a review from a team May 27, 2026 01:21
@dimartiro
Copy link
Copy Markdown
Contributor Author

/cmd bench --pallet snowbridge_pallet_outbound_queue_v2 --runtime bridge-hub-westend

@github-actions
Copy link
Copy Markdown
Contributor

Command "bench --pallet snowbridge_pallet_outbound_queue_v2 --runtime bridge-hub-westend" has started 🚀 See logs here

@github-actions
Copy link
Copy Markdown
Contributor

Command "bench --pallet snowbridge_pallet_outbound_queue_v2 --runtime bridge-hub-westend" has failed ❌! See logs here

Details

Command output:

✅ Successful benchmarks of runtimes/pallets:
-- bridge-hub-westend: ['snowbridge_pallet_outbound_queue_v2']

@dimartiro dimartiro force-pushed the snowbridge/7971-drop-message-leaves branch from a5c7518 to f2ab526 Compare May 27, 2026 14:04
@dimartiro dimartiro force-pushed the snowbridge/7971-drop-message-leaves branch from aed6100 to b5c6eab Compare May 27, 2026 22:24
@dimartiro
Copy link
Copy Markdown
Contributor Author

@acatangiu You might be interested in this

@yrong
Copy link
Copy Markdown
Contributor

yrong commented May 29, 2026

Nice improvement! Some potential issues and suggestions came up from AI review — not directly related to the changes in this PR, but still worth taking a look at. Just FYI.

  • prove_message can still panic for an out-of-range leaf_index

merkle_proof() panics if leaf_index >= number_of_leaves. Since prove_message() returns Option, it would be cleaner and safer to return None for out-of-range
indexes:

if leaf_index >= messages.len() as u64 {
return None;
}

This is not newly introduced by the PR — the old implementation had the same risk if MessageLeaves existed — but this PR is touching the API logic, so it is a good opportunity
to fix it.

Relevant location: bridges/snowbridge/pallets/outbound-queue-v2/src/api.rs:11.

  • Benchmark setup may not use the same leaf encoding as production

In benchmarking, initialize_with_one_message() still does:

let leaf = ::Hashing::hash(&message.encode());

at bridges/snowbridge/pallets/outbound-queue-v2/src/benchmarking.rs:70.

Production now uses Pallet::::message_leaf(&outbound_message), which hashes the ABI-encoded OutboundMessageWrapper, not the SCALE-encoded Message.

For weight benchmarking, the exact hash value probably does not affect cost much because it is still one H256 per message. But for consistency and future-proofing, I would
prefer the benchmark to use the same helper:

let leaf = OutboundQueue::::message_leaf(&outbound_message);

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.

[Snowbridge v2] storage optimization: MessageLeaves not stored but built in runtime api

2 participants