Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move duplicate procedures to shared util modules #1070

Merged
merged 5 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
- Made `AccountIdError` public (#1067).
- Made `BasicFungibleFaucet::MAX_DECIMALS` public (#1063).
- [BREAKING] Removed `miden-tx-prover` crate and created `miden-proving-service` and `miden-remote-provers` (#1047).
- Deduplicate `masm` procedures across kernel and miden lib to a shared `util` module (#1070).

## 0.6.2 (2024-11-20)

Expand Down
235 changes: 17 additions & 218 deletions miden-lib/asm/kernels/transaction/lib/account.masm
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use.std::collections::smt
use.std::crypto::hashes::rpo
use.std::mem

use.kernel::util::account_id
use.kernel::constants
use.kernel::memory

Expand All @@ -12,9 +13,6 @@ use.kernel::memory
# Account nonce cannot be increased by a greater than u32 value
const.ERR_ACCOUNT_NONCE_INCREASE_MUST_BE_U32=0x00020004

# Least significant byte of the account ID suffix must be zero.
const.ERR_ACCOUNT_ID_LEAST_SIGNIFICANT_BYTE_MUST_BE_ZERO=0x00020005

# Account code must be updatable for it to be possible to set new code
const.ERR_ACCOUNT_CODE_IS_NOT_UPDATABLE=0x00020006

Expand Down Expand Up @@ -117,20 +115,6 @@ const.NON_FUNGIBLE_FAUCET_ACCOUNT=0x30 # 0b11_0000
# Bit pattern for a faucet account, after the account type mask has been applied.
const.FAUCET_ACCOUNT=0x20 # 0b10_0000

# The maximum number of account interface procedures.
const.MAX_NUM_PROCEDURES=256

# The account storage slot at which faucet data is stored.
# Fungible faucet: The faucet data consists of [0, 0, 0, total_issuance]
# Non-fungible faucet: The faucet data consists of SMT root containing minted non-fungible assets.
const.FAUCET_STORAGE_DATA_SLOT=0

# The maximum storage slot index
const.MAX_STORAGE_SLOT_INDEX=254

# The maximum number of account storage slots.
const.MAX_NUM_STORAGE_SLOTS=MAX_STORAGE_SLOT_INDEX+1

# Depth of the account database tree.
const.ACCOUNT_TREE_DEPTH=64

Expand Down Expand Up @@ -174,9 +158,7 @@ const.ACCOUNT_PUSH_PROCEDURE_INDEX_EVENT=131082
#!
#! Where:
#! - faucet_storage_data_slot is the account storage slot at which faucet data is stored.
export.get_faucet_storage_data_slot
push.FAUCET_STORAGE_DATA_SLOT
end
export.::kernel::util::account_id::get_faucet_storage_data_slot

#! Returns the maximum number of account storage slots.
#!
Expand All @@ -185,9 +167,7 @@ end
#!
#! Where:
#! - max_num_storage_slots is the maximum number of account storage slots.
export.get_max_num_storage_slots
push.MAX_NUM_STORAGE_SLOTS
end
export.::kernel::util::account_id::get_max_num_storage_slots

#! Returns the maximum number of account interface procedures.
#!
Expand All @@ -196,9 +176,7 @@ end
#!
#! Where:
#! - max_num_procedures is the maximum number of account interface procedures.
export.get_max_num_procedures
push.MAX_NUM_PROCEDURES
end
export.::kernel::util::account_id::get_max_num_procedures

# PROCEDURES
# =================================================================================================
Expand Down Expand Up @@ -282,10 +260,7 @@ export.memory::get_init_acct_hash->get_initial_hash
#! Where:
#! - acct_id_prefix is the prefix of the account ID.
#! - is_fungible_faucet is a boolean indicating whether the account is a fungible faucet.
export.is_fungible_faucet
exec.type push.FUNGIBLE_FAUCET_ACCOUNT eq
# => [is_fungible_faucet]
end
export.::kernel::util::account_id::is_fungible_faucet

#! Returns a boolean indicating whether the account is a non-fungible faucet.
#!
Expand All @@ -295,10 +270,7 @@ end
#! Where:
#! - acct_id_prefix is the prefix of the account ID.
#! - is_non_fungible_faucet is a boolean indicating whether the account is a non-fungible faucet.
export.is_non_fungible_faucet
exec.type push.NON_FUNGIBLE_FAUCET_ACCOUNT eq
# => [is_non_fungible_faucet]
end
export.::kernel::util::account_id::is_non_fungible_faucet

#! Returns a boolean indicating whether the account is a faucet.
#!
Expand All @@ -308,10 +280,7 @@ end
#! Where:
#! - acct_id_prefix is the prefix of the account ID.
#! - is_faucet is a boolean indicating whether the account is a faucet.
export.is_faucet
u32split drop push.FAUCET_ACCOUNT u32and eq.0 not
# => [is_faucet]
end
export.::kernel::util::account_id::is_faucet

#! Returns a boolean indicating whether the account is a regular updatable account.
#!
Expand All @@ -322,10 +291,7 @@ end
#! - acct_id_prefix is the prefix of the account ID.
#! - is_updatable_account is a boolean indicating whether the account is a regular updatable
#! account.
export.is_updatable_account
exec.type push.REGULAR_ACCOUNT_UPDATABLE_CODE eq
# => [is_updatable_account]
end
export.::kernel::util::account_id::is_updatable_account

#! Returns a boolean indicating whether the account is a regular immutable account.
#!
Expand All @@ -336,10 +302,7 @@ end
#! - acct_id_prefix is the prefix of the account ID.
#! - is_immutable_account is a boolean indicating whether the account is a regular immutable
#! account.
export.is_immutable_account
exec.type push.REGULAR_ACCOUNT_IMMUTABLE_CODE eq
# => [is_immutable_account]
end
export.::kernel::util::account_id::is_immutable_account

#! Returns a boolean indicating whether the given account_ids are equal.
#!
Expand All @@ -350,14 +313,7 @@ end
#! - acct_id_{prefix,suffix} are the prefix and suffix felts of an account ID.
#! - other_acct_id_{prefix,suffix} are the prefix and suffix felts of the other account ID to compare against.
#! - is_id_equal is a boolean indicating whether the account IDs are equal.
export.is_id_eq
movup.2 eq
# => [is_prefix_equal, acct_id_suffix, other_acct_id_suffix]
movdn.2 eq
# => [is_suffix_equal, is_prefix_equal]
and
# => [is_id_equal]
end
export.::kernel::util::account_id::is_id_eq

#! Validates an account ID. Note that this does not validate anything about the account type,
#! since any bit pattern is a valid account type.
Expand All @@ -373,43 +329,7 @@ end
#! - account_id_prefix does not contain either the public or private storage mode.
#! - account_id_suffix contains an anchor epoch that is greater or equal to 2^16.
#! - account_id_suffix does not have its lower 8 bits set to zero.
export.validate_id
# Validate version in prefix. For now only version 0 is supported.
# ---------------------------------------------------------------------------------------------

dup exec.id_version
# => [id_version, account_id_prefix, account_id_suffix]
assertz.err=ERR_ACCOUNT_ID_UNKNOWN_VERSION
# => [account_id_prefix, account_id_suffix]

# Validate storage mode in prefix.
# ---------------------------------------------------------------------------------------------

u32split drop
# => [account_id_prefix_lo, account_id_suffix]
u32and.ACCOUNT_ID_STORAGE_MODE_MASK_U32 dup eq.ACCOUNT_ID_STORAGE_MODE_PRIVATE_U32
# => [is_private_storage_mode, id_storage_mode_masked, account_id_suffix]
swap eq.ACCOUNT_ID_STORAGE_MODE_PUBLIC_U32
# => [is_public_storage_mode, is_private_storage_mode, account_id_suffix]
or assert.err=ERR_ACCOUNT_ID_UNKNOWN_STORAGE_MODE
# => [account_id_suffix]

# Validate anchor epoch is less than u16::MAX (0xffff) in suffix.
# ---------------------------------------------------------------------------------------------

dup exec.id_anchor_epoch
# => [anchor_epoch, account_id_suffix]
lt.0xffff assert.err=ERR_ACCOUNT_ID_EPOCH_MUST_BE_LESS_THAN_U16_MAX
# => [account_id_suffix]

# Validate lower 8 bits of suffix are zero.
# ---------------------------------------------------------------------------------------------

u32split drop u32and.0xff eq.0
# => [is_least_significant_byte_zero]
assert.err=ERR_ACCOUNT_ID_LEAST_SIGNIFICANT_BYTE_MUST_BE_ZERO
# => []
end
export.::kernel::util::account_id::validate_id

#! Sets the code of the account the transaction is being executed against.
#!
Expand Down Expand Up @@ -448,15 +368,7 @@ end
#!
#! Panics if:
#! - the computed index is out of bounds
export.apply_storage_offset
# offset index
dup movup.3 add
# => [offset_slot_index, storage_offset, storage_size]

# verify that slot_index is in bounds
movdn.2 add dup.1 gt assert.err=ERR_STORAGE_SLOT_INDEX_OUT_OF_BOUNDS
# => [offset_slot_index]
end
export.::kernel::util::account_id::apply_storage_offset

#! Validates all account procedures storage metadata by checking that:
#! - All storage offsets and sizes are in bounds.
Expand Down Expand Up @@ -783,7 +695,7 @@ export.validate_seed
# => [0, 0, account_id_prefix, account_id_suffix]

# get the anchor block's number
dup.3 exec.id_anchor_block_num
dup.3 exec.account_id::id_anchor_block_num
# => [anchor_block_num, 0, 0, account_id_prefix, account_id_suffix]

exec.memory::get_chain_mmr_ptr swap
Expand Down Expand Up @@ -847,112 +759,18 @@ export.validate_seed
# => [account_id_suffix, hashed_account_id_prefix, hashed_account_id_suffix, account_id_prefix]

# extract anchor epoch from ID of the new account
dup movdn.4 exec.id_anchor_epoch
dup movdn.4 exec.account_id::id_anchor_epoch
# => [anchor_epoch, hashed_account_id_prefix, hashed_account_id_suffix, account_id_prefix, account_id_suffix]

# shape suffix of hashed id, adding the anchor epoch and setting the lower 8 bits to zero
movup.2 exec.shape_suffix swap
movup.2 exec.account_id::shape_suffix swap
# => [hashed_account_id_prefix, hashed_account_id_suffix, account_id_prefix, account_id_suffix]

# assert the account ID matches the account ID of the new account
exec.is_id_eq assert.err=ERR_ACCOUNT_SEED_ANCHOR_BLOCK_HASH_DIGEST_MISMATCH
# => []
end

#! Shapes the suffix so it meets the requirements of the account ID, by overwriting the
#! upper 16 bits with the anchor epoch and setting the lower 8 bits to zero.
#!
#! Inputs: [seed_digest_suffix, anchor_epoch]
#! Outputs: [account_id_suffix]
#!
#! Where:
#! - seed_digest_suffix is the suffix of the digest that should be shaped into the suffix
#! of an account ID.
#! - account_id_suffix is the suffix of an account ID.
#! - anchor_epoch is the epoch number to which this account ID is anchored.
proc.shape_suffix
u32split
# => [seed_digest_suffix_hi, seed_digest_suffix_lo, anchor_epoch]

# clear epoch bits in hi part so we can set them later
u32and.0x0000ffff swap
# => [seed_digest_suffix_lo, seed_digest_suffix_hi', anchor_epoch]

# clear lower 8 bits of the lo part
u32and.0xffffff00 swap.2
# => [anchor_epoch, seed_digest_suffix_hi', seed_digest_suffix_lo']

# assert epoch is not 2^16
# this is technically optional as we will compare this id with the provided one for which
# this property was already checked, but since this check is cheap we include it anyway
dup eq.0xffff assertz.err=ERR_ACCOUNT_ID_EPOCH_MUST_BE_LESS_THAN_U16_MAX
# => [anchor_epoch, seed_digest_suffix_hi', seed_digest_suffix_lo']

# shift epoch left by 16 bits and set epoch bits on hi part
u32shl.16 u32or
# => [seed_digest_suffix_hi'', seed_digest_suffix_lo']

# reassemble the suffix by multiplying the hi part with 2^32 and adding the lo part
mul.0x0100000000 add
# => [account_id_suffix]
end

#! Extracts the block number of the anchor block from the suffix of an account ID.
#!
#! Inputs: [account_id_suffix]
#! Outputs: [anchor_block_num]
#!
#! Where:
#! - account_id_suffix is the suffix of an account ID.
#! - anchor_block_num is the number of the block to which this account ID is anchored.
proc.id_anchor_block_num
# extract the upper 32 bits
u32split swap drop
# => [account_id_suffix_hi]

# to get the epoch's block number we would have to multiply the epoch in the account ID by 2^16
# since the epoch is already in the upper 16 bits of the u32, we can simply zero out the
# lower 16 bits to achieve the same result.
u32and.0xffff0000
# => [anchor_block_num]
end

#! Extracts the epoch from the suffix of an account ID.
#!
#! Inputs: [account_id_suffix]
#! Outputs: [anchor_epoch]
#!
#! Where:
#! - account_id_suffix is the suffix of an account ID.
#! - anchor_epoch is the epoch number to which this account ID is anchored.
proc.id_anchor_epoch
# extract the upper 32 bits
u32split swap drop
# => [account_id_suffix_hi]

# shift the upper 16 bits to the right to produce the epoch
u32shr.16
# => [anchor_epoch]
end

#! Extracts the account ID version from the prefix of an account ID.
#!
#! Inputs: [account_id_prefix]
#! Outputs: [id_version]
#!
#! Where:
#! - account_id_prefix is the prefix of an account ID.
#! - id_version is the version number of the ID.
proc.id_version
# extract the lower 32 bits
u32split drop
# => [account_id_prefix_lo]

# mask out the version
u32and.ACCOUNT_VERSION_MASK_U32
# => [id_version]
end

# DATA LOADERS
# =================================================================================================

Expand Down Expand Up @@ -1097,25 +915,6 @@ end
# HELPER PROCEDURES
# =================================================================================================

#! Returns the least significant half of an account ID prefix with the account type bits masked out.
#!
#! The account type can be obtained by comparing this value with the following constants:
#! - REGULAR_ACCOUNT_UPDATABLE_CODE
#! - REGULAR_ACCOUNT_IMMUTABLE_CODE
#! - FUNGIBLE_FAUCET_ACCOUNT
#! - NON_FUNGIBLE_FAUCET_ACCOUNT
#!
#! Inputs: [acct_id_prefix]
#! Outputs: [acct_type]
#!
#! Where:
#! - acct_id_prefix is the prefix of the account ID.
#! - acct_type is the account type.
proc.type
u32split drop push.ACCOUNT_ID_TYPE_MASK_U32 u32and
# => [acct_type]
end

#! Sets an item in the account storage. Doesn't emit any events.
#!
#! Inputs: [index, NEW_VALUE]
Expand Down Expand Up @@ -1233,7 +1032,7 @@ export.get_foreign_account_ptr

# check that the loading of one more account won't exceed the maximum number of the foreign
# accounts which can be loaded.
dup exec.memory::get_max_foreign_account_ptr lte
dup exec.memory::get_max_foreign_account_ptr lte
assert.err=ERR_FOREIGN_ACCOUNT_MAX_NUMBER_EXCEEDED
# => [curr_account_ptr, foreign_account_id_prefix, foreign_account_id_suffix, is_equal_id]

Expand Down Expand Up @@ -1272,4 +1071,4 @@ export.validate_current_foreign_account

# clean the stack
dropw drop drop dropw
end
end
Loading
Loading