Skip to content

Tracking PR for v0.15.0 release#2674

Draft
bobbinth wants to merge 112 commits into
mainfrom
next
Draft

Tracking PR for v0.15.0 release#2674
bobbinth wants to merge 112 commits into
mainfrom
next

Conversation

@bobbinth
Copy link
Copy Markdown
Contributor

This is a tracking PR for v0.15.0 release.

bobbinth and others added 30 commits March 23, 2026 20:41
* fix(ci): install Rust 1.91 for cargo-msrv compatibility

cargo-msrv 0.19.3 requires rustc 1.91.1 or newer, but the stable
toolchain currently ships 1.90.0. Install the 1.91 toolchain and
set RUSTUP_TOOLCHAIN=1.91 on the cargo-msrv install and MSRV
check steps so the tool can build and run.

* Revert "fix(ci): install Rust 1.91 for cargo-msrv compatibility"

This reverts commit 4485176.

* chore: bump toolchain

* chore: clippy
Add scheme-specific constructors that accept typed public keys instead
of a generic PublicKeyCommitment, preventing mismatches between key type
and authentication scheme:

- falcon512_poseidon2(pub_key): creates component from a Falcon512 key
- ecdsa_k256_keccak(pub_key): creates component from an ECDSA K256 key
- from_public_key(pub_key): creates component from a PublicKey enum

Also add From<ecdsa_k256_keccak::PublicKey> for PublicKeyCommitment for
parity with the existing Falcon512 conversion.
* chore: rename from PSM to Guardian

* fix: prefer state guardian in comments

* fix: rename guardian multisig to guarded multisig

* fix: restore changelog note and apply nightly formatting

* fix: move guardian rename changelog notes to v0.15

* style: clarify guardian masm comments

* fix: comment
…#2736)

* refactor: lowercase note script filenames in miden-agglayer

* docs(agglayer): update SPEC.md note script filenames to lowercase

Agent-Logs-Url: https://github.com/0xMiden/protocol/sessions/4f7eb749-9710-4a36-8caf-486f12ae21d7

Co-authored-by: partylikeits1983 <77119221+partylikeits1983@users.noreply.github.com>

* fix: update SPEC.md to reference .masm

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
* feat(asset): add AssetAmount wrapper type for fungible amounts

Introduce a validated AssetAmount(u64) newtype that encapsulates the
max-amount check (2^63 - 2^31) at construction time.

- Add AssetAmount with MAX constant, new(), as_u64(), From<u8/u16/u32>,
  TryFrom<u64>, Display, Serializable, Deserializable
- Integrate into FungibleAsset: replace raw u64 amount field
- Delegate validation in FungibleAsset::new() to AssetAmount::new()
- Keep FungibleAsset::MAX_AMOUNT as backward-compatible alias
- Keep amount() returning u64 to minimize downstream churn

Closes #2532

* refactor: remove as_u64, delegate add/sub to AssetAmount

Remove the redundant as_u64() accessor since From<AssetAmount> for u64
already provides the same conversion. Replace all call sites with
u64::from().

Add add() and sub() methods to AssetAmount so that FungibleAsset can
delegate arithmetic to the inner type instead of performing it inline.
Add unit tests for both new methods.

* style: fix rustfmt and clippy lints

Expand import list to one-per-line, merge duplicate use super
statements, collapse single-line assert_eq, and suppress
should_implement_trait on AssetAmount::add/sub.

* docs: add changelog entry for AssetAmount wrapper

* refactor: make AssetAmount::MAX a u64 constant, use .into() in tests

* fix: add type annotations for .into() in tests to resolve ambiguity

* refactor: implement Add and Sub traits for AssetAmount

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
Co-authored-by: Marti <marti@miden.team>
* feat: add `metadata_into_note_type` procedure to note.masm

Add a procedure to extract the note type from the metadata header
and unit tests for both public and private note types.

* refactor: address PR review — move stack layout to Where docs, consolidate tests with rstest

* chore: add CHANGELOG entry for metadata_into_note_type

* refactor: address review — clarify bit position, add stack layout docs, use NoteType comparison

* refactoring changes

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* docs: link CHANGELOG entry for metadata_into_note_type to PR #2738

---------

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>
…er build scripts (#2538)

* refactor: avoid unnecessary asm/ tree copy in standards build script

miden-standards: Remove the full asm/ directory copy to OUT_DIR entirely.
This crate never mutates its source tree, so the assembler and error
extractor can read directly from the crate's asm/ directory.

miden-protocol: Replace the bulk copy of the entire asm/ tree with
targeted staging of only the two directories that need modification
(kernels/transaction/ and protocol/). The assembler requires shared
modules to be physically present alongside these source files, but
shared_utils/ and shared_modules/ themselves don't need to be copied.
Event extraction now reads directly from the original source.

Also simplifies copy_dir_recursive (replacing the old copy_directory
with its awkward prefix-stripping API) and removes dead code.

https://claude.ai/code/session_01HDd5o3XxcgZiGrvBDFsUr1

refactor: scope change to standards build only, leave protocol as-is

The protocol crate needs source-level staging because the assembler's
`$kernel::` import resolution requires shared modules to be physically
co-located with kernel source. This cannot be avoided without assembler
changes, so revert the protocol build.rs to the base branch version.

https://claude.ai/code/session_01HDd5o3XxcgZiGrvBDFsUr1

* refactor: remove copy_directory from agglayer build.rs

Read MASM sources directly from the crate's asm/ directory instead of
copying them to OUT_DIR first. The copy is unnecessary because agglayer
doesn't mutate the directory structure during compilation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: generate agglayer error constants into OUT_DIR

Write error constants to OUT_DIR instead of src/errors/agglayer.rs, matching
the pattern used by miden-standards. The include now uses
concat!(env!("OUT_DIR"), ...) so error generation always runs regardless of
BUILD_GENERATED_FILES_IN_SRC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: validate canonical_zeros.masm instead of generating it

The canonical zeros are deterministic Keccak256 values that never change.
Instead of generating the file at build time (guarded by BUILD_GENERATED_FILES_IN_SRC),
the committed file is now validated against the expected content. To regenerate,
run with REGENERATE_CANONICAL_ZEROS=1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: remove BUILD_GENERATED_FILES_IN_SRC from agglayer

Both error constants and canonical zeros no longer write to src/, so
BUILD_GENERATED_FILES_IN_SRC is unused and can be removed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: fix trailing empty doc comment line

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
* refactor: reduce max assets per note from 255 to 64

* feat: add add_assets_exceeding_max_per_note_fails test

* Update crates/miden-protocol/asm/kernels/transaction/lib/note.masm

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update crates/miden-protocol/asm/kernels/transaction/lib/memory.masm

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: correct CHANGELOG issue link from miden-base to protocol repo

Agent-Logs-Url: https://github.com/0xMiden/protocol/sessions/7e834550-7f38-4d90-9c05-d46e3a7e37fa

Co-authored-by: partylikeits1983 <77119221+partylikeits1983@users.noreply.github.com>

* refactor: address PR comments: add max assets success test, fix memory layout table

* chore: fix changelog

* Update crates/miden-protocol/src/transaction/kernel/memory.rs

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* Update crates/miden-testing/src/kernel_tests/tx/test_output_note.rs

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* refactor: use rstest for tests & update changelog

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
…onstruction (#2758)

* chore: make note procedure names consistent

* chore: add changelog

* chore: update swap tag construction
* Add cycle counts to successful and failed notes

* Changelog

* Cycle count order comment

* Make fields private
* fix: improve deserialization error handling in AccountCode

* chore: update changelog

* refactor: removed AccountCode::from_bytes()
* refactor: always enable concurrent on std in miden-tx

* chore: delete miden-protocol-macros crate

* chore: update changelog
* Added the pswap masm contract and its supportive functions

* Added the pswap masm contract and its supportive functions

* refactor: rename swapp_tag to pswap_tag, NUM_ITEMS to NUM_STORAGE_ITEMS, remove create_ wrappers, add builder finish_fn

- Rename swapp_tag -> pswap_tag and SWAPp -> PSWAP throughout
- Rename NUM_ITEMS -> NUM_STORAGE_ITEMS for clarity
- Remove create_p2id_payback_note and create_remainder_note wrappers,
  make build_ functions public instead
- Compute p2id_tag inside build_p2id_payback_note from self.storage
- Add #[builder(finish_fn(vis = "", name = build_internal))] to PswapNote

* refactor: remove redundant test helpers, use pswap lib functions directly

Replace all test helper wrappers with direct calls to library functions:
- create_pswap_note -> PswapNote::create()
- create_expected_pswap_p2id_note + create_expected_pswap_remainder_note -> pswap.execute()
- build_pswap_storage -> PswapNoteStorage::from_parts()
- Remove make_pswap_tag, make_note_assets, make_note_args, compute_p2id_tag_*
- Inline calculate_output_amount as PswapNote::calculate_output_amount()

* docs: polish pswap doc comments to match sibling note style

- Replace storage layout list with markdown table
- Remove trivial "Returns the X" docs on simple getters
- Add # Errors sections where relevant
- Rewrite method docs to describe intent, not implementation
- Add one-line docs on From/TryFrom conversion impls
- Tighten PswapNote struct doc

* refactor: make assets a required field on PswapNote builder

* fix: adapt pswap to upstream API changes after rebase

- Rename RpoRandomCoin to RandomCoin (miden-crypto 0.23 rename)
- Store full ASSET_KEY instead of prefix/suffix to preserve callback
  metadata in faucet_id_suffix_and_metadata
- Replace create_fungible_asset calls with direct ASSET_KEY + manual
  ASSET_VALUE construction, avoiding the new enable_callbacks parameter
- Update hardcoded P2ID script root to match current P2idNote::script_root()

* refactor: use procref for P2ID script root, clean up pswap MASM

- Replace hardcoded P2ID script root with procref.p2id::main for
  compile-time resolution
- Default to full fill when both input and inflight amounts are zero
- Replace magic address 4000 with named P2ID_RECIPIENT_STORAGE constant
- Remove step numbering from comments, fix memory layout docs

* refactor: address PR review comments on pswap MASM

- Rename P2ID_RECIPIENT_STORAGE to P2ID_RECIPIENT_SUFFIX/PREFIX
- Add METADATA_HEADER word layout docs with source reference
- Document attachment_scheme parameter in set_word_attachment call
- Add stack views after condition checks

* refactor: rename pswap storage accessors, add offered_asset_amount helper, simplify build_p2id_payback_note

Rename requested_key/requested_value/requested_amount to
requested_asset_key/requested_asset_value/requested_asset_amount for
clarity. Extract offered_asset_amount() helper on PswapNote to
deduplicate offered asset extraction. Simplify build_p2id_payback_note
to take fill_amount: u64 instead of aux_word: Word, constructing the
aux word internally.

* refactor: address PR review comments on pswap Rust module

- Use NoteTag::default() instead of NoteTag::new(0)
- Change swap_count from u64 to u16 with safe try_into conversion
- Rename p2id_tag to payback_note_tag, p2id_payback_note to payback_note
- Rename build_ prefix to create_ for consistency
- Rename aux_word to attachment_word
- Replace Felt::new with Felt::from where possible
- Rename inputs to note_storage in TryFrom impl
- Make create_payback_note and create_remainder_pswap_note private
- Add offered_faucet_id helper to replace unreachable!()

* refactor: use builder pattern for PswapNote and PswapNoteStorage

- Remove PswapNote::create, add public build() with validation on builder
- Add bon::Builder to PswapNoteStorage, remove new() and from_parts()
- Remove payback_note_tag field, compute from creator_account_id on the fly
- Fix clippy warnings (useless conversions, needless borrows)
- Update all unit and integration tests to use builder pattern

* refactor: clean up pswap tests and fix clippy warnings

- Compare full faucet_id instead of just prefix in build validation
- Rename swap_note to pswap_note in integration tests for consistency
- Extract PswapNoteStorage builder into separate let bindings
- Replace manual current_swap_count counter with enumerate index
- Fix clippy useless_conversion and needless_borrow warnings

* refactor: rename inputs to storage_items in pswap_note_storage_try_from test

* chore: fix Cargo.toml dependency ordering and add CHANGELOG entry for PSWAP

* refactor: address PR review comments — use FungibleAsset types, improve safety and docs

- PswapNoteStorage: store FungibleAsset instead of raw key/value Words
- PswapNote: store offered_asset as FungibleAsset instead of NoteAssets
- execute(): take Option<FungibleAsset> for input/inflight assets
- Split execute into execute() and execute_full_fill_network() for clarity
- create_tag(): accept &FungibleAsset instead of &Asset
- Eliminate all Felt::new usage (use Felt::from, Felt::try_from, + ONE)
- Add swap_count overflow protection via checked_add
- Add script root verification in TryFrom<&Note>
- Add MASM fill validation (fill_amount <= requested)
- Rename MASM constants: _INPUT -> _ITEM, SWAPP_ -> PSWAP_
- Make calculate_output_amount private, add precision doc comment
- Add doc comments on all public accessors and methods
- Add network account full fill test
- Document network transaction compatibility throughout

* refactor: pass creator ID via stack to is_consumer_creator and use account_id::is_equal

* refactor: optimize requested asset storage to 4 felts and add NUM_STORAGE_ITEMS constant

Store requested asset as individual felts [enable_callbacks, faucet_suffix,
faucet_prefix, amount] instead of full ASSET_KEY + ASSET_VALUE (8 felts).
Use create_fungible_asset to reconstruct when needed. Reduces note storage
items from 18 to 14. Add NUM_STORAGE_ITEMS constant and execute_pswap doc comment.

* refactor: use p2id::new, pass inputs via stack, unify serial derivation

- Replace manual recipient building with p2id::new in create_p2id_note
- Pass all inputs via stack, store intermediates in @Locals
- Remove build_p2id_recipient_hash, P2ID_RECIPIENT_*, P2ID_NOTE_IDX
- Payback serial: serial[0] + 1, remainder serial: serial[3] + 1
- Update Rust side to match new serial derivation, remove Hasher import

* refactor: pass all inputs via stack to create_remainder_note, eliminate global memory reads

- create_remainder_note takes 8 stack inputs, stores to @Locals(6)
- Extract offered faucet info from ASSET_KEY in execute_pswap
- Use create_fungible_asset for consumer receive_asset and remainder asset
- Remove OFFERED_ASSET_KEY, PSWAP_NOTE_IDX constants

* feat: add P2ID reconstruction test, overfill docs, and stack comments

- Add test verifying Alice can reconstruct and consume P2ID payback note
  from her PSWAP data after Bob's partial fill
- Document why overfill is not allowed (likely unintentional error)
- Add missing stack comment on partial fill check

* fix: use Rust-predicted note for aux data in P2ID reconstruction test

The test framework doesn't preserve word attachment content in executed
transaction outputs. Use the Rust-predicted note to read the fill amount
from aux data, which mirrors production behavior where aux is visible.

* refactor: rename input to account fill, extract load_offered_asset proc

- Rename AMT_REQUESTED_IN to AMT_REQUESTED_ACCT_FILL and related variables
- Extract load_offered_asset proc centralizing asset loading and validation
- Remove OFFERED_ASSET_WORD global memory constant

* refactor: extract test helpers and reduce verbosity in pswap unit tests

* refactor: guard zero-amount receive_asset in MASM, add NUM_STORAGE_ITEMS alias on PswapNote

* refactor: rename ERR_PSWAP_WRONG_NUMBER_OF_INPUTS to ERR_PSWAP_WRONG_NUMBER_OF_STORAGE_ITEMS

* refactor: replace global memory with @Locals in execute_pswap and pass fill amounts via stack

* refactor(pswap): apply PR review nits from #2636

- Drop duplicated u64 stdlib docs inside calculate_tokens_offered_for_requested
- Replace `swap push.MAX_U32 mul add` with `swap mul.MAX_U32 add`
- Fold redundant empty-input guard in PswapNote::execute into the match arm

* feat(pswap): make payback note type configurable via PswapNoteStorage

Adds a `payback_note_type: NoteType` field on `PswapNoteStorage` (default
`Private`) so the payback note produced on fill can be private even when
the pswap note itself is public. Private payback notes are cheaper in
fees and bandwidth and don't lose information — the fill amount is
already recorded in the executed transaction's output.

Stored in the previously-reserved storage slot [6]. MASM now loads the
type from that slot when building the payback p2id note instead of using
the active note's own type. Remainder pswap note continues to inherit
the parent pswap's note type (unchanged).

Addresses PhilippGackstatter's review comment on PR #2636.

* perf(pswap): compress note storage layout from 14 to 10 items

Drops four reserved/zero padding slots ([7] and [9-11] in the old layout)
that served no purpose. The compressed layout is contiguous:

  [0-3] requested asset (callbacks, faucet suffix/prefix, amount)
  [4]   pswap_tag
  [5]   payback_note_tag
  [6]   payback_note_type
  [7]   swap_count
  [8-9] creator account id (prefix, suffix)

Saves 4 felts per pswap note on-chain, reducing fees and bandwidth for
every pswap created. No information is lost. Addresses PR #2636 review
comment from PhilippGackstatter on compressing the storage layout.

* test(pswap): cover combined input+inflight partial and full fill paths

Adds two unit tests against `PswapNote::execute` for the input+inflight
code path flagged in PR #2636 review:

- partial fill: account fill 10 + inflight 20 of a 50-requested pswap.
  Asserts payback carries 30 of the requested asset and a remainder
  pswap is produced with 20 requested / 40 offered remaining.
- full fill: account fill 30 + inflight 20 of a 50-requested pswap.
  Asserts payback carries 50 of the requested asset and no remainder.

Also factors out a `dummy_consumer_id()` helper alongside
`dummy_creator_id()` to keep the new tests readable.

* refactor(pswap): rename input/inflight to account_fill/note_fill

Addresses the naming feedback on PR #2636. The old `input` / `inflight`
terminology was ambiguous — "input" could mean the total fill amount,
the note_args input word, or the account-side fill, while "inflight"
conflated the transport mechanism with its role. The new names are
explicit about where the fill comes from:

  - offered_out             -> payout_amount
  - input / input_amount    -> fill_amount (when referring to the total
                               fill amount) or account_fill_amount
                               (when referring to the native-account
                               portion specifically)
  - inflight_amount         -> note_fill_amount
  - input_asset             -> account_fill_asset
  - inflight_asset          -> note_fill_asset

Touches the public `PswapNote::execute` parameters, all internal Rust
locals and doc comments, the MASM stack annotations / doc blocks /
local-var labels, and the integration test callers.

* refactor(pswap): fetch active note_type inline, drop global NOTE_TYPE

Upstream PR #2738 added `miden::protocol::note::metadata_into_note_type`
which does the bit-correct extraction against the new 1-bit NoteType
encoding. The pswap script no longer needs its own `extract_note_type`
proc or the `NOTE_TYPE` global slot.

Changes:
- Drop the `extract_note_type` proc and the `NOTE_TYPE_MASK` / `NOTE_TYPE`
  consts.
- The payback note already reads its type from `PAYBACK_NOTE_TYPE_ITEM`
  in storage (no active-note fetch needed).
- The remainder branch inlines `active_note::get_metadata dropw
  exec.note::metadata_into_note_type` where the type is actually used,
  instead of eagerly computing it once and stashing it in global memory.
- Update `pswap_note_alice_reconstructs_and_consumes_p2id` to set
  `payback_note_type(NoteType::Public)` so the reconstructed P2ID payback
  matches — the previous test implicitly relied on the payback inheriting
  the pswap's Public type (broken since the bit-encoding change).

This also fixes the previously-failing
`pswap_note_alice_reconstructs_and_consumes_p2id` test, which was hitting
the broken extract_note_type mask (always returning 0 under the new
encoding).

* refactor(pswap): switch storage consts to STORAGE_PTR base pattern

Matches the convention used in p2id.masm: declare a single
`STORAGE_PTR` base and derive every note-storage item offset relative
to it. This makes the storage layout easier to read and relocate.
Also use `push.STORAGE_PTR` at the load site instead of a bare `0`.

* docs(pswap): add #! doc block to @note_script main procedure

Closes PR #2636 review comment: `pub proc main` lacked a proper `#!`
doc block with `Inputs`/`Outputs`/storage layout/panic conditions.
Adds one modelled after the canonical style in p2id.masm / swap.masm.

* refactor(pswap): scrub last inflight/input references in tests

Rename `pswap_note_inflight_cross_swap_test` to
`pswap_note_note_fill_cross_swap_test` and update two stale comments
that still said "input" / "inflight" to match the new account_fill /
note_fill terminology used throughout the module.

* style(pswap): readability nits across pswap.masm

Minor cleanups surfaced during review, no behavior changes:
- Sort imports alphabetically by path.
- Reshape storage layout doc block to `[i..j] : N felts` + `Where:` form
  and drop the duplicate listing in the main proc docstring.
- Drop the stale "Memory Addresses" meta-block.
- Name local slots via top-of-file consts (e.g. CALC_FILL_AMOUNT,
  P2ID_NOTE_IDX, REMAINDER_AMT_OFFERED, EXEC_AMT_OFFERED, ...) so
  loc_store/loc_load sites read like variables rather than loc.N.
- Expand the rationale for the FACTOR=1e5 choice (precision vs u64
  overflow headroom) and switch the literal to decimal.
- Rename boolean stack-comment markers from operator syntax
  (`amt > 0`, `requested > offered`, `requested == fill_amount`) to
  readable predicates (`has_account_fill`, `has_note_fill`,
  `has_account_fill_payout`, `requested_exceeds_offered`,
  `is_full_fill`).
- Drop obvious/redundant comments (error-const headers, `gt pops…`
  primitive explanation, proc-start stack echoes, validate/calculate
  rationale moved into the execute_pswap docstring).
- Split `push.NUM_STORAGE_ITEMS.0` into two pushes using the
  STORAGE_PTR constant to match the `bridge_out.masm` pattern.
- Add converged stack markers (`# => [...]`) after every if/else `end`
  and before every proc return.

* test(pswap): dedupe integration tests via helpers + rstest

- Add shared helpers at the top of the test file: `build_pswap_note`,
  `note_args`, `assert_fungible_asset`, `assert_vault_added_removed`,
  `assert_vault_single_added`. Removes the repeated 13-line pswap-note
  setup and the `if let Asset::Fungible(f) = …` / vault-delta
  boilerplate.
- Consolidate variant-heavy tests with `#[rstest]`:
  - `pswap_fill_test` merges full/private/partial/network fill cases
    into one parameterized async test (4 cases).
  - `pswap_multiple_partial_fills_test` replaces the inner for-loop
    with 9 `#[case]`s, one per fill amount.
  - `pswap_partial_fill_ratio_test` merges the non-exact-ratio and
    hand-listed fuzz suites into one rstest with 27 regression cases,
    delegating to a new `run_partial_fill_ratio_case` helper.
  - `pswap_chained_partial_fills_test` parameterizes the outer chain
    loop with 10 `#[case]`s; the stateful per-chain inner fill loop
    is preserved intact.
- Add `pswap_partial_fill_ratio_fuzz` as a seeded-random coverage
  sibling: two `#[case]`s (seed 42, seed 1337) × 30 random
  `(offered, requested, fill)` triples each, drawn from `SmallRng`.
  Failure message includes seed, iter, and the failing triple so any
  regression is reproducible from the rstest case name alone. The
  regression `#[case]` block stays as a permanent edge-case suite.
- Leave `alice_reconstructs`, `cross_swap`, `creator_reclaim`,
  `invalid_input`, `compare`, and `parse_inputs` as standalone tests
  but rewrite their bodies to use the shared helpers.

Net: 1325 → 956 non-helper lines (-369), test count 14 → 58.

* style(pswap): apply nightly rustfmt

* fix(pswap): guard user-provided fill sum against u64 overflow

Switch `execute_pswap`'s `account_fill + note_fill` check to
`u64::overflowing_add` + `ERR_PSWAP_FILL_SUM_OVERFLOW`, so a malicious
consumer cannot pick operands whose felt sum wraps past u64 and
spuriously satisfies the `lte requested` guard. Also document why the
matching sums/subs in `create_p2id_note` and `create_remainder_note`
cannot over/underflow, and drop a stray trailing space on `FACTOR`.

* fix(pswap): correctness + layout cleanups from PR review theme 2

- create_p2id_note: drop three stray zero pads that shoved the real
  `note_idx` to stack depth 11 in the `has_account_fill` branch, so
  `move_asset_to_note` was reading a pad zero as the note index. The
  bug was masked in every existing test because `note_idx == 0`; add a
  SPAWN-note regression test that forces P2ID to `note_idx == 1`.
- load_offered_asset: bump `@locals(2)` to `@locals(8)` — we store two
  words (8 felts), not two felts.
- Drop `pswap_tag` from note storage (10 -> 9 items). The remainder
  path now lifts the tag out of the active note's metadata via
  `dup.2 movdn.4` + `metadata_into_note_type`, since the asset pair
  is unchanged across remainder creation. `PswapNoteStorage` loses
  the field, `with_pswap_tag`, and the getter; storage offsets and
  `NUM_STORAGE_ITEMS` shift accordingly.
- Document why `create_p2id_note`'s add (P2ID attachment), why
  `create_remainder_note`'s sub (amt_offered - amt_payout), and why
  `create_p2id_note` itself are reachable but safe (invariants come
  from the caller, not local checks).
- Correct the `payback_note_type` storage-layout docstring (only P2ID
  payback uses it; remainder inherits from active-note metadata).
- Note in a comment why `procref.main` cannot replace the runtime
  `active_note::get_script_root` call in `create_remainder_note`
  (compile-time call-graph cycle via main -> execute_pswap ->
  create_remainder_note -> procref.main).

* fix(pswap): align attachment layout + drop dead swap_count slot

- Attachment layout: MASM now emits `[fill, 0, 0, 0]` (Word[0] = fill)
  for both the P2ID and remainder attachments, matching the Rust-side
  `Word::from([fill, 0, 0, 0])` convention. Previously the two sides
  disagreed (Rust wrote Word[0], MASM wrote Word[3]), and the
  alice-reconstructs test was silently compensating by reading
  `aux_word[3]` against a Rust prediction it never compared to.
- alice-reconstructs test: read from the executed transaction's output
  (was already), read `aux_word[0]`, and add a direct Rust <-> MASM
  attachment-word parity `assert_eq!` so a future drift actually fails.
- Extend alice-reconstructs to also reconstruct the remainder PSWAP
  from her original pswap data + the remainder's on-chain attachment,
  verifying recipient + attachment parity against the executed output.
- Drop `pswap_count` from note storage (9 -> 8 items). The field was
  never read or written by pswap.masm — a dead pass-through slot. The
  Rust side was silently bumping it on remainder creation, so the
  Rust-predicted remainder recipient diverged from MASM's (caught only
  by extending the alice test). Remove the field, getter, builder arg,
  storage offsets, and all callers; shift creator ID to slots [6-7].

* refactor(pswap): masm perf + style cleanups from PR review theme 4

- Replace three `push.0 gt` (~16 cycles) zero-checks with `neq.0`
  (~3 cycles) at the has_account_fill, has_note_fill, and
  has_account_fill_payout branches.
- Use `dup.1 dup.1 neq` instead of `lt` for the `is_partial` check;
  the `lte requested` assertion above guarantees `total_in <=
  total_requested`, so `!=` is equivalent and cheaper.
- Flip the faucet-ID limb order at the create_remainder_note boundary
  from prefix-then-suffix to suffix-then-prefix (standard miden
  convention), updating the caller in execute_pswap, the proc
  docstring, local-slot comment, and the store block.
- Drop the redundant `movdn.2` / `movup.2` pair in create_remainder_note
  — `remaining_requested` is already on top, so `mem_store` can take it
  directly.
- Drop the `(4)` suffix on NOTE_ATTACHMENT / METADATA_HEADER stack
  comments; uppercase identifiers already imply a full word.
- Remove `exec.sys::truncate_stack` and its stale `use` import from
  execute_pswap. Tracing the proc end-to-end (including every syscall
  wrapper, call frame, and proc-local store) shows the stack is
  already balanced at exit, and all 59 pswap integration tests pass
  without it.

* refactor(pswap/tests): PR review theme 5 test quality cleanups

- `pswap_note_invalid_input_test` asserts the specific error kind via
  `assert_transaction_executor_error!(result, ERR_PSWAP_FILL_EXCEEDS_REQUESTED)`
  instead of a bare `.is_err()`. A future bug that fails the tx for the
  wrong reason will now surface.
- Drop the `rng: &mut RandomCoin` parameter from `build_pswap_note` —
  the helper draws its serial number from `builder.rng_mut()` directly.
  Remove all the `let mut rng = RandomCoin::new(Word::default())`
  declarations at call sites that only existed to feed this param.
- Rename local helper `note_args` -> `pswap_args` so it reads clearly
  next to the (unrelated) `TransactionContextBuilder::extend_note_args`
  method it gets passed into.
- Switch `assert_vault_added_removed` / `assert_vault_single_added` /
  `assert_fungible_asset_eq` helpers to take `FungibleAsset` instead of
  `(AccountId, u64)` tuples, and update every call site.
- `pswap_note_note_fill_cross_swap_test`: replace the flag-and-for-loop
  "which note contains which asset" check with `iter().any()` against
  two locally-built `Asset::Fungible(FungibleAsset::new(...))` values.
- `pswap_note_alice_reconstructs_and_consumes_p2id`: propagate the
  `prove_next_block()` error via `?` instead of swallowing it with
  `let _ =`.

Still outstanding from theme 5:
- realistic large amounts (20 * 10^18) in the happy-path tests
- an integration test where both account_fill and note_fill are
  non-zero on the same note (the Rust unit tests cover the predictor
  path, but the integration-level cross-flow needs a cleaner two-note
  setup than a simple adaption of the existing cross-swap test).
- skipping `Note -> PswapNote::try_from` roundtrips by having
  `build_pswap_note` return the `PswapNote` directly — a broader
  signature churn that is orthogonal to the items above.

* test(pswap): finish theme 5 — realistic amounts, combined fill, skip try_from

- `pswap_fill_test`: scale every amount by `AMOUNT_SCALE = 10^12` so
  the happy path exercises 12-decimal token values instead of single
  digits. The scale cap is chosen so `requested * FACTOR` stays under
  `u64::MAX`, matching the current MASM assumption.
- `build_pswap_note` now returns `(PswapNote, Note)` instead of just
  the `Note`, so call sites can execute the PswapNote directly and
  skip the `PswapNote::try_from(&note)?` round-trip the reviewer
  flagged. Every caller updated.
- New `pswap_note_combined_account_fill_and_note_fill_test`: exercises
  a PSWAP fill where the consumer supplies BOTH `account_fill` and
  `note_fill` on the same note in the same transaction. Alice offers
  100 USDC for 50 ETH, Bob offers 30 ETH for 60 USDC, Charlie consumes
  both — Alice's pswap uses combined fill (20 ETH from Charlie's vault
  + 30 ETH sourced from inflight via Bob's pswap payout), Bob's pswap
  uses pure note_fill. Asserts output notes, recipient parity, and
  Charlie's vault delta (-20 ETH / +40 USDC; the note_fill legs flow
  through inflight and never touch his vault).

