Skip to content

feat: add lock / unlock functionality to agg_bridge for native miden assets#2771

Open
partylikeits1983 wants to merge 16 commits intoagglayerfrom
ajl-agg-bridge-lock-unlock
Open

feat: add lock / unlock functionality to agg_bridge for native miden assets#2771
partylikeits1983 wants to merge 16 commits intoagglayerfrom
ajl-agg-bridge-lock-unlock

Conversation

@partylikeits1983
Copy link
Copy Markdown
Contributor

@partylikeits1983 partylikeits1983 commented Apr 14, 2026

Closes #2700. Adds a lock/unlock path for Miden-native tokens to the AggLayer bridge, mirroring PolygonZkEVMBridgeV2.claimAsset()'s handling of originNetwork == networkID.

The bridge no longer needs to be the faucet's owner to support it, so user-created faucets are now bridgeable once the bridge admin registers them via a CONFIG_AGG_BRIDGE note with is_native = true. Registration is still admin-gated (register_faucet is caller-restricted); what changed is the ownership requirement.

Approach

Native faucet branch, end-to-end:

  • Bridge-out: if is_native, call lock_assetnative_account::add_asset to park the asset in the bridge's own vault. No BURN note is emitted.
  • Bridge-in: if is_native, call unlock_and_sendnative_account::remove_asset + p2id::new to emit a P2ID note to the recipient. No MINT note, no faucet ntx. PROOF_DATA_KEY is used as the serial number so the note commitment is deterministic per claim.
  • LET leaf construction and the existing non-native burn/mint flow are untouched.

Metadata moved to the bridge. All three FPI calls from the bridge into the faucet (asset_to_origin_asset, get_metadata_hash, get_scale) are replaced with bridge-local reads out of a new faucet_metadata_map.

A single map with four faucet-ID-keyed sub-keys holds everything:

Sub-key Value
[0, 0, fid_s, fid_p] [addr0, addr1, addr2, addr3]
[1, 0, fid_s, fid_p] [addr4, origin_network, scale, 0]
[2, 0, fid_s, fid_p] [mh_lo0..3]
[3, 0, fid_s, fid_p] [mh_hi0..3]

faucet_registry_map is extended from [1, 0, 0, 0] to [1, is_native, 0, 0], which is backward-compatible since existing entries have is_native = 0 implicitly. CONFIG_AGG_BRIDGE carries the full metadata payload at registration (split across two calls to fit the 16-element stack).

AggLayer faucet slimmed. With metadata on the bridge, the faucet's conversion-info / metadata-hash slots and its asset_to_origin_asset / get_metadata_hash / get_scale procs are dead code. Removed: the AggLayerFaucet component now only re-exports mint_and_send + burn on top of Ownable2Step + OwnerControlled. A Miden-native faucet which wants to integrate with Agglayer, now is just a plain network fungible faucet, no AggLayer-specific storage or FPI surface needed.

Follow-ups

Not in this PR; filing separately per @bobbinth's comments in the original issue for this PR:

@partylikeits1983 partylikeits1983 changed the title feat: add scale data to bridge storage feat: add lock / unlock functionality to agg_bridge for native miden assets Apr 16, 2026
@mmagician mmagician added agglayer PRs or issues related to AggLayer bridging integration pr-from-maintainers PRs that come from internal contributors or integration partners. They should be given priority labels Apr 16, 2026
@partylikeits1983 partylikeits1983 force-pushed the ajl-agg-bridge-lock-unlock branch from 650b79d to d1d9938 Compare April 17, 2026 17:47
@partylikeits1983 partylikeits1983 marked this pull request as ready for review April 20, 2026 17:27
@partylikeits1983 partylikeits1983 self-assigned this Apr 20, 2026
Copy link
Copy Markdown
Contributor

@Fumuran Fumuran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thank you!
It is a partial review, for now I only reviewed masm code. Mostly formatting suggestions and code optimizations

