diff --git a/crates/miden-lib/asm/agglayer/note_scripts/B2AGG.masm b/crates/miden-lib/asm/agglayer/note_scripts/B2AGG.masm index 73ea4a1124..7df3ffd65e 100644 --- a/crates/miden-lib/asm/agglayer/note_scripts/B2AGG.masm +++ b/crates/miden-lib/asm/agglayer/note_scripts/B2AGG.masm @@ -2,6 +2,7 @@ use.agglayer::bridge_out -> agglayer use.miden::account_id use.miden::active_account use.miden::active_note +use.miden::note # CONSTANTS # ================================================================================================= @@ -14,11 +15,34 @@ const.ERR_B2AGG_WRONG_NUMBER_OF_ASSETS="B2AGG script requires exactly 1 note ass const.ERR_B2AGG_WRONG_NUMBER_OF_INPUTS="B2AGG script expects exactly 6 note inputs" +const.ACTIVE_ACCOUNT_TAG_DOES_NOT_MATCH_TARGET="B2AGG note tag does not match active account ntx tag" + +# Verifies that the consuming account is the bridge contract by comparing note tags. +# Panics if the B2AGG note's tag doesn't match the consuming account's network tag. +#! +#! Inputs: [account_id_prefix, account_id_suffix] +#! Outputs: [] +proc assert_account_id_is_target + # => [account_id_prefix, account_id_suffix] + + exec.note::build_note_tag_for_network_account + # => [active_account_tag] + + exec.active_note::get_metadata + # => [METADATA, active_account_tag] + + drop swap drop swap drop + # => [b2agg_tag, active_account_tag] + + eq assert.err=ACTIVE_ACCOUNT_TAG_DOES_NOT_MATCH_TARGET + # => [] +end + #! Bridge-to-AggLayer (B2AGG) note script: bridges assets from Miden to an AggLayer-connected chain. #! #! This note can be consumed in two ways: #! - If the consuming account is the sender (reclaim): the note's assets are added back to the consuming account. -#! - If the consuming account is the Agglayer Bridge: the note's assets are moved to a BURN note, +#! - If the consuming account is the Agglayer Bridge: the note's assets are moved to a BURN note, #! and the note details are hashed into a leaf and appended to the Local Exit Tree. #! global exit root (GER) merkle tree structure. #! @@ -44,19 +68,28 @@ begin # Check if reclaim exec.active_account::get_id - # => [account_id_prefix, account_id_suffix, pad(16)] + # => [id_prefix, id_suffix, pad(16)] + + dup.1 dup.1 + # => [id_prefix, id_suffix, id_prefix, id_suffix, pad(16)] exec.active_note::get_sender - # => [sender_id_prefix, sender_id_suffix, account_id_prefix, account_id_suffix, pad(16)] + # => [sender_id_prefix, sender_id_suffix, id_prefix, id_suffix, id_prefix, id_suffix, pad(16)] exec.account_id::is_equal - # => [reclaim, pad(16)] + # => [reclaim, id_prefix, id_suffix, pad(16)] # B2AGG note is being reclaimed; adding note assets to account if.true + drop drop + # => [pad(16)] + exec.active_note::add_assets_to_account # => [pad(16)] else + exec.assert_account_id_is_target + # => [pad(16)] + # Store note inputs -> mem[8..14] push.8 exec.active_note::get_inputs # => [num_inputs, dest_ptr, pad(16)] diff --git a/crates/miden-testing/tests/agglayer/bridge_out.rs b/crates/miden-testing/tests/agglayer/bridge_out.rs index 21d8351509..60a5395dc5 100644 --- a/crates/miden-testing/tests/agglayer/bridge_out.rs +++ b/crates/miden-testing/tests/agglayer/bridge_out.rs @@ -60,7 +60,7 @@ async fn test_bridge_out_consumes_b2agg_note() -> anyhow::Result<()> { let storage_slots = vec![StorageSlot::with_empty_map(storage_slot_name)]; let bridge_component = bridge_out_component(storage_slots); let account_builder = Account::builder(builder.rng_mut().random()) - .storage_mode(AccountStorageMode::Public) + .storage_mode(AccountStorageMode::Network) .with_component(bridge_component); let mut bridge_account = builder.add_account_from_builder(Auth::IncrNonce, account_builder, AccountState::Exists)?; @@ -70,7 +70,7 @@ async fn test_bridge_out_consumes_b2agg_note() -> anyhow::Result<()> { let amount = Felt::new(100); let bridge_asset: Asset = FungibleAsset::new(faucet.id(), amount.into()).unwrap().into(); - let tag = NoteTag::for_local_use_case(0, 0).unwrap(); + let tag = NoteTag::from_account_id(bridge_account.id()); let aux = Felt::new(0); let note_execution_hint = NoteExecutionHint::always(); let note_type = NoteType::Public; // Use Public note type for network transaction @@ -217,6 +217,13 @@ async fn test_b2agg_note_reclaim_scenario() -> anyhow::Result<()> { AccountStorageMode::Private, ); + let bridge_account_id = AccountId::dummy( + [1; 15], + AccountIdVersion::Version0, + AccountType::RegularAccountImmutableCode, + AccountStorageMode::Network, + ); + // Create a network faucet to provide assets for the B2AGG note let faucet = builder.add_existing_network_faucet("AGG", 1000, faucet_owner_account_id, Some(100))?; @@ -229,7 +236,7 @@ async fn test_b2agg_note_reclaim_scenario() -> anyhow::Result<()> { let amount = Felt::new(50); let bridge_asset: Asset = FungibleAsset::new(faucet.id(), amount.into()).unwrap().into(); - let tag = NoteTag::for_local_use_case(0, 0).unwrap(); + let tag = NoteTag::from_account_id(bridge_account_id); let aux = Felt::new(0); let note_execution_hint = NoteExecutionHint::always(); let note_type = NoteType::Public;