* refactor(pswap): rename execute_full_fill_network -> execute_full_fill

The method has nothing network-specific about it — a "network
transaction" is just one where the kernel defaults note_args to
`[0, 0, 0, 0]` and the MASM script falls back to a full fill, which
any caller can trigger by calling this method directly. Rename to
reflect that, update the sole caller in the pswap_fill_test, and
rewrite the doc comment to describe the behavior (full fill producing
only the payback note, no remainder) rather than the network use case.

Also scrub stale doc references left over from theme 3's `swap_count`
removal:
- drop the "swap count overflows u16::MAX" bullet from `execute`'s
  errors section
- drop "swap count overflow" from `execute_full_fill`'s errors section
  (the whole section is gone — no error paths remain)
- update the PswapNote struct doc: the remainder carries "an updated
  serial number", not "an incremented swap count"
- update `create_remainder_pswap_note`'s doc for the same reason

* refactor(pswap): drop FACTOR, use u128 math for payout calculation

`calculate_tokens_offered_for_requested` previously used a fixed-point
1e5 precision factor with two separate branches (offered >= requested
vs requested > offered) plus a full-fill early return, to approximate
`offered * fill / requested` without overflowing u64 intermediates.

That design had three problems:

- Four `u64::wrapping_mul` calls silently produced wrong results for
  inputs where `x * FACTOR >= 2^64`, capping each operand at about
  1.84e14 — roughly 0.000184 whole tokens for any 18-decimal asset.
- The two-branch structure was fragile and harder to reason about than
  a single linear formula.
- The FACTOR-scaled intermediate introduced rounding error in `ratio`
  that then got amplified by `fill`.

Replace the whole proc with one linear path:

  product = u64::widening_mul(offered, fill_amount)   # -> u128
  quot    = u128::div(product, requested_u128)        # -> u128
  assert  q.hi_limbs == 0                              # payout fits in u64
  return  q.lo_limbs combined back into a felt

miden-core-lib 0.22 already exposes `u128::div` (advice-provider
assisted, same host-compute-and-verify pattern as `u64::div`), so no
custom division implementation is needed.

Properties of the new version:
- Exact integer precision (one floor division at the end, no FACTOR
  rounding).
- Each operand can go up to `FungibleAsset::MAX ≈ 2^63`, so 18-decimal
  tokens now work at realistic volumes (~9.2 billion whole tokens
  per swap) — a ~50,000x improvement in dynamic range.
- No branching on the offered/requested relationship. No full-fill
  early return. One generic formula that also handles the
  `fill_amount == requested` case trivially.
- All wrapping_mul references gone, closing the last deferred theme-1
  item from the PR review.

Also mirror the same change on the Rust side: `calculate_output_amount`
now just does `(offered as u128) * (fill as u128) / (requested as u128)`
and `try_from`s back to u64, matching MASM exactly. Scrub the old
PRECISION_FACTOR constant, the two-branch Rust logic, and the FACTOR
doc block.

The 8 in-crate unit tests and all 60 pswap script tests (including
the 27-case hand-picked ratio regression suite and two seeded
30-iteration fuzzers) still pass.

* test(pswap): second pass on PR review follow-ups

- `calculate_output_amount` doc: fix a mismatched paren and the empty
  blank line between doc and fn signature that triggered clippy's
  `empty_line_after_doc_comments` (caught by CI after the last push).
- `pswap_note_alice_reconstructs_and_consumes_p2id`: build the
  `PswapNote` via the builder, call `pswap.clone().into()` to get the
  protocol `Note`, and keep `pswap` in scope for `.execute(...)`. Drops
  the `PswapNote::try_from(&pswap_note)?` roundtrip the reviewer flagged
  on this exact test as a nit.
- `pswap_chained_partial_fills_test`: same pattern — replace the manual
  `Note::new(NoteAssets / NoteMetadata / NoteRecipient)` construction
  with `PswapNote::builder().serial_number(current_serial)...build()?`
  + `pswap.clone().into()`. The raw-Note construction was only there to
  inject a specific serial per chain position, which the builder
  already supports. Also drops the dependent `PswapNote::try_from`
  roundtrip.
- `pswap_fill_test`: bump `AMOUNT_SCALE` from 10^12 to 10^18 so the
  happy-path test exercises the MASM u128 calculation at realistic
  18-decimal token magnitudes. Base values adjusted (offered=8,
  requested=4, fills=3/4) so every amount stays under AssetAmount::MAX
  ≈ 9.22 × 10^18. Previously the 10^12 scale was chosen to stay under
  the old FACTOR=1e5 cap; now that the u128 rewrite lifted that cap,
  the test can stress the calculation at the actual wei-equivalent
  scale the reviewer asked for.
- New `pswap_attachment_layout_matches_masm_test`: dedicated
  regression test for the shared P2ID and remainder attachment-word
  layout. Does a partial fill, then explicitly asserts the executed
  transaction's P2ID attachment equals `[fill_amount, 0, 0, 0]` and
  the remainder attachment equals `[amt_payout, 0, 0, 0]`, and
  cross-checks both against the Rust-predicted attachments. Fires if
  either MASM or Rust drifts the load-bearing felt off `Word[0]`.
- Apply the "blank line after every `# => [...]` stack comment"
  convention across pswap.masm where it was missing — one reviewer
  tends to leave this as a nit so sweep the whole file for
  consistency rather than wait for the comments.

* style(pswap/tests): apply rustfmt

* refactor(pswap): expose `PswapNote::create_args` as public helper

