diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d6c7bf585..c6bbf6925d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Added shared `ProcedurePolicy` for AuthMultisig ([#2670](https://github.com/0xMiden/protocol/pull/2670)). - [BREAKING] Changed `NoteType` encoding from 2 bits to 1 and makes `NoteType::Private` the default ([#2691](https://github.com/0xMiden/miden-base/issues/2691)). - Added `BlockNumber::saturating_sub()` ([#2660](https://github.com/0xMiden/protocol/issues/2660)). +- [BREAKING] Stored `origin_network` in LE-packed format in AggLayer faucet storage ([#2745](https://github.com/0xMiden/protocol/pull/2745)). ## 0.14.3 (2026-04-07) diff --git a/crates/miden-agglayer/asm/agglayer/faucet/mod.masm b/crates/miden-agglayer/asm/agglayer/faucet/mod.masm index 408c0e93e1..f442a646e6 100644 --- a/crates/miden-agglayer/asm/agglayer/faucet/mod.masm +++ b/crates/miden-agglayer/asm/agglayer/faucet/mod.masm @@ -1,5 +1,4 @@ use miden::core::sys -use agglayer::common::utils use agglayer::common::asset_conversion use miden::protocol::active_account @@ -20,42 +19,27 @@ const METADATA_HASH_HI_SLOT = word("agglayer::faucet::metadata_hash_hi") # PUBLIC INTERFACE # ================================================================================================= -#! Returns the origin token address (5 felts) from faucet conversion storage. +#! Returns the origin token address (5 felts) and origin network identifier from faucet conversion +#! storage. #! -#! Reads conversion_info_1 (first 4 felts of address) and conversion_info_2 (5th felt) from storage. +#! Reads conversion_info_1 (first 4 felts of address) and conversion_info_2 (5th felt + origin +#! network) from storage in a single pass. #! #! Inputs: [] -#! Outputs: [addr0, addr1, addr2, addr3, addr4] +#! Outputs: [addr0, addr1, addr2, addr3, addr4, origin_network] #! #! Invocation: exec -pub proc get_origin_token_address +proc get_origin_token_address_and_network push.CONVERSION_INFO_1_SLOT[0..2] exec.active_account::get_item # => [addr0, addr1, addr2, addr3] - # Read slot 2: [addr4, origin_network, scale, 0] push.CONVERSION_INFO_2_SLOT[0..2] exec.active_account::get_item # => [addr4, origin_network, scale, 0, addr0, addr1, addr2, addr3] - # Keep only addr4, drop origin_network, scale, 0 - movdn.7 drop drop drop - # => [addr0, addr1, addr2, addr3, addr4] -end - -#! Returns the origin network identifier from faucet conversion storage. -#! -#! Inputs: [] -#! Outputs: [origin_network] -#! -#! Invocation: exec -pub proc get_origin_network - push.CONVERSION_INFO_2_SLOT[0..2] - exec.active_account::get_item - # => [addr4, origin_network, scale, 0] - - drop movdn.2 drop drop - # => [origin_network] + movdn.7 movdn.7 drop drop + # => [addr0, addr1, addr2, addr3, addr4, origin_network] end #! Returns the scale factor from faucet conversion storage. @@ -145,21 +129,12 @@ pub proc asset_to_origin_asset exec.asset_conversion::reverse_limbs_and_change_byte_endianness # => [U256_LO, U256_HI, pad(15)] - # Step 3: Get origin token address - exec.get_origin_token_address - # => [addr0, addr1, addr2, addr3, addr4, U256_LO, U256_HI, pad(15)] - - # Move address below the U256 amount - repeat.5 movdn.12 end - # => [U256_LO, U256_HI, addr0, addr1, addr2, addr3, addr4, pad(15)] - - # Step 4: Get origin network - exec.get_origin_network - exec.utils::swap_u32_bytes - # => [origin_network, U256_LO, U256_HI, addr0..addr4, pad(15)] + # Step 3: Get origin token address and network + exec.get_origin_token_address_and_network + # => [addr0, addr1, addr2, addr3, addr4, origin_network, U256_LO, U256_HI, pad(15)] - # Move origin_network after the address fields - movdn.13 + # Move address + network below the U256 amount + repeat.6 movdn.13 end # => [U256_LO, U256_HI, addr0, addr1, addr2, addr3, addr4, origin_network, pad(15)] exec.sys::truncate_stack diff --git a/crates/miden-agglayer/src/faucet.rs b/crates/miden-agglayer/src/faucet.rs index 306a8acc99..16f09b3a1b 100644 --- a/crates/miden-agglayer/src/faucet.rs +++ b/crates/miden-agglayer/src/faucet.rs @@ -3,6 +3,7 @@ extern crate alloc; use alloc::vec; use alloc::vec::Vec; +use miden_core::utils::bytes_to_packed_u32_elements; use miden_core::{Felt, Word}; use miden_protocol::account::component::AccountComponentMetadata; use miden_protocol::account::{ @@ -264,10 +265,9 @@ impl AggLayerFaucet { .get_item(&CONVERSION_INFO_2_SLOT_NAME) .expect("should be able to read the second conversion info slot"); - Ok(conversion_info_2[1] - .as_canonical_u64() - .try_into() - .expect("origin network ID should fit into u32")) + let le_packed = u32::try_from(conversion_info_2[1].as_canonical_u64()) + .expect("origin network ID should fit into u32"); + Ok(u32::from_be_bytes(le_packed.to_le_bytes())) } /// Extracts the scaling factor in form of the u8 from the corresponding storage slot of the @@ -436,7 +436,7 @@ pub enum AgglayerFaucetError { /// - Slot 1 (`agglayer::faucet::conversion_info_1`): `[addr0, addr1, addr2, addr3]` — first 4 felts /// of the origin token address (5 × u32 limbs). /// - Slot 2 (`agglayer::faucet::conversion_info_2`): `[addr4, origin_network, scale, 0]` — -/// remaining address felt + origin network + scale factor. +/// remaining address felt + origin network (LE-packed) + scale factor. /// /// # Parameters /// - `origin_token_address`: The EVM token address in Ethereum format @@ -454,8 +454,14 @@ fn agglayer_faucet_conversion_slots( let slot1 = Word::new([addr_elements[0], addr_elements[1], addr_elements[2], addr_elements[3]]); + let origin_network_packed = bytes_to_packed_u32_elements(&origin_network.to_be_bytes()); + assert_eq!( + origin_network_packed.len(), + 1, + "origin_network should pack into exactly one Felt" + ); let slot2 = - Word::new([addr_elements[4], Felt::from(origin_network), Felt::from(scale), Felt::ZERO]); + Word::new([addr_elements[4], origin_network_packed[0], Felt::from(scale), Felt::ZERO]); (slot1, slot2) }