Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions crates/miden-agglayer/SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ Bridges an asset out of Miden into the AggLayer:
| **Panics** | Note sender is not the bridge admin |

Asserts the note sender matches the bridge admin stored in
`miden::agglayer::bridge::admin`, then writes
`agglayer::bridge::admin_account_id`, then writes
`[0, 0, faucet_id_suffix, faucet_id_prefix] -> [1, 0, 0, 0]` into the
`faucet_registry` map slot.
`faucet_registry_map` map slot.

#### `bridge_config::update_ger`

Expand All @@ -101,9 +101,9 @@ Asserts the note sender matches the bridge admin stored in
| **Panics** | Note sender is not the GER manager |

Asserts the note sender matches the GER manager stored in
`miden::agglayer::bridge::ger_manager`, then computes
`agglayer::bridge::ger_manager_account_id`, then computes
`KEY = rpo256::merge(GER_UPPER, GER_LOWER)` and stores
`KEY -> [1, 0, 0, 0]` in the `ger` map slot. This marks the GER as "known".
`KEY -> [1, 0, 0, 0]` in the `ger_map` map slot. This marks the GER as "known".

#### `bridge_in::verify_leaf_bridge`
TODO ([#2624](https://github.com/0xMiden/protocol/issues/2624)): document new CLAIM note flow.
Expand All @@ -129,17 +129,17 @@ Verifies a bridge-in claim:

| Slot name | Slot type | Key encoding | Value encoding | Purpose |
|-----------|-----------|-------------|----------------|---------|
| `miden::agglayer::bridge::ger` | Map | `rpo256::merge(GER_UPPER, GER_LOWER)` | `[1, 0, 0, 0]` if known; `[0, 0, 0, 0]` if absent | Known Global Exit Root set |
| `miden::agglayer::let` | Map | `[h, 0, 0, 0]` and `[h, 1, 0, 0]` (for h = 0..31) | Per index h: two keys yield one double-word (2 words = 8 felts, a Keccak-256 digest). Absent keys return zeros. | Local Exit Tree MMR frontier |
| `miden::agglayer::let::root_lo` | Value | -- | `[root_0, root_1, root_2, root_3]` | LET root low word (Keccak-256 lower 16 bytes) |
| `miden::agglayer::let::root_hi` | Value | -- | `[root_4, root_5, root_6, root_7]` | LET root high word (Keccak-256 upper 16 bytes) |
| `miden::agglayer::let::num_leaves` | Value | -- | `[count, 0, 0, 0]` | Number of leaves appended to the LET |
| `miden::agglayer::bridge::faucet_registry` | Map | `[0, 0, faucet_id_suffix, faucet_id_prefix]` | `[1, 0, 0, 0]` if registered; `[0, 0, 0, 0]` if absent | Registered faucet lookup |
| `miden::agglayer::bridge::admin` | Value | -- | `[0, 0, admin_suffix, admin_prefix]` | Bridge admin account ID for CONFIG note authorization |
| `miden::agglayer::bridge::ger_manager` | Value | -- | `[0, 0, mgr_suffix, mgr_prefix]` | GER manager account ID for UPDATE_GER note authorization |

Initial state: all map slots empty, all value slots `[0, 0, 0, 0]` except `admin` and
`ger_manager` which are set at account creation time.
| `agglayer::bridge::ger_map` | Map | `rpo256::merge(GER_UPPER, GER_LOWER)` | `[1, 0, 0, 0]` if known; `[0, 0, 0, 0]` if absent | Known Global Exit Root set |
| `agglayer::bridge::let_frontier` | Map | `[h, 0, 0, 0]` and `[h, 1, 0, 0]` (for h = 0..31) | Per index h: two keys yield one double-word (2 words = 8 felts, a Keccak-256 digest). Absent keys return zeros. | Local Exit Tree MMR frontier |
| `agglayer::bridge::let_root_lo` | Value | -- | `[root_0, root_1, root_2, root_3]` | LET root low word (Keccak-256 lower 16 bytes) |
| `agglayer::bridge::let_root_hi` | Value | -- | `[root_4, root_5, root_6, root_7]` | LET root high word (Keccak-256 upper 16 bytes) |
| `agglayer::bridge::let_num_leaves` | Value | -- | `[count, 0, 0, 0]` | Number of leaves appended to the LET |
| `agglayer::bridge::faucet_registry_map` | Map | `[0, 0, faucet_id_suffix, faucet_id_prefix]` | `[1, 0, 0, 0]` if registered; `[0, 0, 0, 0]` if absent | Registered faucet lookup |
| `agglayer::bridge::admin_account_id` | Value | -- | `[0, 0, admin_suffix, admin_prefix]` | Bridge admin account ID for CONFIG note authorization |
| `agglayer::bridge::ger_manager_account_id` | Value | -- | `[0, 0, mgr_suffix, mgr_prefix]` | GER manager account ID for UPDATE_GER note authorization |

Initial state: all map slots empty, all value slots `[0, 0, 0, 0]` except
`admin_account_id` and `ger_manager_account_id` which are set at account creation time.

### 2.2 Faucet Account Component

Expand Down Expand Up @@ -204,9 +204,8 @@ This is a re-export of `miden::standards::faucets::basic_fungible::burn`. It bur
| Slot name | Slot type | Value encoding | Purpose |
|-----------|-----------|----------------|---------|
| Faucet metadata (standard) | Value | `[token_supply, max_supply, decimals, token_symbol]` | Standard `NetworkFungibleFaucet` metadata |
| `miden::agglayer::faucet` (TODO (Future): rename for clarity [#2356](https://github.com/0xMiden/protocol/issues/2356)) | Value | `[0, 0, bridge_suffix, bridge_prefix]` | Bridge account ID this faucet is paired with |
| `miden::agglayer::faucet::conversion_info_1` | Value | `[addr_0, addr_1, addr_2, addr_3]` | Origin token address, first 4 u32 limbs |
| `miden::agglayer::faucet::conversion_info_2` | Value | `[addr_4, origin_network, scale, 0]` | Origin token address 5th limb, origin network ID, scale exponent |
| `agglayer::faucet::conversion_info_1` | Value | `[addr_0, addr_1, addr_2, addr_3]` | Origin token address, first 4 u32 limbs |
| `agglayer::faucet::conversion_info_2` | Value | `[addr_4, origin_network, scale, 0]` | Origin token address 5th limb, origin network ID, scale exponent |

---

Expand Down Expand Up @@ -615,7 +614,7 @@ extract the recipient's `AccountId` from the embedded Ethereum address and e.g.

#### 5.4.3 Ethereum Address → `AccountId` (MASM)

`eth_address::to_account_id` — Module: `miden::agglayer::common::eth_address`
`eth_address::to_account_id` — Module: `agglayer::common::eth_address`

This is the in-VM counterpart of the Rust `to_account_id`, invoked during CLAIM note
consumption to decode the recipient's address from the leaf data, and eventually for building the P2ID note for the recipient.
Expand Down
22 changes: 11 additions & 11 deletions crates/miden-agglayer/asm/agglayer/bridge/bridge_config.masm
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ const ERR_SENDER_NOT_GER_MANAGER="note sender is not the global exit root manage
# =================================================================================================

# Storage slots
const BRIDGE_ADMIN_SLOT=word("miden::agglayer::bridge::admin")
const GER_MANAGER_SLOT=word("miden::agglayer::bridge::ger_manager")
const GER_STORAGE_SLOT=word("miden::agglayer::bridge::ger")
const FAUCET_REGISTRY_SLOT=word("miden::agglayer::bridge::faucet_registry")
const TOKEN_REGISTRY_SLOT=word("miden::agglayer::bridge::token_registry")
const BRIDGE_ADMIN_SLOT=word("agglayer::bridge::admin_account_id")
const GER_MANAGER_SLOT=word("agglayer::bridge::ger_manager_account_id")
const GER_MAP_STORAGE_SLOT=word("agglayer::bridge::ger_map")
const FAUCET_REGISTRY_MAP_SLOT=word("agglayer::bridge::faucet_registry_map")
const TOKEN_REGISTRY_MAP_SLOT=word("agglayer::bridge::token_registry_map")

# Flags
const GER_KNOWN_FLAG=1
Expand Down Expand Up @@ -61,7 +61,7 @@ pub proc update_ger
swapw
# => [GER_HASH, VALUE, pad(12)]

push.GER_STORAGE_SLOT[0..2]
push.GER_MAP_STORAGE_SLOT[0..2]
# => [slot_id_prefix, slot_id_suffix, GER_HASH, VALUE, pad(12)]

exec.native_account::set_map_item
Expand All @@ -87,7 +87,7 @@ pub proc assert_valid_ger
exec.rpo256::merge
# => [GER_HASH]

push.GER_STORAGE_SLOT[0..2]
push.GER_MAP_STORAGE_SLOT[0..2]
# => [slot_id_prefix, slot_id_suffix, GER_HASH]

exec.active_account::get_map_item
Expand Down Expand Up @@ -135,7 +135,7 @@ pub proc register_faucet
swapw
# => [[faucet_id_prefix, faucet_id_suffix, 0, 0], [0, 0, 0, 1], origin_token_addr(5), faucet_id_prefix, faucet_id_suffix, pad(9)]

push.FAUCET_REGISTRY_SLOT[0..2]
push.FAUCET_REGISTRY_MAP_SLOT[0..2]
exec.native_account::set_map_item
# => [OLD_VALUE, origin_token_addr(5), faucet_id_prefix, faucet_id_suffix, pad(9)]

Expand All @@ -158,7 +158,7 @@ pub proc register_faucet
swapw
# => [TOKEN_ADDR_HASH, faucet_id_prefix, faucet_id_suffix, 0, 0, pad(10)]

push.TOKEN_REGISTRY_SLOT[0..2]
push.TOKEN_REGISTRY_MAP_SLOT[0..2]
exec.native_account::set_map_item
# => [OLD_VALUE, pad(12)]

Expand All @@ -184,7 +184,7 @@ pub proc assert_faucet_registered
movup.3 movup.3
# => [faucet_id_prefix, faucet_id_suffix, 0, 0]

push.FAUCET_REGISTRY_SLOT[0..2]
push.FAUCET_REGISTRY_MAP_SLOT[0..2]
exec.active_account::get_map_item
# => [VALUE(4)]

Expand All @@ -211,7 +211,7 @@ pub proc lookup_faucet_by_token_address
exec.hash_token_address
# => [TOKEN_ADDR_HASH]

push.TOKEN_REGISTRY_SLOT[0..2]
push.TOKEN_REGISTRY_MAP_SLOT[0..2]
exec.active_account::get_map_item
# => [faucet_id_prefix, faucet_id_suffix, 0, 0]

Expand Down
32 changes: 14 additions & 18 deletions crates/miden-agglayer/asm/agglayer/bridge/bridge_in.masm
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use miden::agglayer::bridge::bridge_config
use miden::agglayer::bridge::leaf_utils
use miden::agglayer::common::utils
use miden::agglayer::common::asset_conversion
use miden::agglayer::common::eth_address
use miden::agglayer::faucet -> agglayer_faucet
use agglayer::bridge::bridge_config
use agglayer::bridge::leaf_utils
use agglayer::common::utils
use agglayer::common::asset_conversion
use agglayer::common::eth_address
use agglayer::faucet -> agglayer_faucet
use miden::core::crypto::hashes::keccak256
use miden::core::crypto::hashes::rpo256
use miden::core::mem
Expand Down Expand Up @@ -41,23 +41,20 @@ const ERR_SOURCE_BRIDGE_NETWORK_OVERFLOW = "source bridge network overflowed u32
# CONSTANTS
# =================================================================================================

# Storage slots
# -------------------------------------------------------------------------------------------------

# Storage slot constants for the CGI (claimed global index) chain hash.
# It is stored in two separate value slots.
const CGI_CHAIN_HASH_LO_SLOT_NAME = word("miden::agglayer::bridge::cgi_chain_hash_lo")
const CGI_CHAIN_HASH_HI_SLOT_NAME = word("miden::agglayer::bridge::cgi_chain_hash_hi")
# Claim Nullifier Flag
const IS_CLAIMED_FLAG = [1, 0, 0, 0]

# Storage Slots
# Storage slots
# -------------------------------------------------------------------------------------------------

# The slot in this component's storage layout where claim nullifiers are stored.
# Map entries: RPO(leaf_index, source_bridge_network) => [1, 0, 0, 0]
const CLAIM_NULLIFIERS_SLOT = word("miden::agglayer::bridge::claim_nullifiers")
const CLAIM_NULLIFIERS_SLOT = word("agglayer::bridge::claim_nullifiers")

# Claim Nullifier Flag
const IS_CLAIMED_FLAG = [1, 0, 0, 0]
# Storage slot constants for the CGI (claimed global index) chain hash.
# It is stored in two separate value slots.
const CGI_CHAIN_HASH_LO_SLOT_NAME = word("agglayer::bridge::cgi_chain_hash_lo")
const CGI_CHAIN_HASH_HI_SLOT_NAME = word("agglayer::bridge::cgi_chain_hash_hi")

# Data sizes
# -------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -160,7 +157,6 @@ const CLAIM_DEST_ID_SUFFIX_LOCAL = 1
# PUBLIC INTERFACE
# =================================================================================================


#! Validates a claim against the AggLayer bridge and creates a MINT note for the aggfaucet.
#!
#! This procedure is called by the CLAIM note script. It validates the Merkle proof and then
Expand Down
37 changes: 25 additions & 12 deletions crates/miden-agglayer/asm/agglayer/bridge/bridge_out.masm
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ use miden::protocol::output_note
use miden::core::crypto::hashes::keccak256
use miden::core::crypto::hashes::rpo256
use miden::core::word
use miden::agglayer::common::utils
use miden::agglayer::faucet -> agglayer_faucet
use miden::agglayer::bridge::bridge_config
use miden::agglayer::bridge::leaf_utils
use miden::agglayer::bridge::mmr_frontier32_keccak
use agglayer::common::utils
use agglayer::faucet -> agglayer_faucet
use agglayer::bridge::bridge_config
use agglayer::bridge::leaf_utils
use agglayer::bridge::mmr_frontier32_keccak


# TYPE ALIASES
Expand All @@ -27,21 +27,29 @@ type MemoryAddress = u32
# CONSTANTS
# =================================================================================================

# Storage slots
# -------------------------------------------------------------------------------------------------

# Storage slot constants for the LET (Local Exit Tree).
# The frontier is stored as a double-word array in a map slot.
# The root and num_leaves are stored in separate value slots.
const LOCAL_EXIT_TREE_SLOT=word("miden::agglayer::let")
const LET_ROOT_LO_SLOT=word("miden::agglayer::let::root_lo")
const LET_ROOT_HI_SLOT=word("miden::agglayer::let::root_hi")
const LET_NUM_LEAVES_SLOT=word("miden::agglayer::let::num_leaves")
const LET_FRONTIER_SLOT=word("agglayer::bridge::let_frontier")
const LET_ROOT_LO_SLOT=word("agglayer::bridge::let_root_lo")
const LET_ROOT_HI_SLOT=word("agglayer::bridge::let_root_hi")
const LET_NUM_LEAVES_SLOT=word("agglayer::bridge::let_num_leaves")

# Global memory pointers
# -------------------------------------------------------------------------------------------------

# Memory pointers
const LEAF_DATA_START_PTR=44
# Memory pointer for loading the LET (Local Exit Tree) frontier into memory.
# The memory layout at this address matches what append_and_update_frontier expects:
# [num_leaves, 0, 0, 0, [[FRONTIER_NODE_LO, FRONTIER_NODE_HI]; 32]]
const LET_FRONTIER_MEM_PTR=100

# Field offsets
# -------------------------------------------------------------------------------------------------

# Leaf data field offsets (relative to LEAF_DATA_START_PTR)
const LEAF_TYPE_OFFSET=0
const ORIGIN_NETWORK_OFFSET=1
Expand All @@ -52,6 +60,9 @@ const AMOUNT_OFFSET=13
const METADATA_HASH_OFFSET=21
const PADDING_OFFSET=29

# Local memory offsets
# -------------------------------------------------------------------------------------------------

# bridge_out memory locals
const BRIDGE_OUT_BURN_ASSET_LOC=0
const DESTINATION_ADDRESS_0_LOC=4
Expand All @@ -68,6 +79,8 @@ const ATTACHMENT_SCHEME_LOC=8
const ATTACHMENT_KIND_LOC=9

# Other constants
# -------------------------------------------------------------------------------------------------

const LEAF_TYPE_ASSET=0
const PUBLIC_NOTE=1
const BURN_NOTE_NUM_STORAGE_ITEMS=0
Expand Down Expand Up @@ -306,7 +319,7 @@ proc load_let_frontier_to_memory
# => [h]

# Read frontier[h] as a double word from the map
dup push.LOCAL_EXIT_TREE_SLOT[0..2]
dup push.LET_FRONTIER_SLOT[0..2]
exec.double_word_array::get
# => [VALUE_0, VALUE_1, h]

Expand Down Expand Up @@ -375,7 +388,7 @@ proc save_let_frontier_to_storage
# => [VALUE_0, VALUE_1, h]

# Write it back to the map at index h
dup.8 push.LOCAL_EXIT_TREE_SLOT[0..2]
dup.8 push.LET_FRONTIER_SLOT[0..2]
exec.double_word_array::set
dropw dropw
# => [h]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ const ZERO_30_R = [1078065138, 2904706143, 1223587258, 1350312851]
const ZERO_31_L = [2840985724, 1653344606, 4049365781, 2389186238]
const ZERO_31_R = [3759582231, 2660540036, 1648733876, 2340505732]

use ::miden::agglayer::common::utils::mem_store_double_word
use ::agglayer::common::utils::mem_store_double_word

#! Inputs: [zeros_ptr]
#! Outputs: []
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use miden::core::crypto::hashes::keccak256
use ::miden::agglayer::bridge::canonical_zeros::load_zeros_to_memory
use ::miden::agglayer::common::utils::mem_store_double_word
use ::miden::agglayer::common::utils::mem_load_double_word
use ::agglayer::bridge::canonical_zeros::load_zeros_to_memory
use ::agglayer::common::utils::mem_store_double_word
use ::agglayer::common::utils::mem_load_double_word

# An MMR Frontier is a data structure based on an MMR, which combines some features of an MMR and an
# SMT.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use miden::core::math::u64
use miden::core::word
use miden::agglayer::common::utils
use agglayer::common::utils
use ::miden::protocol::asset::FUNGIBLE_ASSET_MAX_AMOUNT

# ERRORS
Expand Down
2 changes: 1 addition & 1 deletion crates/miden-agglayer/asm/agglayer/common/eth_address.masm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use miden::agglayer::common::utils
use agglayer::common::utils
use miden::core::crypto::hashes::keccak256
use miden::core::word

Expand Down
10 changes: 5 additions & 5 deletions crates/miden-agglayer/asm/agglayer/faucet/mod.masm
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use miden::core::sys
use miden::agglayer::common::utils
use miden::agglayer::common::asset_conversion
use miden::agglayer::common::eth_address
use agglayer::common::utils
use agglayer::common::asset_conversion
use agglayer::common::eth_address
use miden::protocol::active_account
use miden::protocol::active_note
use miden::standards::faucets
Expand All @@ -14,9 +14,9 @@ use miden::core::word

# Storage slots for conversion metadata.
# Slot 1: [addr_felt0, addr_felt1, addr_felt2, addr_felt3] — first 4 felts of origin token address
const CONVERSION_INFO_1_SLOT = word("miden::agglayer::faucet::conversion_info_1")
const CONVERSION_INFO_1_SLOT = word("agglayer::faucet::conversion_info_1")
# Slot 2: [addr_felt4, origin_network, scale, 0] — remaining address felt + origin network + scale
const CONVERSION_INFO_2_SLOT = word("miden::agglayer::faucet::conversion_info_2")
const CONVERSION_INFO_2_SLOT = word("agglayer::faucet::conversion_info_2")

# PUBLIC INTERFACE
# =================================================================================================
Expand Down
8 changes: 4 additions & 4 deletions crates/miden-agglayer/asm/components/bridge.masm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# This is a thin wrapper that re-exports bridge-related procedures from the
# agglayer library.

pub use ::miden::agglayer::bridge::bridge_config::register_faucet
pub use ::miden::agglayer::bridge::bridge_config::update_ger
pub use ::miden::agglayer::bridge::bridge_in::claim
pub use ::miden::agglayer::bridge::bridge_out::bridge_out
pub use ::agglayer::bridge::bridge_config::register_faucet
pub use ::agglayer::bridge::bridge_config::update_ger
pub use ::agglayer::bridge::bridge_in::claim
pub use ::agglayer::bridge::bridge_out::bridge_out
8 changes: 4 additions & 4 deletions crates/miden-agglayer/asm/components/faucet.masm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# - `get_scale` for bridge-in FPI (amount verification)
# - `burn` for bridge-out

pub use ::miden::agglayer::faucet::distribute
pub use ::miden::agglayer::faucet::asset_to_origin_asset
pub use ::miden::agglayer::faucet::get_scale
pub use ::miden::agglayer::faucet::burn
pub use ::agglayer::faucet::distribute
pub use ::agglayer::faucet::asset_to_origin_asset
pub use ::agglayer::faucet::get_scale
pub use ::agglayer::faucet::burn
2 changes: 1 addition & 1 deletion crates/miden-agglayer/asm/note_scripts/B2AGG.masm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use miden::agglayer::bridge::bridge_out
use agglayer::bridge::bridge_out
use miden::protocol::account_id
use miden::protocol::active_account
use miden::protocol::active_note
Expand Down
2 changes: 1 addition & 1 deletion crates/miden-agglayer/asm/note_scripts/CLAIM.masm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use miden::agglayer::bridge::bridge_in -> bridge
use agglayer::bridge::bridge_in -> bridge
use miden::protocol::active_note
use miden::protocol::note
use miden::core::crypto::hashes::keccak256
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use miden::agglayer::bridge::bridge_config
use agglayer::bridge::bridge_config
use miden::protocol::active_note
use miden::protocol::active_account
use miden::protocol::account_id
Expand Down
2 changes: 1 addition & 1 deletion crates/miden-agglayer/asm/note_scripts/UPDATE_GER.masm
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use miden::agglayer::bridge::bridge_config
use agglayer::bridge::bridge_config
use miden::protocol::active_note
use miden::protocol::active_account
use miden::protocol::account_id
Expand Down
Loading
Loading