Add `PswapNote::create_args(account_fill: u64, note_fill: u64) ->
Result<Word, NoteError>` so downstream consumers building PSWAP
`NOTE_ARGS` words don't need to know the `[account_fill, note_fill,
0, 0]` layout by hand. Returns a `Result` instead of panicking so the
underlying `Felt::try_from` conversion errors propagate cleanly
through the standard `NoteError` path — although for any amount that
fits in `FungibleAsset::MAX_AMOUNT` this cannot actually fail, the
conversion is surfaced explicitly rather than hidden behind an
`.expect(...)` in a public API.

Drop the local `pswap_args` test helper — every call site now uses
`PswapNote::create_args(...)?` directly, matching the reviewer's
suggestion that the layout helper live on `PswapNote` rather than
being reimplemented in each consumer.

All 61 pswap script tests pass with the new signature (twelve call
sites updated to propagate the Result via `?`).

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* fix(pswap): CI green — unused imports + duplicated exec

Two fixes triggered by `make check-features` / `clippy -D warnings`
and the full pswap test suite:

- `tests/scripts/pswap.rs`: drop `NoteAssets`, `NoteMetadata`,
  `NoteRecipient`, `NoteStorage` from the `miden_protocol::note`
  import list. Leftovers from the theme-5 chained-fills refactor that
  switched from low-level `Note::new(NoteAssets, NoteMetadata,
  NoteRecipient)` construction to `PswapNote::builder()`. CI compiles
  with `-D warnings` so the unused-imports warning was fatal.

- `asm/standards/notes/pswap.masm`: remove a duplicate
  `exec.calculate_tokens_offered_for_requested` line that had crept
  into the note-fill payout path in one of the upstream edits, plus a
  duplicate stack comment above the account-fill payout block. With
  the duplicate `exec`, the second call read garbage off a stack that
  only held the first call's payout — specifically a zero divisor,
  which surfaced as `u128::div` "division by zero" and failed 57/61
  pswap tests.

All 61 pswap script tests pass after the fix, and
`cargo check --all-targets --all-features` on miden-testing is clean.

* refactoring changes

* fix(pswap): address PR review — storage, attachments, asset validation

- Derive payback note tag from creator ID in MASM via
  note_tag::create_account_target instead of storing in note storage,
  reducing storage from 8 to 7 items.
- Add dedicated attachment constructors (payback_attachment,
  remainder_attachment) on PswapNote for clarity and reuse.
- Validate computed amounts as valid fungible asset amounts:
  - calculate_output_amount now returns Result and checks via AssetAmount.
  - MASM assert_valid_asset_amount proc checks u64 values against
    FUNGIBLE_ASSET_MAX_AMOUNT before felt conversion to prevent silent
    wrapping, applied to both fill sum and payout quotient.
- Fix P2ID comment nit per reviewer suggestion.
- Remove unused NoteTag import from p2id test.

* style: apply nightly rustfmt

* fix(pswap): simplify assert_valid_asset_amount and rename procedure

- Replace manual hi/lo branch logic with exec.u64::lte
- Rename calculate_tokens_offered_for_requested to calculate_output_amount (matches Rust)
- Simplify tag derivation in create_p2id_note: swap+dup+swap+movup.2 → dup.1+movdn.2

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* test(pswap): add rstest cases for fill-sum overflow and max-asset-amount validation

Converts pswap_note_invalid_input_test to rstest with three named cases:
- fill_exceeds_requested (existing)
- fill_sum_u64_overflow: both fills at 2^63, sum overflows u64 → ERR_PSWAP_FILL_SUM_OVERFLOW
- fill_sum_exceeds_max_asset_amount: both fills at MAX_AMOUNT, sum > MAX_AMOUNT → ERR_PSWAP_NOT_VALID_ASSET_AMOUNT

---------

Co-authored-by: Vaibhav Jindal <vaibhavjindal@Vaibhavs-MacBook-Pro.local>
Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>
* chore: remove attachment parameters from SWAP and MINT

* chore: add changelog

* chore: remove outdated comment
* Refactor code structure for improved readability and maintainability

* fix: fixing after rebase.

* refactor: improve formatting and readability in various files

* Refactor metadata handling in fungible faucets

- Updated the `create_basic_fungible_faucet` and `create_network_fungible_faucet` functions to use boolean flags for description, logo URI, and external link mutability instead of integer flags.
- Modified the `Info` struct to replace the previous flag system with separate boolean fields for initialized and mutable states.
- Adjusted storage layout documentation to reflect changes in metadata configuration.
- Updated tests to align with the new boolean flag system for mutability and initialization.
- Ensured backward compatibility by updating mock chain builder and test cases to use the new structure.

* refactor: update token metadata references in faucet tests to use FungibleTokenMetadata

* chore: lint

* Refactor token metadata encoding to use 7-bytes-per-felt, length-prefixed format

- Updated `TokenName`, `Description`, `LogoURI`, and `ExternalLink` structs to support new encoding scheme.
- Adjusted maximum byte lengths and encoding/decoding methods to accommodate the new format.
- Modified metadata module to reflect changes in field sizes and encoding conventions.
- Updated tests to validate new field sizes and encoding behavior.
- Changed mock chain builder and associated tests to handle updated metadata structure.

* refactor: replace RPO256 with Poseidon2 for hashing in fungible metadata and update related tests

* refactor: format BasicFungibleFaucet initialization for improved readability

* fix: adapt metadata MASM to little-endian word ordering after upstream migration

The upstream LE migration (PR #2512) changed get_item to return [word[0], ..., word[3]]
(word[0] on top) instead of [word[3], ..., word[0]]. This commit:

- Reverses element extraction logic in all getters (get_token_metadata, get_max_supply,
  get_decimals, get_token_symbol, get_token_supply, mutability checks)
- Fixes mutability flag extraction in all optional setters
- Fixes max_supply replacement logic in optional_set_max_supply
- Changes loc_storew_be/loc_loadw_be to loc_storew_le/loc_loadw_le to preserve
  natural word element ordering in memory for hash computations
- Updates test hasher from Rpo256 to Poseidon2 to match MASM poseidon2 module
- Fixes get_owner stack depth (get_item returns +2 net elements with 2-felt slot IDs)
- Updates all inline MASM test assertions to match LE stack ordering

* chore: adding type as entry instead of separate variables

* refactor: enforce defining supported types on metadata (#2554)

* feat: enforce maximum serialized size for output notes (#2205)

* feat: introduce `AccountIdKey` (#2495)

* Introducing a dedicated AccountIdKey type to unify and centralize all AccountId

* changelog for introduce AccountIdKey type

* refactor: clean up comments and improve code readability in AccountIdKey and tests

* refactor: update AccountIdKey conversion method and clean up imports

* refactor: reorganize AccountIdKey indices and clean up related code

* Apply suggestions from code review

* Update crates/miden-protocol/src/block/account_tree/account_id_key.rs

* Update crates/miden-protocol/src/block/account_tree/account_id_key.rs

* feat: validate account ID in `AccountTree::new`

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* fix: make format and remove unused import (#2564)

* feat: make `NoteMetadataHeader` public (#2561)

* chore: ProvenBlock constructor with validation (#2553)

* refactor: include fee in TransactionId computation

* refactor: remove `Ord` and `PartialOrd` from `StorageSlot` (#2549)

* chore: Replace SMT leaf conversion function (#2271)

* feat: add ability to submit user batches for the MockChain (#2565)

* chore: Explicitly use `get_native_account_active_storage_slots_ptr` in `account::set_item` and `account::set_map_item`

* chore: fix typos

* feat: integrate PSM contracts to AuthMultisig  (#2527)

* chore: remove `ProvenTransactionBuilder` in favor of `ProvenTransaction::new` (#2567)

* feat: implement `Ownable2Step` (#2292)

* feat: implement two-step ownership management for account components

- Add `ownable2step.masm` to provide two-step ownership functionality, requiring explicit acceptance of ownership transfers.
- Create Rust module for `Ownable2Step` struct to manage ownership state and storage layout.
- Introduce error handling for ownership operations in `standards.rs`.
- Develop comprehensive tests for ownership transfer, acceptance, and renouncement scenarios in `ownable2step.rs`.

* feat: add Ownable2Step account component for two-step ownership transfer

* fix: correct ownership word layout and update transfer ownership logic in ownable2step

* Refactor ownership management to use Ownable2Step pattern

- Updated the access control mechanism to implement a two-step ownership transfer pattern in the ownable2step module.
- Modified the storage layout to accommodate the new ownership structure, reversing the order of owner and nominated owner fields.
- Refactored the network fungible faucet to utilize the new Ownable2Step for ownership management.
- Adjusted related tests to validate the new ownership transfer logic and ensure correct behavior when transferring and accepting ownership.
- Updated error handling to reflect changes in ownership management, including new error messages for ownership transfer scenarios.

* refactor: update ownership word layout and adjust related logic in Ownable2Step

* refactor: rename owner and nominated_owner to get_owner and get_nominated_owner for consistency

* refactor: streamline ownership management in tests by utilizing Ownable2Step according to philip

* fix: `make format`

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* feat: add token metadata support to NetworkFungibleFaucet

* feat: enforce maximum serialized size for output notes (#2205)

* feat: implement `Ownable2Step` (#2292)

* feat: implement two-step ownership management for account components

- Add `ownable2step.masm` to provide two-step ownership functionality, requiring explicit acceptance of ownership transfers.
- Create Rust module for `Ownable2Step` struct to manage ownership state and storage layout.
- Introduce error handling for ownership operations in `standards.rs`.
- Develop comprehensive tests for ownership transfer, acceptance, and renouncement scenarios in `ownable2step.rs`.

* feat: add Ownable2Step account component for two-step ownership transfer

* fix: correct ownership word layout and update transfer ownership logic in ownable2step

* Refactor ownership management to use Ownable2Step pattern

- Updated the access control mechanism to implement a two-step ownership transfer pattern in the ownable2step module.
- Modified the storage layout to accommodate the new ownership structure, reversing the order of owner and nominated owner fields.
- Refactored the network fungible faucet to utilize the new Ownable2Step for ownership management.
- Adjusted related tests to validate the new ownership transfer logic and ensure correct behavior when transferring and accepting ownership.
- Updated error handling to reflect changes in ownership management, including new error messages for ownership transfer scenarios.

* refactor: update ownership word layout and adjust related logic in Ownable2Step

* refactor: rename owner and nominated_owner to get_owner and get_nominated_owner for consistency

* refactor: streamline ownership management in tests by utilizing Ownable2Step according to philip

* fix: `make format`

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* feat: prefix account components with miden::standards namespace (#2400)

* Refactor code structure for improved readability and maintainability

* Refactor metadata handling in fungible faucets

- Updated the `create_basic_fungible_faucet` and `create_network_fungible_faucet` functions to use boolean flags for description, logo URI, and external link mutability instead of integer flags.
- Modified the `Info` struct to replace the previous flag system with separate boolean fields for initialized and mutable states.
- Adjusted storage layout documentation to reflect changes in metadata configuration.
- Updated tests to align with the new boolean flag system for mutability and initialization.
- Ensured backward compatibility by updating mock chain builder and test cases to use the new structure.

* refactor: update token metadata references in faucet tests to use FungibleTokenMetadata

* chore: adding type as entry instead of separate variables

* feat: add owner support to TokenMetadata and update related components

* fix: correct output order in get_owner function

* feat: enhance ownership handling in fungible faucets and metadata components

* fix: update documentation for metadata_slot and description commitment tests

* Update crates/miden-standards/asm/standards/access/ownable.masm

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* refactor: improve comments and assertions in distribute function for minting constraints

* Refactor fungible metadata procedures: rename optional setters to standard setters and remove unused commitment functions

* refactor: standardize TokenMetadata usage across faucets and tests

* chore: Refactor code structure for improved readability and maintainability

* feat: add TokenMetadata and AccountSchemaCommitment components for enhanced account metadata management, split from mod.

* chore: lint

* refactor: replace TokenName::new("") with TokenName::default() for consistency

* refactor: update metadata field limits and improve code consistency

* chore: lint

* remove duplicates!

* refactor: remove unused scale_down_amount procedure

* refactor: account metadata handling and remove owner dependency in favor of ownable2steps.

- Updated account metadata module to clarify ownership management, removing direct references to the owner in metadata.
- Simplified `TokenMetadata` struct by eliminating owner-related fields and methods, focusing on name and optional fields.
- Adjusted storage layout and accessors to reflect changes in metadata structure.
- Removed owner-related tests and mock implementations from testing suite.
- Introduced Rpo256 hashing for field data to enhance integrity checks in metadata operations.

* refactor: simplify network fungible faucet creation by consolidating metadata parameters

* refactor: clone token symbol in FungibleTokenMetadata creation to avoid ownership issues

* refactor: update comments for clarity and fixed hash handling in token metadata tests

* refactor: streamline fungible token metadata handling in tests and simplify faucet creation

* Refactor FungibleTokenMetadata creation to use builder pattern

- Introduced FungibleTokenMetadataBuilder to simplify the creation of FungibleTokenMetadata instances.
- Updated all instances of FungibleTokenMetadata creation across the codebase to utilize the new builder pattern.
- Enhanced readability and maintainability by allowing optional fields to be set in a chainable manner.
- Adjusted tests and mock implementations to accommodate the new builder approach.

* refactor: update faucet initialization to use FungibleTokenMetadataBuilder

* refactor: format imports and streamline FungibleTokenMetadataBuilder usage in tests

* refactor: rename mutability flags for clarity and consistency in token metadata handling

* docs: update comments to clarify procedures in BasicFungibleFaucet, fixing lint/doc

* feat: integrate AuthControlled mint policy into BasicFungibleFaucet setup

* feat: changed metadata structure and fixed-width string utility

- moved `TokenMetadata` and `TokenName` structs to manage token metadata including name, description, logo URI, and external link.
- Implemented `FixedWidthString` for encoding fixed-width UTF-8 strings into storage words.
- Added utility functions for reading and writing token metadata to account storage.
- Created a new module for string utilities and organized existing modules.

* chore: ci/cd fix

* chore: change for rust doc

* chore: fmt

* refactor: update fungible token metadata methods to be on pair with comments and discussion on github.

* chore: lint wrong import

* refactor: update fungible token metadata structure and error handling

* reset files in crates agglayer to be exactly the same the next.

* chore: reset files in crates agglayer to be exactly the same the next.

* chore: MASM - rename + refactor fungible_faucet

* refactor: core metadata restructure

* chore: faucets cleanup

* refactor: clean up imports and update token metadata handling

* refactor: simplify FungibleTokenMetadataBuilder usage and improve readability

* fix: update layout sync reference for fungible faucet metadata

* refactor: update imports for FungibleTokenMetadataBuilder and clean up faucet references

* refactor: update function calls to use fungible_faucet metadata

* sync agglayer with upstream/next

* chore: remove agglayer changes.

* refactor: update versioning and error handling in token metadata and faucet modules

* refactor: reorganize token metadata handling and maintain backward compatibility on Agglayer

* refactor: update slot name for token metadata to align with FungibleTokenMetadata

* refactor: update token metadata handling and error messages for fungible tokens

* refactor: enhance fungible token metadata handling and validation logic

* refactor: change new_validated + builder to accept u64 for supply fields

Move max_supply validation and Felt conversion into new_validated so the
check lives in exactly one place. Builder token_supply field is now u64
for API consistency, removing the Felt::new() with SAFETY comment.

* fix: propagate TokenName errors in network_faucet_metadata helper

Replace silent fallback to empty TokenName with ? operator so test
failures surface the actual error instead of hiding it.

* refactor: replace Felt::new assertions with try_from storage roundtrip

Use FungibleTokenMetadata::try_from(storage) to verify stored values
instead of raw Felt::new comparisons on individual storage word elements.

* test: remove duplicate MASM name readback tests

Remove basic_faucet_name_readable_from_masm and
network_faucet_name_readable_from_masm which are functionally
equivalent to get_name_from_masm.

* test: remove name_32_bytes_accepted duplicate test

Already covered by basic_faucet_with_max_name_and_full_description
which builds an account with a 32-byte name and verifies storage
round-trip.

* test: move name_33_bytes_rejected + description_7_words to unit tests

Delete name_33_bytes_rejected (already covered by token_name_too_long)
and description_7_words_full_capacity from integration tests. Add
description_7_words_full_capacity as a pure unit test in miden-standards
using into_storage_slots() instead of building a full Account.

* refactor: convert is_field_mutable_checks to rstest parametrized test

Replace manual Vec of cases with rstest #[case] attributes using
build_faucet_metadata() + with_*_mutable() for conciseness. No content
fields needed since these tests only check the flag bit.

* refactor: simplify field setter test scripts

Remove .add_note_script() from owner-succeeds test since notes already
have code via .code(). Simplify non-owner-fails test by removing hash
push and advice_map since the auth check fires before data is touched.

* test: use multi-word token name in build_pol_faucet_metadata

Change token name from "POL" (3 bytes, single word chunk) to "Polygon
Token" (13 bytes) so both name_chunk_0 and name_chunk_1 are non-zero,
exercising both storage slots.

* test: remove unnecessary push.0 between getter calls

The push.0 padding between successive call-convention getter invocations
was unnecessary — call already pads the stack to 16 elements. Verified
the test passes without them.

* refactor: remove unused import and redundant note script compilation

* refactor: remove unused note script compilation from max supply tests

* refactor: simplify hash handling in test_field_setter_owner_succeeds

* refactor: simplify note script code in set_max_supply_mutable_non_owner_fails test

* refactor: update `miden-vm` to v0.22.1 and apply compatibility fixes (#2742)

* chore: increment crate versions to v0.14.3 (#2744)

* refactor(agglayer): lowercase note script filenames in miden-agglayer (#2736)

* refactor: lowercase note script filenames in miden-agglayer

* docs(agglayer): update SPEC.md note script filenames to lowercase

Agent-Logs-Url: https://github.com/0xMiden/protocol/sessions/4f7eb749-9710-4a36-8caf-486f12ae21d7

Co-authored-by: partylikeits1983 <77119221+partylikeits1983@users.noreply.github.com>

* fix: update SPEC.md to reference .masm

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* refactor: change `TokenSymbol` to `Symbol` and add new `TokenSymbol` and `RoleSymbol` types (#2690)

* feat(asset): add AssetAmount wrapper type (#2721)

* feat(asset): add AssetAmount wrapper type for fungible amounts

Introduce a validated AssetAmount(u64) newtype that encapsulates the
max-amount check (2^63 - 2^31) at construction time.

- Add AssetAmount with MAX constant, new(), as_u64(), From<u8/u16/u32>,
  TryFrom<u64>, Display, Serializable, Deserializable
- Integrate into FungibleAsset: replace raw u64 amount field
- Delegate validation in FungibleAsset::new() to AssetAmount::new()
- Keep FungibleAsset::MAX_AMOUNT as backward-compatible alias
- Keep amount() returning u64 to minimize downstream churn

Closes #2532

* refactor: remove as_u64, delegate add/sub to AssetAmount

Remove the redundant as_u64() accessor since From<AssetAmount> for u64
already provides the same conversion. Replace all call sites with
u64::from().

Add add() and sub() methods to AssetAmount so that FungibleAsset can
delegate arithmetic to the inner type instead of performing it inline.
Add unit tests for both new methods.

* style: fix rustfmt and clippy lints

Expand import list to one-per-line, merge duplicate use super
statements, collapse single-line assert_eq, and suppress
should_implement_trait on AssetAmount::add/sub.

* docs: add changelog entry for AssetAmount wrapper

* refactor: make AssetAmount::MAX a u64 constant, use .into() in tests

* fix: add type annotations for .into() in tests to resolve ambiguity

* refactor: implement Add and Sub traits for AssetAmount

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
Co-authored-by: Marti <marti@miden.team>

* fix: validate leafType on CLAIM note processing (#2730)

* chore: bump rand to 0.9.3 and 0.10.1 (#2756)

* feat: add `metadata_into_note_type` procedure to note.masm (#2738)

* feat: add `metadata_into_note_type` procedure to note.masm

Add a procedure to extract the note type from the metadata header
and unit tests for both public and private note types.

* refactor: address PR review — move stack layout to Where docs, consolidate tests with rstest

* chore: add CHANGELOG entry for metadata_into_note_type

* refactor: address review — clarify bit position, add stack layout docs, use NoteType comparison

* refactoring changes

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* docs: link CHANGELOG entry for metadata_into_note_type to PR #2738

---------

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* refactor: remove unnecessary asm/ tree copy from standards and agglayer build scripts (#2538)

* refactor: avoid unnecessary asm/ tree copy in standards build script

miden-standards: Remove the full asm/ directory copy to OUT_DIR entirely.
This crate never mutates its source tree, so the assembler and error
extractor can read directly from the crate's asm/ directory.

miden-protocol: Replace the bulk copy of the entire asm/ tree with
targeted staging of only the two directories that need modification
(kernels/transaction/ and protocol/). The assembler requires shared
modules to be physically present alongside these source files, but
shared_utils/ and shared_modules/ themselves don't need to be copied.
Event extraction now reads directly from the original source.

Also simplifies copy_dir_recursive (replacing the old copy_directory
with its awkward prefix-stripping API) and removes dead code.

https://claude.ai/code/session_01HDd5o3XxcgZiGrvBDFsUr1

refactor: scope change to standards build only, leave protocol as-is

The protocol crate needs source-level staging because the assembler's
`$kernel::` import resolution requires shared modules to be physically
co-located with kernel source. This cannot be avoided without assembler
changes, so revert the protocol build.rs to the base branch version.

https://claude.ai/code/session_01HDd5o3XxcgZiGrvBDFsUr1

* refactor: remove copy_directory from agglayer build.rs

Read MASM sources directly from the crate's asm/ directory instead of
copying them to OUT_DIR first. The copy is unnecessary because agglayer
doesn't mutate the directory structure during compilation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: generate agglayer error constants into OUT_DIR

Write error constants to OUT_DIR instead of src/errors/agglayer.rs, matching
the pattern used by miden-standards. The include now uses
concat!(env!("OUT_DIR"), ...) so error generation always runs regardless of
BUILD_GENERATED_FILES_IN_SRC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* refactor: validate canonical_zeros.masm instead of generating it

The canonical zeros are deterministic Keccak256 values that never change.
Instead of generating the file at build time (guarded by BUILD_GENERATED_FILES_IN_SRC),
the committed file is now validated against the expected content. To regenerate,
run with REGENERATE_CANONICAL_ZEROS=1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: remove BUILD_GENERATED_FILES_IN_SRC from agglayer

Both error constants and canonical zeros no longer write to src/, so
BUILD_GENERATED_FILES_IN_SRC is unused and can be removed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: fix trailing empty doc comment line

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>

* refactor: reduce max assets per note from 255 to 64 (#2741)

* refactor: reduce max assets per note from 255 to 64

* feat: add add_assets_exceeding_max_per_note_fails test

* Update crates/miden-protocol/asm/kernels/transaction/lib/note.masm

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update crates/miden-protocol/asm/kernels/transaction/lib/memory.masm

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: correct CHANGELOG issue link from miden-base to protocol repo

Agent-Logs-Url: https://github.com/0xMiden/protocol/sessions/7e834550-7f38-4d90-9c05-d46e3a7e37fa

Co-authored-by: partylikeits1983 <77119221+partylikeits1983@users.noreply.github.com>

* refactor: address PR comments: add max assets success test, fix memory layout table

* chore: fix changelog

* Update crates/miden-protocol/src/transaction/kernel/memory.rs

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* Update crates/miden-testing/src/kernel_tests/tx/test_output_note.rs

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* refactor: use rstest for tests & update changelog

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* chore: make metadata procedure names consistent and update swap tag construction (#2758)

* chore: make note procedure names consistent

* chore: add changelog

* chore: update swap tag construction

* feat: document reentrancy of auth procedures (#2784)

* feat: Add cycle counts to successful and failed notes (#2772)

* Add cycle counts to successful and failed notes

* Changelog

* Cycle count order comment

* Make fields private

* fix(bench): enable concurrent feature for miden-tx in bench-transaction (#2790)

* Improve deserialization error handling in AccountCode (#2788)

* fix: improve deserialization error handling in AccountCode

* chore: update changelog

* refactor: removed AccountCode::from_bytes()

* Enable `concurrent` feature for `std` context (#2791)

* refactor: always enable concurrent on std in miden-tx

* chore: delete miden-protocol-macros crate

* chore: update changelog

* PSwap Contract (#2636)

* Added the pswap masm contract and its supportive functions

* Added the pswap masm contract and its supportive functions

* refactor: rename swapp_tag to pswap_tag, NUM_ITEMS to NUM_STORAGE_ITEMS, remove create_ wrappers, add builder finish_fn

- Rename swapp_tag -> pswap_tag and SWAPp -> PSWAP throughout
- Rename NUM_ITEMS -> NUM_STORAGE_ITEMS for clarity
- Remove create_p2id_payback_note and create_remainder_note wrappers,
  make build_ functions public instead
- Compute p2id_tag inside build_p2id_payback_note from self.storage
- Add #[builder(finish_fn(vis = "", name = build_internal))] to PswapNote

* refactor: remove redundant test helpers, use pswap lib functions directly

Replace all test helper wrappers with direct calls to library functions:
- create_pswap_note -> PswapNote::create()
- create_expected_pswap_p2id_note + create_expected_pswap_remainder_note -> pswap.execute()
- build_pswap_storage -> PswapNoteStorage::from_parts()
- Remove make_pswap_tag, make_note_assets, make_note_args, compute_p2id_tag_*
- Inline calculate_output_amount as PswapNote::calculate_output_amount()

* docs: polish pswap doc comments to match sibling note style

- Replace storage layout list with markdown table
- Remove trivial "Returns the X" docs on simple getters
- Add # Errors sections where relevant
- Rewrite method docs to describe intent, not implementation
- Add one-line docs on From/TryFrom conversion impls
- Tighten PswapNote struct doc

* refactor: make assets a required field on PswapNote builder

* fix: adapt pswap to upstream API changes after rebase

- Rename RpoRandomCoin to RandomCoin (miden-crypto 0.23 rename)
- Store full ASSET_KEY instead of prefix/suffix to preserve callback
  metadata in faucet_id_suffix_and_metadata
- Replace create_fungible_asset calls with direct ASSET_KEY + manual
  ASSET_VALUE construction, avoiding the new enable_callbacks parameter
- Update hardcoded P2ID script root to match current P2idNote::script_root()

* refactor: use procref for P2ID script root, clean up pswap MASM

- Replace hardcoded P2ID script root with procref.p2id::main for
  compile-time resolution
- Default to full fill when both input and inflight amounts are zero
- Replace magic address 4000 with named P2ID_RECIPIENT_STORAGE constant
- Remove step numbering from comments, fix memory layout docs

* refactor: address PR review comments on pswap MASM

- Rename P2ID_RECIPIENT_STORAGE to P2ID_RECIPIENT_SUFFIX/PREFIX
- Add METADATA_HEADER word layout docs with source reference
- Document attachment_scheme parameter in set_word_attachment call
- Add stack views after condition checks

* refactor: rename pswap storage accessors, add offered_asset_amount helper, simplify build_p2id_payback_note

Rename requested_key/requested_value/requested_amount to
requested_asset_key/requested_asset_value/requested_asset_amount for
clarity. Extract offered_asset_amount() helper on PswapNote to
deduplicate offered asset extraction. Simplify build_p2id_payback_note
to take fill_amount: u64 instead of aux_word: Word, constructing the
aux word internally.

* refactor: address PR review comments on pswap Rust module

- Use NoteTag::default() instead of NoteTag::new(0)
- Change swap_count from u64 to u16 with safe try_into conversion
- Rename p2id_tag to payback_note_tag, p2id_payback_note to payback_note
- Rename build_ prefix to create_ for consistency
- Rename aux_word to attachment_word
- Replace Felt::new with Felt::from where possible
- Rename inputs to note_storage in TryFrom impl
- Make create_payback_note and create_remainder_pswap_note private
- Add offered_faucet_id helper to replace unreachable!()

* refactor: use builder pattern for PswapNote and PswapNoteStorage

- Remove PswapNote::create, add public build() with validation on builder
- Add bon::Builder to PswapNoteStorage, remove new() and from_parts()
- Remove payback_note_tag field, compute from creator_account_id on the fly
- Fix clippy warnings (useless conversions, needless borrows)
- Update all unit and integration tests to use builder pattern

* refactor: clean up pswap tests and fix clippy warnings

- Compare full faucet_id instead of just prefix in build validation
- Rename swap_note to pswap_note in integration tests for consistency
- Extract PswapNoteStorage builder into separate let bindings
- Replace manual current_swap_count counter with enumerate index
- Fix clippy useless_conversion and needless_borrow warnings

* refactor: rename inputs to storage_items in pswap_note_storage_try_from test

* chore: fix Cargo.toml dependency ordering and add CHANGELOG entry for PSWAP

* refactor: address PR review comments — use FungibleAsset types, improve safety and docs

- PswapNoteStorage: store FungibleAsset instead of raw key/value Words
- PswapNote: store offered_asset as FungibleAsset instead of NoteAssets
- execute(): take Option<FungibleAsset> for input/inflight assets
- Split execute into execute() and execute_full_fill_network() for clarity
- create_tag(): accept &FungibleAsset instead of &Asset
- Eliminate all Felt::new usage (use Felt::from, Felt::try_from, + ONE)
- Add swap_count overflow protection via checked_add
- Add script root verification in TryFrom<&Note>
- Add MASM fill validation (fill_amount <= requested)
- Rename MASM constants: _INPUT -> _ITEM, SWAPP_ -> PSWAP_
- Make calculate_output_amount private, add precision doc comment
- Add doc comments on all public accessors and methods
- Add network account full fill test
- Document network transaction compatibility throughout

* refactor: pass creator ID via stack to is_consumer_creator and use account_id::is_equal

* refactor: optimize requested asset storage to 4 felts and add NUM_STORAGE_ITEMS constant

Store requested asset as individual felts [enable_callbacks, faucet_suffix,
faucet_prefix, amount] instead of full ASSET_KEY + ASSET_VALUE (8 felts).
Use create_fungible_asset to reconstruct when needed. Reduces note storage
items from 18 to 14. Add NUM_STORAGE_ITEMS constant and execute_pswap doc comment.

* refactor: use p2id::new, pass inputs via stack, unify serial derivation

- Replace manual recipient building with p2id::new in create_p2id_note
- Pass all inputs via stack, store intermediates in @locals
- Remove build_p2id_recipient_hash, P2ID_RECIPIENT_*, P2ID_NOTE_IDX
- Payback serial: serial[0] + 1, remainder serial: serial[3] + 1
- Update Rust side to match new serial derivation, remove Hasher import

* refactor: pass all inputs via stack to create_remainder_note, eliminate global memory reads

- create_remainder_note takes 8 stack inputs, stores to @locals(6)
- Extract offered faucet info from ASSET_KEY in execute_pswap
- Use create_fungible_asset for consumer receive_asset and remainder asset
- Remove OFFERED_ASSET_KEY, PSWAP_NOTE_IDX constants

* feat: add P2ID reconstruction test, overfill docs, and stack comments

- Add test verifying Alice can reconstruct and consume P2ID payback note
  from her PSWAP data after Bob's partial fill
- Document why overfill is not allowed (likely unintentional error)
- Add missing stack comment on partial fill check

* fix: use Rust-predicted note for aux data in P2ID reconstruction test

The test framework doesn't preserve word attachment content in executed
transaction outputs. Use the Rust-predicted note to read the fill amount
from aux data, which mirrors production behavior where aux is visible.

* refactor: rename input to account fill, extract load_offered_asset proc

- Rename AMT_REQUESTED_IN to AMT_REQUESTED_ACCT_FILL and related variables
- Extract load_offered_asset proc centralizing asset loading and validation
- Remove OFFERED_ASSET_WORD global memory constant

* refactor: extract test helpers and reduce verbosity in pswap unit tests

* refactor: guard zero-amount receive_asset in MASM, add NUM_STORAGE_ITEMS alias on PswapNote

* refactor: rename ERR_PSWAP_WRONG_NUMBER_OF_INPUTS to ERR_PSWAP_WRONG_NUMBER_OF_STORAGE_ITEMS

* refactor: replace global memory with @locals in execute_pswap and pass fill amounts via stack

* refactor(pswap): apply PR review nits from #2636

- Drop duplicated u64 stdlib docs inside calculate_tokens_offered_for_requested
- Replace `swap push.MAX_U32 mul add` with `swap mul.MAX_U32 add`
- Fold redundant empty-input guard in PswapNote::execute into the match arm

* feat(pswap): make payback note type configurable via PswapNoteStorage

Adds a `payback_note_type: NoteType` field on `PswapNoteStorage` (default
`Private`) so the payback note produced on fill can be private even when
the pswap note itself is public. Private payback notes are cheaper in
fees and bandwidth and don't lose information — the fill amount is
already recorded in the executed transaction's output.

Stored in the previously-reserved storage slot [6]. MASM now loads the
type from that slot when building the payback p2id note instead of using
the active note's own type. Remainder pswap note continues to inherit
the parent pswap's note type (unchanged).

Addresses PhilippGackstatter's review comment on PR #2636.

* perf(pswap): compress note storage layout from 14 to 10 items

Drops four reserved/zero padding slots ([7] and [9-11] in the old layout)
that served no purpose. The compressed layout is contiguous:

  [0-3] requested asset (callbacks, faucet suffix/prefix, amount)
  [4]   pswap_tag
  [5]   payback_note_tag
  [6]   payback_note_type
  [7]   swap_count
  [8-9] creator account id (prefix, suffix)

Saves 4 felts per pswap note on-chain, reducing fees and bandwidth for
every pswap created. No information is lost. Addresses PR #2636 review
comment from PhilippGackstatter on compressing the storage layout.

* test(pswap): cover combined input+inflight partial and full fill paths

Adds two unit tests against `PswapNote::execute` for the input+inflight
code path flagged in PR #2636 review:

- partial fill: account fill 10 + inflight 20 of a 50-requested pswap.
  Asserts payback carries 30 of the requested asset and a remainder
  pswap is produced with 20 requested / 40 offered remaining.
- full fill: account fill 30 + inflight 20 of a 50-requested pswap.
  Asserts payback carries 50 of the requested asset and no remainder.

Also factors out a `dummy_consumer_id()` helper alongside
`dummy_creator_id()` to keep the new tests readable.

* refactor(pswap): rename input/inflight to account_fill/note_fill

Addresses the naming feedback on PR #2636. The old `input` / `inflight`
terminology was ambiguous — "input" could mean the total fill amount,
the note_args input word, or the account-side fill, while "inflight"
conflated the transport mechanism with its role. The new names are
explicit about where the fill comes from:

  - offered_out             -> payout_amount
  - input / input_amount    -> fill_amount (when referring to the total
                               fill amount) or account_fill_amount
                               (when referring to the native-account
                               portion specifically)
  - inflight_amount         -> note_fill_amount
  - input_asset             -> account_fill_asset
  - inflight_asset          -> note_fill_asset

Touches the public `PswapNote::execute` parameters, all internal Rust
locals and doc comments, the MASM stack annotations / doc blocks /
local-var labels, and the integration test callers.

* refactor(pswap): fetch active note_type inline, drop global NOTE_TYPE

Upstream PR #2738 added `miden::protocol::note::metadata_into_note_type`
which does the bit-correct extraction against the new 1-bit NoteType
encoding. The pswap script no longer needs its own `extract_note_type`
proc or the `NOTE_TYPE` global slot.

Changes:
- Drop the `extract_note_type` proc and the `NOTE_TYPE_MASK` / `NOTE_TYPE`
  consts.
- The payback note already reads its type from `PAYBACK_NOTE_TYPE_ITEM`
  in storage (no active-note fetch needed).
- The remainder branch inlines `active_note::get_metadata dropw
  exec.note::metadata_into_note_type` where the type is actually used,
  instead of eagerly computing it once and stashing it in global memory.
- Update `pswap_note_alice_reconstructs_and_consumes_p2id` to set
  `payback_note_type(NoteType::Public)` so the reconstructed P2ID payback
  matches — the previous test implicitly relied on the payback inheriting
  the pswap's Public type (broken since the bit-encoding change).

This also fixes the previously-failing
`pswap_note_alice_reconstructs_and_consumes_p2id` test, which was hitting
the broken extract_note_type mask (always returning 0 under the new
encoding).

* refactor(pswap): switch storage consts to STORAGE_PTR base pattern

Matches the convention used in p2id.masm: declare a single
`STORAGE_PTR` base and derive every note-storage item offset relative
to it. This makes the storage layout easier to read and relocate.
Also use `push.STORAGE_PTR` at the load site instead of a bare `0`.

* docs(pswap): add #! doc block to @note_script main procedure

Closes PR #2636 review comment: `pub proc main` lacked a proper `#!`
doc block with `Inputs`/`Outputs`/storage layout/panic conditions.
Adds one modelled after the canonical style in p2id.masm / swap.masm.

