feat(AggLayer claim e2e #4): e2e bridge-in flow with real bridge data#2413
feat(AggLayer claim e2e #4): e2e bridge-in flow with real bridge data#2413mmagician merged 18 commits intoagglayer-newfrom
Conversation
19cb775 to
778b6e7
Compare
be37f12 to
43fbf27
Compare
There was a problem hiding this comment.
a lot of the test vectors have duplicated data, maybe we could eventually create one big test vector, but it's not a priority right now
Fumuran
left a comment
There was a problem hiding this comment.
Looks great! I left a few questions and proposals inline.
| # Merkle path is guaranteed to contain 32 nodes | ||
| repeat.32 | ||
| # load the Merkle path node onto the stack | ||
| mem_stream |
There was a problem hiding this comment.
I wonder do we have an incorrect documentation for the mem_stream instruction or it was just already updated to work with the latest VM which uses LE.
If we have [1, 2, 3, 4, 5, 6, 7, 8] memory layout, where 1 is placed at memory address 0 and 8 at memory address 7, then the mem_stream will load this double word onto the stack in the reversed order: [8, 7, 6, 5, 4, 3, 2, 1], where 8 is placed at the top. At the same time in the mem_stream docs it is written:
Stack transition: [C, B, A, a, ... ] -> [E, D, A, a', ... ], where
[E, D] ← [mem[a..(a+4)], mem[(a+4)..(a+8)]], a' ← a+8.
So it describes the transition in LE, not BE.
Also the necessity of whiting the LE mem_stream by your own made me think whether should we create the LE version of the mem_stream (the same way it was done with mem_storew_le and the others) and rename the current mem_stream into the mem_stream_be.
partylikeits1983
left a comment
There was a problem hiding this comment.
This is awesome! Looks great!
Great to see the actual claim in bridge data being finally used in the claim note test!!!!
| // Note: We intentionally do NOT verify the exact note ID or asset amount here because | ||
| // the scale_u256_to_native_amount function is currently a TODO stub that doesn't perform | ||
| // proper u256-to-native scaling. The test verifies that the bridge-in flow correctly | ||
| // validates the Merkle proof using real cryptographic proof data and creates an output note. | ||
| // | ||
| // TODO: Once scale_u256_to_native_amount is properly implemented, add: | ||
| // - Verification that the minted amount matches the expected scaled value | ||
| // - Full note ID comparison with the expected P2ID note | ||
| // - Asset content verification |
There was a problem hiding this comment.
Just FYI, the procedure that checks the u256 amount to Felt scaling amount needs the Felt amount to be provided via NoteStorage
12c5dda to
df775f2
Compare
chore: add claim test gen to makefile
… compatibility The keccak256::merge MASM function applies word::reverse to its input words before hashing. mem_stream (used to load SMT proof nodes) does NOT apply per-word reversal, while loc_loadw_be (used to load the current hash) DOES. To produce consistent per-word reversed format on the stack for both the current hash (via loc_storew_be/loc_loadw_be) and the path nodes (via mem_stream), SMT proof nodes must be stored in fully reversed element order in memory. Exit roots are per-word reversed because they are loaded via mem_load_double_word (which uses mem_loadw_be), and the per-word reversal by mem_loadw_be undoes the storage reversal to produce natural order on the stack. Also adds diagnostic and integration tests for Merkle proof verification using claim_asset_vectors data. Co-authored-by: marti <marti@hungrycats.studio> fix: simplify bridge_in test assertions for stubbed scale function The test now correctly verifies that the bridge-in flow validates the Merkle proof and creates an output note, without asserting specific note content that depends on the stubbed scale_u256_to_native_amount function. Removes diagnostic test test_claim_asset_verify_leaf_via_advice_map which has a stack management issue unrelated to the core fix. Co-authored-by: marti <marti@hungrycats.studio> chore: fix warnings and remove diagnostic test - Remove unused imports (Asset, NoteRecipient, NoteStorage) - Remove unused leaf_elements variable - Remove test_claim_asset_verify_leaf_via_advice_map diagnostic test (covered by test_bridge_in_claim_to_p2id) Co-authored-by: marti <marti@hungrycats.studio> refactor: use data-level fix without MASM changes The keccak256::merge function (from external miden-core-lib) applies word::reverse internally and expects per-word reversed input. Since loc_loadw_be naturally produces per-word reversal, changing to loc_loadw_le would break merge's byte ordering. Instead, fix at the data level: - SMT proof nodes: fully reversed (to_memory_elements) so mem_stream's half-swap produces per-word reversed format matching loc_loadw_be output - Exit roots: per-word reversed (to_word_reversed_elements) so mem_load_double_word's mem_loadw_be reversal produces natural order - No MASM code changes needed Co-authored-by: marti <marti@hungrycats.studio> chore: remove diagnostic tests Remove 7 diagnostic/exploratory tests that were added during debugging. The pre-existing tests (pack_leaf_data, get_leaf_value, test_solidity_verify_merkle_proof_compatibility) plus the fixed test_bridge_in_claim_to_p2id provide sufficient coverage. Co-authored-by: marti <marti@hungrycats.studio>
Replace mem_stream (which requires RPO hasher state padding) with two explicit mem_loadw_be calls for loading Merkle path nodes. This uses the same instruction as loc_loadw_be for the current hash, ensuring both undergo identical element ordering. The change eliminates 12 elements of RPO padding from the stack, simplifies pointer management, and makes the memory access pattern more explicit. Co-authored-by: marti <marti@hungrycats.studio>
- Replace loc_storew_be/loc_loadw_be with loc_storew_le/loc_loadw_le - Replace mem_load_double_word with inline mem_loadw_le - Replace mem_store_double_word with inline mem_storew_le - Update canonical_zeros.masm and build.rs to use mem_storew_le Co-authored-by: marti <marti@hungrycats.studio> chore: update mem_load/store_double_word to LE and resolve TODO - Update utils.masm: mem_storew_be -> mem_storew_le, mem_loadw_be -> mem_loadw_le - Replace inline mem_loadw_le in crypto_utils.masm with exec.utils::mem_load_double_word - Restore mem_load/store_double_word usage in mmr_frontier32_keccak.masm and canonical_zeros.masm - Update stale comment in claim_note.rs Co-authored-by: marti <marti@hungrycats.studio>
4bf984c to
e8c4306
Compare
Changes:
ProofDataelements (exit roots, merkle paths) to use LE orderingloc_storew_be ... loc_loadw_beorloc_storew_le ... loc_loadw_le)claimAssettx on Katana on Katana to a Miden-like address0x00000000b0E79c68cafC54802726C6F102Cca300addresson L1 must be decodable into a MidenAccountIdThis concludes the PR tower: we now fully verify the data inside the
CLAIMnote.What's missing for a full integration is actually checking that the GER we compute is part of onchain storage, which is tackled separately in #2388