use miden::protocol::account_id
use miden::protocol::asset
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_ID_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_NONCE_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_INITIAL_COMMITMENT_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_COMPUTE_COMMITMENT_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_CODE_COMMITMENT_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_INITIAL_STORAGE_COMMITMENT_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_COMPUTE_STORAGE_COMMITMENT_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_INITIAL_VAULT_ROOT_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_VAULT_ROOT_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_ITEM_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_INITIAL_ITEM_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_MAP_ITEM_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_INITIAL_MAP_ITEM_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_ASSET_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_INITIAL_ASSET_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_NUM_PROCEDURES_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_GET_PROCEDURE_ROOT_OFFSET
use miden::protocol::kernel_proc_offsets::ACCOUNT_HAS_PROCEDURE_OFFSET
use miden::core::word
# ACTIVE ACCOUNT PROCEDURES
# =================================================================================================
# ERRORS
# -------------------------------------------------------------------------------------------------
const ERR_VAULT_GET_BALANCE_CAN_ONLY_BE_CALLED_ON_FUNGIBLE_ASSET="get_balance can only be called on a fungible asset"
const ERR_VAULT_HAS_NON_FUNGIBLE_ASSET_PROC_CAN_BE_CALLED_ONLY_WITH_NON_FUNGIBLE_ASSET="the has_non_fungible_asset procedure can only be called on a non-fungible faucet"
# ID AND NONCE
# -------------------------------------------------------------------------------------------------
#! Returns the ID of the active account.
#!
#! Inputs: []
#! Outputs: [account_id_suffix, account_id_prefix]
#!
#! Where:
#! - account_id_{suffix,prefix} are the suffix and prefix felts of the ID of the active account.
#!
#! Invocation: exec
pub proc get_id
# pad the stack
padw padw padw push.0.0
# => [pad(14)]
# push the flag indicating that the ID of the current account was requested
push.0
# => [is_native = 0, pad(14)]
push.ACCOUNT_GET_ID_OFFSET
# => [offset, is_native = 0, pad(14)]
syscall.exec_kernel_proc
# => [account_id_suffix, account_id_prefix, pad(14)]
# clean the stack
swapdw dropw dropw swapw dropw movdn.3 movdn.3 drop drop
# => [account_id_suffix, account_id_prefix]
end
#! Returns the nonce of the active account.
#!
#! This procedure always returns the initial account nonce, as the nonce can only be incremented
#! in the authentication procedure when signing the transaction after all user code has been
#! executed.
#!
#! Inputs: []
#! Outputs: [nonce]
#!
#! Where:
#! - nonce is the active account's nonce.
#!
#! Invocation: exec
pub proc get_nonce
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.ACCOUNT_GET_NONCE_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [nonce, pad(15)]
# clean the stack
swapdw dropw dropw swapw dropw movdn.3 drop drop drop
# => [nonce]
end
# COMMITMENTS
# -------------------------------------------------------------------------------------------------
#! Returns the commitment of the active account at the beginning of the transaction.
#!
#! Inputs: []
#! Outputs: [INIT_COMMITMENT]
#!
#! Where:
#! - INIT_COMMITMENT is the initial account commitment.
#!
#! Invocation: exec
pub proc get_initial_commitment
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.ACCOUNT_GET_INITIAL_COMMITMENT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [INIT_COMMITMENT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [INIT_COMMITMENT]
end
#! Computes and returns commitment to the state of the active account.
#!
#! Inputs: []
#! Outputs: [ACCOUNT_COMMITMENT]
#!
#! Where:
#! - ACCOUNT_COMMITMENT is the commitment of the account data.
#!
#! Invocation: exec
pub proc compute_commitment
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.ACCOUNT_COMPUTE_COMMITMENT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [ACCOUNT_COMMITMENT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [ACCOUNT_COMMITMENT]
end
#! Gets the code commitment of the active account.
#!
#! Notice that the account code cannot be changed during the user code execution, so the code
#! commitment doesn't change during transaction execution: commitment returned by this procedure
#! could be used as both the initial and the current.
#!
#! The commitment to an empty delta is defined as the empty word.
#!
#! During an account-creating transaction (when the initial nonce is 0), this procedure will not
#! return the empty word even if the initial storage commitment and the current storage commitment
#! are identical (storage hasn't changed). This is because the delta for a new account must
#! represent its entire newly created state, and the initial storage in a transaction is
#! initialized to the the storage that the account ID commits to, which may be non-empty. This
#! does not have any consequences other than being inconsistent in this edge case.
#!
#! Inputs: []
#! Outputs: [CODE_COMMITMENT]
#!
#! Where:
#! - CODE_COMMITMENT is the commitment of the account code.
#!
#! Invocation: exec
pub proc get_code_commitment
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.ACCOUNT_GET_CODE_COMMITMENT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [CODE_COMMITMENT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [CODE_COMMITMENT]
end
#! Returns the storage commitment of the active account at the beginning of the transaction.
#!
#! During an account-creating transaction (when the initial nonce is 0), this procedure and
#! compute_storage_commitment will return the same value at the beginning of the transaction
#! (before any note or transaction scripts were executed). Despite that, the account delta may
#! not be empty. See account::compute_delta_commitment for more.
#!
#! Inputs: []
#! Outputs: [INIT_STORAGE_COMMITMENT]
#!
#! Where:
#! - INIT_STORAGE_COMMITMENT is the initial account storage commitment.
#!
#! Invocation: exec
pub proc get_initial_storage_commitment
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.ACCOUNT_GET_INITIAL_STORAGE_COMMITMENT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [INIT_STORAGE_COMMITMENT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [INIT_STORAGE_COMMITMENT]
end
#! Computes the latest storage commitment of the active account.
#!
#! Notice that this procedure always returns the latest commitment, but it doesn't actually always
#! recompute it: recomputation is performed only if the account's storage has been changed,
#! otherwise the cached value is returned.
#!
#! During an account-creating transaction (when the initial nonce is 0), this procedure and
#! get_initial_storage_commitment will return the same value at the beginning of the transaction
#! (before any note or transaction scripts were executed). Despite that, the account delta may
#! not be empty. See account::compute_delta_commitment for more.
#!
#! Inputs: []
#! Outputs: [STORAGE_COMMITMENT]
#!
#! Where:
#! - STORAGE_COMMITMENT is the commitment of the account storage.
#!
#! Invocation: exec
pub proc compute_storage_commitment
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.ACCOUNT_COMPUTE_STORAGE_COMMITMENT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [STORAGE_COMMITMENT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [STORAGE_COMMITMENT]
end
#! Returns the vault root of the active account at the beginning of the transaction.
#!
#! Inputs: []
#! Outputs: [INIT_VAULT_ROOT]
#!
#! Where:
#! - INIT_VAULT_ROOT is the initial account vault root.
#!
#! Invocation: exec
pub proc get_initial_vault_root
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.ACCOUNT_GET_INITIAL_VAULT_ROOT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [INIT_VAULT_ROOT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [INIT_VAULT_ROOT]
end
#! Returns the vault root of the active account.
#!
#! Inputs: []
#! Outputs: [VAULT_ROOT]
#!
#! Where:
#! - VAULT_ROOT is the root of the account vault.
#!
#! Invocation: exec
pub proc get_vault_root
# pad the stack for syscall invocation
padw padw padw push.0.0.0
# => [pad(15)]
push.ACCOUNT_GET_VAULT_ROOT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [VAULT_ROOT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [VAULT_ROOT]
end
# STORAGE
# -------------------------------------------------------------------------------------------------
#! Gets an item from the active account storage.
#!
#! Inputs: [slot_id_suffix, slot_id_prefix]
#! Outputs: [VALUE]
#!
#! Where:
#! - slot_id_{suffix, prefix} are the suffix and prefix felts of the slot identifier, which are
#! the first two felts of the hashed slot name.
#! - VALUE is the value of the item.
#!
#! Panics if:
#! - a slot with the provided slot ID does not exist in account storage.
#!
#! Invocation: exec
pub proc get_item
push.0 movdn.2
# => [slot_id_suffix, slot_id_prefix, 0]
push.ACCOUNT_GET_ITEM_OFFSET
# => [offset, slot_id_suffix, slot_id_prefix, 0]
# pad the stack
padw swapw padw padw swapdw
# => [offset, slot_id_suffix, slot_id_prefix, pad(13)]
syscall.exec_kernel_proc
# => [VALUE, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [VALUE]
end
#! Gets the initial item from the active account storage slot as it was at the beginning of the
#! transaction.
#!
#! Inputs: [slot_id_suffix, slot_id_prefix]
#! Outputs: [INIT_VALUE]
#!
#! Where:
#! - slot_id_{suffix, prefix} are the suffix and prefix felts of the slot identifier, which are
#! the first two felts of the hashed slot name.
#! - INIT_VALUE is the initial value of the item at the beginning of the transaction.
#!
#! Panics if:
#! - a slot with the provided slot ID does not exist in account storage.
#!
#! Invocation: exec
pub proc get_initial_item
push.0 movdn.2
# => [slot_id_suffix, slot_id_prefix, 0]
push.ACCOUNT_GET_INITIAL_ITEM_OFFSET
# => [offset, slot_id_suffix, slot_id_prefix, 0]
# pad the stack
padw swapw padw padw swapdw
# => [offset, slot_id_suffix, slot_id_prefix, pad(13)]
syscall.exec_kernel_proc
# => [INIT_VALUE, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [INIT_VALUE]
end
#! Gets a map item from the active account storage.
#!
#! Inputs: [slot_id_suffix, slot_id_prefix, KEY]
#! Outputs: [VALUE]
#!
#! Where:
#! - slot_id_{suffix, prefix} are the suffix and prefix felts of the slot identifier, which are
#! the first two felts of the hashed slot name.
#! - the slot must point to the root of the storage map.
#! - KEY is the key of the item to get.
#! - VALUE is the value of the item.
#!
#! Panics if:
#! - a slot with the provided slot ID does not exist in account storage.
#! - the slot item at index is not a map.
#!
#! Invocation: exec
pub proc get_map_item
push.ACCOUNT_GET_MAP_ITEM_OFFSET
# => [offset, slot_id_suffix, slot_id_prefix, KEY]
# pad the stack
push.0 movdn.7 padw padw swapdw
# => [offset, slot_id_suffix, slot_id_prefix, KEY, pad(9)]
syscall.exec_kernel_proc
# => [VALUE, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [VALUE]
end
#! Gets the initial VALUE from the active account storage map as it was at the beginning of the
#! transaction.
#!
#! Inputs: [slot_id_suffix, slot_id_prefix, KEY]
#! Outputs: [INIT_VALUE]
#!
#! Where:
#! - slot_id_{suffix, prefix} are the suffix and prefix felts of the slot identifier, which are
#! the first two felts of the hashed slot name.
#! - KEY is the key of the item to get.
#! - INIT_VALUE is the initial value of the item at the beginning of the transaction.
#!
#! Panics if:
#! - a slot with the provided slot ID does not exist in account storage.
#! - the slot item at index is not a map.
#!
#! Invocation: exec
pub proc get_initial_map_item
push.ACCOUNT_GET_INITIAL_MAP_ITEM_OFFSET
# => [offset, slot_id_suffix, slot_id_prefix, KEY]
push.0 movdn.7 padw padw swapdw
# => [offset, slot_id_suffix, slot_id_prefix, KEY, pad(9)]
syscall.exec_kernel_proc
# => [INIT_VALUE, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [INIT_VALUE]
end
# VAULT
# -------------------------------------------------------------------------------------------------
#! Returns the asset associated with the provided asset vault key in the active account's vault.
#!
#! Inputs: [ASSET_KEY]
#! Outputs: [ASSET_VALUE]
#!
#! Where:
#! - ASSET_KEY is the asset vault key of the asset to fetch.
#! - ASSET_VALUE is the value of the asset from the vault, which can be the EMPTY_WORD if it isn't
#! present.
#!
#! Invocation: exec
pub proc get_asset
push.ACCOUNT_GET_ASSET_OFFSET
# => [offset, ASSET_KEY]
# pad the stack
push.0 movdn.5 push.0 movdn.5 push.0 movdn.5
padw padw swapdw
# => [offset, ASSET_KEY, pad(11)]
syscall.exec_kernel_proc
# => [ASSET_VALUE, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [ASSET_VALUE]
end
#! Returns the asset associated with the provided asset vault key in the active account's vault at
#! the beginning of the transaction.
#!
#! Inputs: [ASSET_KEY]
#! Outputs: [ASSET_VALUE]
#!
#! Where:
#! - ASSET_KEY is the asset vault key of the asset to fetch.
#! - ASSET_VALUE is the value of the asset from the vault, which can be the EMPTY_WORD if it isn't
#! present.
#!
#! Invocation: exec
pub proc get_initial_asset
push.ACCOUNT_GET_INITIAL_ASSET_OFFSET
# => [offset, ASSET_KEY]
# pad the stack
push.0 movdn.5 push.0 movdn.5 push.0 movdn.5
padw padw swapdw
# => [offset, ASSET_KEY, pad(11)]
syscall.exec_kernel_proc
# => [ASSET_VALUE, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [ASSET_VALUE]
end
#! Returns the balance of the fungible asset associated with the provided faucet_id in the active
#! account's vault.
#!
#! Inputs: [faucet_id_suffix, faucet_id_prefix]
#! Outputs: [balance]
#!
#! Where:
#! - faucet_id_{suffix,prefix} are the suffix and prefix felts of the faucet ID of the fungible
#! asset of interest.
#! - balance is the vault balance of the fungible asset.
#!
#! Panics if:
#! - the provided faucet ID is not an ID of a fungible faucet.
#!
#! Invocation: exec
pub proc get_balance
# assert that the faucet id is a fungible faucet
dup.1 exec.account_id::is_fungible_faucet
assert.err=ERR_VAULT_GET_BALANCE_CAN_ONLY_BE_CALLED_ON_FUNGIBLE_ASSET
# => [faucet_id_suffix, faucet_id_prefix]
# TODO(callbacks): This should take ASSET_KEY as input to avoid hardcoding the callbacks flag.
push.0
# => [enable_callbacks = 0, faucet_id_suffix, faucet_id_prefix]
exec.asset::create_fungible_key
# => [ASSET_KEY]
exec.get_asset
# => [ASSET_VALUE]
# extract the asset's balance
exec.::miden::protocol::util::asset::fungible_value_into_amount
# => [balance]
end
#! Returns the balance of the fungible asset associated with the provided faucet_id in the active
#! account's vault at the beginning of the transaction.
#!
#! Inputs: [faucet_id_suffix, faucet_id_prefix]
#! Outputs: [init_balance]
#!
#! Where:
#! - faucet_id_{suffix, prefix} are the suffix and prefix felts of the faucet id of the fungible
#! asset of interest.
#! - init_balance is the vault balance of the fungible asset at the beginning of the transaction.
#!
#! Panics if:
#! - the provided faucet ID is not an ID of a fungible faucet.
#!
#! Invocation: exec
pub proc get_initial_balance
# assert that the faucet id is a fungible faucet
dup.1 exec.account_id::is_fungible_faucet
assert.err=ERR_VAULT_GET_BALANCE_CAN_ONLY_BE_CALLED_ON_FUNGIBLE_ASSET
# => [faucet_id_suffix, faucet_id_prefix]
# TODO(callbacks): This should take ASSET_KEY as input to avoid hardcoding the callbacks flag.
push.0
# => [enable_callbacks = 0, faucet_id_suffix, faucet_id_prefix]
exec.asset::create_fungible_key
# => [ASSET_KEY]
exec.get_initial_asset
# => [ASSET_VALUE]
# extract the asset's balance
exec.::miden::protocol::util::asset::fungible_value_into_amount
# => [balance]
end
#! Returns a boolean indicating whether the active account stores an asset with the provided
#! non-fungible asset vault key in its vault.
#!
#! Inputs: [ASSET_KEY]
#! Outputs: [has_asset]
#!
#! Where:
#! - ASSET_KEY is the key of the fungible asset to check.
#! - has_asset is a boolean indicating whether the account vault has the asset.
#!
#! Panics if:
#! - the ASSET_VALUE is a fungible asset.
#!
#! Invocation: exec
pub proc has_non_fungible_asset
# => [faucet_id_prefix, faucet_id_suffix, asset_id_prefix, asset_id_suffix]
# assert that the faucet id is a non-fungible faucet
dup.3 exec.account_id::is_non_fungible_faucet
assert.err=ERR_VAULT_HAS_NON_FUNGIBLE_ASSET_PROC_CAN_BE_CALLED_ONLY_WITH_NON_FUNGIBLE_ASSET
# => [ASSET_KEY]
exec.get_asset
# => [ASSET_VALUE]
# compare with EMPTY_WORD to assess if the asset exists in the vault
exec.word::eqz not
# => [has_asset]
end
#! Returns the number of procedures in the active account.
#!
#! Inputs: []
#! Outputs: [num_procedures]
#!
#! Where:
#! - num_procedures is the number of procedures in the active account.
#!
#! Invocation: exec
pub proc get_num_procedures
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.ACCOUNT_GET_NUM_PROCEDURES_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [num_procedures, pad(15)]
# clean the stack
swap.15 dropw dropw dropw drop drop drop
# => [num_procedures]
end
#! Returns the procedure root for the procedure at the specified index in the active account.
#!
#! Inputs: [index]
#! Outputs: [PROC_ROOT]
#!
#! Where:
#! - index is the index of the procedure.
#! - PROC_ROOT is the hash of the procedure.
#!
#! Panics if:
#! - the procedure index is out of bounds.
#!
#! Invocation: exec
pub proc get_procedure_root
# => [index]
push.0.0 movup.2
push.ACCOUNT_GET_PROCEDURE_ROOT_OFFSET
# => [offset, index, 0, 0]
# pad the stack
padw swapw padw padw swapdw
# => [offset, index, pad(14)]
syscall.exec_kernel_proc
# => [PROC_ROOT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [PROC_ROOT]
end
#! Returns the binary flag indicating whether the procedure with the provided root is available on
#! the active account.
#!
#! Returns 1 if the procedure is available on the active account and 0 otherwise.
#!
#! Inputs: [PROC_ROOT]
#! Outputs: [is_procedure_available]
#!
#! Where:
#! - PROC_ROOT is the hash of the procedure of interest.
#! - is_procedure_available is the binary flag indicating whether the procedure with PROC_ROOT is
#! available on the active account.
#!
#! Invocation: exec
pub proc has_procedure
push.ACCOUNT_HAS_PROCEDURE_OFFSET
# => [offset, PROC_ROOT]
# pad the stack
push.0.0.0 movdn.7 movdn.7 movdn.7 padw padw swapdw
# => [offset, PROC_ROOT, pad(11)]
syscall.exec_kernel_proc
# => [is_procedure_available, pad(15)]
# clean the stack
swapdw dropw dropw swapw dropw movdn.3 drop drop drop
# => [is_procedure_available]
end