* refactor(pswap): scrub last inflight/input references in tests

Rename `pswap_note_inflight_cross_swap_test` to
`pswap_note_note_fill_cross_swap_test` and update two stale comments
that still said "input" / "inflight" to match the new account_fill /
note_fill terminology used throughout the module.

* style(pswap): readability nits across pswap.masm

Minor cleanups surfaced during review, no behavior changes:
- Sort imports alphabetically by path.
- Reshape storage layout doc block to `[i..j] : N felts` + `Where:` form
  and drop the duplicate listing in the main proc docstring.
- Drop the stale "Memory Addresses" meta-block.
- Name local slots via top-of-file consts (e.g. CALC_FILL_AMOUNT,
  P2ID_NOTE_IDX, REMAINDER_AMT_OFFERED, EXEC_AMT_OFFERED, ...) so
  loc_store/loc_load sites read like variables rather than loc.N.
- Expand the rationale for the FACTOR=1e5 choice (precision vs u64
  overflow headroom) and switch the literal to decimal.
- Rename boolean stack-comment markers from operator syntax
  (`amt > 0`, `requested > offered`, `requested == fill_amount`) to
  readable predicates (`has_account_fill`, `has_note_fill`,
  `has_account_fill_payout`, `requested_exceeds_offered`,
  `is_full_fill`).
- Drop obvious/redundant comments (error-const headers, `gt pops…`
  primitive explanation, proc-start stack echoes, validate/calculate
  rationale moved into the execute_pswap docstring).
- Split `push.NUM_STORAGE_ITEMS.0` into two pushes using the
  STORAGE_PTR constant to match the `bridge_out.masm` pattern.
- Add converged stack markers (`# => [...]`) after every if/else `end`
  and before every proc return.

* test(pswap): dedupe integration tests via helpers + rstest

- Add shared helpers at the top of the test file: `build_pswap_note`,
  `note_args`, `assert_fungible_asset`, `assert_vault_added_removed`,
  `assert_vault_single_added`. Removes the repeated 13-line pswap-note
  setup and the `if let Asset::Fungible(f) = …` / vault-delta
  boilerplate.
- Consolidate variant-heavy tests with `#[rstest]`:
  - `pswap_fill_test` merges full/private/partial/network fill cases
    into one parameterized async test (4 cases).
  - `pswap_multiple_partial_fills_test` replaces the inner for-loop
    with 9 `#[case]`s, one per fill amount.
  - `pswap_partial_fill_ratio_test` merges the non-exact-ratio and
    hand-listed fuzz suites into one rstest with 27 regression cases,
    delegating to a new `run_partial_fill_ratio_case` helper.
  - `pswap_chained_partial_fills_test` parameterizes the outer chain
    loop with 10 `#[case]`s; the stateful per-chain inner fill loop
    is preserved intact.
- Add `pswap_partial_fill_ratio_fuzz` as a seeded-random coverage
  sibling: two `#[case]`s (seed 42, seed 1337) × 30 random
  `(offered, requested, fill)` triples each, drawn from `SmallRng`.
  Failure message includes seed, iter, and the failing triple so any
  regression is reproducible from the rstest case name alone. The
  regression `#[case]` block stays as a permanent edge-case suite.
- Leave `alice_reconstructs`, `cross_swap`, `creator_reclaim`,
  `invalid_input`, `compare`, and `parse_inputs` as standalone tests
  but rewrite their bodies to use the shared helpers.

Net: 1325 → 956 non-helper lines (-369), test count 14 → 58.

* style(pswap): apply nightly rustfmt

* fix(pswap): guard user-provided fill sum against u64 overflow

Switch `execute_pswap`'s `account_fill + note_fill` check to
`u64::overflowing_add` + `ERR_PSWAP_FILL_SUM_OVERFLOW`, so a malicious
consumer cannot pick operands whose felt sum wraps past u64 and
spuriously satisfies the `lte requested` guard. Also document why the
matching sums/subs in `create_p2id_note` and `create_remainder_note`
cannot over/underflow, and drop a stray trailing space on `FACTOR`.

* fix(pswap): correctness + layout cleanups from PR review theme 2

- create_p2id_note: drop three stray zero pads that shoved the real
  `note_idx` to stack depth 11 in the `has_account_fill` branch, so
  `move_asset_to_note` was reading a pad zero as the note index. The
  bug was masked in every existing test because `note_idx == 0`; add a
  SPAWN-note regression test that forces P2ID to `note_idx == 1`.
- load_offered_asset: bump `@locals(2)` to `@locals(8)` — we store two
  words (8 felts), not two felts.
- Drop `pswap_tag` from note storage (10 -> 9 items). The remainder
  path now lifts the tag out of the active note's metadata via
  `dup.2 movdn.4` + `metadata_into_note_type`, since the asset pair
  is unchanged across remainder creation. `PswapNoteStorage` loses
  the field, `with_pswap_tag`, and the getter; storage offsets and
  `NUM_STORAGE_ITEMS` shift accordingly.
- Document why `create_p2id_note`'s add (P2ID attachment), why
  `create_remainder_note`'s sub (amt_offered - amt_payout), and why
  `create_p2id_note` itself are reachable but safe (invariants come
  from the caller, not local checks).
- Correct the `payback_note_type` storage-layout docstring (only P2ID
  payback uses it; remainder inherits from active-note metadata).
- Note in a comment why `procref.main` cannot replace the runtime
  `active_note::get_script_root` call in `create_remainder_note`
  (compile-time call-graph cycle via main -> execute_pswap ->
  create_remainder_note -> procref.main).

* fix(pswap): align attachment layout + drop dead swap_count slot

- Attachment layout: MASM now emits `[fill, 0, 0, 0]` (Word[0] = fill)
  for both the P2ID and remainder attachments, matching the Rust-side
  `Word::from([fill, 0, 0, 0])` convention. Previously the two sides
  disagreed (Rust wrote Word[0], MASM wrote Word[3]), and the
  alice-reconstructs test was silently compensating by reading
  `aux_word[3]` against a Rust prediction it never compared to.
- alice-reconstructs test: read from the executed transaction's output
  (was already), read `aux_word[0]`, and add a direct Rust <-> MASM
  attachment-word parity `assert_eq!` so a future drift actually fails.
- Extend alice-reconstructs to also reconstruct the remainder PSWAP
  from her original pswap data + the remainder's on-chain attachment,
  verifying recipient + attachment parity against the executed output.
- Drop `pswap_count` from note storage (9 -> 8 items). The field was
  never read or written by pswap.masm — a dead pass-through slot. The
  Rust side was silently bumping it on remainder creation, so the
  Rust-predicted remainder recipient diverged from MASM's (caught only
  by extending the alice test). Remove the field, getter, builder arg,
  storage offsets, and all callers; shift creator ID to slots [6-7].

* refactor(pswap): masm perf + style cleanups from PR review theme 4

- Replace three `push.0 gt` (~16 cycles) zero-checks with `neq.0`
  (~3 cycles) at the has_account_fill, has_note_fill, and
  has_account_fill_payout branches.
- Use `dup.1 dup.1 neq` instead of `lt` for the `is_partial` check;
  the `lte requested` assertion above guarantees `total_in <=
  total_requested`, so `!=` is equivalent and cheaper.
- Flip the faucet-ID limb order at the create_remainder_note boundary
  from prefix-then-suffix to suffix-then-prefix (standard miden
  convention), updating the caller in execute_pswap, the proc
  docstring, local-slot comment, and the store block.
- Drop the redundant `movdn.2` / `movup.2` pair in create_remainder_note
  — `remaining_requested` is already on top, so `mem_store` can take it
  directly.
