Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
3660c4d
feat: Implement `NamedStorageSlot`
PhilippGackstatter Oct 6, 2025
368a3b6
feat: Use `find_half_key_value`
PhilippGackstatter Oct 8, 2025
93aeb3b
feat: Implement `AccountStorage::get`
PhilippGackstatter Oct 9, 2025
dd30279
feat: Reimplement account storage APIs
PhilippGackstatter Oct 9, 2025
a8845e9
chore: Add compat APIs
PhilippGackstatter Oct 9, 2025
326df51
feat: Reinstantiate apply_delta and reimpl set_item_raw
PhilippGackstatter Oct 9, 2025
ffdaa41
fix: get_storage_slot_type
PhilippGackstatter Oct 9, 2025
8b29817
fix: name layout in memory
PhilippGackstatter Oct 9, 2025
dcdf55b
feat: Implement get_size_hint for named slot and slot name
PhilippGackstatter Oct 9, 2025
9d49150
chore: Reinstantiate commented tests
PhilippGackstatter Oct 9, 2025
3629f05
feat: Implement `SequentialCommit` and make `StorageSlotHeader` private
PhilippGackstatter Oct 9, 2025
5243e39
chore: Various cleanup
PhilippGackstatter Oct 9, 2025
b26bd46
fix: toml fmt and `typ` "typo"
PhilippGackstatter Oct 9, 2025
f6e0add
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Oct 9, 2025
9ada60c
chore: Add changelog entry
PhilippGackstatter Oct 9, 2025
d8acfcf
feat: Enforce max length on `SlotName`
PhilippGackstatter Oct 10, 2025
d8e643e
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Oct 10, 2025
4822684
chore: Emit event earlier in `get_map_item_raw`
PhilippGackstatter Oct 10, 2025
09ffc89
feat: Update docs of storage slot header and account storage header
PhilippGackstatter Oct 10, 2025
e854f2c
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Oct 15, 2025
f0fc368
chore: Document `NamedStorageSlot` fields
PhilippGackstatter Oct 15, 2025
ffc25de
chore: Rename `get_storage_slot_ptr` -> `find_storage_slot`
PhilippGackstatter Oct 15, 2025
2ca79f9
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Oct 24, 2025
95afca4
chore: use branch from VM PR
PhilippGackstatter Oct 24, 2025
b537a92
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Oct 28, 2025
21b63a6
chore: Bump miden-vm to 0.18.3
PhilippGackstatter Oct 28, 2025
3888f16
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Nov 3, 2025
0a3447a
chore: Address post-merge changes
PhilippGackstatter Nov 3, 2025
02c2aa3
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Nov 6, 2025
426d6a2
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Nov 7, 2025
383c5fd
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Nov 10, 2025
8dda2fc
chore: move changelog entry to 0.13 and remove duplicate entries
PhilippGackstatter Nov 10, 2025
945d8bc
fix: make format
PhilippGackstatter Nov 10, 2025
aee125a
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Nov 23, 2025
c4725b0
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Dec 1, 2025
ed6decd
chore: Use `get_storage_slot_type` instead
PhilippGackstatter Dec 1, 2025
f73ce80
chore: Use BTreeSet to check for name uniqueness
PhilippGackstatter Dec 1, 2025
365d062
chore: Rename `name_id` to `id`
PhilippGackstatter Dec 1, 2025
8e3618b
chore: Use `project_name` in slot name example
PhilippGackstatter Dec 1, 2025
b72626a
chore: Remove `SlotName::is_empty`
PhilippGackstatter Dec 1, 2025
69ca866
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Dec 3, 2025
dd85a8c
Merge remote-tracking branch 'origin/next' into pgackst-named-storage…
PhilippGackstatter Dec 5, 2025
5661d74
Merge branch 'next' into pgackst-named-storage-slots
bobbinth Dec 6, 2025
1588fba
Merge remote-tracking branch 'origin/pgackst-named-storage-slots' int…
PhilippGackstatter Dec 8, 2025
ec2443e
chore: regengerate kernel procedure files
PhilippGackstatter Dec 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

