use.std::collections::smt use.std::sys use.kernel::account use.kernel::asset_vault use.kernel::constants use.kernel::faucet use.kernel::memory use.kernel::note use.kernel::tx # NOTE # ================================================================================================= # `exec_kernel_proc` procedure is expected to be invoked using a `syscall` instruction. It makes # # no guarantees about the contents of the `pad` elements shown in the inputs and outputs. It is # # the caller's responsibility to make sure these elements do not contain any meaningful data. # # All other procedures must be invoked using a `dynexec` instruction by their hashes stored in # # the memory. # # ================================================================================================= # ERRORS # ================================================================================================= # For faucets the FAUCET_STORAGE_DATA_SLOT storage slot is reserved and can not be used with set_account_item const.ERR_FAUCET_STORAGE_DATA_SLOT_IS_RESERVED=0x00020000 # The get_fungible_faucet_total_issuance procedure can only be called on a fungible faucet const.ERR_ACCOUNT_TOTAL_ISSUANCE_PROC_CAN_ONLY_BE_CALLED_ON_FUNGIBLE_FAUCET=0x00020001 # Failed to read an account map item from a non-map storage slot const.ERR_ACCOUNT_READING_MAP_VALUE_FROM_NON_MAP_SLOT=0x00020002 # Provided kernel procedure offset is out of bounds const.ERR_KERNEL_PROCEDURE_OFFSET_OUT_OF_BOUNDS=0x00020003 # EVENTS # ================================================================================================= # Event emitted before an asset is added to the account vault. const.ACCOUNT_VAULT_BEFORE_ADD_ASSET_EVENT=131072 # Event emitted after an asset is added to the account vault. const.ACCOUNT_VAULT_AFTER_ADD_ASSET_EVENT=131073 # Event emitted before an asset is removed from the account vault. const.ACCOUNT_VAULT_BEFORE_REMOVE_ASSET_EVENT=131074 # Event emitted after an asset is removed from the account vault. const.ACCOUNT_VAULT_AFTER_REMOVE_ASSET_EVENT=131075 # AUTHENTICATION # ================================================================================================= #! Authenticates that the invocation of a kernel procedure originates from the account context. #! #! Stack: [] #! Output: [storage_offset, storage_size] #! #! Panics if: #! - the invocation of the kernel procedure does not originate from the account context. proc.authenticate_account_origin # get the hash of the caller padw caller # => [CALLER] # assert that the caller is from the user context exec.account::authenticate_procedure # => [storage_offset, storage_size] end # KERNEL PROCEDURES # ================================================================================================= #! Returns the account id. #! #! Stack: [0] #! Output: [acct_id] #! #! Where: #! - acct_id is the account id. export.get_account_id # get the account id exec.account::get_id # => [acct_id, 0] swap drop # => [acct_id] end #! Returns the account nonce. #! #! Stack: [0] #! Output: [nonce] #! #! Where: #! - nonce is the account nonce. export.get_account_nonce # get the account nonce exec.account::get_nonce # => [0, nonce] swap drop # => [nonce] end #! Returns the initial account hash. #! #! Stack: [0, 0, 0, 0] #! Output: [H] #! #! Where: #! - H is the initial account hash. export.get_initial_account_hash # get the initial account hash exec.account::get_initial_hash # => [H, 0, 0, 0, 0] swapw dropw # => [H] end #! Computes and returns the account hash from account data stored in memory. #! #! Stack: [0, 0, 0, 0] #! Output: [ACCT_HASH] #! #! Where: #! - ACCT_HASH is the hash of the account data. export.get_current_account_hash # get the current account hash exec.account::get_current_hash # => [ACCT_HASH, 0, 0, 0, 0] swapw dropw # => [ACCT_HASH] end #! Increments the account nonce by the provided value. #! #! Stack: [value] #! Output: [0] #! #! Where: #! - value is the value to increment the nonce by. #! #! Panics if: #! - the invocation of this procedure does not originate from the native account. #! - the value is greater than 2^32 - 1 export.incr_account_nonce # check that this procedure was executed against the native account exec.memory::assert_native_account # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop drop # => [value] # arrange stack push.0 swap # => [value, 0] # increment the account nonce exec.account::incr_nonce # => [0] end #! Gets an item from the account storage. #! #! Stack: [index, 0, 0, 0] #! Output: [VALUE] #! #! Where: #! - index is the index of the item to get. #! - VALUE is the value of the item. #! #! Panics if: #! - the index is out of bounds. export.get_account_item # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin # => [storage_offset, storage_size, index, 0, 0, 0] # apply offset to storage slot index exec.account::apply_storage_offset # => [index_with_offset, 0, 0, 0] # fetch the account storage item exec.account::get_item # => [VALUE, 0, 0, 0] # organize the stack for return movup.4 drop movup.4 drop movup.4 drop # => [VALUE] end #! Sets an item in the account storage. #! #! Stack: [index, V', 0, 0, 0] #! Output: [R', V] #! #! Where: #! - index is the index of the item to set. #! - V' is the value to set. #! - V is the previous value of the item. #! - R' is the new storage commitment. #! #! Panics if: #! - the index is out of bounds. #! - the invocation of this procedure does not originate from the native account. export.set_account_item # check that this procedure was executed against the native account exec.memory::assert_native_account # if the transaction is being executed against a faucet account then assert # index != FAUCET_STORAGE_DATA_SLOT (reserved slot) dup exec.account::get_faucet_storage_data_slot eq exec.account::get_id exec.account::is_faucet and assertz.err=ERR_FAUCET_STORAGE_DATA_SLOT_IS_RESERVED # => [index, V', 0, 0, 0] # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin # => [storage_offset, storage_size, index, V', 0, 0, 0] # apply offset to storage slot index exec.account::apply_storage_offset # => [index_with_offset, V', 0, 0, 0] # set the account storage item exec.account::set_item # => [R', V, 0, 0, 0] # organize the stack for return movup.8 drop movup.8 drop movup.8 drop # => [R', V] end #! Returns VALUE located under specified KEY in map in specified account storage slot. #! #! Stack: [index, KEY, ...] #! Output: [VALUE, 0] #! #! Where: #! - index is the index of the item to get. #! - VALUE is the value of the item. #! #! Panics if: #! - the index is out of bounds (>255). #! - the requested storage slot type is not map export.get_account_map_item # check if storage type is map dup exec.account::get_storage_slot_type # => [slot_type, index, KEY, ...] # check if type == map exec.constants::get_storage_slot_type_map eq assert.err=ERR_ACCOUNT_READING_MAP_VALUE_FROM_NON_MAP_SLOT # => [index, KEY, ...] # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin # => [storage_offset, storage_size, index, KEY, ...] # apply offset to storage slot index exec.account::apply_storage_offset # => [index_with_offset, KEY, ...] # fetch the account storage item, which is ROOT of the map exec.account::get_item swapw # => [KEY, ROOT ...] # fetch the VALUE located under KEY in the tree exec.smt::get # => [VALUE, ROOT, ...] # prepare the stack for return swapw dropw # => [VALUE, 0] end #! Inserts specified NEW_VALUE under specified KEY in map in specified account storage slot. #! #! Stack: [index, KEY, NEW_VALUE, ...] #! Output: [OLD_MAP_ROOT, OLD_MAP_VALUE, 0] #! #! Where: #! - index is the index of the item to get. #! - NEW_VALUE is the value of the new map item for the respective KEY. #! - OLD_VALUE is the value of the old map item for the respective KEY. #! - KEY is the key of the new item. #! - OLD_MAP_ROOT is the root of the old map before insertion #! - NEW_MAP_ROOT is the root of the new map after insertion. #! #! Panics if: #! - the index is out of bounds (>255). #! - the requested storage slot type is not map #! - the procedure is called from a non-account context #! - the invocation of this procedure does not originate from the native account. export.set_account_map_item.1 # check that this procedure was executed against the native account exec.memory::assert_native_account # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin # => [storage_offset, storage_size, index, KEY, NEW_VALUE, ...] # apply offset to storage slot index exec.account::apply_storage_offset # => [index_with_offset, KEY, NEW_VALUE, ...] # store index for later dup loc_store.0 # => [index, KEY, NEW_VALUE, ...] # fetch the account storage item, which is ROOT of the map exec.account::get_item movdnw.2 # => [KEY, NEW_VALUE, OLD_MAP_ROOT, ...] # set the new map item loc_load.0 exec.account::set_map_item # => [OLD_MAP_ROOT, OLD_VALUE, ...] # organize the stack for return (16 elements) movupw.2 dropw # => [OLD_MAP_ROOT, OLD_MAP_VALUE, 0, ...] end #! Sets the code of the account the transaction is being executed against. #! This procedure can only be executed on regular accounts with updatable code. Otherwise, this #! procedure fails. #! #! Stack: [CODE_COMMITMENT] #! Output: [0, 0, 0, 0] #! #! Where: #! - CODE_COMMITMENT is the hash of the code to set. #! #! Panics if: #! - the invocation of this procedure does not originate from the native account. export.set_account_code # check that this procedure was executed against the native account exec.memory::assert_native_account # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop drop # => [CODE_COMMITMENT] # arrange stack padw swapw # => [CODE_COMMITMENT, 0, 0, 0, 0] # set the account code exec.account::set_code # => [0, 0, 0, 0] end #! Returns the balance of a fungible asset associated with a faucet_id. #! #! Stack: [faucet_id] #! Output: [balance] #! #! Where: #! - faucet_id is the faucet id of the fungible asset of interest. #! - balance is the vault balance of the fungible asset. #! #! Panics if: #! - the asset is not a fungible asset. export.account_vault_get_balance # get the vault root exec.memory::get_acct_vault_root_ptr swap # => [faucet_id, acct_vault_root_ptr] # get the asset balance exec.asset_vault::get_balance # => [balance] end #! Returns a boolean indicating whether the non-fungible asset is present in the vault. #! #! Stack: [ASSET] #! Output: [has_asset, 0, 0, 0] #! #! Where: #! - ASSET is the non-fungible asset of interest #! - has_asset is a boolean indicating whether the account vault has the asset of interest #! #! Panics if: #! - the ASSET is a fungible asset. export.account_vault_has_non_fungible_asset # arrange stack and get the vault root push.0 movdn.4 push.0 movdn.4 push.0 movdn.4 exec.memory::get_acct_vault_root_ptr movdn.4 # => [ASSET, 0, 0, 0] # check if the account vault has the non-fungible asset exec.asset_vault::has_non_fungible_asset # => [has_asset, 0, 0, 0] end #! Add the specified asset to the vault. #! #! Stack: [ASSET] #! Output: [ASSET'] #! #! Where: #! - ASSET is the asset to add to the vault. #! - ASSET' final asset in the account vault defined as follows: #! - If ASSET is a non-fungible asset, then ASSET' is the same as ASSET. #! - If ASSET is a fungible asset, then ASSET' is the total fungible asset in the account vault #! after ASSET was added to it. #! #! Panics if: #! - the asset is not valid. #! - the total value of two fungible assets is greater than or equal to 2^63. #! - the vault already contains the same non-fungible asset. #! - the invocation of this procedure does not originate from the native account. export.account_vault_add_asset # check that this procedure was executed against the native account exec.memory::assert_native_account # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop drop # => [ASSET] push.19891 drop # TODO: remove line, see miden-vm/#1122 emit.ACCOUNT_VAULT_BEFORE_ADD_ASSET_EVENT # => [ASSET] # duplicate the ASSET to be able to emit an event after an asset is being added dupw # => [ASSET, ASSET] # fetch the vault root exec.memory::get_acct_vault_root_ptr movdn.4 # => [ASSET, acct_vault_root_ptr, ASSET] # add the asset to the account vault exec.asset_vault::add_asset # => [ASSET', ASSET] # emit event to signal that an asset is being added to the account vault swapw push.21383 drop # TODO: remove line, see miden-vm/#1122 emit.ACCOUNT_VAULT_AFTER_ADD_ASSET_EVENT dropw # => [ASSET'] end #! Remove the specified asset from the vault. #! #! Stack: [ASSET] #! Output: [ASSET] #! #! Where: #! - ASSET is the asset to remove from the vault. #! #! Panics if: #! - the fungible asset is not found in the vault. #! - the amount of the fungible asset in the vault is less than the amount to be removed. #! - the non-fungible asset is not found in the vault. #! - the invocation of this procedure does not originate from the native account. export.account_vault_remove_asset # check that this procedure was executed against the native account exec.memory::assert_native_account # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop drop # => [ASSET] push.20071 drop # TODO: remove line, see miden-vm/#1122 emit.ACCOUNT_VAULT_BEFORE_REMOVE_ASSET_EVENT # => [ASSET] # fetch the vault root exec.memory::get_acct_vault_root_ptr movdn.4 # => [ASSET, acct_vault_root_ptr] # remove the asset from the account vault exec.asset_vault::remove_asset # => [ASSET] # emit event to signal that an asset is being removed from the account vault push.20149 drop # TODO: remove line, see miden-vm/#1122 emit.ACCOUNT_VAULT_AFTER_REMOVE_ASSET_EVENT # => [ASSET] end #! Returns the number of assets and the assets hash of the note currently being processed. #! #! Inputs: [0, 0, 0, 0, 0] #! Outputs: [ASSETS_HASH, num_assets] #! #! Where: #! - num_assets is the number of assets in the note currently being processed. #! - ASSETS_HASH is the assets hash of the note currently being processed. #! #! Panics if: #! - a note is not being processed. export.get_note_assets_info # get the assets info exec.note::get_assets_info # => [ASSETS_HASH, num_assets, 0, 0, 0, 0, 0] # organize the stack for return movup.5 drop movup.5 drop movup.5 drop movup.5 drop movup.5 drop # => [ASSETS_HASH, num_assets] end #! Returns the current note's inputs hash. #! #! Inputs: [EMPTY_WORD] #! Outputs: [NOTE_INPUTS_HASH] #! #! Where: #! - NOTE_INPUTS_HASH is the current note's inputs hash. export.get_note_inputs_hash exec.note::get_note_inputs_hash # => [NOTE_INPUTS_HASH, EMPTY_WORD] swapw dropw # => [NOTE_INPUTS_HASH] end #! Returns the sender of the note currently being processed. #! #! Inputs: [0] #! Outputs: [sender] #! #! Where: #! - sender is the sender of the note currently being processed. #! #! Panics if: #! - a note is not being processed. export.get_note_sender exec.note::get_sender swap drop # => [sender] end #! Returns the block number of the last known block at the time of transaction execution. #! #! Inputs: [0] #! Outputs: [num] #! #! Where: #! - num is the last known block number. export.get_block_number # get the block number exec.tx::get_block_number # => [num, 0] # organize the stack for return swap drop # => [num] end #! Returns the block hash of the reference block. #! #! Stack: [EMPTY_WORD] #! Output: [BLOCK_HASH] #! #! Where: #! - BLOCK_HASH is the reference block for the transaction execution. export.get_block_hash dropw exec.tx::get_block_hash # => [BLOCK_HASH] end #! Returns the input notes commitment. #! #! This is computed as a sequential hash of `(NULLIFIER, EMPTY_WORD_OR_NOTE_HASH)` over all input notes. The #! data `EMPTY_WORD_OR_NOTE_HASH` functions as a flag, if the value is set to zero, then the notes are #! authenticated by the transaction kernel. If the value is non-zero, then note authentication will #! be delayed to the batch/block kernel. The delayed authentication allows a transaction to consume a #! public note that is not yet included to a block. #! #! Inputs: [0, 0, 0, 0] #! Outputs: [INPUT_NOTES_COMMITMENT] #! #! Where: #! - INPUT_NOTES_COMMITMENT is the input notes commitment hash. export.get_input_notes_commitment exec.tx::get_input_notes_commitment # => [COM, 0, 0, 0, 0] swapw dropw # => [COM] end #! Returns the output notes hash. This is computed as a sequential hash of (note_id, note_metadata) #! tuples over all output notes. #! #! Inputs: [0, 0, 0, 0] #! Outputs: [COM] #! #! Where: #! - COM is the output notes hash. export.get_output_notes_hash # get the output notes hash exec.tx::get_output_notes_hash # => [COM, 0, 0, 0, 0] # organize the stack for return swapw dropw # => [COM] end #! Creates a new note and returns the index of the note. #! #! Inputs: [tag, aux, note_type, execution_hint, RECIPIENT, pad(4)] #! Outputs: [note_idx, pad(15)] #! #! Where: #! - tag is the tag to be included in the note. #! - aux is the auxiliary metadata to be included in the note. #! - note_type is the note storage type. #! - execution_hint is the note execution hint tag and payload. #! - RECIPIENT is the recipient of the note. #! - note_idx is the index of the crated note. #! #! Panics if: #! - the procedure is called from a non-account context. #! - the invocation of this procedure does not originate from the native account. export.create_note # check that this procedure was executed against the native account exec.memory::assert_native_account # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop drop # => [tag, aux, note_type, execution_hint, RECIPIENT, pad(8)] exec.tx::create_note # => [note_idx, pad(15)] end #! Adds the ASSET to the note specified by the index. #! #! Inputs: [note_idx, ASSET, pad(7)] #! Outputs: [note_idx, ASSET, pad(11)] #! #! Where: #! - note_idx is the index of the the note to which the asset is added. #! - ASSET can be a fungible or non-fungible asset. #! #! Panics if: #! - the procedure is called from a non-account context. #! - the invocation of this procedure does not originate from the native account. export.add_asset_to_note # check that this procedure was executed against the native account exec.memory::assert_native_account # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop drop # => [note_idx, ASSET] # duplicate the asset word to be able to return it movdn.4 dupw movup.8 # => [note_idx, ASSET, ASSET] exec.tx::add_asset_to_note # => [note_idx, ASSET] end #! Returns a commitment to the account vault the transaction is being executed against. #! #! Stack: [0, 0, 0, 0] #! Outputs: [COM] #! #! Where: #! - COM is the commitment to the account vault. export.get_account_vault_commitment # fetch the account vault root exec.memory::get_acct_vault_root # => [COM, 0, 0, 0, 0] # organize the stack for return swapw dropw # => [COM] end #! Mint an asset from the faucet the transaction is being executed against. #! #! Stack: [ASSET] #! Outputs: [ASSET] #! #! Where: #! - ASSET is the asset that was minted. #! #! Panics if: #! - the transaction is not being executed against a faucet. #! - the invocation of this procedure does not originate from the native account. #! - the asset being minted is not associated with the faucet the transaction is being executed #! against. #! - the asset is not well formed. #! - For fungible faucets: #! - if the total issuance after minting is greater than the maximum amount allowed. #! - For non-fungible faucets: #! - if the non-fungible asset being minted already exists. export.mint_asset # check that this procedure was executed against the native account exec.memory::assert_native_account # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop drop # => [ASSET] # mint the asset exec.faucet::mint # => [ASSET] end #! Burn an asset from the faucet the transaction is being executed against. #! #! Stack: [ASSET] #! Outputs: [ASSET] #! #! Where: #! - ASSET is the asset that was burned. #! #! Panics if: #! - the transaction is not being executed against a faucet. #! - the invocation of this procedure does not originate from the native account. #! - the asset being burned is not associated with the faucet the transaction is being executed #! against. #! - the asset is not well formed. #! - For fungible faucets: #! - if the amount being burned is greater than the total input to the transaction. #! - For non-fungible faucets: #! - if the non-fungible asset being burned does not exist or was not provided as input to the #! transaction via a note or the accounts vault. export.burn_asset # check that this procedure was executed against the native account exec.memory::assert_native_account # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop drop # => [ASSET] # burn the asset exec.faucet::burn # => [ASSET] end #! Returns the total issuance of the fungible faucet the transaction is being executed against. #! #! Stack: [0] #! Outputs: [total_issuance] #! #! Where: #! - total_issuance is the total issuance of the fungible faucet the transaction is being executed #! against. #! #! Panics if: #! - the transaction is not being executed against a fungible faucet. export.get_fungible_faucet_total_issuance # assert that we are executing a transaction against a fungible faucet (access checks) exec.account::get_id exec.account::is_fungible_faucet assert.err=ERR_ACCOUNT_TOTAL_ISSUANCE_PROC_CAN_ONLY_BE_CALLED_ON_FUNGIBLE_FAUCET # => [0] # get the total issuance exec.faucet::get_total_issuance # => [total_issuance] # drop the padding swap drop # => [] end #! Returns the serial number of the note currently being processed. #! #! Inputs: [] #! Outputs: [SERIAL_NUMBER] #! #! Where: #! - SERIAL_NUMBER is the serial number of the note currently being processed. #! #! Panics if: #! - no note is not being processed. export.get_note_serial_number exec.note::get_serial_number # => [SERIAL_NUMBER] # drop the padding swapw dropw # => [SERIAL_NUMBER] end #! Tells the transaction kernel that we are about to execute a procedure on a foreign account. #! #! Checks whether the current foreign account was already loaded to the memory, and loads it if not. #! Moves the account pointer to the currently accessing foreign account. #! #! Inputs: #! Operand stack: [foreign_account_id, pad(11)] #! Advice map: { #! FOREIGN_ACCOUNT_ID: [[foreign_account_id, 0, 0, account_nonce], VAULT_ROOT, STORAGE_ROOT, CODE_ROOT], #! STORAGE_ROOT: [[STORAGE_SLOT_DATA]], #! CODE_ROOT: [num_procs, [ACCOUNT_PROCEDURE_DATA]] #! } #! Outputs: #! Operand stack: [] #! #! Where: #! - foreign_account_id is the ID of the foreign account whose procedure is going to be executed. #! - FOREIGN_ACCOUNT_ID is the word constructed from the foreign_account_id as follows: #! [foreign_account_id, 0, 0, 0]. #! - account_nonce is the nonce of the foreign account. #! - VAULT_ROOT is the commitment of the foreign account's vault. #! - STORAGE_ROOT is the commitment of the foreign account's storage. #! - STORAGE_SLOT_DATA is the data contained in the storage slot which is constructed as follows: #! [SLOT_VALUE, slot_type, 0, 0, 0] #! - CODE_ROOT is the commitment of the foreign account's code. #! - ACCOUNT_PROCEDURE_DATA is the information about account procedure which is constructed as #! follows: [PROCEDURE_MAST_ROOT, storage_offset, 0, 0, 0] #! #! Panics if: #! - the current context is not a native context. export.start_foreign_context # check that this procedure was executed against the native account exec.memory::assert_native_account # OS => [foreign_account_id] # get the memory address and a flag whether this account was already loaded. exec.account::get_foreign_account_ptr # OS => [was_loaded, ptr, foreign_account_id] if.true exec.memory::set_current_account_data_ptr drop # OS => [] else exec.memory::set_current_account_data_ptr # OS => [foreign_account_id] # construct the word with account ID to load the core account data from the advice map push.0.0.0 # OS => [0, 0, 0, foreign_account_id] # move the core account data to the advice stack adv.push_mapval # OS => [0, 0, 0, foreign_account_id] # AS => [[foreign_account_id, 0, 0, account_nonce], VAULT_ROOT, STORAGE_ROOT, CODE_ROOT] # store the id and nonce of the foreign account to the memory dropw adv_loadw exec.memory::set_acct_id_and_nonce dropw # OS => [] # AS => [VAULT_ROOT, STORAGE_ROOT, CODE_ROOT] # store the vault root of the foreign account to the memory adv_loadw exec.memory::set_acct_vault_root dropw # OS => [] # AS => [STORAGE_ROOT, CODE_ROOT] # move the storage root and the code root to the operand stack adv_loadw padw adv_loadw # OS => [CODE_ROOT, STORAGE_ROOT] # AS => [] # store the code root into the memory exec.memory::set_acct_code_commitment # OS => [CODE_ROOT, STORAGE_ROOT] # AS => [] # save the account procedure data into the memory exec.account::save_account_procedure_data # OS => [STORAGE_ROOT] # AS => [] # store the storage root to the memory exec.memory::set_acct_storage_commitment # OS => [STORAGE_ROOT] # AS => [] # save the storage slots data into the memory exec.account::save_account_storage_data # OS => [] # AS => [] end # make sure that the state of the loaded foreign account corresponds to this commitment in the # account database exec.account::validate_current_foreign_account # => [] end #! Tells the transaction kernel that we are done executing a procedure on a foreign account. #! #! Inputs: [...] #! Outputs: [...] #! #! Panics if: #! - the current context is a native context. export.end_foreign_context exec.memory::set_current_account_data_ptr_to_native_account end #! Updates the transaction expiration time delta. #! Once set, the delta can be decreased but not increased. #! #! The input block height delta is added to the reference block in order to output an upper limit #! up until which the transaction will be considered valid (not expired). #! #! Inputs: [block_height_delta, ...] #! Output: [...] #! #! Where: #! - block_height_delta is the desired expiration time delta (1 to 0xFFFF). export.update_expiration_block_num exec.tx::update_expiration_block_num end #! Gets the transaction expiration delta. #! #! Inputs: [...] #! Output: [block_height_delta, ...] #! #! Where: #! - block_height_delta is the stored expiration time delta (1 to 0xFFFF). export.get_expiration_delta exec.tx::get_expiration_delta end #! Executes a kernel procedure specified by its offset. #! #! Inputs: [procedure_offset, , ] #! Outputs: [, ] #! #! Where: #! - procedure_offset is an offset of the kernel procedure, specified in the #! `miden/kernel_proc_offsets.masm` file. #! - procedure_inputs are inputs of the procedure to be executed, which is specified by the #! procedure_offset. Note that the length of this inputs cannot exceed 15 elements, since the #! first element on the stack will be occupied by the memory pointer to the procedure hash. #! - procedure_outputs are the outputs of the procedure to be executed. #! #! Panics if: #! - the provided procedure offset exceeds the number of kernel procedures. export.exec_kernel_proc # check that the provided procedure offset is within expected bounds dup exec.memory::get_num_kernel_procedures lt assert.err=ERR_KERNEL_PROCEDURE_OFFSET_OUT_OF_BOUNDS # => [procedure_offset, , ] # compute the memory pointer at which desired procedure is stored exec.memory::get_kernel_procedures_ptr add # => [procedure_pointer, , ] # execute loaded procedure dynexec # => [, ] exec.sys::truncate_stack end