Skip to content
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Features

- Added `active_note::get_storage_info` and `active_note::get_bounded_storage`, and switched the standard and agglayer note scripts with a bounded storage layout over to the latter ([#3563](https://github.com/0xMiden/protocol/pull/3563)).

### Changes

- [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)).
Expand Down
3 changes: 2 additions & 1 deletion crates/miden-agglayer/asm/agglayer/notes/b2agg.masm
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ pub proc main
# => [pad(16)]

# Store note storage -> mem[8..14]
push.B2AGG_NOTE_STORAGE_PTR exec.active_note::get_storage
push.B2AGG_NOTE_NUM_STORAGE_ITEMS push.B2AGG_NOTE_STORAGE_PTR
exec.active_note::get_bounded_storage
# => [num_storage_items, pad(16)]

# Validate the number of storage items
Expand Down
7 changes: 6 additions & 1 deletion crates/miden-agglayer/asm/agglayer/notes/claim.masm
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ const PROOF_DATA_SIZE = 536
const LEAF_DATA_SIZE = 32
const OUTPUT_NOTE_SIZE = 8

# The number of storage items of a CLAIM note, see the layout in the script's doc comment.
const CLAIM_NOTE_NUM_STORAGE_ITEMS = 569

const CLAIM_NOTE_STORAGE_PTR = 0
const PROOF_DATA_START_PTR = CLAIM_NOTE_STORAGE_PTR
const LEAF_DATA_START_PTR = 536
Expand Down Expand Up @@ -75,6 +78,7 @@ const ERR_CLAIM_TARGET_ACCT_MISMATCH = "CLAIM note attachment target account doe
#! Panics if:
#! - account does not expose claim procedure.
#! - note attachment target account does not match the consuming account.
#! - the note carries more than CLAIM_NOTE_NUM_STORAGE_ITEMS storage items.
@note_script
pub proc main
dropw
Expand All @@ -86,7 +90,8 @@ pub proc main
# => [pad(16)]

# Load CLAIM note storage into memory, starting at address 0
push.CLAIM_NOTE_STORAGE_PTR exec.active_note::get_storage drop
push.CLAIM_NOTE_NUM_STORAGE_ITEMS push.CLAIM_NOTE_STORAGE_PTR
exec.active_note::get_bounded_storage drop
# => [pad(16)]

exec.write_claim_data_into_advice_map_by_key
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ pub proc main
# => [pad(16)]

# Load note storage to memory
push.STORAGE_START_PTR exec.active_note::get_storage
push.CONFIG_AGG_BRIDGE_NUM_STORAGE_ITEMS push.STORAGE_START_PTR
exec.active_note::get_bounded_storage
# => [num_storage_items, pad(16)]

# Validate the number of storage items
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ pub proc main
# => [pad(16)]

# Load note storage to memory
push.STORAGE_START_PTR exec.active_note::get_storage
push.DEREGISTER_AGG_FAUCET_NUM_STORAGE_ITEMS push.STORAGE_START_PTR
exec.active_note::get_bounded_storage
# => [num_storage_items, pad(16)]

# Validate the number of storage items
Expand Down
3 changes: 2 additions & 1 deletion crates/miden-agglayer/asm/agglayer/notes/remove_ger.masm
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ pub proc main
# => [pad(16)]

# Load note storage to memory
push.STORAGE_PTR_GER_LOWER exec.active_note::get_storage
push.REMOVE_GER_NOTE_NUM_STORAGE_ITEMS push.STORAGE_PTR_GER_LOWER
exec.active_note::get_bounded_storage
# => [num_storage_items, pad(16)]

# Validate the number of storage items
Expand Down
3 changes: 2 additions & 1 deletion crates/miden-agglayer/asm/agglayer/notes/update_ger.masm
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ pub proc main
# => [pad(16)]

# Load note storage to memory
push.STORAGE_PTR_GER_LOWER exec.active_note::get_storage
push.UPDATE_GER_NOTE_NUM_STORAGE_ITEMS push.STORAGE_PTR_GER_LOWER
exec.active_note::get_bounded_storage
# => [num_storage_items, pad(16)]

# Validate the number of storage items
Expand Down
63 changes: 63 additions & 0 deletions crates/miden-protocol/asm/protocol/src/active_note.masm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const ERR_NOTE_DATA_DOES_NOT_MATCH_COMMITMENT = "note data does not match the co
const ERR_NOTE_INVALID_NUMBER_OF_STORAGE_ITEMS =
"the specified number of note storage items does not match the actual number"

const ERR_NOTE_TOO_MANY_STORAGE_ITEMS =
"the number of note storage items exceeds the maximum accepted by the note script"

# ACTIVE NOTE PROCEDURES
# =================================================================================================
#
Expand Down Expand Up @@ -242,6 +245,28 @@ pub proc get_note_id() -> NoteId
# => [NOTE_ID]
end

#! Returns the storage commitment and the number of storage items of the active note.
#!
#! Inputs: []
#! Outputs: [NOTE_STORAGE_COMMITMENT, num_storage_items]
#!
#! Where:
#! - NOTE_STORAGE_COMMITMENT is the commitment to the note's storage.
#! - num_storage_items is the number of storage items the active note was created with.
#!
#! Panics if:
#! - no note is currently active.
#!
#! Invocation: exec
pub proc get_storage_info() -> (word, u16)
# push a placeholder note_index (ignored when is_active_note = 1) and the active note flag
push.0.1
# => [is_active_note = 1, note_index = 0]

exec.input_note_internal::get_storage_info_raw
# => [NOTE_STORAGE_COMMITMENT, num_storage_items]
end

#! Writes the active note's storage to memory starting at the specified address.
#!
#! Inputs:
Expand Down Expand Up @@ -276,6 +301,44 @@ pub proc get_storage(dest_ptr: MemoryAddress) -> u16
# => [num_storage_items]
end

#! Writes the active note's storage to memory starting at the specified address, provided the note
#! carries at most `max_num_storage_items` items.
#!
#! Inputs:
#! Stack: [dest_ptr, max_num_storage_items]
#! Advice Map: { NOTE_STORAGE_COMMITMENT: [STORAGE] }
#! Outputs:
#! Stack: [num_storage_items]
#!
#! Where:
#! - dest_ptr is the memory address to write the note storage.
#! - max_num_storage_items is the largest number of storage items the caller accepts.
#! - NOTE_STORAGE_COMMITMENT is the commitment to the note's storage.
#! - STORAGE is the data corresponding to the note's storage.
#! - num_storage_items is the number of storage items the active note was created with.
#!
#! Panics if:
#! - no note is currently active.
#! - num_storage_items is greater than max_num_storage_items.
#!
#! Invocation: exec
pub proc get_bounded_storage(dest_ptr: MemoryAddress, max_num_storage_items: u16) -> u16

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Probably not a good idea, but I wonder if we should just change the get_storage procedure to work like this. The biggest issue is that that would be a pretty bad breaking change (not easy to detect downstream) - but if we were designing the protocol from scratch, that's how I'd probably make get_storage work.

exec.get_storage_info
# => [NOTE_STORAGE_COMMITMENT, num_storage_items, dest_ptr, max_num_storage_items]

# reject an oversized note before its storage preimage is loaded and hashed
dup.4 movup.7 lte assert.err=ERR_NOTE_TOO_MANY_STORAGE_ITEMS
# => [NOTE_STORAGE_COMMITMENT, num_storage_items, dest_ptr]

# save num_storage_items for the return value
dup.4 movdn.6
# => [NOTE_STORAGE_COMMITMENT, num_storage_items, dest_ptr, num_storage_items]

# write the inputs to the provided destination pointer
exec.write_storage_to_memory
# => [num_storage_items]
end

#! Returns the metadata of the active note.
#!
#! Inputs: []
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use miden::standards::faucets::policies::transfer::allowlist::manager
# CONSTANTS
# =================================================================================================

# Memory base at which the note storage is written by `active_note::get_storage`.
# Memory base at which the note storage is written by `active_note::get_bounded_storage`.
const STORAGE_PTR = 0

# Memory addresses of the AllowlistConfig note storage. Both actions carry the same arguments: the
Expand All @@ -23,6 +23,9 @@ const SELECTOR_DISALLOW_ACCOUNT = 1
const NUM_ITEMS_ALLOW_ACCOUNT = 3
const NUM_ITEMS_DISALLOW_ACCOUNT = 3

# Largest storage item count any action uses
const MAX_NUM_ITEMS = NUM_ITEMS_ALLOW_ACCOUNT

# ERRORS
# =================================================================================================

Expand Down Expand Up @@ -57,6 +60,7 @@ const ERR_ALLOWLIST_CONFIG_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS = "allowlist confi
#!
#! Panics if:
#! - the consuming account is not the note's target account, or the target attachment is missing.
#! - the number of storage items exceeds MAX_NUM_ITEMS.
#! - the selector is not a known action.
#! - the number of storage items does not match the selected action.
#! - the caller is not authorized for the selected action per the installed `Authority` component.
Expand All @@ -72,7 +76,7 @@ pub proc main
# => [pad(16)]

# write the note storage to memory starting at STORAGE_PTR
push.STORAGE_PTR exec.active_note::get_storage
push.MAX_NUM_ITEMS push.STORAGE_PTR exec.active_note::get_bounded_storage
# => [num_storage_items]

mem_load.SELECTOR_PTR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use miden::standards::faucets::policies::transfer::blocklist::manager
# CONSTANTS
# =================================================================================================

# Memory base at which the note storage is written by `active_note::get_storage`.
# Memory base at which the note storage is written by `active_note::get_bounded_storage`.
const STORAGE_PTR = 0

# Memory addresses of the BlocklistConfig note storage. Both actions carry the same arguments: the
Expand All @@ -23,6 +23,9 @@ const SELECTOR_UNBLOCK_ACCOUNT = 1
const NUM_ITEMS_BLOCK_ACCOUNT = 3
const NUM_ITEMS_UNBLOCK_ACCOUNT = 3

# Largest storage item count any action uses
const MAX_NUM_ITEMS = NUM_ITEMS_BLOCK_ACCOUNT

# ERRORS
# =================================================================================================

Expand Down Expand Up @@ -57,6 +60,7 @@ const ERR_BLOCKLIST_CONFIG_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS = "blocklist confi
#!
#! Panics if:
#! - the consuming account is not the note's target account, or the target attachment is missing.
#! - the number of storage items exceeds MAX_NUM_ITEMS.
#! - the selector is not a known action.
#! - the number of storage items does not match the selected action.
#! - the caller is not authorized for the selected action per the installed `Authority` component.
Expand All @@ -72,7 +76,7 @@ pub proc main
# => [pad(16)]

# write the note storage to memory starting at STORAGE_PTR
push.STORAGE_PTR exec.active_note::get_storage
push.MAX_NUM_ITEMS push.STORAGE_PTR exec.active_note::get_bounded_storage
# => [num_storage_items]

mem_load.SELECTOR_PTR
Expand Down
2 changes: 1 addition & 1 deletion crates/miden-standards/asm/standards/notes/burn.masm
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub proc main
# => [pad(16)]

# Load the asset embedded in storage and require the canonical eight-felt asset layout.
push.STORAGE_PTR exec.active_note::get_storage
push.NUM_STORAGE_ITEMS push.STORAGE_PTR exec.active_note::get_bounded_storage
eq.NUM_STORAGE_ITEMS assert.err=ERR_BURN_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS
# => [pad(16)]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use miden::standards::fees::policies::constant_fee_manager
# CONSTANTS
# =================================================================================================

# Memory base at which the note storage is written by `active_note::get_storage`.
# Memory base at which the note storage is written by `active_note::get_bounded_storage`.
const STORAGE_PTR = 0

# Memory addresses of the ConstantFeePolicyConfig note storage: the note script root word
Expand Down Expand Up @@ -71,7 +71,7 @@ pub proc main
# => [pad(16)]

# write the note storage to memory starting at STORAGE_PTR
push.STORAGE_PTR exec.active_note::get_storage
push.NUM_STORAGE_ITEMS push.STORAGE_PTR exec.active_note::get_bounded_storage
# => [num_storage_items, pad(16)]

eq.NUM_STORAGE_ITEMS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use miden::standards::faucets::fungible
# Number of felts encoding a metadata string: 7 Words.
const STRING_NUM_ELEMENTS = 28

# Memory base at which the note storage is written by `active_note::get_storage`.
# Memory base at which the note storage is written by `active_note::get_bounded_storage`.
const STORAGE_PTR = 0

# Memory addresses of the FaucetMetadataConfig note storage. The selector is one felt padded out to
Expand All @@ -32,6 +32,9 @@ const SELECTOR_SET_EXTERNAL_LINK = 3
const NUM_ITEMS_SET_MAX_SUPPLY = 2
const NUM_ITEMS_SET_STRING = 32

# Largest storage item count any action uses
const MAX_NUM_ITEMS = NUM_ITEMS_SET_STRING

# ERRORS
# =================================================================================================

Expand Down Expand Up @@ -61,7 +64,7 @@ const ERR_FAUCET_METADATA_CONFIG_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS = "faucet me
#! - `3` SetExternalLink: `[3, 0, 0, 0, external_link(28)]`.
#!
#! The three string setters take the Poseidon2 commitment of their new value on the operand stack
#! and read the preimage from the advice map. This script commits to the payload `get_storage` wrote
#! and read the preimage from the advice map. This script commits to the payload `get_bounded_storage` wrote
#! to memory and inserts it into the advice map under that commitment, so the value is bound into
#! the note commitment through the note storage and needs no out-of-band advice inputs.
#!
Expand All @@ -78,6 +81,7 @@ const ERR_FAUCET_METADATA_CONFIG_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS = "faucet me
#!
#! Panics if:
#! - the consuming account is not the note's target account, or the target attachment is missing.
#! - the number of storage items exceeds MAX_NUM_ITEMS.
#! - the selector is not a known action.
#! - the number of storage items does not match the selected action.
#! - the selected field's mutability flag is not set, or the account is paused.
Expand All @@ -94,7 +98,7 @@ pub proc main
# => [pad(16)]

# write the note storage to memory starting at STORAGE_PTR
push.STORAGE_PTR exec.active_note::get_storage
push.MAX_NUM_ITEMS push.STORAGE_PTR exec.active_note::get_bounded_storage
# => [num_storage_items]

mem_load.SELECTOR_PTR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use miden::standards::faucets::policies::policy_manager
# CONSTANTS
# =================================================================================================

# Memory base at which the note storage is written by `active_note::get_storage`.
# Memory base at which the note storage is written by `active_note::get_bounded_storage`.
const STORAGE_PTR = 0

# Memory addresses of the FaucetPolicyConfig note storage. The policy root word comes first so that
Expand Down Expand Up @@ -60,6 +60,7 @@ const ERR_FAUCET_POLICY_CONFIG_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS = "faucet poli
#!
#! Panics if:
#! - the consuming account is not the note's target account, or the target attachment is missing.
#! - the number of storage items exceeds NUM_ITEMS_SET_POLICY.
#! - the selector is not a known action.
#! - the number of storage items does not match the selected action.
#! - the caller is not authorized per the installed `Authority` component, or the policy root is not
Expand All @@ -76,7 +77,7 @@ pub proc main
# => [pad(16)]

# write the note storage to memory starting at STORAGE_PTR
push.STORAGE_PTR exec.active_note::get_storage
push.NUM_ITEMS_SET_POLICY push.STORAGE_PTR exec.active_note::get_bounded_storage
# => [num_storage_items]

mem_load.SELECTOR_PTR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use {AccountId, BlockNumber, NoteRecipient, NoteId, NoteTag, NoteType} from mide
#! The memory address at which the note storage is written.
const STORAGE_PTR = 0

# Note storage layout (7 items, loaded at STORAGE_PTR by get_storage):
# Note storage layout (7 items, loaded at STORAGE_PTR by get_bounded_storage):
# - FEATURE_NOTE_ID [0..3] : ID of the feature note this sponsorship pays for
# - reclaimer_suffix [4] : suffix of the account allowed to reclaim the note
# - reclaimer_prefix [5] : prefix of the account allowed to reclaim the note
Expand Down Expand Up @@ -138,7 +138,7 @@ pub proc main
dropw
# => [pad(16)]

push.STORAGE_PTR exec.active_note::get_storage
push.NUM_STORAGE_ITEMS push.STORAGE_PTR exec.active_note::get_bounded_storage
# => [num_storage_items, pad(16)]

eq.NUM_STORAGE_ITEMS assert.err=ERR_FEE_SPONSORSHIP_UNEXPECTED_NUMBER_OF_STORAGE_ITEMS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use miden::standards::faucets::policies::burn::min_burn_amount
# CONSTANTS
# =================================================================================================

# Memory base at which the note storage is written by `active_note::get_storage`.
# Memory base at which the note storage is written by `active_note::get_bounded_storage`.
const STORAGE_PTR = 0

# Memory address of the new minimum burn amount in the MinBurnAmountConfig note storage.
Expand Down Expand Up @@ -63,7 +63,7 @@ pub proc main
# => [pad(16)]

# write the note storage to memory starting at STORAGE_PTR
push.STORAGE_PTR exec.active_note::get_storage
push.NUM_STORAGE_ITEMS push.STORAGE_PTR exec.active_note::get_bounded_storage
# => [num_storage_items, pad(16)]

eq.NUM_STORAGE_ITEMS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use miden::standards::fees::fee_manager
# CONSTANTS
# =================================================================================================

# Memory base at which the note storage is written by `active_note::get_storage`.
# Memory base at which the note storage is written by `active_note::get_bounded_storage`.
const STORAGE_PTR = 0

# Memory addresses of the NetworkAccountConfig note storage. The root word occupies the first four
Expand Down Expand Up @@ -89,7 +89,7 @@ pub proc main
# => [pad(16)]

# write the note storage to memory starting at STORAGE_PTR
push.STORAGE_PTR exec.active_note::get_storage
push.NUM_STORAGE_ITEMS push.STORAGE_PTR exec.active_note::get_bounded_storage
# => [num_storage_items, pad(16)]

mem_load.SELECTOR_PTR
Expand Down
Loading
Loading