### Features

- [BREAKING] Refactor storage slots to be accessed by names instead of indices ([#1987](https://github.com/0xMiden/miden-base/pull/1987)).

## 0.12.2 (unreleased)
- Add proc-macro `WordWrapper` to ease implementation of `Word`-wrapping types ([#2071](https://github.com/0xMiden/miden-base/pull/2108)).
- [BREAKING] Added fee to `TransactionHeader` ([#2131](https://github.com/0xMiden/miden-base/pull/2131)).

Expand Down
213 changes: 181 additions & 32 deletions crates/miden-lib/asm/kernels/transaction/lib/account.masm
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use.$kernel::account_id
use.$kernel::asset_vault
use.$kernel::constants
use.$kernel::memory

use.std::collections::smt
use.std::collections::sorted_array
use.std::crypto::hashes::rpo
use.std::mem
use.std::word
Expand All @@ -30,8 +30,11 @@ const.ERR_ACCOUNT_PROC_INDEX_OUT_OF_BOUNDS="provided procedure index is out of b

const.ERR_ACCOUNT_PROC_NOT_AUTH_PROC="account procedure is not the authentication procedure; some procedures (e.g. `incr_nonce`) can be called only from the authentication procedure"

# TODO(named_slots): Remove along with index APIs.
const.ERR_ACCOUNT_STORAGE_SLOT_INDEX_OUT_OF_BOUNDS="provided storage slot index is out of bounds"

const.ERR_ACCOUNT_ID_UNKNOWN_STORAGE_SLOT_NAME="storage slot with the provided name does not exist"

const.ERR_FAUCET_INVALID_STORAGE_OFFSET="storage offset is invalid for a faucet account (0 is prohibited as it is the reserved data slot for faucets)"

const.ERR_ACCOUNT_CODE_COMMITMENT_MISMATCH="computed account code commitment does not match recorded account code commitment"
Expand Down Expand Up @@ -120,6 +123,9 @@ const.ACCOUNT_STORAGE_SLOT_DATA_LENGTH=8
# The number of field elements it takes to store one account procedure.
const.ACCOUNT_PROCEDURE_DATA_LENGTH=8

# The offset of the slot type in the storage slot.
const.ACCOUNT_SLOT_TYPE_OFFSET=1

# EVENTS
# =================================================================================================

Expand Down Expand Up @@ -476,7 +482,7 @@ export.set_item
# => [index, VALUE]

# get storage slot type
dup exec.get_storage_slot_type
dup exec.get_storage_slot_type_by_index
# => [storage_slot_type, index, VALUE]

# check if type == slot
Expand Down Expand Up @@ -583,7 +589,7 @@ export.set_map_item.12
# => [index, KEY, NEW_VALUE, OLD_ROOT, ...]

# check if storage type is map
exec.get_storage_slot_type
exec.get_storage_slot_type_by_index
# => [slot_type, KEY, NEW_VALUE, OLD_ROOT]

# check if slot_type == map
Expand Down Expand Up @@ -671,15 +677,33 @@ end
#!
#! Panics if:
#! - the slot index is out of bounds.
export.get_storage_slot_type
export.get_storage_slot_type_by_index
# check that index is in bounds
dup exec.memory::get_num_storage_slots lt assert.err=ERR_ACCOUNT_STORAGE_SLOT_INDEX_OUT_OF_BOUNDS
# => [index]

exec.memory::get_account_storage_slots_section_ptr
# => [curr_account_storage_slots_section_ptr, index]

exec.memory::get_storage_slot_type
exec.get_storage_slot_type
# => [slot_type]
end

#! Returns the type of the requested storage slot.
#!
#! Inputs: [account_storage_slots_section_ptr, index]
#! Outputs: [slot_type]
#!
#! Where:
#! - index is the location in memory of the storage slot.
#! - slot_type is the type of the storage slot.
export.get_storage_slot_type
# compute storage slot ptr
swap mul.8 add
# => [storage_slot_ptr]

# load the slot type
add.ACCOUNT_SLOT_TYPE_OFFSET mem_load
# => [slot_type]
end

Expand Down Expand Up @@ -1350,7 +1374,7 @@ export.insert_new_storage
sub.1
# => [slot_idx]

dup exec.get_storage_slot_type
dup exec.get_storage_slot_type_by_index
# => [slot_type, slot_idx]

exec.constants::get_storage_slot_type_map eq
Expand Down Expand Up @@ -1482,8 +1506,81 @@ end
#! - index is the index of the item to get.
#! - VALUE is the value of the item.
export.get_item_raw
# TODO(named_slots): pass in name
exec.find_indexed_storage_slot
# => [slot_ptr]

# offset the pointer to point to the VALUE in the slot
add.4
# => [slot_value_ptr]

# load the item from storage
padw movup.4 mem_loadw_be
# => [VALUE]
end

#! Gets an item from the storage slot at the provided index.
#!
#! WARNING: The index must be in bounds.
#!
#! Inputs: [index]
#! Outputs: [VALUE]
#!
#! Where:
#! - storage_slots_ptr is the pointer to the storage slots section.
#! - index is the index of the item to get.
#! - VALUE is the value of the item.
export.get_item_by_index
# get account storage slots section offset
exec.memory::get_account_storage_slots_section_ptr
# => [acct_storage_slots_section_offset, index]

exec.get_item_by_index_raw
# => [VALUE]
end

#! Gets the initial item from the storage slot at the provided index.
#!
#! WARNING: The index must be in bounds.
#!
#! Inputs: [index]
#! Outputs: [VALUE]
#!
#! Where:
#! - storage_slots_ptr is the pointer to the storage slots section.
#! - index is the index of the item to get.
#! - VALUE is the value of the item.
export.get_initial_item_by_index
# get account initial storage slots section offset
exec.memory::get_account_initial_storage_slots_ptr
# => [account_initial_storage_slots_ptr, index]

exec.get_item_by_index_raw
# => [VALUE]
end

#! Gets an item from storage using the provided storage slots pointer and index.
#!
#! WARNING: The index must be in bounds.
#!
#! Inputs: [storage_slots_ptr, index]
#! Outputs: [VALUE]
#!
#! Where:
#! - storage_slots_ptr is the pointer to the storage slots section.
#! - index is the index of the item to get.
#! - VALUE is the value of the item.
proc.get_item_by_index_raw
# get the item from storage
swap mul.8 add padw movup.4 mem_loadw_be
swap mul.8 add
# => [storage_slot_ptr]

# offset the pointer to point to the VALUE in the slot
add.4
# => [slot_value_ptr]

# load the item from storage
padw movup.4 mem_loadw_be
# => [VALUE]
end

Expand All @@ -1503,29 +1600,29 @@ end
#! Panics if:
#! - the requested storage slot type is not map.
proc.get_map_item_raw
emit.ACCOUNT_STORAGE_BEFORE_GET_MAP_ITEM_EVENT
# => [KEY, ROOT, index]

# check storage slot type
dup.8 exec.get_storage_slot_type
# => [slot_type, KEY, ROOT, index]
movup.8 exec.get_storage_slot_type_by_index
# => [slot_type, KEY, ROOT]

# check if storage slot type is map
exec.constants::get_storage_slot_type_map eq
assert.err=ERR_ACCOUNT_READING_MAP_VALUE_FROM_NON_MAP_SLOT
# => [KEY, ROOT, index]

emit.ACCOUNT_STORAGE_BEFORE_GET_MAP_ITEM_EVENT
# => [KEY, ROOT, index]
# => [KEY, ROOT]

# see hash_map_key's docs for why this is done
exec.hash_map_key
# => [HASHED_KEY, ROOT, index]
# => [HASHED_KEY, ROOT]

# fetch the VALUE located under HASHED_KEY in the tree
exec.smt::get
# => [VALUE, ROOT, index]
# => [VALUE, ROOT]

# remove the ROOT from the stack
swapw dropw
# => [VALUE, index]
# => [VALUE]

movup.4 drop
# => [VALUE]
Expand All @@ -1541,32 +1638,84 @@ end
#! - NEW_VALUE is the value to set.
#! - OLD_VALUE is the previous value of the item.
proc.set_item_raw
# get old value from storage
dup movdn.5 exec.get_item
# => [OLD_VALUE, NEW_VALUE, index]

# arrange stack for storage update
swapw movup.8
# => [index, NEW_VALUE, OLD_VALUE]
# TODO(named_slots): pass in name

# get account storage slots section offset
exec.memory::get_account_storage_slots_section_ptr
# => [acct_storage_slots_section_offset, index, NEW_VALUE, OLD_VALUE]
# => [storage_slots_ptr, index, NEW_VALUE]

exec.find_indexed_storage_slot
# => [slot_ptr, NEW_VALUE]

# offset the pointer to point to the VALUE in the slot
add.4 movdn.4
# => [NEW_VALUE, slot_value_ptr]

# update storage
swap mul.8 add mem_storew_be
# => [NEW_VALUE, OLD_VALUE]
# load the item from storage
padw dup.8 mem_loadw_be
# => [OLD_VALUE, NEW_VALUE, slot_value_ptr]

swapw movup.8
# => [slot_value_ptr, NEW_VALUE, OLD_VALUE]

mem_storew_be dropw
# => [OLD_VALUE]

# update the storage commitment dirty flag, indicating that the commitment is outdated
push.1
exec.memory::set_native_account_storage_commitment_dirty_flag
# => [NEW_VALUE, OLD_VALUE]

# drop value
dropw
# => [OLD_VALUE]
end

#! TODO(named_slots): Remove this API.
#!
#! Inputs: [storage_slots_ptr, index]
#! Outputs: [slot_ptr]
proc.find_indexed_storage_slot
# set the suffix to 0
push.0 movup.2
# => [name_id_prefix = index, name_id_suffix = 0, storage_slots_ptr]

movup.2
# => [storage_slots_ptr, name_id_prefix = index, name_id_suffix = 0]

exec.find_storage_slot
# => [slot_ptr]
end

#! Finds the slot identified by the key constructed from the name ID and slot type and returns the
#! pointer to that slot.
#!
#! Inputs: [storage_slots_ptr, name_id_prefix, name_id_suffix]
#! Outputs: [slot_ptr]
#!
#! Where:
#! - storage_slots_ptr is the pointer to the storage slots section.
#! - slot_ptr is the pointer to the resolved storage slot.
#! - name_id_{prefix, suffix} are the prefix and suffix felts of the name identifier, which are
#! the first two felts of the hashed slot name.
proc.find_storage_slot
# construct the start and end pointers of the storage slot section in which we will search
dup exec.memory::get_num_storage_slots mul.8 add
# => [storage_slots_end_ptr, storage_slots_start_ptr, name_id_prefix, name_id_suffix]

# TODO: Check if we can get here if num_storage_slots == 0. If so, return a better error than
# what find_key_value returns.

movdn.3 movdn.2
# => [name_id_prefix, name_id_suffix, storage_slots_start_ptr, storage_slots_end_ptr]

# find the slot whose slot key matches [name_id_prefix, name_id_suffix, 0, 0]
# if the slot key does not exist, this procedure will validate its absence
exec.sorted_array::find_half_key_value
# => [is_slot_found, slot_ptr, storage_slots_start_ptr, storage_slots_end_ptr]

assert.err=ERR_ACCOUNT_ID_UNKNOWN_STORAGE_SLOT_NAME
# => [slot_ptr, storage_slots_start_ptr, storage_slots_end_ptr]

swap.2 drop drop
# => [slot_ptr]
end

#! Returns the procedure root.
#!
#! Inputs: [index]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ proc.update_slot_delta
dup exec.memory::get_native_account_storage_slots_ptr
# => [native_account_storage_slots_section_ptr, slot_idx, slot_idx, RATE, RATE, PERM]

exec.memory::get_storage_slot_type
exec.account::get_storage_slot_type
# => [storage_slot_type, slot_idx, RATE, RATE, PERM]

# check if type == slot
Expand All @@ -170,10 +170,10 @@ end
#! Inputs: [slot_idx, RATE, RATE, PERM]
#! Outputs: [RATE, RATE, PERM]
proc.update_value_slot_delta
dup exec.account::get_item
dup exec.account::get_item_by_index
# => [CURRENT_VALUE, slot_idx, RATE, RATE, PERM]

dup.4 exec.account::get_initial_item
dup.4 exec.account::get_initial_item_by_index
# => [INIT_VALUE, CURRENT_VALUE, slot_idx, RATE, RATE, PERM]

exec.word::test_eq not
Expand Down
14 changes: 0 additions & 14 deletions crates/miden-lib/asm/kernels/transaction/lib/memory.masm
Original file line number Diff line number Diff line change
Expand Up @@ -1358,20 +1358,6 @@ export.set_num_storage_slots
mem_store
end

#! Returns the type of the requested storage slot.
#!
#! Inputs: [account_storage_slots_section_ptr, index]
#! Outputs: [slot_type]
#!
#! Where:
#! - index is the location in memory of the storage slot.
#! - slot_type is the type of the storage slot.
export.get_storage_slot_type
# get storage slot type
swap mul.8 add add.4 mem_load
# => [slot_type]
end

#! Returns the memory pointer to the account storage slots section.
#!
#! Inputs: []
Expand Down
4 changes: 2 additions & 2 deletions crates/miden-lib/asm/kernels/transaction/lib/prologue.masm
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ proc.validate_new_account
# => []

# get the faucet reserved storage data slot type
exec.account::get_faucet_storage_data_slot exec.account::get_storage_slot_type
exec.account::get_faucet_storage_data_slot exec.account::get_storage_slot_type_by_index
# => [slot_type]

# assert the fungible faucet reserved slot type == value
Expand All @@ -347,7 +347,7 @@ proc.validate_new_account
# => []

# get the faucet reserved storage data slot type
exec.account::get_faucet_storage_data_slot exec.account::get_storage_slot_type
exec.account::get_faucet_storage_data_slot exec.account::get_storage_slot_type_by_index
# => [slot_type]

# assert the non-fungible faucet reserved slot type == map
Expand Down
2 changes: 2 additions & 0 deletions crates/miden-lib/src/errors/tx_kernel_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub const ERR_ACCOUNT_ID_SUFFIX_LEAST_SIGNIFICANT_BYTE_MUST_BE_ZERO: MasmError =
pub const ERR_ACCOUNT_ID_SUFFIX_MOST_SIGNIFICANT_BIT_MUST_BE_ZERO: MasmError = MasmError::from_static_str("most significant bit of the account ID suffix must be zero");
/// Error Message: "unknown account storage mode in account ID"
pub const ERR_ACCOUNT_ID_UNKNOWN_STORAGE_MODE: MasmError = MasmError::from_static_str("unknown account storage mode in account ID");
/// Error Message: "storage slot with the provided name does not exist"
pub const ERR_ACCOUNT_ID_UNKNOWN_STORAGE_SLOT_NAME: MasmError = MasmError::from_static_str("storage slot with the provided name does not exist");
/// Error Message: "unknown version in account ID"
pub const ERR_ACCOUNT_ID_UNKNOWN_VERSION: MasmError = MasmError::from_static_str("unknown version in account ID");
/// Error Message: "storage size can only be zero if storage offset is also zero"
Expand Down
Loading