Comment thread crates/miden-agglayer/asm/agglayer/bridge/bridge_config.masm Outdated
Comment thread crates/miden-agglayer/asm/agglayer/bridge/bridge_config.masm Outdated
Comment thread crates/miden-agglayer/asm/agglayer/bridge/bridge_config.masm
Comment thread crates/miden-agglayer/asm/agglayer/bridge/bridge_config.masm Outdated
Comment thread crates/miden-agglayer/asm/agglayer/bridge/bridge_config.masm Outdated
Comment thread crates/miden-agglayer/asm/note_scripts/CONFIG_AGG_BRIDGE.masm Outdated
Comment thread crates/miden-agglayer/asm/note_scripts/CONFIG_AGG_BRIDGE.masm Outdated
Comment thread crates/miden-agglayer/asm/note_scripts/CONFIG_AGG_BRIDGE.masm Outdated
Comment thread crates/miden-agglayer/asm/note_scripts/CONFIG_AGG_BRIDGE.masm Outdated
Comment thread crates/miden-agglayer/asm/note_scripts/CONFIG_AGG_BRIDGE.masm Outdated
Copy link
Copy Markdown
Contributor

@Fumuran Fumuran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rust part looks great, thank you! I left just one question inline

Comment thread crates/miden-agglayer/src/config_note.rs Outdated
@partylikeits1983
Copy link
Copy Markdown
Contributor Author

@Fumuran I went with your suggestion, and packaged ConfigAggBridgeNote::create's six faucet-metadata parameters into a new ConversionMetadata struct with a to_elements() helper.

Separately, extracted build_mint_output_note, unlock_and_send, and their MINT/UNLOCK memory constants from bridge_in.masm into a new bridge_in_output.masm module (otherwise bridge_in.masm was getting too big), and updated the SPEC reference accordingly.

Copy link
Copy Markdown
Contributor

@Fumuran Fumuran left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! For now (I see that currently PR is in draft mode) I have just one small masm-related comment.

Comment thread crates/miden-agglayer/asm/agglayer/bridge/bridge_in.masm Outdated
Comment thread crates/miden-agglayer/asm/agglayer/bridge/bridge_in.masm Outdated
The inter-call dropw sequences were removed, so the input pad(12) now
persists across both call boundaries. Update every # => [...] comment
to reflect the true sdepth (verified with sdepth debug.stack drop):
pad(16) through the setup, pad(32) after call 1, pad(48) after call 2,
pad(16) after the final repeat.8 cleanup.
- bridge_config.masm: reword the register_faucet local-offset comment and
  move an implementation detail out of get_faucet_metadata_hash's docstring
  into an inline comment.
- bridge_in_output.masm: document that unlock_and_send's replay safety comes
  from the nullifier check in bridge_in::claim, not serial-number uniqueness.
- bridge_in.rs: add bridge_in_unlock_native_duplicate_rejected. Seeds the
  bridge vault with 2x the claim amount so the nullifier is the only thing
  stopping a second unlock, then asserts the replay fails with
  ERR_CLAIM_ALREADY_SPENT.
@partylikeits1983 partylikeits1983 force-pushed the ajl-agg-bridge-lock-unlock branch from d5766f2 to 90ca6e4 Compare April 30, 2026 02:09
@partylikeits1983 partylikeits1983 marked this pull request as ready for review April 30, 2026 02:10
Make CLAIM_OUTPUT_NOTE_FAUCET_AMOUNT and CLAIM_PROOF_DATA_KEY_MEM_ADDR
public in bridge_in.masm and import them from bridge_in_output.masm,
removing the duplicate definitions and the "keep in sync" comments.
Move UNLOCK_*_LOC consts to sit immediately above unlock_and_send so the
local-memory layout lives next to the procedure that uses it.
@partylikeits1983 partylikeits1983 force-pushed the ajl-agg-bridge-lock-unlock branch from 90ca6e4 to e197f46 Compare April 30, 2026 02:13
Resolves conflicts in faucet/mod.masm and src/faucet.rs by taking ours
(metadata moved to bridge); accepts upstream deletion of errors/agglayer.rs
(now generated into OUT_DIR by build.rs).
@partylikeits1983
Copy link
Copy Markdown
Contributor Author

partylikeits1983 commented Apr 30, 2026

@mmagician this is ready for another look. Andrey's comments are all addressed and resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agglayer PRs or issues related to AggLayer bridging integration pr-from-maintainers PRs that come from internal contributors or integration partners. They should be given priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants