From b5fa1d2bf7356e993366ed862f1ea8cce73b5198 Mon Sep 17 00:00:00 2001 From: "Claude (Opus)" Date: Thu, 20 Aug 2026 13:29:27 +0000 Subject: [PATCH 1/4] docs(standards): document that note scripts claim only remaining note assets Standard note scripts move the assets remaining in a note at consumption time and do not compare them against the note's initial assets info. Per the discussion in #3601 this is intentional (it enables authorized deductions such as fees), so document the behavior where notes claim their assets. Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 1 + .../asm/standards/notes/p2id.masm | 2 +- .../asm/standards/notes/p2ide.masm | 2 +- .../asm/standards/notes/pswap.masm | 24 +++++++++++++++++-- .../asm/standards/notes/swap.masm | 9 +++++-- .../asm/standards/notes/tx_fee.masm | 2 +- .../asm/standards/wallets/basic.masm | 13 +++++++++- crates/miden-standards/src/note/pswap.rs | 11 +++++++++ crates/miden-standards/src/note/swap.rs | 9 +++++++ docs/src/note.md | 6 +++-- 10 files changed, 69 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 767e66fe64..58870cf879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ ### Changes +- Documented that standard note scripts claim only the assets remaining in a note at consumption time ([#3601](https://github.com/0xMiden/protocol/issues/3601)). - [BREAKING] Moved the internal shared helpers of `miden::protocol::input_note`, `miden::protocol::active_note`, and the note memory-write helpers into private `input_note_internal` and `note_internal` modules ([#3501](https://github.com/0xMiden/protocol/pull/3501)). - [BREAKING] Sorted the procedures of `AccountCode` after the authentication procedure at index 0, making the account code commitment independent of the order in which components are provided ([#2961](https://github.com/0xMiden/protocol/issues/2961)). - The transaction kernel now validates that a new account's procedures are sorted and unique ([#3567](https://github.com/0xMiden/protocol/pull/3567)). diff --git a/crates/miden-standards/asm/standards/notes/p2id.masm b/crates/miden-standards/asm/standards/notes/p2id.masm index d377650b7a..c3db7bb19d 100644 --- a/crates/miden-standards/asm/standards/notes/p2id.masm +++ b/crates/miden-standards/asm/standards/notes/p2id.masm @@ -21,7 +21,7 @@ const TARGET_ACCOUNT_ID_PREFIX_PTR = STORAGE_PTR + 1 # PROCEDURES # ================================================================================================= -#! Pay-to-ID script: adds all assets from the note to the account, assuming ID of the account +#! Pay-to-ID script: adds the note's remaining assets to the account, assuming ID of the account #! matches target account ID specified by the note storage. #! #! Requires that the account exposes: diff --git a/crates/miden-standards/asm/standards/notes/p2ide.masm b/crates/miden-standards/asm/standards/notes/p2ide.masm index 1d5e918ce0..6b3b859061 100644 --- a/crates/miden-standards/asm/standards/notes/p2ide.masm +++ b/crates/miden-standards/asm/standards/notes/p2ide.masm @@ -96,7 +96,7 @@ end #! Extended Pay-to-ID note script (Reclaimable & Timelockable) #! -#! Adds all assets from the note to the account if all of the following conditions are true: +#! Adds the note's remaining assets to the account if all of the following conditions are true: #! - The transaction's reference block number is greater than or equal to the note's timelock block height. #! - Any of the following conditions is true: #! - The account ID against which the transaction is executed matches the note's target account id. diff --git a/crates/miden-standards/asm/standards/notes/pswap.masm b/crates/miden-standards/asm/standards/notes/pswap.masm index 62bb20873a..c45f341993 100644 --- a/crates/miden-standards/asm/standards/notes/pswap.masm +++ b/crates/miden-standards/asm/standards/notes/pswap.masm @@ -451,6 +451,20 @@ end #! Loads the offered asset from the active note and validates there is exactly one asset. #! +#! The single-asset check fails if the offered asset was fully removed earlier in the transaction. +#! A partially removed fungible asset still occupies its slot, and the reduced amount becomes the +#! offered amount used downstream: the reclaim path returns only the remainder, and the fill path +#! prices the fill and sizes the creator's remainder note from the reduced amount (see +#! execute_pswap). +#! +#! Warning: the remaining amount is not bound to the amount the creator funded, so PSWAP prices +#! the fill against a value the consumer can influence. If the consuming account exposes a +#! procedure that performs indexed removal (input_note::remove_asset / remove_all_assets), any +#! note script in the same transaction can invoke it to shrink this note's offered asset before +#! the script runs; the fill is then priced against the reduced amount and the difference is +#! shifted out of the creator's remainder note. Making PSWAP price against the note's initial +#! assets is discussed in https://github.com/0xMiden/protocol/issues/3601. +#! #! Inputs: [] #! Outputs: [ASSET_ID, ASSET_VALUE] #! @@ -469,7 +483,7 @@ proc load_offered_asset # => [ASSET_ID, ASSET_VALUE] end -#! Reclaims all assets from the note back to the creator's vault. +#! Reclaims the note's remaining assets back to the creator's vault. #! #! Called when the consumer IS the creator (cancel/reclaim path). #! @@ -782,6 +796,12 @@ end #! proportional amount of the requested asset, producing a P2ID payback note for the creator #! and, on partial fills, a remainder PSWAP note carrying the unfilled balance. #! +#! Warning: the fill is priced against the offered asset remaining in the note at consumption +#! time, not the amount the creator funded. A consumer able to perform indexed removal on the +#! note can drain part of the offered asset outright before this script runs; on a partial fill +#! the creator's remainder note then shrinks by the drained amount. See `load_offered_asset` for +#! details. +#! #! The consumer specifies two fill amounts via `NOTE_ARGS`: #! - `account_fill_amount`: portion of the requested asset debited from the consumer's vault. #! - `note_fill_amount`: portion of the requested asset sourced from another note in the @@ -807,7 +827,7 @@ end #! #! Panics if: #! - the number of note storage items is not `NUM_STORAGE_ITEMS`. -#! - the note does not carry exactly one offered asset. +#! - the note does not hold exactly one offered asset at consumption time. #! - the total fill (account_fill + note_fill) overflows u64 or exceeds the max asset amount. #! - the account does not expose `receive_asset` / `move_asset_to_note`. @note_script diff --git a/crates/miden-standards/asm/standards/notes/swap.masm b/crates/miden-standards/asm/standards/notes/swap.masm index ad7e800828..125bfd0deb 100644 --- a/crates/miden-standards/asm/standards/notes/swap.masm +++ b/crates/miden-standards/asm/standards/notes/swap.masm @@ -42,7 +42,7 @@ const ERR_SWAP_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS="SWAP script expects exactly 1 const ERR_SWAP_WRONG_NUMBER_OF_ASSETS="SWAP script requires exactly 1 note asset" -#! Swap script: adds the offered asset from the note into the consumer's account and creates a +#! Swap script: adds the note's remaining offered asset into the consumer's account and creates a #! P2ID payback note addressed to the creator carrying the requested asset. #! #! The payback note type (selected by the creator) determines how the payback recipient is @@ -59,6 +59,7 @@ const ERR_SWAP_WRONG_NUMBER_OF_ASSETS="SWAP script requires exactly 1 note asset #! #! Panics if: #! - account does not expose the required wallet procedures. +#! - the note does not hold exactly one asset at consumption time. #! - account vault does not contain the requested asset. #! - adding a fungible asset would result in amount overflow, i.e., the total amount would be #! greater than 2^63. @@ -145,7 +146,11 @@ pub proc main push.ASSET_PTR exec.active_note::remove_all_assets # => [num_assets, pad(8)] - # make sure the number of assets is 1 + # make sure the number of assets is 1; this fails if the offered asset was fully removed + # earlier in the transaction, while a reduced fungible amount still passes and is claimed + # as-is. The loss falls on the consuming account, not the creator: the payback amount is + # fixed in note storage and is independent of the remaining offered amount. If the account + # exposes a procedure performing indexed removal, any note script it consumes can trigger it. assert.err=ERR_SWAP_WRONG_NUMBER_OF_ASSETS # => [pad(8)] diff --git a/crates/miden-standards/asm/standards/notes/tx_fee.masm b/crates/miden-standards/asm/standards/notes/tx_fee.masm index d75d6219ed..379d2689e2 100644 --- a/crates/miden-standards/asm/standards/notes/tx_fee.masm +++ b/crates/miden-standards/asm/standards/notes/tx_fee.masm @@ -28,7 +28,7 @@ const ERR_TX_FEE_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS = "TX_FEE note expects exact # PROCEDURES # ================================================================================================= -#! TX_FEE note script: adds all assets from the note to the consuming account. +#! TX_FEE note script: adds the note's remaining assets to the consuming account. #! #! A TX_FEE note is the canonical way for a transaction to pay its fee to the batch builder. Unlike #! P2ID, the note does not restrict who can consume it: any account can consume the note and claim diff --git a/crates/miden-standards/asm/standards/wallets/basic.masm b/crates/miden-standards/asm/standards/wallets/basic.masm index 538a30d53e..4af526236a 100644 --- a/crates/miden-standards/asm/standards/wallets/basic.masm +++ b/crates/miden-standards/asm/standards/wallets/basic.masm @@ -72,7 +72,18 @@ end # PUBLIC HELPERS # ================================================================================================= -#! Moves all assets from the active note to the native account's vault. +#! Moves all assets remaining in the active note to the native account's vault. +#! +#! The moved assets are those remaining in the note at the time of the call; they are not compared +#! against the note's initial assets info. Assets may already have been removed earlier in the +#! transaction, by the note's own script or by a native-account procedure via indexed removal +#! (input_note::remove_asset / remove_all_assets); in that case only the remainder is credited +#! and note consumption still succeeds. This is intentional, but safe only where the consuming +#! account is the beneficiary of the note's assets. Note that an account procedure performing +#! indexed removal is callable by every note script in the transaction, not just by the account's +#! owner. Logic that prices or validates a note based on its assets must use the note's initial +#! assets (active_note::get_initial_assets for the values, or get_initial_assets_info / +#! get_initial_num_assets for the commitment / count) rather than its remaining assets. #! #! Inputs: [] #! Outputs: [] diff --git a/crates/miden-standards/src/note/pswap.rs b/crates/miden-standards/src/note/pswap.rs index ac360be6c9..4e21857d49 100644 --- a/crates/miden-standards/src/note/pswap.rs +++ b/crates/miden-standards/src/note/pswap.rs @@ -267,6 +267,17 @@ impl From for NoteAttachment { /// `[0, 0, 0, 0]`, triggering a full fill). To route a PSWAP note to a network account, /// set the `attachment` to a [`NetworkAccountTarget`](crate::note::NetworkAccountTarget) /// via the builder. +/// +/// # Warning +/// +/// The fill is priced against the offered asset *remaining* in the note at consumption time, +/// not the amount the creator funded. Indexed removal requires a native-account procedure, so +/// this is only reachable when the consuming account exposes a procedure that performs it (via +/// `input_note::remove_asset` / `remove_all_assets`) and another note script earlier in the same +/// transaction invokes it; the standard basic wallet exposes no such procedure. Where it is +/// reachable, the offered asset can be shrunk before the script runs and the difference shifted +/// out of the creator's remainder note. See +/// [issue #3601](https://github.com/0xMiden/protocol/issues/3601). #[derive(Debug, Clone, bon::Builder)] #[builder(finish_fn(vis = "", name = build_internal))] pub struct PswapNote { diff --git a/crates/miden-standards/src/note/swap.rs b/crates/miden-standards/src/note/swap.rs index 5bb1a6c648..fedc75d910 100644 --- a/crates/miden-standards/src/note/swap.rs +++ b/crates/miden-standards/src/note/swap.rs @@ -54,6 +54,15 @@ static SWAP_SCRIPT: LazyLock = LazyLock::new(|| { /// Construct one with the [builder](SwapNote::builder), which defaults both the note type and the /// payback note type to [`NoteType::Private`] and adds no attachments; convert it into a protocol /// [`Note`] infallibly via `Note::from`. +/// +/// # Warning +/// +/// The consumer receives the offered asset *remaining* in the note at consumption time, while the +/// payback is fixed in note storage. If the consuming account exposes a procedure that performs +/// indexed removal, another note script in the same transaction can shrink the offered asset +/// before this script runs; the consumer then pays the full payback for a reduced offered asset. +/// The loss falls on the consuming account, not the creator. See +/// [issue #3601](https://github.com/0xMiden/protocol/issues/3601). #[derive(Debug, Clone, PartialEq, Eq)] pub struct SwapNote { sender: AccountId, diff --git a/docs/src/note.md b/docs/src/note.md index f66047f1a5..199f7fad10 100644 --- a/docs/src/note.md +++ b/docs/src/note.md @@ -205,9 +205,11 @@ For a private note, the operator stores only its ID and never sees these compone The `miden::standards` library provides several standard note scripts that implement common use cases for asset transfers and interactions. These pre-built note types offer secure, tested implementations for typical scenarios. +Input-note assets are stateful within a transaction: a note script claims the assets remaining in the note at consumption time, which may be less than the note was created with if assets were removed earlier in the transaction. Removal by index requires a native-account procedure, so any note script in the transaction can trigger it against another note when the consuming account exposes such a procedure. Logic that prices or validates a note based on its assets must use the note's initial assets info rather than its remaining assets. + ### P2ID (Pay-to-ID) -The P2ID note script implements a simple pay-to-account-ID pattern. It adds all assets from the note to a specific target account. +The P2ID note script implements a simple pay-to-account-ID pattern. It adds the note's remaining assets to a specific target account. **Key characteristics:** @@ -243,7 +245,7 @@ The P2IDE note script extends P2ID with additional features including time-locki ### TX_FEE -The TX_FEE note script is the canonical way for a transaction to pay its fee to a batch builder. It adds all assets from the note to the consuming account, without restricting who that account is. +The TX_FEE note script is the canonical way for a transaction to pay its fee to a batch builder. It adds the note's remaining assets to the consuming account, without restricting who that account is. **Key characteristics:** From 96393bf01c5f1efcc8d1129b29e1ed95f35bb82b Mon Sep 17 00:00:00 2001 From: "Claude (Opus)" Date: Thu, 20 Aug 2026 14:57:32 +0000 Subject: [PATCH 2/4] docs(standards): drop PSWAP-specific warnings, deferred to follow-up fix The PSWAP offered-amount drain is being fixed directly in a follow-up PR rather than documented as accepted behavior, so remove the PSWAP hazard warnings from this docs change. The neutral remaining-vs-initial wording is kept consistent with the rest of the standards pass, and the SWAP note (whose loss is consumer-side and not being changed) stays documented here. Co-Authored-By: Claude Fable 5 --- .../asm/standards/notes/pswap.masm | 20 ------------------- crates/miden-standards/src/note/pswap.rs | 11 ---------- 2 files changed, 31 deletions(-) diff --git a/crates/miden-standards/asm/standards/notes/pswap.masm b/crates/miden-standards/asm/standards/notes/pswap.masm index c45f341993..4db17dc4c6 100644 --- a/crates/miden-standards/asm/standards/notes/pswap.masm +++ b/crates/miden-standards/asm/standards/notes/pswap.masm @@ -451,20 +451,6 @@ end #! Loads the offered asset from the active note and validates there is exactly one asset. #! -#! The single-asset check fails if the offered asset was fully removed earlier in the transaction. -#! A partially removed fungible asset still occupies its slot, and the reduced amount becomes the -#! offered amount used downstream: the reclaim path returns only the remainder, and the fill path -#! prices the fill and sizes the creator's remainder note from the reduced amount (see -#! execute_pswap). -#! -#! Warning: the remaining amount is not bound to the amount the creator funded, so PSWAP prices -#! the fill against a value the consumer can influence. If the consuming account exposes a -#! procedure that performs indexed removal (input_note::remove_asset / remove_all_assets), any -#! note script in the same transaction can invoke it to shrink this note's offered asset before -#! the script runs; the fill is then priced against the reduced amount and the difference is -#! shifted out of the creator's remainder note. Making PSWAP price against the note's initial -#! assets is discussed in https://github.com/0xMiden/protocol/issues/3601. -#! #! Inputs: [] #! Outputs: [ASSET_ID, ASSET_VALUE] #! @@ -796,12 +782,6 @@ end #! proportional amount of the requested asset, producing a P2ID payback note for the creator #! and, on partial fills, a remainder PSWAP note carrying the unfilled balance. #! -#! Warning: the fill is priced against the offered asset remaining in the note at consumption -#! time, not the amount the creator funded. A consumer able to perform indexed removal on the -#! note can drain part of the offered asset outright before this script runs; on a partial fill -#! the creator's remainder note then shrinks by the drained amount. See `load_offered_asset` for -#! details. -#! #! The consumer specifies two fill amounts via `NOTE_ARGS`: #! - `account_fill_amount`: portion of the requested asset debited from the consumer's vault. #! - `note_fill_amount`: portion of the requested asset sourced from another note in the diff --git a/crates/miden-standards/src/note/pswap.rs b/crates/miden-standards/src/note/pswap.rs index 4e21857d49..ac360be6c9 100644 --- a/crates/miden-standards/src/note/pswap.rs +++ b/crates/miden-standards/src/note/pswap.rs @@ -267,17 +267,6 @@ impl From for NoteAttachment { /// `[0, 0, 0, 0]`, triggering a full fill). To route a PSWAP note to a network account, /// set the `attachment` to a [`NetworkAccountTarget`](crate::note::NetworkAccountTarget) /// via the builder. -/// -/// # Warning -/// -/// The fill is priced against the offered asset *remaining* in the note at consumption time, -/// not the amount the creator funded. Indexed removal requires a native-account procedure, so -/// this is only reachable when the consuming account exposes a procedure that performs it (via -/// `input_note::remove_asset` / `remove_all_assets`) and another note script earlier in the same -/// transaction invokes it; the standard basic wallet exposes no such procedure. Where it is -/// reachable, the offered asset can be shrunk before the script runs and the difference shifted -/// out of the creator's remainder note. See -/// [issue #3601](https://github.com/0xMiden/protocol/issues/3601). #[derive(Debug, Clone, bon::Builder)] #[builder(finish_fn(vis = "", name = build_internal))] pub struct PswapNote { From 83d41777c1145e8c0959ed2ec49bd9fdb134de4d Mon Sep 17 00:00:00 2001 From: Marti Date: Thu, 20 Aug 2026 22:26:24 +0200 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: Marti --- crates/miden-standards/asm/standards/notes/swap.masm | 6 +----- .../miden-standards/asm/standards/wallets/basic.masm | 11 +++-------- crates/miden-standards/src/note/swap.rs | 9 --------- docs/src/note.md | 2 +- 4 files changed, 5 insertions(+), 23 deletions(-) diff --git a/crates/miden-standards/asm/standards/notes/swap.masm b/crates/miden-standards/asm/standards/notes/swap.masm index 125bfd0deb..b32fe786cd 100644 --- a/crates/miden-standards/asm/standards/notes/swap.masm +++ b/crates/miden-standards/asm/standards/notes/swap.masm @@ -146,11 +146,7 @@ pub proc main push.ASSET_PTR exec.active_note::remove_all_assets # => [num_assets, pad(8)] - # make sure the number of assets is 1; this fails if the offered asset was fully removed - # earlier in the transaction, while a reduced fungible amount still passes and is claimed - # as-is. The loss falls on the consuming account, not the creator: the payback amount is - # fixed in note storage and is independent of the remaining offered amount. If the account - # exposes a procedure performing indexed removal, any note script it consumes can trigger it. + # make sure the number of assets is 1 assert.err=ERR_SWAP_WRONG_NUMBER_OF_ASSETS # => [pad(8)] diff --git a/crates/miden-standards/asm/standards/wallets/basic.masm b/crates/miden-standards/asm/standards/wallets/basic.masm index 4af526236a..a75874c1a5 100644 --- a/crates/miden-standards/asm/standards/wallets/basic.masm +++ b/crates/miden-standards/asm/standards/wallets/basic.masm @@ -75,15 +75,10 @@ end #! Moves all assets remaining in the active note to the native account's vault. #! #! The moved assets are those remaining in the note at the time of the call; they are not compared -#! against the note's initial assets info. Assets may already have been removed earlier in the +#! against the note's initial assets info. Some assets may already have been removed earlier in the #! transaction, by the note's own script or by a native-account procedure via indexed removal -#! (input_note::remove_asset / remove_all_assets); in that case only the remainder is credited -#! and note consumption still succeeds. This is intentional, but safe only where the consuming -#! account is the beneficiary of the note's assets. Note that an account procedure performing -#! indexed removal is callable by every note script in the transaction, not just by the account's -#! owner. Logic that prices or validates a note based on its assets must use the note's initial -#! assets (active_note::get_initial_assets for the values, or get_initial_assets_info / -#! get_initial_num_assets for the commitment / count) rather than its remaining assets. +#! Logic that prices or validates a note based on its assets must use the note's initial +#! assets rather than its remaining ones. #! #! Inputs: [] #! Outputs: [] diff --git a/crates/miden-standards/src/note/swap.rs b/crates/miden-standards/src/note/swap.rs index fedc75d910..5bb1a6c648 100644 --- a/crates/miden-standards/src/note/swap.rs +++ b/crates/miden-standards/src/note/swap.rs @@ -54,15 +54,6 @@ static SWAP_SCRIPT: LazyLock = LazyLock::new(|| { /// Construct one with the [builder](SwapNote::builder), which defaults both the note type and the /// payback note type to [`NoteType::Private`] and adds no attachments; convert it into a protocol /// [`Note`] infallibly via `Note::from`. -/// -/// # Warning -/// -/// The consumer receives the offered asset *remaining* in the note at consumption time, while the -/// payback is fixed in note storage. If the consuming account exposes a procedure that performs -/// indexed removal, another note script in the same transaction can shrink the offered asset -/// before this script runs; the consumer then pays the full payback for a reduced offered asset. -/// The loss falls on the consuming account, not the creator. See -/// [issue #3601](https://github.com/0xMiden/protocol/issues/3601). #[derive(Debug, Clone, PartialEq, Eq)] pub struct SwapNote { sender: AccountId, diff --git a/docs/src/note.md b/docs/src/note.md index 199f7fad10..6505b408ab 100644 --- a/docs/src/note.md +++ b/docs/src/note.md @@ -205,7 +205,7 @@ For a private note, the operator stores only its ID and never sees these compone The `miden::standards` library provides several standard note scripts that implement common use cases for asset transfers and interactions. These pre-built note types offer secure, tested implementations for typical scenarios. -Input-note assets are stateful within a transaction: a note script claims the assets remaining in the note at consumption time, which may be less than the note was created with if assets were removed earlier in the transaction. Removal by index requires a native-account procedure, so any note script in the transaction can trigger it against another note when the consuming account exposes such a procedure. Logic that prices or validates a note based on its assets must use the note's initial assets info rather than its remaining assets. +Input-note assets are stateful within a transaction: a note script claims the assets remaining in the note at consumption time, which may be less than the note was created with. Logic that prices or validates a note based on its assets must use the note's **initial assets** info rather than its remaining assets. ### P2ID (Pay-to-ID) From a764b9d5e67bc38eac3e86c2d03bb176250973ab Mon Sep 17 00:00:00 2001 From: Marti Date: Fri, 21 Aug 2026 10:21:29 +0200 Subject: [PATCH 4/4] Update CHANGELOG.md Co-authored-by: zeapoz --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ffc3b9424..d67bcbd7ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ ### Changes -- Documented that standard note scripts claim only the assets remaining in a note at consumption time ([#3601](https://github.com/0xMiden/protocol/issues/3601)). +- Documented that standard note scripts claim only the assets remaining in a note at consumption time ([#3650](https://github.com/0xMiden/protocol/pull/3650)). - [BREAKING] Added the `miden::standards::expiration` MASM module with `apply_default` and used it to apply a default 20-block transaction expiration limit to the standard allowlist and blocklist transfer policies and the fee manager's `estimate_note_fee` procedure ([#3512](https://github.com/0xMiden/protocol/pull/3512)). - [BREAKING] Moved the internal shared helpers of `miden::protocol::input_note`, `miden::protocol::active_note`, and the note memory-write helpers into private `input_note_internal` and `note_internal` modules ([#3501](https://github.com/0xMiden/protocol/pull/3501)). - [BREAKING] Sorted the procedures of `AccountCode` after the authentication procedure at index 0, making the account code commitment independent of the order in which components are provided ([#2961](https://github.com/0xMiden/protocol/issues/2961)).