- Drop the `(4)` suffix on NOTE_ATTACHMENT / METADATA_HEADER stack
  comments; uppercase identifiers already imply a full word.
- Remove `exec.sys::truncate_stack` and its stale `use` import from
  execute_pswap. Tracing the proc end-to-end (including every syscall
  wrapper, call frame, and proc-local store) shows the stack is
  already balanced at exit, and all 59 pswap integration tests pass
  without it.

* refactor(pswap/tests): PR review theme 5 test quality cleanups

- `pswap_note_invalid_input_test` asserts the specific error kind via
  `assert_transaction_executor_error!(result, ERR_PSWAP_FILL_EXCEEDS_REQUESTED)`
  instead of a bare `.is_err()`. A future bug that fails the tx for the
  wrong reason will now surface.
- Drop the `rng: &mut RandomCoin` parameter from `build_pswap_note` —
  the helper draws its serial number from `builder.rng_mut()` directly.
  Remove all the `let mut rng = RandomCoin::new(Word::default())`
  declarations at call sites that only existed to feed this param.
- Rename local helper `note_args` -> `pswap_args` so it reads clearly
  next to the (unrelated) `TransactionContextBuilder::extend_note_args`
  method it gets passed into.
- Switch `assert_vault_added_removed` / `assert_vault_single_added` /
  `assert_fungible_asset_eq` helpers to take `FungibleAsset` instead of
  `(AccountId, u64)` tuples, and update every call site.
- `pswap_note_note_fill_cross_swap_test`: replace the flag-and-for-loop
  "which note contains which asset" check with `iter().any()` against
  two locally-built `Asset::Fungible(FungibleAsset::new(...))` values.
- `pswap_note_alice_reconstructs_and_consumes_p2id`: propagate the
  `prove_next_block()` error via `?` instead of swallowing it with
  `let _ =`.

Still outstanding from theme 5:
- realistic large amounts (20 * 10^18) in the happy-path tests
- an integration test where both account_fill and note_fill are
  non-zero on the same note (the Rust unit tests cover the predictor
  path, but the integration-level cross-flow needs a cleaner two-note
  setup than a simple adaption of the existing cross-swap test).
- skipping `Note -> PswapNote::try_from` roundtrips by having
  `build_pswap_note` return the `PswapNote` directly — a broader
  signature churn that is orthogonal to the items above.

* test(pswap): finish theme 5 — realistic amounts, combined fill, skip try_from

- `pswap_fill_test`: scale every amount by `AMOUNT_SCALE = 10^12` so
  the happy path exercises 12-decimal token values instead of single
  digits. The scale cap is chosen so `requested * FACTOR` stays under
  `u64::MAX`, matching the current MASM assumption.
- `build_pswap_note` now returns `(PswapNote, Note)` instead of just
  the `Note`, so call sites can execute the PswapNote directly and
  skip the `PswapNote::try_from(&note)?` round-trip the reviewer
  flagged. Every caller updated.
- New `pswap_note_combined_account_fill_and_note_fill_test`: exercises
  a PSWAP fill where the consumer supplies BOTH `account_fill` and
  `note_fill` on the same note in the same transaction. Alice offers
  100 USDC for 50 ETH, Bob offers 30 ETH for 60 USDC, Charlie consumes
  both — Alice's pswap uses combined fill (20 ETH from Charlie's vault
  + 30 ETH sourced from inflight via Bob's pswap payout), Bob's pswap
  uses pure note_fill. Asserts output notes, recipient parity, and
  Charlie's vault delta (-20 ETH / +40 USDC; the note_fill legs flow
  through inflight and never touch his vault).

* refactor(pswap): rename execute_full_fill_network -> execute_full_fill

The method has nothing network-specific about it — a "network
transaction" is just one where the kernel defaults note_args to
`[0, 0, 0, 0]` and the MASM script falls back to a full fill, which
any caller can trigger by calling this method directly. Rename to
reflect that, update the sole caller in the pswap_fill_test, and
rewrite the doc comment to describe the behavior (full fill producing
only the payback note, no remainder) rather than the network use case.

Also scrub stale doc references left over from theme 3's `swap_count`
removal:
- drop the "swap count overflows u16::MAX" bullet from `execute`'s
  errors section
- drop "swap count overflow" from `execute_full_fill`'s errors section
  (the whole section is gone — no error paths remain)
- update the PswapNote struct doc: the remainder carries "an updated
  serial number", not "an incremented swap count"
- update `create_remainder_pswap_note`'s doc for the same reason

* refactor(pswap): drop FACTOR, use u128 math for payout calculation

`calculate_tokens_offered_for_requested` previously used a fixed-point
1e5 precision factor with two separate branches (offered >= requested
vs requested > offered) plus a full-fill early return, to approximate
`offered * fill / requested` without overflowing u64 intermediates.

That design had three problems:

- Four `u64::wrapping_mul` calls silently produced wrong results for
  inputs where `x * FACTOR >= 2^64`, capping each operand at about
  1.84e14 — roughly 0.000184 whole tokens for any 18-decimal asset.
- The two-branch structure was fragile and harder to reason about than
  a single linear formula.
- The FACTOR-scaled intermediate introduced rounding error in `ratio`
  that then got amplified by `fill`.

Replace the whole proc with one linear path:

  product = u64::widening_mul(offered, fill_amount)   # -> u128
  quot    = u128::div(product, requested_u128)        # -> u128
  assert  q.hi_limbs == 0                              # payout fits in u64
  return  q.lo_limbs combined back into a felt

miden-core-lib 0.22 already exposes `u128::div` (advice-provider
assisted, same host-compute-and-verify pattern as `u64::div`), so no
custom division implementation is needed.

Properties of the new version:
- Exact integer precision (one floor division at the end, no FACTOR
  rounding).
- Each operand can go up to `FungibleAsset::MAX ≈ 2^63`, so 18-decimal
  tokens now work at realistic volumes (~9.2 billion whole tokens
  per swap) — a ~50,000x improvement in dynamic range.
- No branching on the offered/requested relationship. No full-fill
  early return. One generic formula that also handles the
  `fill_amount == requested` case trivially.
- All wrapping_mul references gone, closing the last deferred theme-1
  item from the PR review.

Also mirror the same change on the Rust side: `calculate_output_amount`
now just does `(offered as u128) * (fill as u128) / (requested as u128)`
and `try_from`s back to u64, matching MASM exactly. Scrub the old
PRECISION_FACTOR constant, the two-branch Rust logic, and the FACTOR
doc block.

The 8 in-crate unit tests and all 60 pswap script tests (including
the 27-case hand-picked ratio regression suite and two seeded
30-iteration fuzzers) still pass.

* test(pswap): second pass on PR review follow-ups

- `calculate_output_amount` doc: fix a mismatched paren and the empty
  blank line between doc and fn signature that triggered clippy's
  `empty_line_after_doc_comments` (caught by CI after the last push).
- `pswap_note_alice_reconstructs_and_consumes_p2id`: build the
  `PswapNote` via the builder, call `pswap.clone().into()` to get the
  protocol `Note`, and keep `pswap` in scope for `.execute(...)`. Drops
  the `PswapNote::try_from(&pswap_note)?` roundtrip the reviewer flagged
  on this exact test as a nit.
- `pswap_chained_partial_fills_test`: same pattern — replace the manual
  `Note::new(NoteAssets / NoteMetadata / NoteRecipient)` construction
  with `PswapNote::builder().serial_number(current_serial)...build()?`
  + `pswap.clone().into()`. The raw-Note construction was only there to
  inject a specific serial per chain position, which the builder
  already supports. Also drops the dependent `PswapNote::try_from`
  roundtrip.
- `pswap_fill_test`: bump `AMOUNT_SCALE` from 10^12 to 10^18 so the
  happy-path test exercises the MASM u128 calculation at realistic
  18-decimal token magnitudes. Base values adjusted (offered=8,
  requested=4, fills=3/4) so every amount stays under AssetAmount::MAX
  ≈ 9.22 × 10^18. Previously the 10^12 scale was chosen to stay under
  the old FACTOR=1e5 cap; now that the u128 rewrite lifted that cap,
  the test can stress the calculation at the actual wei-equivalent
  scale the reviewer asked for.
- New `pswap_attachment_layout_matches_masm_test`: dedicated
  regression test for the shared P2ID and remainder attachment-word
  layout. Does a partial fill, then explicitly asserts the executed
  transaction's P2ID attachment equals `[fill_amount, 0, 0, 0]` and
  the remainder attachment equals `[amt_payout, 0, 0, 0]`, and
  cross-checks both against the Rust-predicted attachments. Fires if
  either MASM or Rust drifts the load-bearing felt off `Word[0]`.
- Apply the "blank line after every `# => [...]` stack comment"
  convention across pswap.masm where it was missing — one reviewer
  tends to leave this as a nit so sweep the whole file for
  consistency rather than wait for the comments.

* style(pswap/tests): apply rustfmt

* refactor(pswap): expose `PswapNote::create_args` as public helper

Add `PswapNote::create_args(account_fill: u64, note_fill: u64) ->
Result<Word, NoteError>` so downstream consumers building PSWAP
`NOTE_ARGS` words don't need to know the `[account_fill, note_fill,
0, 0]` layout by hand. Returns a `Result` instead of panicking so the
underlying `Felt::try_from` conversion errors propagate cleanly
through the standard `NoteError` path — although for any amount that
fits in `FungibleAsset::MAX_AMOUNT` this cannot actually fail, the
conversion is surfaced explicitly rather than hidden behind an
`.expect(...)` in a public API.

Drop the local `pswap_args` test helper — every call site now uses
`PswapNote::create_args(...)?` directly, matching the reviewer's
suggestion that the layout helper live on `PswapNote` rather than
being reimplemented in each consumer.

All 61 pswap script tests pass with the new signature (twelve call
sites updated to propagate the Result via `?`).

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* fix(pswap): CI green — unused imports + duplicated exec

Two fixes triggered by `make check-features` / `clippy -D warnings`
and the full pswap test suite:

- `tests/scripts/pswap.rs`: drop `NoteAssets`, `NoteMetadata`,
  `NoteRecipient`, `NoteStorage` from the `miden_protocol::note`
  import list. Leftovers from the theme-5 chained-fills refactor that
  switched from low-level `Note::new(NoteAssets, NoteMetadata,
  NoteRecipient)` construction to `PswapNote::builder()`. CI compiles
  with `-D warnings` so the unused-imports warning was fatal.

- `asm/standards/notes/pswap.masm`: remove a duplicate
  `exec.calculate_tokens_offered_for_requested` line that had crept
  into the note-fill payout path in one of the upstream edits, plus a
  duplicate stack comment above the account-fill payout block. With
  the duplicate `exec`, the second call read garbage off a stack that
  only held the first call's payout — specifically a zero divisor,
  which surfaced as `u128::div` "division by zero" and failed 57/61
  pswap tests.

All 61 pswap script tests pass after the fix, and
`cargo check --all-targets --all-features` on miden-testing is clean.

* refactoring changes

* fix(pswap): address PR review — storage, attachments, asset validation

- Derive payback note tag from creator ID in MASM via
  note_tag::create_account_target instead of storing in note storage,
  reducing storage from 8 to 7 items.
- Add dedicated attachment constructors (payback_attachment,
  remainder_attachment) on PswapNote for clarity and reuse.
- Validate computed amounts as valid fungible asset amounts:
  - calculate_output_amount now returns Result and checks via AssetAmount.
  - MASM assert_valid_asset_amount proc checks u64 values against
    FUNGIBLE_ASSET_MAX_AMOUNT before felt conversion to prevent silent
    wrapping, applied to both fill sum and payout quotient.
- Fix P2ID comment nit per reviewer suggestion.
- Remove unused NoteTag import from p2id test.

* style: apply nightly rustfmt

* fix(pswap): simplify assert_valid_asset_amount and rename procedure

- Replace manual hi/lo branch logic with exec.u64::lte
- Rename calculate_tokens_offered_for_requested to calculate_output_amount (matches Rust)
- Simplify tag derivation in create_p2id_note: swap+dup+swap+movup.2 → dup.1+movdn.2

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* test(pswap): add rstest cases for fill-sum overflow and max-asset-amount validation

Converts pswap_note_invalid_input_test to rstest with three named cases:
- fill_exceeds_requested (existing)
- fill_sum_u64_overflow: both fills at 2^63, sum overflows u64 → ERR_PSWAP_FILL_SUM_OVERFLOW
- fill_sum_exceeds_max_asset_amount: both fills at MAX_AMOUNT, sum > MAX_AMOUNT → ERR_PSWAP_NOT_VALID_ASSET_AMOUNT

---------

Co-authored-by: Vaibhav Jindal <vaibhavjindal@Vaibhavs-MacBook-Pro.local>
Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* chore: remove unused SWAP and MINT attachments (#2789)

* chore: remove attachment parameters from SWAP and MINT

* chore: add changelog

* chore: remove outdated comment

---------

Co-authored-by: igamigo <ignacio.amigo@lambdaclass.com>
Co-authored-by: Forostovec <ilonaforostovec22@gmail.com>
Co-authored-by: Nikhil Patil <nikhil876706@gmail.com>
Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
Co-authored-by: Santiago Pittella <87827390+SantiagoPittella@users.noreply.github.com>
Co-authored-by: Serge Radinovich <47865535+sergerad@users.noreply.github.com>
Co-authored-by: Bobbin Threadbare <bobbinth@protonmail.com>
Co-authored-by: Percy Dikec <112529374+PercyDikec@users.noreply.github.com>
Co-authored-by: onurinanc <e191322@metu.edu.tr>
Co-authored-by: Himess <95512809+Himess@users.noreply.github.com>
Co-authored-by: djole <djolertrk@gmail.com>
Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Giwa Victor <132751591+giwaov@users.noreply.github.com>
Co-authored-by: Marti <marti@miden.team>
Co-authored-by: nad <100929843+addnad@users.noreply.github.com>
Co-authored-by: VaibhavJindal <vaibhavjindal29@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Al-Kindi-0 <82364884+Al-Kindi-0@users.noreply.github.com>
Co-authored-by: Vaibhav Jindal <vaibhavjindal@Vaibhavs-MacBook-Pro.local>
…kens (#2664)

* add burn policies

* changelog

* fix comments

* refactor OwnerControlled and AuthControlled

* review fix

* move slots to a shared location

* remove OwnerControlled

* add owner only burn for agglayer faucet

* use native_word remove FeltSchema

* merge next

* fix

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* fix(hooks): pre-push-review fires only on real git push and ignores '- None.' bullets

Two related defects in `.claude/hooks/pre-push-review.sh`:

1. The hook is wired in settings.json under `if: Bash(*git push*)` but the
   matcher does not reliably filter — observed firing on unrelated Bash
   calls (grep surveys, ls, etc.) and spawning two reviewer agents per
   call. Adds a defensive command guard at the top of the hook that
   reads the PreToolUse JSON from stdin and exits 0 unless the command
   actually contains `git push`.

2. The awk pass that counts blocking findings under
   ### Critical/Important/Warnings counted every bullet under those
   headings, including the literal absence markers like `- None.` or
   `- N/A` that reviewers use to indicate "no findings in this section".
   That made any clean review register 2+ blocking findings and refuse
   to push. Skip absence markers explicitly before incrementing the
   count.

Verified locally: the hook still spawns reviewers on `git push`, no
longer fires on `grep`/`echo`/`find`/etc., and a review that says
"Critical Issues: None" / "Important Issues: None" / nits-only now
correctly returns 0.

Sibling hooks (`pre-push-test.sh`, `pre-pr-draft.sh`, `pre-commit-lint.sh`)
likely have the same `if`-matcher unreliability and would benefit from
a similar command guard. Left for follow-up to keep this PR focused.

* fix(hooks): extend defensive command guard to the remaining four hooks

Companion to the pre-push-review.sh fix earlier on this branch. The
`if: Bash(*<pattern>*)` matcher in settings.json does not reliably
filter, so every Bash call ran every hook regardless of whether the
command actually matched. This produced two visible regressions:

- pre-pr-draft.sh denied unrelated Bash calls because it only checked
  for `--draft`, not for `gh pr create` being the actual command.
- pre-commit-lint.sh and pre-push-test.sh ran `make lint` and `make test`
  on every Bash call (silently, often timed out).
- post-pr-create-changelog.sh would have spawned the changelog agent on
  any Bash call whose output happened to contain a GitHub pull URL.

Each hook now reads `tool_input.command` from its stdin (the PreToolUse /
PostToolUse JSON contract) and exits 0 unless the command actually
matches the intended trigger:

- pre-commit-lint.sh — permissive `git ... commit` (covers
  `git -c user.name=... commit -m ...`)
- pre-pr-draft.sh, post-pr-create-changelog.sh — strict `gh pr create`
- pre-push-test.sh — strict `git push`

For PostToolUse hooks the `tool_input.command` is still in the JSON
payload alongside `tool_response`, so the same check works.

* refactor(hooks): rewrite all 5 hooks in python with shared classifier + pytest

Addresses PR #2922 review feedback from huitseeker (three concrete
bugs, all with the same root cause) and PhilippGackstatter (shell
scripts unreadable; consider python). Replaces the shell versions in
one coherent change.

Root cause of huitseeker's findings:
  the shell guards matched the raw command STRING with regex/substring
  patterns rather than parsing the actual command. That produced both
  false positives (`echo gh pr create` triggered the draft hook) and
  false negatives (`git -C . push`, `git -c k=v push`,
  `gh -R repo pr create` were not recognized as real invocations).

New design:
  .claude/hooks/_classify.py is the shared classifier. Each hook is
  one ~50-line python script that:
    1. reads the PreToolUse/PostToolUse JSON from stdin
    2. checks `_classify.matches(command, *TARGET)` where TARGET is a
       module-level tuple (e.g. ("git", ["push"]))
    3. exits 0 if it doesn't match; otherwise runs the original logic
       (make lint, spawn reviewers, deny non-draft PR, etc.)

`_classify.matches`:
  - splits the command on UNQUOTED top-level separators (&&, ||, ;,
    |, &, newlines) via a small state-machine that respects
    "..."/'...' quoting and backslash-newline continuation
  - tokenizes each segment with shlex.split (posix=True)
  - strips leading FOO=bar env-var assignments
  - walks past known global flags per binary
    (git: -C, -c, --git-dir, --work-tree, --namespace, --exec-path;
     gh:  -R, --repo, --hostname; --flag=value form handled by the
     tokenizer)
  - fires if ANY pipeline segment matches, preserving the
    `cd repo && git push` intent without accepting `echo "git push"`

Tests:
  .claude/hooks/tests/test_classify.py (37 cases) covers the
  classifier primitives plus edge cases (empty input, unbalanced
  quotes, line continuation, redirection, pipes, etc).
  .claude/hooks/tests/test_hooks.py (35 cases) parametrizes
  per-hook routing — each case ID embeds the hook name so a failure
  attributes directly to the responsible script. All hooks
  (pre_commit_lint, pre_pr_draft, pre_push_review, pre_push_test,
  post_pr_create_changelog) exercise their TARGET against the
  reviewer-reported must-run / must-not-run cases.

Wiring:
  - Makefile gains `make hooks-test` (standalone; not chained from
    `make lint` since .claude/hooks/ is rarely touched and pytest
    would just be tax on unrelated commits)
  - .github/workflows/lint.yml gains a `hooks-test` CI job
    (ubuntu-latest, setup-python 3.10, pip install pytest, make
    hooks-test). Single enforcement point on every PR.
  - settings.json paths repointed from .sh to .py
  - .gitignore adds __pycache__/ etc. for python bytecode

Replaces (deleted):
  pre-commit-lint.sh, pre-pr-draft.sh, pre-push-review.sh,
  pre-push-test.sh, post-pr-create-changelog.sh

* refactor(hooks): extract repo_root/makefile_has_target to _hookutils

Reviewer noted that `_repo_root()` was copied verbatim across three
hooks (pre_commit_lint, pre_push_review, pre_push_test) and
`_makefile_has_target()` across two (pre_commit_lint, pre_push_test),
which would drift over time.

Move both into a new `.claude/hooks/_hookutils.py` module. Kept
separate from `_classify.py` because the concerns are distinct —
`_classify` parses Bash command strings; `_hookutils` wraps
filesystem / git inspection. Each hook imports the shared functions
via the same sys.path shim that already exposes `_classify`.

Net: -46 lines across three hooks, +35 lines in one shared module.
Pytest suite still 71/71.

* test(hooks): dedupe paired-target cases; guard the sharing claim

Reviewer noted that pre_push_test and post_pr_create_changelog were
each running the same routing cases as their target-sharing partner
(pre_push_review and pre_pr_draft respectively).

Drop the replayed cases. In their place, add a tiny
`test_paired_hooks_share_target` that asserts the paired hooks really
do share TARGET — if anyone changes one without the other, this test
fails and the missing per-hook coverage is restored by re-adding
explicit entries to HOOK_CASES.

PAIRED_TARGETS is the single source of truth for the sharing claim.
HOOK_CASES picks one representative hook per target, with a comment
pointing to the partner.

Net: 71 -> 66 cases. Same coverage, no duplication, the "shared
target" comment is enforced rather than aspirational.

* fix(hooks): segment-scoped, flag-value-aware --draft check; widen settings.json filters

Addresses second round of huitseeker review feedback on PR #2922:

1. _has_draft_flag scanned the whole shell command, so two cases
   slipped past:
     - `gh pr create && echo --draft` — the `--draft` is in the echo
       segment, not the actual create.
     - `gh pr create --title "--draft"` — shlex strips the quotes,
       leaving --draft as a token. The previous check mistook it for
       the flag when it's the value of --title.

   New _classify.match_args() returns the tokens that follow the
   subcommand chain in the FIRST matching pipeline segment (or None
   if no segment matches). pre_pr_draft.has_draft_flag() walks those
   args left-to-right with a hardcoded set of arg-taking gh pr create
   flags (--title/-t, --body/-b, --label/-l, etc.) so a value that
   happens to be `--draft` doesn't get misread as the flag. Verified
   end-to-end via both new tests and live smoke runs of the hook
   binary with each reviewer-reported command.

2. settings.json `if: Bash(*git push*)` skipped real `git -C . push`
   and `git -c k=v push` at the Claude Code level — the classifier
   inside the hook supported those forms but never got the chance to
   run. Same shape for `Bash(*gh pr create*)` blocking `gh -R repo pr
   create`. Widened the five outer filters to `Bash(*git*)` /
   `Bash(*gh*)` so the python hooks are the real gate. They exit 0
   quickly for non-matching commands (~50ms python startup), so the
   broader matcher is cheap.

3. Drive-by .gitignore: exclude .claude/scheduled_tasks.lock so the
   Claude Code runtime lock file doesn't keep showing up in
   `git status`.

Tests:
- test_classify gains 6 cases for match_args
- test_pre_pr_draft is new: 17 parametrized DRAFT_CASES (including
  both huitseeker bugs as named cases) + 3 standalone has_draft_flag
  cases.
- Net: 71 -> 89 passing.

* fix(hooks): close --draft=false bypass + multi-segment fold + defensive payload parsing

Third round of huitseeker / pre-push-review feedback on PR #2922.

1. `--draft=false` bypass. Cobra/pflag accept `--flag=true` and
   `--flag=false` to set/unset a boolean. The previous check returned
   True for any token starting with `--draft=`, so
   `gh pr create --draft=false` slipped past. has_draft_flag now
   parses the value: only `1|t|T|true|TRUE|True` count as truthy;
   everything else (including `false`, `0`, `no`) reads as draft NOT
   requested. New parametrized test covers ten pflag-style values.

2. Trim `_FLAGS_WITH_ARG` to real `gh pr create` flags. The
   `--add-label` / `--remove-*` entries were `gh pr edit` flags that
   never appear here; their presence suggested the list was
   carelessly curated. Also added a `_BOOLEAN_FLAGS` table for known
   no-arg flags (`--draft`, `--web`, `--fill`, ...) so the walker
   knows not to consume the next token as a value.

3. Multi-segment fold. `match_args` returned the FIRST matching
   segment, so `gh pr create --draft && gh pr create` (second is
   non-draft) was silently allowed. New `iter_match_args` yields all
   matching segments and `pre_pr_draft.main()` denies if ANY segment
   lacks `--draft`. `match_args` is preserved as the single-segment
   convenience but is no longer the primary API.

4. Conservative unknown-flag handling. If gh ever adds a new
   arg-taking flag we don't know about (e.g. `--new-flag value`),
   `gh pr create --new-flag --draft` would previously misread
   `--draft` as a flag and allow. The walker now treats any unknown
   `-...` token as arg-taking (consumes the next token); only flags
   in the known `_BOOLEAN_FLAGS` set stand alone. Failure mode flips
   from "let through" to "deny when uncertain", which is safer.

5. Defensive payload parsing. `payload.get("tool_input", {}).get(...)`
   would crash if `tool_input` was None or a string. Moved JSON
   parsing into a shared `_hookutils.read_payload()` /
   `command_from_payload()` / `read_command()` trio that returns
   None on any unexpected shape; all five hooks now use it.
   Malformed payloads (`"not json"`, `tool_input: 42`, `command: []`,
   etc.) cause `sys.exit(0)` rather than an unhandled exception.

6. Token-boundary in settings.json `if` filters. Tightened
   `Bash(*git*)` -> `Bash(*git *)` and `Bash(*gh*)` -> `Bash(*gh *)`
   so substrings inside other words (`cough`, `weight`, `right p...`)
   no longer trigger a python interpreter spawn. Filter still misses
   some valid invocations (`mygit push`), but the classifier inside
   the hook remains the source of truth — the filter is now strictly
   a perf hint, not a correctness gate.

7. Tests: new `test_hookutils.py` covers `read_payload` /
   `command_from_payload` / `read_command` against every malformed
   shape. `test_pre_pr_draft.py` gains 8 end-to-end `main()` cases
   (deny payload shape, allow path, malformed JSON, non-dict
   `tool_input`, missing keys, non-string `command`, multi-segment
   fold). `test_classify.py` gains 5 cases for `iter_match_args`.
   Net: 89 -> 159 passing.

---------

Co-authored-by: Claude (Opus) <noreply@anthropic.com>
@github-advanced-security
Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

bobbinth and others added 28 commits May 16, 2026 00:35
* chore: update miden-vm dependencies to v0.23

* chore: refresh Cargo.lock

* chore: update changelog

* chore: fix lints

* chore: improve formatting

* chore: address review comments

* refactor: use stronger type for max asset amount

---------

Co-authored-by: Claude (Opus) <noreply@anthropic.com>
…ENT` computation (#2947)

* chore: commitment/hash -> note ID

* chore: refactor RECEIPIENT docs

* Update docs/src/note.md

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

---------

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
…2752)

* perf(agglayer): selective frontier load/save in bridge-out

Replace unconditional load/save of all 32 LET frontier entries with
selective operations based on the bit pattern of num_leaves:

- load_let_frontier_selective: only loads entries where bit h=1
  (entries that will be READ by append_and_update_frontier)
- save_let_frontier_selective: only saves entries where bit h=0
  (entries that were WRITTEN by append_and_update_frontier)

This halves the number of storage map syscalls from 128 to 64 per
B2AGG note consumption. Cycle savings vary by frontier occupancy:
- Empty tree (0 leaves): 145k -> 116k (-20%)
- Populated tree (2^31-1 leaves): 140k -> 60k (-57%)

Also adds benchmarks with pre-populated frontier states (2^31 and
2^31-1 leaves) to measure the impact across different access patterns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review nits

- Add v0.15.0 CHANGELOG entry for selective frontier optimization
- Add newline after stack comment to separate logic blocks
- Move add.1 to same line as swap u32shr.1 swap
- Use if.false instead of eq.0 if.true for bit check
- Add stack comment after double_word_array::set

https://claude.ai/code/session_01GjjUe9KUggLJMAdiuBw8vk

* Apply suggestions from code review

Co-authored-by: Marti <marcin.gorny.94@protonmail.com>

* perf(agglayer): avoid num_leaves memory round-trip in load_let_frontier_selective

Keep num_leaves on the stack across the storew of [num_leaves, 0, 0, 0] to
LET_FRONTIER_MEM_PTR, instead of dropping the word and reloading from memory.

* chore: clarify load and save docs

* docs: read/write frontier with explanations

* chore: test large `num_leaves` for selective frontier loading (#2853)

* test(agglayer): exercise selective frontier load/save at high num_leaves

Adds bridge_out_at_high_num_leaves with two parameterised cases that pre-populate
the bridge LET storage and consume one B2AGG note each, verifying the resulting
Local Exit Root against an in-process MerkleTreeFrontier32 reference (already
Solidity-compatible via test_solidity_mtf_compatibility):

- peak_read  (num_leaves = 2^31 - 1, binary 0111...1): every bit 0-30 is 1, bit 31
  is 0. The masm READs frontier[0..30] from storage and WRITEs frontier[31] back.
- peak_write (num_leaves = 2^31, binary 1000...0): every bit 0-30 is 0, bit 31
  is 1. The masm READs frontier[31] and WRITEs frontier[0..30].

Together these two single-leaf inserts exercise every height in both READ and
WRITE roles. The existing bridge_out_consecutive only walks num_leaves through
0..32, exercising bits 0-4; this fills in bits 5-31.

To support pre-populating the frontier, MerkleTreeFrontier32 gains a from_state
constructor and is made pub(super). The populate_let_state helper sets storage
map keys as Word [0, 0, 0, h] (lo) / [0, 0, 1, h] (hi) — matching what the masm
builds via push.0.0.0 / push.1.0.0 with the index at the bottom of the 4-felt
key window.

* chore: simplify docs; remove silly assertion

* test(agglayer): seed initial frontier with a random byte stream

Replaces the hand-rolled byte pattern with a seeded StdRng-driven fill, matching
the StdRng-from-u64 pattern already used in asset_conversion.rs. Keeps the test
deterministic across runs.

---------

Co-authored-by: Claude (Opus) <noreply@anthropic.com>

---------

Co-authored-by: Claude (Opus) <noreply@anthropic.com>
(cherry picked from commit 4e4a496)
…ddress) (#2860)

* fix(AggLayer): key faucet registry by (origin_network, origin_token_address)

* chore: add CHANGELOG entry for #2860

* test(agglayer): pass origin_network to ConfigAggBridgeNote::create in bridge_out_at_high_num_leaves

The new test added on agglayer (#2752) used the old 5-arg ConfigAggBridgeNote::create
signature; this PR's signature change (adding origin_network) needed to be threaded
through after the merge.

* fix(testing): align agglayer-imported tests with new ConfigAggBridgeNote::create signature

The merged agglayer cherry-pick introduced tests that called the 5-argument
ConfigAggBridgeNote::create and referenced ClaimDataSource::SimulatedL1ToMiden,
neither of which exist on this branch. Pass the origin_network argument and use
the renamed L1ToMiden variant so these tests compile.

* fix: address review comments on bridge_config.masm

- register_faucet: correct pad(8) to pad(10) after exec.hash_token_address;
  callable procs auto-pad the stack to 16, so the annotation must reflect the
  two zero felts that come up from overflow when hash_token_address consumes 6
  felts and produces 4.
- lookup_faucet_by_token_address: trim the docblock to drop the contextual
  "keying on the address alone..." sentence that only made sense in the
  context of this PR.
- hash_token_address: collapse the per-store inline comments back to a single
  umbrella comment, matching the original's terser style.

(cherry picked from commit 0003d0a)
…n assets (#2771)

* feat: add scale data to bridge storage

* feat: update config_agg_bridge note & fix register_faucet proc

* feat: extend faucet registration with full metadata, is_native flag, and metadata hash

* feat: replace FPI with bridge-local reads in bridge_out, add lock path for native tokens

* feat: add unlock path for native tokens in bridge_in, plus lock/unlock tests

* chore: add changelog entry & bump rand to fix cargo-deny

Bumps rand 0.9.2 → 0.9.4 and rand 0.10.0 → 0.10.1 to resolve
RUSTSEC-2026-0097 flagged by `cargo deny check` in CI.

* refactor: slim faucet & update SPEC section

* style: rustfmt import grouping

* refactor: tighten MASM stack ops, normalize stack-comment style

* refactor: cleanup masm & stack comments

* refactor: pack ConfigAggBridgeNote::create args into ConversionMetadata

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: split bridge_in output-note emission into bridge_in_output.masm

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: fix stack-comment depths in CONFIG_AGG_BRIDGE.masm

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.

* refactor: clarify docstrings and add native-path duplicate-claim test

- 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.

* refactor: dedupe shared CLAIM_* consts and colocate UNLOCK_*_LOC

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.

* refactor: apply PR suggestions

Co-authored-by: Marti <marcin.gorny.94@protonmail.com>

* refactor(agglayer): drop redundant memory layout description in CONFIG_AGG_BRIDGE.masm

The 18-felt note storage layout was documented in three places:
the top-of-file comment block, the constant definitions immediately
below, and the docblock above 'begin'. The constants are self-documenting
and the docblock covers it for callers, so drop the top-of-file block.

* refactor(agglayer): add mem_load_double_word_unaligned helper

Mirror mem_store_double_word_unaligned in asm/agglayer/common/utils.masm
and use it in CONFIG_AGG_BRIDGE.masm to load the metadata-hash double word
from offset 10..17, replacing eight individual mem_load.METADATA_HASH_*
ops with a single push.METADATA_HASH_LO_0 exec.utils::mem_load_double_word_unaligned.

* refactor(agglayer): pre-pad CONFIG_AGG_BRIDGE call frames to drop the movdn dance

Push the call's 6 trailing pad zeros first, then build the args on top, instead
of pushing args first and then doing 'movdn.15 movdn.15 movdn.15 movdn.15 movdn.15
movdn.15' to move 6 pads to the bottom. The end-state stack is identical; this
just removes a 6-instruction shuffle from each of the two call sites.

* refactor(agglayer): introduce sub-key constants for faucet_metadata_map

Replace literal push.0.0 / push.0.1 / push.0.2 / push.0.3 sub-key
prefixes with named constants FAUCET_METADATA_SUBKEY_{ADDR_LO,ADDR_HI,
HASH_LO,HASH_HI}. Only the metadata-map sites are touched; push.0.0 in
faucet_registry / token_registry contexts is a different map and stays
literal.

* refactor(agglayer): cheaper register_faucet local stash via repeated movup.5

Replace movup.9/.8/.7/.6/.5 with five repeated movup.5 starting from
the now-deepest non-address element. Each movup always lifts from depth
5 (instead of climbing 9→5), and the post-iteration stack is identical.

* refactor(agglayer): use repeat.5 dup.4 to duplicate origin token address

Replace 'dup.4 dup.4 dup.4 dup.4 dup.4' with 'repeat.5 dup.4 end'. The
five-fold dup-from-depth-4 produces the same stack pattern (top word is
the duplicate address with addr0 at the very top) which is what
hash_token_address expects when it stores the 5-felt address into local
memory before computing Poseidon2.

* refactor(agglayer): unify get_faucet_metadata_hash key-prep with sibling proc

Rewrite get_faucet_metadata_hash to use the same 'prep both keys
first, then swapw between reads' pattern as get_faucet_conversion_info.
The previous shape used 'dup.1 dup.1 ... movup.5 movup.5' to reshuffle
faucet_id around the first read, which read awkwardly next to a sibling
proc with the opposite mechanism. This subsumes the swapw / movup.5
movup.5 oddity Marti called out.

* refactor(agglayer): correct stack-padding annotations in register_faucet

Re-walk stack annotations from proc-entry through Steps 2-4. Pads grow
on pops (via Miden's auto-padding to depth-16 floor) and stay constant
on pushes; the previous comments treated them as if pad+named always
equaled 16, which understated the depth after each new push.

* refactor(agglayer): clarify is_faucet_native trailing-zeros comment

'sink ... below the trailing zeros' was misleading because the stack
direction it implied is the opposite of what movdn.2 does. Reword to
'move is_native past the two trailing zeros'.

* refactor(agglayer): clarify unlock_and_send local-stash comment

The previous comment referenced 'claim's CLAIM_DEST_ID_*_LOCAL' and the
'exec invocations get their own local frame' detail, both of which are
distracting. State the actual reason for the stash: we'll need the
destination ID again after native_account::remove_asset clears the stack.

* docs(agglayer): document native faucet registration and updated bridge flows

- Section 2.1 (bridge-out): drop FPI references, replace with bridge-local
  faucet_metadata_map reads. Add the is_native dispatch (BURN vs lock_asset).
- Section 2.2 (bridge-in): drop the unconditional MINT description, replace
  with the is_native dispatch (MINT vs remove_asset + direct P2ID). Update
  the token-registry lookup to mention the (address, network) pair.
- Section 2.4 (faucet registration): describe the CONFIG_AGG_BRIDGE 18-felt
  payload and the two-call register_faucet / store_faucet_metadata_hash flow.
- Section 7.1: rename to 'Registering faucets on Miden' (covers both wrapped
  and Miden-native faucets), and add a new sub-section explaining the
  wrapped-vs-native distinction at the dispatch level.

* Apply suggestions from code review

Co-authored-by: Marti <marcin.gorny.94@protonmail.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Marti <marcin.gorny.94@protonmail.com>
Co-authored-by: Marti <marti@miden.team>
(cherry picked from commit 9c9f847)
* feat: Introduce `AssetComposition` enum

* feat: implement asset composition in MASM

* chore: add changelog

* chore: remove unused dependencies

* chore: ensure asset metadata fits in u8

* chore: check upper 24 bits of asset metadata for validity

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* feat: Introduce `AssetComposition` enum

* feat: implement asset composition in MASM

* chore: add changelog

* chore: remove unused dependencies

* chore: ensure asset metadata fits in u8

* chore: check upper 24 bits of asset metadata for validity

* chore: take ASSET_KEY in get_balance APIs

* chore: remove is_updatable_account, is_immutable_account

* chore: remove faucet checks from asset creation procedures

* chore: remove account_id::is_*_faucet procedures

* chore: remove supported types from AccountComponentMetadata

* chore: make non-fungible asset construction infallible

* chore: remove faucet type check from FungibleAsset

* chore: remove account type checks from vault key

* chore: remove `AccountType` from `AccountId::dummy`

* chore: require callback flag in `AssetVault::get_balance`

* chore: make AssetVault::get_balance infallible

* chore: remove `FeeError`

* chore: remove AccountType from account_id helper

* chore: remove account type accessors

* chore: remove `AccountType` from seed computation

* chore: remove account type from account builder

* chore: remove AccountType accessors on account & ID

* feat: remove `AccountType`

* chore: add changelog

* chore: correct ACCOUNT_ID_MAX_ZEROES

* chore: update broken doc links

* fix: AccountIdBuilder doc test

* chore: remove unused constants in account.masm

* chore: add test for key_to_composition

* chore: rename to METADATA_RESERVED_MASK

* chore: address review comments

* chore: unify account ID serde roundtrip test

* chore: rework Asset docs

* chore: remove fee_asset_callback_flag from mock chain builder

* chore: slightly improve the composition assumptions on fee asset

* chore: change get_balance to take AssetVaultKey

* fix: mock chain doc test

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…o-next-sync

# Conflicts:
#	crates/miden-agglayer/asm/agglayer/bridge/bridge_out.masm
* feat: Introduce `AssetComposition` enum

* feat: implement asset composition in MASM

* chore: add changelog

* chore: remove unused dependencies

* chore: ensure asset metadata fits in u8

* chore: check upper 24 bits of asset metadata for validity

* chore: take ASSET_KEY in get_balance APIs

* chore: remove is_updatable_account, is_immutable_account

* chore: remove faucet checks from asset creation procedures

* chore: remove account_id::is_*_faucet procedures

* chore: remove supported types from AccountComponentMetadata

* chore: make non-fungible asset construction infallible

* chore: remove faucet type check from FungibleAsset

* chore: remove account type checks from vault key

* chore: remove `AccountType` from `AccountId::dummy`

* chore: require callback flag in `AssetVault::get_balance`

* chore: make AssetVault::get_balance infallible

* chore: remove `FeeError`

* chore: remove AccountType from account_id helper

* chore: remove account type accessors

* chore: remove `AccountType` from seed computation

* chore: remove account type from account builder

* chore: remove AccountType accessors on account & ID

* feat: remove `AccountType`

* chore: add changelog

* chore: correct ACCOUNT_ID_MAX_ZEROES

* chore: update broken doc links

* fix: AccountIdBuilder doc test

* chore: remove unused constants in account.masm

* chore: add test for key_to_composition

* chore: rename to METADATA_RESERVED_MASK

* feat: rearrange ID layout; move storage mode to account type

* chore: remove account type references from docs

* refactor: rename AccountStorageMode to AccountType

Renames the AccountStorageMode enum (and the associated
storage_mode field/parameter/method names, STORAGE_MODE_* encoding
constants, UnknownAccountStorageMode error variant, and architecture
docs) to AccountType / account_type. Variant names Public/Private and
the is_public()/is_private() helpers (plus Display strings) are kept
since they still describe storage location.

Followup to cf78d68 which removed the 2-bit account-type field from
the ID layout, leaving the remaining 1-bit field which is now named
"account type" throughout.

* chore: add changelog

* chore: address review comments

* chore: unify account ID serde roundtrip test

* chore: rework Asset docs

* chore: remove fee_asset_callback_flag from mock chain builder

* chore: slightly improve the composition assumptions on fee asset

* chore: change get_balance to take AssetVaultKey

* fix: mock chain doc test

* chore: address review comments

* chore: remove outdated network account type reference

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
Co-authored-by: Claude (Opus) <noreply@anthropic.com>
…o-next-sync

# Conflicts:
#	crates/miden-agglayer/src/faucet.rs
#	crates/miden-testing/tests/agglayer/bridge_out.rs
* test: implement tests in proposed batch

* refactor: update nullifier computation

* docs: update Note doc comments

* refactor: use metadata and attachments to compute nullifier

* chore: update doc comments

* test: update proposed batch test to use input notes

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…pprovers, enabling unreachable overrides (#2941)

* fix get_threshold_and_num_approvers

* changelog

* remove unnecessary comments

* remove redundant comments

* new_unchecked -> from_u8

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* refactor(protocol): extract slot-name validation to a shared internal helper

Pulls the const-fn validator out of StorageSlotName into a new internal
name_validation module so the same rules can be reused by an upcoming
AccountComponentName type. StorageSlotName now delegates to the helper and
exhaustively maps each internal error variant onto its StorageSlotNameError
counterpart.

* feat(protocol): add AccountComponentName

Introduces a validated newtype for canonical component names:

- AccountComponentName: a Cow<'static, str>-backed newtype with a const
  fn from_static_str constructor (so hard-coded NAME constants can become
  typed names at compile time without runtime allocation) and a runtime
  fallible new() constructor. Display, FromStr, TryFrom, From-into-String
  are provided; PartialEq, Eq, Hash, PartialOrd, Ord are derived through
  Cow's content-based impls.
- AccountComponentNameError: public error mirroring StorageSlotNameError,
  populated by an exhaustive map from the internal NameValidationError
  that was extracted in the prior commit.

Validation is delegated to the shared name_validation helper, so the
syntactic rules stay in lockstep with StorageSlotName.

* feat(standards): add name() accessor on standard components

Adds an inherent `pub const fn name() -> AccountComponentName` method to
every leaf standard component, returning the canonical typed component
name built via AccountComponentName::from_static_str(Self::NAME):

- BasicWallet, FungibleFaucet, TokenPolicyManager
- AuthSingleSig, AuthSingleSigAcl, AuthMultisig, AuthGuardedMultisig,
  NoAuth, AuthNetworkAccount
- Ownable2Step, RoleBasedAccessControl
- MintAllowAll, MintOwnerOnly, BurnAllowAll, BurnOwnerOnly

Renames the existing FungibleFaucet::name(&self) -> &TokenName accessor to
token_name() so the new associated AccountComponentName constructor can
keep the canonical name() identifier.

* chore: add changelog

* chore: move name_validation to src/account

* chore: move storage slot names to name_validation module

* fix: better error messages for account component name

---------

Co-authored-by: Claude (Opus) <noreply@anthropic.com>
* perf(agglayer): selective frontier load/save in `B2AGG` processing (#2752)

* perf(agglayer): selective frontier load/save in bridge-out

Replace unconditional load/save of all 32 LET frontier entries with
selective operations based on the bit pattern of num_leaves:

- load_let_frontier_selective: only loads entries where bit h=1
  (entries that will be READ by append_and_update_frontier)
- save_let_frontier_selective: only saves entries where bit h=0
  (entries that were WRITTEN by append_and_update_frontier)

This halves the number of storage map syscalls from 128 to 64 per
B2AGG note consumption. Cycle savings vary by frontier occupancy:
- Empty tree (0 leaves): 145k -> 116k (-20%)
- Populated tree (2^31-1 leaves): 140k -> 60k (-57%)

Also adds benchmarks with pre-populated frontier states (2^31 and
2^31-1 leaves) to measure the impact across different access patterns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review nits

- Add v0.15.0 CHANGELOG entry for selective frontier optimization
- Add newline after stack comment to separate logic blocks
- Move add.1 to same line as swap u32shr.1 swap
- Use if.false instead of eq.0 if.true for bit check
- Add stack comment after double_word_array::set

https://claude.ai/code/session_01GjjUe9KUggLJMAdiuBw8vk

* Apply suggestions from code review

Co-authored-by: Marti <marcin.gorny.94@protonmail.com>

* perf(agglayer): avoid num_leaves memory round-trip in load_let_frontier_selective

Keep num_leaves on the stack across the storew of [num_leaves, 0, 0, 0] to
LET_FRONTIER_MEM_PTR, instead of dropping the word and reloading from memory.

* chore: clarify load and save docs

* docs: read/write frontier with explanations

* chore: test large `num_leaves` for selective frontier loading (#2853)

* test(agglayer): exercise selective frontier load/save at high num_leaves

Adds bridge_out_at_high_num_leaves with two parameterised cases that pre-populate
the bridge LET storage and consume one B2AGG note each, verifying the resulting
Local Exit Root against an in-process MerkleTreeFrontier32 reference (already
Solidity-compatible via test_solidity_mtf_compatibility):

- peak_read  (num_leaves = 2^31 - 1, binary 0111...1): every bit 0-30 is 1, bit 31
  is 0. The masm READs frontier[0..30] from storage and WRITEs frontier[31] back.
- peak_write (num_leaves = 2^31, binary 1000...0): every bit 0-30 is 0, bit 31
  is 1. The masm READs frontier[31] and WRITEs frontier[0..30].

Together these two single-leaf inserts exercise every height in both READ and
WRITE roles. The existing bridge_out_consecutive only walks num_leaves through
0..32, exercising bits 0-4; this fills in bits 5-31.

To support pre-populating the frontier, MerkleTreeFrontier32 gains a from_state
constructor and is made pub(super). The populate_let_state helper sets storage
map keys as Word [0, 0, 0, h] (lo) / [0, 0, 1, h] (hi) — matching what the masm
builds via push.0.0.0 / push.1.0.0 with the index at the bottom of the 4-felt
key window.

* chore: simplify docs; remove silly assertion

* test(agglayer): seed initial frontier with a random byte stream

Replaces the hand-rolled byte pattern with a seeded StdRng-driven fill, matching
the StdRng-from-u64 pattern already used in asset_conversion.rs. Keeps the test
deterministic across runs.

---------

Co-authored-by: Claude (Opus) <noreply@anthropic.com>

---------

Co-authored-by: Claude (Opus) <noreply@anthropic.com>
(cherry picked from commit 4e4a496)

* fix(AggLayer): key faucet registry by (origin_network, origin_token_address) (#2860)

* fix(AggLayer): key faucet registry by (origin_network, origin_token_address)

* chore: add CHANGELOG entry for #2860

* test(agglayer): pass origin_network to ConfigAggBridgeNote::create in bridge_out_at_high_num_leaves

The new test added on agglayer (#2752) used the old 5-arg ConfigAggBridgeNote::create
signature; this PR's signature change (adding origin_network) needed to be threaded
through after the merge.

* fix(testing): align agglayer-imported tests with new ConfigAggBridgeNote::create signature

The merged agglayer cherry-pick introduced tests that called the 5-argument
ConfigAggBridgeNote::create and referenced ClaimDataSource::SimulatedL1ToMiden,
neither of which exist on this branch. Pass the origin_network argument and use
the renamed L1ToMiden variant so these tests compile.

* fix: address review comments on bridge_config.masm

- register_faucet: correct pad(8) to pad(10) after exec.hash_token_address;
  callable procs auto-pad the stack to 16, so the annotation must reflect the
  two zero felts that come up from overflow when hash_token_address consumes 6
  felts and produces 4.
- lookup_faucet_by_token_address: trim the docblock to drop the contextual
  "keying on the address alone..." sentence that only made sense in the
  context of this PR.
- hash_token_address: collapse the per-store inline comments back to a single
  umbrella comment, matching the original's terser style.

(cherry picked from commit 0003d0a)

* feat: add lock / unlock functionality to `agg_bridge` for native miden assets (#2771)

* feat: add scale data to bridge storage

* feat: update config_agg_bridge note & fix register_faucet proc

* feat: extend faucet registration with full metadata, is_native flag, and metadata hash

* feat: replace FPI with bridge-local reads in bridge_out, add lock path for native tokens

* feat: add unlock path for native tokens in bridge_in, plus lock/unlock tests

* chore: add changelog entry & bump rand to fix cargo-deny

Bumps rand 0.9.2 → 0.9.4 and rand 0.10.0 → 0.10.1 to resolve
RUSTSEC-2026-0097 flagged by `cargo deny check` in CI.

* refactor: slim faucet & update SPEC section

* style: rustfmt import grouping

* refactor: tighten MASM stack ops, normalize stack-comment style

* refactor: cleanup masm & stack comments

* refactor: pack ConfigAggBridgeNote::create args into ConversionMetadata

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: split bridge_in output-note emission into bridge_in_output.masm

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: fix stack-comment depths in CONFIG_AGG_BRIDGE.masm

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.

* refactor: clarify docstrings and add native-path duplicate-claim test

- 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.

* refactor: dedupe shared CLAIM_* consts and colocate UNLOCK_*_LOC

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.

* refactor: apply PR suggestions

Co-authored-by: Marti <marcin.gorny.94@protonmail.com>

* refactor(agglayer): drop redundant memory layout description in CONFIG_AGG_BRIDGE.masm

The 18-felt note storage layout was documented in three places:
the top-of-file comment block, the constant definitions immediately
below, and the docblock above 'begin'. The constants are self-documenting
and the docblock covers it for callers, so drop the top-of-file block.

* refactor(agglayer): add mem_load_double_word_unaligned helper

Mirror mem_store_double_word_unaligned in asm/agglayer/common/utils.masm
and use it in CONFIG_AGG_BRIDGE.masm to load the metadata-hash double word
from offset 10..17, replacing eight individual mem_load.METADATA_HASH_*
ops with a single push.METADATA_HASH_LO_0 exec.utils::mem_load_double_word_unaligned.

* refactor(agglayer): pre-pad CONFIG_AGG_BRIDGE call frames to drop the movdn dance

Push the call's 6 trailing pad zeros first, then build the args on top, instead
of pushing args first and then doing 'movdn.15 movdn.15 movdn.15 movdn.15 movdn.15
movdn.15' to move 6 pads to the bottom. The end-state stack is identical; this
just removes a 6-instruction shuffle from each of the two call sites.

* refactor(agglayer): introduce sub-key constants for faucet_metadata_map

Replace literal push.0.0 / push.0.1 / push.0.2 / push.0.3 sub-key
prefixes with named constants FAUCET_METADATA_SUBKEY_{ADDR_LO,ADDR_HI,
HASH_LO,HASH_HI}. Only the metadata-map sites are touched; push.0.0 in
faucet_registry / token_registry contexts is a different map and stays
literal.

* refactor(agglayer): cheaper register_faucet local stash via repeated movup.5

Replace movup.9/.8/.7/.6/.5 with five repeated movup.5 starting from
the now-deepest non-address element. Each movup always lifts from depth
5 (instead of climbing 9→5), and the post-iteration stack is identical.

* refactor(agglayer): use repeat.5 dup.4 to duplicate origin token address

Replace 'dup.4 dup.4 dup.4 dup.4 dup.4' with 'repeat.5 dup.4 end'. The
five-fold dup-from-depth-4 produces the same stack pattern (top word is
the duplicate address with addr0 at the very top) which is what
hash_token_address expects when it stores the 5-felt address into local
memory before computing Poseidon2.

* refactor(agglayer): unify get_faucet_metadata_hash key-prep with sibling proc

Rewrite get_faucet_metadata_hash to use the same 'prep both keys
first, then swapw between reads' pattern as get_faucet_conversion_info.
The previous shape used 'dup.1 dup.1 ... movup.5 movup.5' to reshuffle
faucet_id around the first read, which read awkwardly next to a sibling
proc with the opposite mechanism. This subsumes the swapw / movup.5
movup.5 oddity Marti called out.

* refactor(agglayer): correct stack-padding annotations in register_faucet

Re-walk stack annotations from proc-entry through Steps 2-4. Pads grow
on pops (via Miden's auto-padding to depth-16 floor) and stay constant
on pushes; the previous comments treated them as if pad+named always
equaled 16, which understated the depth after each new push.

* refactor(agglayer): clarify is_faucet_native trailing-zeros comment

'sink ... below the trailing zeros' was misleading because the stack
direction it implied is the opposite of what movdn.2 does. Reword to
'move is_native past the two trailing zeros'.

* refactor(agglayer): clarify unlock_and_send local-stash comment

The previous comment referenced 'claim's CLAIM_DEST_ID_*_LOCAL' and the
'exec invocations get their own local frame' detail, both of which are
distracting. State the actual reason for the stash: we'll need the
destination ID again after native_account::remove_asset clears the stack.

* docs(agglayer): document native faucet registration and updated bridge flows

- Section 2.1 (bridge-out): drop FPI references, replace with bridge-local
  faucet_metadata_map reads. Add the is_native dispatch (BURN vs lock_asset).
- Section 2.2 (bridge-in): drop the unconditional MINT description, replace
  with the is_native dispatch (MINT vs remove_asset + direct P2ID). Update
  the token-registry lookup to mention the (address, network) pair.
- Section 2.4 (faucet registration): describe the CONFIG_AGG_BRIDGE 18-felt
  payload and the two-call register_faucet / store_faucet_metadata_hash flow.
- Section 7.1: rename to 'Registering faucets on Miden' (covers both wrapped
  and Miden-native faucets), and add a new sub-section explaining the
  wrapped-vs-native distinction at the dispatch level.

* Apply suggestions from code review

Co-authored-by: Marti <marcin.gorny.94@protonmail.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Marti <marcin.gorny.94@protonmail.com>
Co-authored-by: Marti <marti@miden.team>
(cherry picked from commit 9c9f847)

---------

Co-authored-by: Marti <marti@miden.team>
Co-authored-by: Claude (Opus) <noreply@anthropic.com>
Co-authored-by: Marti <marcin.gorny.94@protonmail.com>
…t` transfer policy (#2938)

* add basic allowlist transfer policy

* wrap AllowlistStorage
* fix: bind MINT note to its faucet via asset-in-storage (#2798)

A MINT note produced by `bridge_in::claim` previously carried only the
amount in storage; the consuming faucet was determined by whichever
account the note was executed against. Because all AggLayer faucets
share the bridge as owner, the `owner_only` mint policy passed for any
same-bridge faucet, so a claim for token A could be redirected into a
mint-and-export on faucet B.

The MINT note now embeds the full ASSET (`ASSET_KEY` + `ASSET_VALUE`,
8 felts) in its storage. `fungible::mint_and_send` stashes the stored
`ASSET_KEY`, extracts the amount for the supply checks, runs the mint
policy unchanged, and then feeds the stashed key to the kernel
`faucet::mint` syscall. The kernel's existing `validate_origin` check
panics with `ERR_FUNGIBLE_ASSET_FAUCET_IS_NOT_ORIGIN` if the active
account does not match the stored faucet ID, so a MINT bound to faucet
A cannot be minted by faucet B.

Bridge-side, `bridge_in::write_mint_note_storage` builds the ASSET via
`miden::protocol::asset::create_fungible_asset` with `enable_callbacks
= 0` (AggLayer faucets do not declare callbacks). The MINT note layout
grows from 14 to 22 items in public mode (13 in private mode in the
standards library).

The `NetworkAccountTarget` attachment stays on MINT notes for routing
but is no longer security-load-bearing.

Tests:
- New `test_mint_cannot_be_consumed_by_unrelated_faucet` in
  `crates/miden-testing/tests/agglayer/bridge_in.rs`: two AggLayer
  faucets, claim for faucet A's token, attack tries to mint against
  faucet B, expects `ERR_FUNGIBLE_ASSET_FAUCET_IS_NOT_ORIGIN`.
- Existing MINT-note constructions in
  `crates/miden-testing/tests/scripts/faucet.rs` and direct
  `mint_and_send` tx-script callers updated to the new signature.
- `send_note_body` code generator for the `FungibleFaucet` interface
  in `crates/miden-standards/src/account/interface/component.rs`
  emits `push.{ASSET_VALUE} push.{ASSET_KEY}` and an expanded cleanup.

* chore: apply nightly rustfmt

* docs: address #2798 doc fallout (SPEC, MASM comments, CHANGELOG)

The MINT-note asset-in-storage fix for #2798 landed earlier on this branch
(commit d558948). This commit cleans up the docs and comments that did
not get refreshed at that time, per pre-push review feedback.

CHANGELOG.md
  - Add a v0.15.0 Fixes entry describing the cross-faucet bind, linking
    both issue #2798 (the original report) and PR #2911 (this branch).

crates/miden-agglayer/SPEC.md
  - §3 `agglayer_faucet::mint_and_send`: update Inputs row to the new
    `[ASSET_KEY, ASSET_VALUE, tag, note_type, RECIPIENT, pad(2)]` shape,
    update the re-export path from `network_fungible::` to `fungible::`
    (the merge in #2890 collapsed network_fungible into fungible), and
    list the kernel `faucet::mint` bind as a panic condition.
  - §4.7 MINT note: rewrite the storage-layout table from the pre-#2798
    18-felt shape (`tag`, `amount`, `attachment_kind`, ...) to the
    actual 22-felt layout (`P2ID_SCRIPT_ROOT`, `SERIAL_NUM`, `ASSET_KEY`,
    `ASSET_VALUE`, `dest_tag`, padding, `account_id_{suffix,prefix}`).
  - §4.7 Consumption paragraph: describe the actual call ordering -- the
    MINT script reconstructs `RECIPIENT` from the storage, calls
    `mint_and_send`, which stashes `ASSET_KEY`, runs the owner policy,
    creates the skeleton output note, invokes the kernel bind via
    `faucet::mint`, and finally attaches the minted asset.
  - §4.7 Permissions: downgrade `NetworkAccountTarget` from
    security-load-bearing to routing-only, and call out the kernel
    `faucet::mint` syscall as the consume-side trust anchor.

crates/miden-agglayer/asm/agglayer/bridge/bridge_in.masm
  - Update the storage-layout block comment (L65-76) from 18 to 22 felts
    and document the implicit zero-init invariant for the padding at
    [17..19] (the recipient digest hashes the full 22-felt window).
  - Update the `claim` doc block from "18 storage items" to 22 to match
    the actual constant `MINT_NOTE_NUM_STORAGE_ITEMS = 22`.
  - Update the `create_mint_note_with_attachment` doc and inline comment
    to reflect that the `NetworkAccountTarget` attachment is for routing,
    not security; the consume-side bind is the kernel `faucet::mint`
    syscall inside `fungible::mint_and_send`.
  - Lowercase all newly-added inline comments in `write_mint_note_storage`
    plus the two pre-existing capital-W comments inside the same proc, so
    the whole helper is uniform per the masm-inline-comments skill.

crates/miden-standards/asm/standards/faucets/fungible.masm
  - Fix the vague `pad(...)` placeholder on the `mint_and_send` stack
    tracker after `movdn.3 drop drop drop` to `pad(9)`, matching the
    explicit `pad(9)` on the next tracker.
  - Lowercase four new inline comments per masm-inline-comments.

No production logic changes; all 29 tests in
`miden-testing::lib::agglayer::bridge_in` and
`miden-testing::lib::scripts::faucet` remain green, including the new
`test_mint_cannot_be_consumed_by_unrelated_faucet` regression.

* docs: second-round review polish

Pre-push review caught a few more items in the doc fallout from #2798:

- SPEC.md §3.2 "Companion component storage slots": replace remaining
  `network_fungible::mint_and_send` reference with `fungible::mint_and_send`
  to match the merged module name (per #2890).
- SPEC.md §4.7 Permissions row: soften "no longer security-load-bearing"
  to "no longer the sole consume-side bind" so the wording does not invite
  a future maintainer to remove the `NetworkAccountTarget` attachment that
  still provides the network-routing primitive.
- agglayer/faucet/mod.masm:162: drop "network" from "Re-export the
  network fungible faucet's `mint_and_send` procedure." doc comment so it
  matches the actual `pub use ::miden::standards::faucets::fungible::mint_and_send`
  target two lines below.
- bridge_in.masm storage-layout block (L65-76): rephrase the zero-init
  invariant comment. The previous wording "would change RECIPIENT and
  break consumption" was misleading -- drift would change the note ID
  (and therefore break off-chain references that precompute the ID), but
  consumption itself would still proceed because `compute_and_store_recipient`
  inserts the full memory window into the advice provider verbatim.
  The padding inline comments at [17..19] are updated to match.
- fungible.masm: revert the four inline comments I previously lowercased
  inside `mint_and_send` (Stash/Rebuild/Load/Kernel-enforced) so the
  procedure is back to consistent sentence-case with its surrounding
  comments (Get the configured.../Assert that.../Compute the new.../etc.).
  The masm-inline-comments skill prescribes lowercase, but the rest of
  this file uses sentence-case and mixing both styles inside one proc is
  worse than either choice; per the user's "no fmt-only commits" /
  "Minimal Impact" preferences, the lowercasing is dropped here.
  The `pad(9)` correction at L255 is kept.

No production logic changes; all 6 tests in
`miden-testing::lib::agglayer::bridge_in` remain green, including the
new `test_mint_cannot_be_consumed_by_unrelated_faucet` regression.

* chore: drop stray duplicate 0.14.6 changelog heading

The merge from `next` brought in a stray empty `## 0.14.6 (2026-05-05)`
heading directly above the existing `## 0.14.6 (2026-05-09)` section.
The duplicate has no entries; it would confuse downstream changelog
parsers that index by version heading. Dropping the empty one.

* test(agglayer): add faucet AuthNetworkAccount allowlist regressions

PR #2818 installed `AuthNetworkAccount` on both the AggLayer bridge AND
the AggLayer faucet (with `allowed_notes() = {MintNote, BurnNote}`), but
only added regression tests for the bridge side. Pre-push code-review
flagged the gap.

Adds two faucet-side tests symmetric to `bridge_rejects_tx_script` and
`bridge_rejects_non_allowlisted_input_note`:

- `faucet_rejects_tx_script`: any transaction submitting a tx script
  against an AggLayer faucet aborts with
  `ERR_NOTE_SCRIPT_ALLOWLIST_TX_SCRIPT_NOT_ALLOWED`.
- `faucet_rejects_non_allowlisted_input_note`: any input note whose
  script root is neither MINT nor BURN aborts with
  `ERR_NOTE_SCRIPT_ALLOWLIST_NOTE_NOT_ALLOWED`.

Without these, a future refactor that drops the faucet's auth component
or breaks its allowlist would keep the suite green and re-open the
forged-MINT attack surface that #2797 / #2818 set out to close.

* chore: review feedback on #2911 comments and naming

- bridge_in.masm: drop absolute memory addresses (817-819) from the
  storage padding invariant comment; refer to the [17..19] offset range
  instead so the note doesn't go stale if the storage base moves.
- bridge_in.masm: collapse `movdn.2` and `push.0` onto one line and
  retitle the comment to "prepare stack for asset::create_fungible_asset".
- bridge_in.masm: rename stack-comment placeholders
  `faucet_id_{suffix,prefix}(orig)` -> `faucet_id_{suffix,prefix}_origin`;
  parenthesised stack constants are not idiomatic.
- bridge_in.rs: drop the "Regression test for issue #2798" prose from
  the test doc; describe the property being asserted instead.
- fungible.masm: drop the "#2798" issue reference from the ASSET_KEY
  stash comment; describe the bind in plain terms.

* chore: drop issue link from #2911 changelog entry, keep only the PR

* test(agglayer): drop unrelated faucet AuthNetworkAccount regressions

The faucet allowlist tests cover the AuthNetworkAccount component from
#2818, not the MINT faucet-bind fix of this PR. Revert
network_account_regression.rs to its `next` state to keep #2911 scoped.

Also fixes merge fallout from `next`: the new `AssetAmount`-typed
`FungibleAsset::MAX_AMOUNT`, and `MintNoteStorage::new_private` now
taking an `Asset`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(standards): bind MINT via explicit asset-key comparison

`mint_and_send` now derives the asset to mint for the active faucet via
`faucet::create_fungible_asset` and asserts its key equals the ASSET_KEY
stored in the MINT note, rather than rebuilding the asset value by hand
and relying on the kernel `faucet::mint` origin check. The faucet bind
is now an explicit standards-level assert, matching the agreed design.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: address review feedback on MINT faucet-bind wording

- Describe behavior at each layer's abstraction instead of naming the
  kernel `faucet::mint` syscall in the MINT script docs, the `MintNote`
  builder docs, and the AggLayer SPEC.
- Drop coined terms ("stash", "load-bearing bind"); reuse existing
  vocabulary.
- Reword the CHANGELOG entry to reflect that the change is to the
  standard MINT note and fungible faucet, not only AggLayer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test(agglayer): make cross-faucet MINT regression prove the bug

Register faucet_B in the bridge so it is a fully legitimate same-bridge
faucet; the cross-faucet consumption then fails only because of the
faucet bind, not because faucet_B is unknown to the bridge. Verified
that with the bind removed the attack transaction succeeds, so the test
genuinely exercises the regression.

Assert the standards-level `ERR_FUNGIBLE_MINT_NOTE_ASSET_NOT_FROM_THIS_FAUCET`
raised by `mint_and_send`. Build the destination account from its
decoded ID, matching `test_bridge_in_claim_to_p2id`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(skills): add prose conventions for MASM comments

Add generic guidance to the masm-doc-comments and masm-inline-comments
skills so agents stop introducing review churn:

- reuse existing terminology; do not coin new terms or colloquialisms
- document the code as it stands, not the PR that changed it
- stay at the current layer's abstraction; do not leak lower-layer
  (kernel/syscall) implementation details

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(standards): bind MINT by faucet ID, not full asset key

Comparing the full derived asset key against the stored ASSET_KEY is too
strict: the key embeds the faucet's callbacks metadata, so a MINT note
whose stored key was built without that metadata (e.g. for a callbacks-
enabled faucet) would be rejected even when issued by the right faucet.

Compare the faucet ID extracted from the stored ASSET_KEY against the
active account instead, matching what the original issue specified
(`asset.faucet_id == active_account::get_id`). Fixes the
`network_faucet_mint_with_blocklist` faucet-script test.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: update blocklist mint_and_send call for new signature

`mint_and_send_on_blocklist_basic_faucet` (merged in from `next`) called
`mint_and_send` with the pre-PR stack layout that passed a bare amount.
Update the tx script to pass the full asset (ASSET_KEY + ASSET_VALUE)
that the procedure now expects.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: address code review on MINT faucet-bind

- MintNoteStorage and MintNote now take a `FungibleAsset` instead of the
  `Asset` enum, so the type system rejects a non-fungible asset that the
  MINT masm cannot handle.
- MintNote::create validates that `faucet_id` matches the embedded
  asset's faucet, returning a NoteError instead of deferring to a
  consumption-time panic.
- Reword bridge_in.masm and SPEC.md so the consume-side bind is
  attributed to mint_and_send's faucet-ID check, not the kernel syscall.
- Fix off-by-3 pad() trackers in the generated mint_and_send call.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: restore faucet allowlist regressions; address review round 2

- Restore `faucet_rejects_tx_script` and `faucet_rejects_non_allowlisted_input_note`:
  the security review flagged their removal as a coverage loss for the
  AggLayer faucet's `AuthNetworkAccount` allowlist, a live control.
- `write_mint_note_storage` now writes the MINT note storage padding
  cells [17..19] explicitly as zeros (as part of the tag word) instead
  of relying on VM memory zero-init.
- Add a unit test for the `MintNote::create` faucet-ID guard.
- SPEC.md: the `NetworkAccountTarget` attachment is routing only, not a
  consume-side bind.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(standards): bind MINT via full ASSET_KEY comparison

mint_and_send now asserts the full ASSET_KEY derived for the active faucet
equals the ASSET_KEY stored in the MINT note, instead of comparing only the
faucet ID. The key encodes the faucet's asset-callbacks bit, so a faucet-ID
check would let a callbacks-enabled faucet mint a non-callback asset.

The blocklist faucet test installs callback slots, so its MINT note must
embed an asset with the callback flag set to match the derived key.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: address round-2 review feedback on MINT faucet-bind

- mint.masm: drop the negative-case sentence from the script doc; the
  rejection is already covered by the Panics section.
- CHANGELOG: tighten the #2911 entry to describe the what, not the how.
- bridge_in.masm: replace "padding cells" with "padding elements" and
  explain that the padding aligns the P2ID storage to a word boundary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* test: remove tautological MintNote::create test

The test only exercised the Rust convenience wrapper rather than a protocol
restriction, and asserted behavior already guaranteed by the assembly-level
faucet bind.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: trim MINT comments and CHANGELOG entry per round-3 review

- bridge_in.masm: shorten 22-felt storage layout comment; drop the
  enable_callbacks aside from write_mint_note_storage doc block
- CHANGELOG.md: tighten the MINT-binding entry to describe only the what

* fix(test): update allowlist test for new mint_and_send signature

`scripts::allowlist::mint_and_send_on_allowlist_basic_faucet` (added
by PR #2938) called `mint_and_send` with the pre-PR signature
`[amount, tag, note_type, RECIPIENT, pad(9)]`. The MINT-bind PR
changes the signature to
`[ASSET_KEY, ASSET_VALUE, tag, note_type, RECIPIENT, pad(2)]`, so the
test needs to derive `ASSET_KEY`/`ASSET_VALUE` for the active faucet
before calling. Using `miden::protocol::faucet::create_fungible_asset`
mirrors the pattern already used in
`crates/miden-testing/tests/scripts/faucet.rs`.

`cargo nextest run -p miden-testing scripts::allowlist::*` passes
locally.

* chore(agglayer): mark bridge MINT/unlock callbacks-bit assumption with TODO(#2963)

bridge_in_output.masm hardcodes enable_callbacks=0 in unlock_and_send and
write_mint_note_storage. The consuming faucet's mint_and_send re-derives the
asset for itself, so a bridge-owned faucet with the callbacks bit flipped
would break both the unlock path (asset removal) and the bind check added in
PR #2798 (every MINT rejected). Capture the assumption inline; tracked by
issue #2963.

---------

Co-authored-by: Claude (Opus) <noreply@anthropic.com>
Co-authored-by: Marti <marti@miden.team>
* chore: address nits

* chore: remove unused getters, get back nullifier accessors

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
`set_input_note_metadata` and `set_input_note_attachments_commitment`
are defined but never called: the metadata and attachments-commitment
slots are populated by the bulk `adv_pipe` writes in
`process_input_note_details`, not via these dedicated setters. They
were the only callers either procedure could have had, and they don't
use them. Drop the dead code.

No change to the kernel ABI - these are library-internal `pub proc`
helpers, not entries in the `KERNEL_PROCEDURES` table.

Co-authored-by: Claude (Opus) <noreply@anthropic.com>
Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
* docs(agglayer): drop port-narrative phrases from faucet docstrings

The "conversion metadata lives on the bridge" clause was useful for the
PR #2771 / #2955 port narrative but is not load-bearing for readers of
the merged code. Trim it from the AggLayerFaucet docstring in lib.rs and
the inline comment in faucet.rs.

* test(agglayer): always construct deterministic destination account

The conditional matches! arm in test_bridge_in_claim_to_p2id enumerates
both ClaimDataSource variants (L1ToMiden | L2ToMiden) — the only two —
so the branch is always taken and the Option<Account> wrapping forces a
needless if let Some(...) around the post-mint consume+assert block.

Construct destination_account unconditionally and flatten the consume
block to match the pattern used by the other bridge_in tests.

---------

Co-authored-by: Claude (Opus) <noreply@anthropic.com>
Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>
* refactor(pswap.masm): rename PARENT_ATT_* locals to PARENT_ATTACHMENT_*

The `get_current_depth` scratch-buffer locals named the buffer base
after its semantic content ("AMOUNT"), but only the buffer-base role
matters at the call site (it's passed to `write_attachment_to_memory`).
Rename to `PARENT_ATTACHMENT_BASE` / `PARENT_ATTACHMENT_DEPTH` so the
call sites read as intent rather than coincidence of layout.

* feat(pswap): make payback_note / remainder_note bodies match on-chain commitment

`PswapNote::payback_note` and `PswapNote::remainder_note` previously
produced recipient-matching but commitment-divergent bodies: metadata
sender was hardcoded to the creator (vs. on-chain consumer), and
`remainder_note` returned empty attachments (vs. the on-chain
`PswapAttachment` word). The commitment divergence meant the
reconstructed bodies could not be fed as unauthenticated input notes
against a chain that recorded the on-chain commitment — block proposal
recomputes the leaf from the supplied body and rejects on mismatch.

Both APIs now take the consumer's `AccountId`; `remainder_note` also
takes the per-round payout amount needed to populate its
`PswapAttachment` word. Callers obtain both directly from the on-chain
note (`metadata().sender()` and the attachment's first felt), so
wallet discovery does not need out-of-band consumer identity. Also
introduces the `PswapAttachment` standard scheme variant alongside.

* test(pswap): exercise end-to-end consume + block commit in lineage discovery

`pswap_creator_reconstructs_lineage_from_attachments` previously
asserted only recipient-digest match across three partial-fill rounds
on per-round fresh chains, so the block-proposal authentication path —
which compares the reconstructed body's commitment against the
on-chain leaf — was never exercised.

Restructure to a single mock chain with persistent Alice and Bob. Each
round: Bob fills, Alice reconstructs the payback (and remainder, on
partial) from the on-chain attachment, asserts full commitment match,
consumes the reconstructed payback via the unauthenticated path, and
commits her tx so the chain advances for the next round. The earlier
cumulative-arithmetic recipient-only second loop is dropped — it was
strictly weaker than the per-round commitment check.

Parameterize `pswap_note_alice_reconstructs_and_consumes_p2id` over
the four (full|partial) × (public|private) cases and route both tests
through the new `payback_note` / `remainder_note` signatures, pulling
consumer + payout from the on-chain note rather than passing fixed IDs.

* docs(changelog): document discovery-helper signatures and on-chain-match contract

The existing PSWAP attachment entry mentioned `payback_note` /
`remainder_note` as discovery helpers but elided their signatures and
the load-bearing property that the reconstructed bodies match the
on-chain commitment (and hence are consumable as unauthenticated input
notes). Spell out both, and note that the new required arguments are
recoverable from the on-chain note itself.

* fix(test): satisfy clippy::cloned_ref_to_slice_refs in pswap tests

Clippy 1.94 introduced `cloned_ref_to_slice_refs`, which flags
`&[x.clone()]` as a slow path to a one-element slice. Replace the two
sites in `tests/scripts/pswap.rs` where Alice supplies the reconstructed
payback as an unauthenticated input note with `std::slice::from_ref(&x)`,
avoiding the clone.

* Update crates/miden-standards/src/note/pswap.rs

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* Update crates/miden-standards/src/note/pswap.rs

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* Update crates/miden-standards/src/note/pswap.rs

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* Update crates/miden-standards/src/note/pswap.rs

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* Update crates/miden-standards/src/note/pswap.rs

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>

* refactor(pswap): introduce PswapNoteAttachment for discovery helpers

Replaces the loose `(depth, amount)` u64 pairs on `PswapNote::payback_note`
and `remainder_note` with a typed `PswapNoteAttachment { amount: AssetAmount,
order_id: Felt, depth: u32 }` plus `From<_> for NoteAttachment`. Also switches
`remainder_note`'s `remaining_*` params to `AssetAmount`.

Per PR #2909 review feedback. Trims the related docs and CHANGELOG entry
in the same change.

* fix(pswap): preserve AssetCallbackFlag in execute and discovery helpers

`FungibleAsset::new` defaults `callbacks` to `Disabled`, but the on-chain
MASM preserves the parent note's callback flag via storage slot 0
(requested side) and the asset key (offered side). The Rust-side
`execute_full_fill`, `execute`, `payback_note`, and `remainder_note` were
all silently dropping the flag, so any PSWAP whose assets carry
`Enabled` callbacks would have its reconstructed `Note::commitment`
diverge from the on-chain leaf — breaking the unauthenticated consume
path that `payback_note`/`remainder_note` are meant to enable.

Thread the parent's flag through via `.with_callbacks(...)` in all four
spots, and add `pswap_output_assets_preserve_callback_flag` to pin the
contract.

Also drops the duplicate `#2909` CHANGELOG bullet left behind by the
rebase.

* docs(pswap): update Note::commitment refs to Note::details_commitment

* docs(pswap.masm): annotate stack state after get_current_depth if/else

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/asm/standards/notes/pswap.masm

Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>

* Update crates/miden-standards/src/note/pswap.rs

Co-authored-by: Marti <marcin.gorny.94@protonmail.com>

* Update crates/miden-standards/src/note/pswap.rs

Co-authored-by: Marti <marcin.gorny.94@protonmail.com>

* Update crates/miden-standards/src/note/pswap.rs

Co-authored-by: Marti <marcin.gorny.94@protonmail.com>

* refactor(pswap): rename attachment constants and trim docs per review

Addresses review nits from PR #2909:

- Suffix the MASM attachment locals to distinguish pointer from offset:
  PARENT_ATTACHMENT_BASE -> PARENT_ATTACHMENT_PTR and
  PARENT_ATTACHMENT_DEPTH -> PARENT_ATTACHMENT_DEPTH_OFFSET.
- Mirror that in Rust: ATTACHMENT_DEPTH_INDEX -> PARENT_ATTACHMENT_DEPTH_OFFSET.
- Drop the `_felt` variable suffixes (type need not be encoded in the name).
- Fix the misleading "mirrors get_current_depth" wording on parent_depth
  (the two return parent vs. current depth) and clarify "local-only".
- Drop redundant "matching the on-chain MASM" phrasing from helper docs.
- Trim the verbose CHANGELOG entry.

* refactoring changes

---------

Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
Co-authored-by: Alexander John Lee <77119221+partylikeits1983@users.noreply.github.com>
Co-authored-by: Marti <marcin.gorny.94@protonmail.com>
…2958)

* merge AuthMethod into AccessControl

* changelog

* fix documentation

* fix

* changelog

* fix comments

* add build_auth_component

* fix invalid combination

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
…r policy (#2946)

* fix

* changelog

* add get_balance_enabled

* chore: fix build

* fix: tests should respect the faucets callback flag

* chore: make comments less change-verbose

* align mint scripts with callback-enabled assets

* revert changes

* Update crates/miden-agglayer/asm/agglayer/bridge/bridge_in_output.masm

---------

Co-authored-by: Bobbin Threadbare <43513081+bobbinth@users.noreply.github.com>
Co-authored-by: Bobbin Threadbare <bobbinth@protonmail.com>
Co-authored-by: Marti <marti@miden.team>
* feat: update asset docs with composition and encoding

* chore: address review comments

* chore: add missing enable_callbacks parameter in create_non_fungible_asset

* chore: address review comments
Declare GER_KNOWN_FLAG as a 4-felt word ([1, 0, 0, 0]) and replace the
two `push.0.0.0.GER_KNOWN_FLAG` call sites with `push.GER_KNOWN_FLAG`.
This mirrors the existing const-word pattern already used elsewhere in
the repo (e.g. IS_CLAIMED_FLAG in bridge_in.masm, IS_EXECUTED_FLAG in
multisig.masm, ALLOWED_WORD/BLOCKED_WORD in the standards crate).

These were the only two manual word constructions of this shape left in
the codebase. FAUCET_REGISTERED_FLAG stays a single felt because it is
combined with a runtime `is_native` value, so it cannot be promoted to a
standalone const word.

Co-authored-by: Claude (Opus) <noreply@anthropic.com>
* benchmark: add ecdsa signing during P2ID consumption

* chore: update changelog, fix test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.