From b2b6dbafbd5e7f9c70b206a49cfc68a4ee0ed7e9 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 22 Jul 2024 16:01:34 +0300 Subject: [PATCH 01/11] feat: load kernel to memory, exec syscalls with their hash --- docs/architecture/transactions/contexts.md | 3 +- miden-lib/asm/kernels/transaction/api.masm | 19 + .../asm/kernels/transaction/lib/memory.masm | 384 ++++++++++++++++++ .../asm/kernels/transaction/lib/prologue.masm | 46 ++- miden-lib/asm/miden/account.masm | 47 ++- miden-lib/asm/miden/faucet.masm | 11 +- miden-lib/asm/miden/note.masm | 14 +- miden-lib/asm/miden/tx.masm | 22 +- miden-lib/src/transaction/inputs.rs | 8 +- miden-lib/src/transaction/mod.rs | 32 +- miden-tx/src/verifier/mod.rs | 13 +- 11 files changed, 563 insertions(+), 36 deletions(-) diff --git a/docs/architecture/transactions/contexts.md b/docs/architecture/transactions/contexts.md index 2deca6b55..c37804da3 100644 --- a/docs/architecture/transactions/contexts.md +++ b/docs/architecture/transactions/contexts.md @@ -70,7 +70,8 @@ The [account API](https://github.com/0xPolygonMiden/miden-base/blob/main/miden-l #! Add the specified asset to the vault. #! ... export.add_asset - syscall.account_vault_add_asset + exec.mem::account_vault_add_asset_ptr + syscall.exec_kernel_proc end ``` diff --git a/miden-lib/asm/kernels/transaction/api.masm b/miden-lib/asm/kernels/transaction/api.masm index 515711cf6..7d02c1d46 100644 --- a/miden-lib/asm/kernels/transaction/api.masm +++ b/miden-lib/asm/kernels/transaction/api.masm @@ -676,3 +676,22 @@ export.get_note_serial_number swapw dropw # => [SERIAL_NUMBER] end + +#! Executes a kernel procedure specified by its memory pointer +#! +#! Inputs: [procedure_ptr] +#! Outputs: [*executed_procedure_output*] +#! +#! - procedure_ptr is a pointer to the memory where hash of the desired kernel procedure is stored. +export.exec_kernel_proc + # prepare stack for procedure hash obtaining + padw movup.4 + # => [procedure_ptr, 0, 0, 0, 0] + + # load kernel procedure hash + mem_loadw + # => [KERNEL_PROCEDURE_HASH] + + # execute loaded procedure + dynexec +end diff --git a/miden-lib/asm/kernels/transaction/lib/memory.masm b/miden-lib/asm/kernels/transaction/lib/memory.masm index ae8a4f000..92bc6a233 100644 --- a/miden-lib/asm/kernels/transaction/lib/memory.masm +++ b/miden-lib/asm/kernels/transaction/lib/memory.masm @@ -126,6 +126,43 @@ const.NUM_ACCT_PROCEDURES_PTR=999 # The memory address at which the account procedures section begins const.ACCT_PROCEDURES_SECTION_OFFSET=1000 +# KERNEL DATA +# ------------------------------------------------------------------------------------------------- + +# The memory address at which the hashes of kernel procedures begin. +# TODO: choose the proper memory location for the kernel procedures. +const.KERNEL_PROCEDURES_PTR=1500 + +# The offsets at which hash of the corresponding procedure is stored. +const.GET_ACCOUNT_ID_PTR=KERNEL_PROCEDURES_PTR +const.GET_ACCOUNT_NONCE_PTR=KERNEL_PROCEDURES_PTR+1 +const.GET_INITIAL_ACCOUNT_HASH_PTR=KERNEL_PROCEDURES_PTR+2 +const.GET_CURRENT_ACCOUNT_HASH_PTR=KERNEL_PROCEDURES_PTR+3 +const.INCR_ACCOUNT_NONCE_PTR=KERNEL_PROCEDURES_PTR+4 +const.GET_ACCOUNT_ITEM_PTR=KERNEL_PROCEDURES_PTR+5 +const.SET_ACCOUNT_ITEM_PTR=KERNEL_PROCEDURES_PTR+6 +const.GET_ACCOUNT_MAP_ITEM_PTR=KERNEL_PROCEDURES_PTR+7 +const.SET_ACCOUNT_MAP_ITEM_PTR=KERNEL_PROCEDURES_PTR+8 +const.SET_ACCOUNT_CODE_PTR=KERNEL_PROCEDURES_PTR+9 +const.ACCOUNT_VAULT_GET_BALANCE_PTR=KERNEL_PROCEDURES_PTR+10 +const.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_PTR=KERNEL_PROCEDURES_PTR+11 +const.ACCOUNT_VAULT_ADD_ASSET_PTR=KERNEL_PROCEDURES_PTR+12 +const.ACCOUNT_VAULT_REMOVE_ASSET_PTR=KERNEL_PROCEDURES_PTR+13 +const.GET_NOTE_ASSETS_INFO_PTR=KERNEL_PROCEDURES_PTR+14 +const.GET_NOTE_INPUTS_HASH_PTR=KERNEL_PROCEDURES_PTR+15 +const.GET_NOTE_SENDER_PTR=KERNEL_PROCEDURES_PTR+16 +const.GET_BLOCK_NUMBER_PTR=KERNEL_PROCEDURES_PTR+17 +const.GET_BLOCK_HASH_PTR=KERNEL_PROCEDURES_PTR+18 +const.GET_INPUT_NOTES_COMMITMENT_PTR=KERNEL_PROCEDURES_PTR+19 +const.GET_OUTPUT_NOTES_HASH_PTR=KERNEL_PROCEDURES_PTR+20 +const.CREATE_NOTE_PTR=KERNEL_PROCEDURES_PTR+21 +const.ADD_ASSET_TO_NOTE_PTR=KERNEL_PROCEDURES_PTR+22 +const.GET_ACCOUNT_VAULT_COMMITMENT_PTR=KERNEL_PROCEDURES_PTR+23 +const.MINT_ASSET_PTR=KERNEL_PROCEDURES_PTR+24 +const.BURN_ASSET_PTR=KERNEL_PROCEDURES_PTR+25 +const.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_PTR=KERNEL_PROCEDURES_PTR+26 +const.GET_NOTE_SERIAL_NUMBER_PTR=KERNEL_PROCEDURES_PTR+27 + # INPUT NOTES DATA # ------------------------------------------------------------------------------------------------- @@ -1214,3 +1251,350 @@ export.set_output_note_assets_hash push.OUTPUT_NOTE_ASSETS_HASH_OFFSET add mem_storew end + +# KERNEL DATA +# ------------------------------------------------------------------------------------------------- + +#! Returns a pointer to the memory where hashes of the kernel procedures are stored. +#! +#! Stack: [] +#! Output: [kernel_procs_ptr] +#! +#! Where: +#! - kernel_procs_ptr is the memory address where the hashes of the kernel procedures are stored. +export.get_kernel_procs_ptr + push.KERNEL_PROCEDURES_PTR +end + +#! Returns a pointer to the hash of the `get_account_id` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_account_id` kernel procedure is +#! stored. +export.get_account_id_ptr + push.GET_ACCOUNT_ID_PTR +end + +#! Returns a pointer to the hash of the `get_account_nonce` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_account_nonce` kernel procedure is +#! stored. +export.get_account_nonce_ptr + push.GET_ACCOUNT_NONCE_PTR +end + +#! Returns a pointer to the hash of the `get_initial_account_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_initial_account_hash` kernel +#! procedure is stored. +export.get_initial_account_hash_ptr + push.GET_INITIAL_ACCOUNT_HASH_PTR +end + +#! Returns a pointer to the hash of the `get_current_account_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_current_account_hash` kernel +#! procedure is stored. +export.get_current_account_hash_ptr + push.GET_CURRENT_ACCOUNT_HASH_PTR +end + +#! Returns a pointer to the hash of the `incr_account_nonce` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `incr_account_nonce` kernel procedure is +#! stored. +export.incr_account_nonce_ptr + push.INCR_ACCOUNT_NONCE_PTR +end + +#! Returns a pointer to the hash of the `get_account_item` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_account_item` kernel procedure is +#! stored. +export.get_account_item_ptr + push.GET_ACCOUNT_ITEM_PTR +end + +#! Returns a pointer to the hash of the `set_account_item` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `set_account_item` kernel procedure is +#! stored. +export.set_account_item_ptr + push.SET_ACCOUNT_ITEM_PTR +end + +#! Returns a pointer to the hash of the `get_account_map_item` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_account_map_item` kernel procedure is +#! stored. +export.get_account_map_item_ptr + push.GET_ACCOUNT_MAP_ITEM_PTR +end + +#! Returns a pointer to the hash of the `set_account_map_item` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `set_account_map_item` kernel procedure is +#! stored. +export.set_account_map_item_ptr + push.SET_ACCOUNT_MAP_ITEM_PTR +end + +#! Returns a pointer to the hash of the `set_account_code` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `set_account_code` kernel procedure is +#! stored. +export.set_account_code_item_ptr + push.SET_ACCOUNT_CODE_PTR +end + +#! Returns a pointer to the hash of the `account_vault_get_balance` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `account_vault_get_balance` kernel +#! procedure is stored. +export.account_vault_get_balance_ptr + push.ACCOUNT_VAULT_GET_BALANCE_PTR +end + +#! Returns a pointer to the hash of the `account_vault_has_non_fungible_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `account_vault_has_non_fungible_asset` +#! kernel procedure is stored. +export.account_vault_has_non_fungible_asset_ptr + push.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_PTR +end + +#! Returns a pointer to the hash of the `account_vault_add_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `account_vault_add_asset` kernel procedure +#! is stored. +export.account_vault_add_asset_ptr + push.ACCOUNT_VAULT_ADD_ASSET_PTR +end + +#! Returns a pointer to the hash of the `account_vault_remove_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `account_vault_remove_asset` kernel +#! procedure is stored. +export.account_vault_remove_asset_ptr + push.ACCOUNT_VAULT_REMOVE_ASSET_PTR +end + +#! Returns a pointer to the hash of the `get_note_assets_info` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_note_assets_info` kernel procedure +#! is stored. +export.get_note_assets_info_ptr + push.GET_NOTE_ASSETS_INFO_PTR +end + +#! Returns a pointer to the hash of the `get_note_inputs_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_note_inputs_hash` kernel procedure +#! is stored. +export.get_note_inputs_hash_ptr + push.GET_NOTE_INPUTS_HASH_PTR +end + +#! Returns a pointer to the hash of the `get_note_sender` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_note_sender` kernel procedure is +#! stored. +export.get_note_sender_ptr + push.GET_NOTE_SENDER_PTR +end + +#! Returns a pointer to the hash of the `get_block_number` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_block_number` kernel procedure is +#! stored. +export.get_block_number_ptr + push.GET_BLOCK_NUMBER_PTR +end + +#! Returns a pointer to the hash of the `get_block_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_block_hash` kernel procedure is +#! stored. +export.get_block_hash_ptr + push.GET_BLOCK_HASH_PTR +end + +#! Returns a pointer to the hash of the `get_input_notes_commitment` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_input_notes_commitment` kernel +#! procedure is stored. +export.get_input_notes_commitment_ptr + push.GET_INPUT_NOTES_COMMITMENT_PTR +end + +#! Returns a pointer to the hash of the `get_output_notes_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_output_notes_hash` kernel procedure +#! is stored. +export.get_output_notes_hash_ptr + push.GET_OUTPUT_NOTES_HASH_PTR +end + +#! Returns a pointer to the hash of the `create_note` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `create_note` kernel procedure is stored. +export.create_note_ptr + push.CREATE_NOTE_PTR +end + +#! Returns a pointer to the hash of the `add_asset_to_note` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `add_asset_to_note` kernel procedure is +#! stored. +export.add_asset_to_note_ptr + push.ADD_ASSET_TO_NOTE_PTR +end + +#! Returns a pointer to the hash of the `get_account_vault_commitment` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_account_vault_commitment` kernel +#! procedure is stored. +export.get_account_vault_commitment_ptr + push.GET_ACCOUNT_VAULT_COMMITMENT_PTR +end + +#! Returns a pointer to the hash of the `mint_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `mint_asset` kernel procedure is stored. +export.mint_asset_ptr + push.MINT_ASSET_PTR +end + +#! Returns a pointer to the hash of the `burn_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `burn_asset` kernel procedure is stored. +export.burn_asset_ptr + push.BURN_ASSET_PTR +end + +#! Returns a pointer to the hash of the `get_fungible_faucet_total_issuance` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_fungible_faucet_total_issuance` +#! kernel procedure is stored. +export.get_fungible_faucet_total_issuance_ptr + push.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_PTR +end + +#! Returns a pointer to the hash of the `get_note_serial_number` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_ptr] +#! +#! Where: +#! - proc_ptr is the memory address where the hash of the `get_note_serial_number` kernel procedure +#! is stored. +export.get_note_serial_number_ptr + push.GET_NOTE_SERIAL_NUMBER_PTR +end diff --git a/miden-lib/asm/kernels/transaction/lib/prologue.masm b/miden-lib/asm/kernels/transaction/lib/prologue.masm index 5cf41615c..8b02991f8 100644 --- a/miden-lib/asm/kernels/transaction/lib/prologue.masm +++ b/miden-lib/asm/kernels/transaction/lib/prologue.masm @@ -98,6 +98,38 @@ proc.process_global_inputs exec.memory::set_nullifier_commitment dropw end +# KERNEL DATA +# ================================================================================================= + +#! Saves the hashes of the kernel procedures to memory and verifies that it matches the KERNEL_HASH +#! public input. +#! +#! Stack: [kernel_procs_len, KERNEL_HASH] +#! Advice stack: [ +#! [KERNEL_PROCS] +#! ] +#! Output: [] +#! +#! Where: +#! - kernel_procs_len, number of kernel procedures. +#! - KERNEL_HASH, hash of all kernel procedures. +#! - [KERNEL_PROCS], array of hashes of the kernel procedures. +proc.process_kernel_data + # get the pointer to the memory where hashes of the kernel procedures will be stored + exec.memory::get_kernel_procs_ptr swap + # => [kernel_procs_len, kernel_procs_ptr, KERNEL_HASH] + + # store the kernel procedures to the memory + exec.mem::pipe_preimage_to_memory + # => [kernel_procs_ptr'] + + drop + # => [] + + # kernel hash + # 14953775620698834032, 17523231931899419664, 4825234885919677706, 11125827748116184971 +end + # BLOCK DATA # ================================================================================================= @@ -1090,8 +1122,16 @@ end #! - The account data is invalid. #! - Any of the input notes do note exist in the note db. #! -#! Operand stack: [BLOCK_HASH, account_id, INITIAL_ACCOUNT_HASH, INPUT_NOTES_COMMITMENT] +#! Operand stack: [ +#! BLOCK_HASH, +#! account_id, +#! INITIAL_ACCOUNT_HASH, +#! INPUT_NOTES_COMMITMENT, +#! kernel_procs_len, +#! KERNEL_HASH +#! ] #! Advice stack: [ +#! [KERNEL_PROCS] #! PREVIOUS_BLOCK_HASH, #! CHAIN_MMR_HASH, #! ACCOUNT_ROOT, @@ -1119,6 +1159,9 @@ end #! - account_id, the account that the transaction is being executed against. #! - INITIAL_ACCOUNT_HASH, account state prior to the transaction, EMPTY_WORD for new accounts. #! - INPUT_NOTES_COMMITMENT, see `transaction::api::get_input_notes_commitment`. +#! - kernel_procs_len, number of kernel procedures. +#! - KERNEL_HASH, hash of all kernel procedures. +#! - [KERNEL_PROCS], array of hashes of the kernel procedures. #! - PREVIOUS_BLOCK_HASH, hash of the previous block. #! - CHAIN_MMR_HASH, sequential hash of the reference MMR. #! - ACCOUNT_ROOT, root of the tree with latest account states for all accounts. @@ -1141,6 +1184,7 @@ export.prepare_transaction exec.process_global_inputs # => [] + exec.process_kernel_data exec.process_block_data exec.process_chain_data exec.process_account_data diff --git a/miden-lib/asm/miden/account.masm b/miden-lib/asm/miden/account.masm index 60709883a..63c8687d5 100644 --- a/miden-lib/asm/miden/account.masm +++ b/miden-lib/asm/miden/account.masm @@ -1,3 +1,5 @@ +use.kernel::transaction::lib::memory + #! Returns the account id. #! #! Stack: [] @@ -8,7 +10,8 @@ export.get_id push.0 # => [0] - syscall.get_account_id + exec.memory::get_account_id_ptr + syscall.exec_kernel_proc # => [acct_id] end @@ -22,7 +25,8 @@ export.get_nonce push.0 # => [0] - syscall.get_account_nonce + exec.memory::get_account_nonce_ptr + syscall.exec_kernel_proc # => [nonce] end @@ -36,7 +40,8 @@ export.get_initial_hash padw # => [0, 0, 0, 0] - syscall.get_initial_account_hash + exec.memory::get_initial_account_hash_ptr + syscall.exec_kernel_proc # => [H] end @@ -50,7 +55,8 @@ export.get_current_hash padw # => [0, 0, 0, 0] - syscall.get_current_account_hash + exec.memory::get_current_account_hash_ptr + syscall.exec_kernel_proc # => [ACCT_HASH] end @@ -62,7 +68,8 @@ end #! - value is the value to increment the nonce by. value can be at most 2^32 - 1 otherwise this #! procedure panics. export.incr_nonce - syscall.incr_account_nonce + exec.memory::incr_account_nonce_ptr + syscall.exec_kernel_proc # => [0] drop @@ -80,7 +87,8 @@ export.get_item push.0.0.0 movup.3 # => [index, 0, 0, 0] - syscall.get_account_item + exec.memory::get_account_item_ptr + syscall.exec_kernel_proc # => [VALUE] end @@ -97,7 +105,8 @@ export.set_item push.0 movdn.5 push.0 movdn.5 push.0 movdn.5 # => [index, V', 0, 0, 0] - syscall.set_account_item + exec.memory::set_account_item_ptr + syscall.exec_kernel_proc # => [R', V] end @@ -112,7 +121,8 @@ end #! - KEY is the key of the item to get. #! - VALUE is the value of the item. export.get_map_item - syscall.get_account_map_item + exec.memory::get_account_map_item_ptr + syscall.exec_kernel_proc # => [VALUE] # prepare stack for return @@ -133,7 +143,8 @@ end #! - OLD_MAP_ROOT is the old map root. #! - OLD_MAP_VALUE is the old value at KEY. export.set_map_item - syscall.set_account_map_item + exec.memory::set_account_map_item_ptr + syscall.exec_kernel_proc # => [OLD_MAP_ROOT, OLD_MAP_VALUE, 0] movup.8 drop @@ -148,7 +159,8 @@ end #! #! - CODE_COMMITMENT is the hash of the code to set. export.set_code - syscall.set_account_code + exec.memory::set_account_code_ptr + syscall.exec_kernel_proc # => [0, 0, 0, 0] dropw @@ -164,7 +176,8 @@ end #! - faucet_id is the faucet id of the fungible asset of interest. #! - balance is the vault balance of the fungible asset. export.get_balance - syscall.account_vault_get_balance + exec.memory::account_vault_get_balance_ptr + syscall.exec_kernel_proc # => [balance] end @@ -177,7 +190,8 @@ end #! - ASSET is the non-fungible asset of interest #! - has_asset is a boolean indicating whether the account vault has the asset of interest export.has_non_fungible_asset - syscall.account_vault_has_non_fungible_asset + exec.memory::account_vault_has_non_fungible_asset_ptr + syscall.exec_kernel_proc # => [has_asset, 0, 0, 0] swap drop swap drop swap drop @@ -199,7 +213,8 @@ end #! - If ASSET is a fungible asset, then ASSET' is the total fungible asset in the account vault #! after ASSET was added to it. export.add_asset - syscall.account_vault_add_asset + exec.memory::account_vault_add_asset_ptr + syscall.exec_kernel_proc end #! Remove the specified asset from the vault. @@ -214,7 +229,8 @@ end #! #! - ASSET is the asset to remove from the vault. export.remove_asset - syscall.account_vault_remove_asset + exec.memory::account_vault_remove_asset_ptr + syscall.exec_kernel_proc end #! Returns a commitment to the account vault. @@ -229,7 +245,8 @@ export.get_vault_commitment # => [0, 0, 0, 0] # invoke the syscall - syscall.get_account_vault_commitment + exec.memory::get_account_vault_commitment_ptr + syscall.exec_kernel_proc # => [COM] end diff --git a/miden-lib/asm/miden/faucet.masm b/miden-lib/asm/miden/faucet.masm index d6bfb751f..2a2640757 100644 --- a/miden-lib/asm/miden/faucet.masm +++ b/miden-lib/asm/miden/faucet.masm @@ -1,3 +1,5 @@ +use.miden::kernels::tx::memory + #! Mint an asset from the faucet the transaction is being executed against. #! #! Panics: @@ -14,7 +16,8 @@ #! #! - ASSET is the asset that was minted. export.mint - syscall.mint_asset + exec.memory::mint_asset_ptr + syscall.exec_kernel_proc # => [ASSET] end @@ -35,7 +38,8 @@ end #! #! - ASSET is the asset that was burned. export.burn - syscall.burn_asset + exec.memory::burn_asset_ptr + syscall.exec_kernel_proc # => [ASSET] end @@ -55,6 +59,7 @@ export.get_total_issuance # => [0] # invoke the `get_fungible_faucet_total_issuance` kernel procedure - syscall.get_fungible_faucet_total_issuance + exec.memory::get_fungible_faucet_total_issuance_ptr + syscall.exec_kernel_proc # => [total_issuance] end diff --git a/miden-lib/asm/miden/note.masm b/miden-lib/asm/miden/note.masm index 0afb93de9..ca9da2fd5 100644 --- a/miden-lib/asm/miden/note.masm +++ b/miden-lib/asm/miden/note.masm @@ -1,3 +1,4 @@ +use.miden::kernels::tx::memory use.std::crypto::hashes::native use.std::mem @@ -49,7 +50,8 @@ export.get_assets # => [0, 0, 0, 0, 0, dest_ptr] # get the current input note assets info - syscall.get_note_assets_info + exec.memory::get_note_assets_info_ptr + syscall.exec_kernel_proc # => [ASSETS_HASH, num_assets, dest_ptr] # load the asset data from the advice map to the advice stack @@ -83,7 +85,9 @@ end #! - inputs_len, the note's input count. #! - INPUTS, the data corresponding to the note's inputs. export.get_inputs - padw syscall.get_note_inputs_hash + padw + exec.memory::get_note_inputs_hash_ptr + syscall.exec_kernel_proc # => [INPUTS_HASH, dest_ptr] # load the inputs from the advice map to the advice stack @@ -125,7 +129,8 @@ export.get_sender push.0 # => [0] - syscall.get_note_sender + exec.memory::get_note_sender_ptr + syscall.exec_kernel_proc # => [sender] end @@ -140,7 +145,8 @@ export.get_serial_number padw # => [0, 0, 0, 0] - syscall.get_note_serial_number + exec.memory::get_note_serial_number_ptr + syscall.exec_kernel_proc # => [SERIAL_NUMBER] end diff --git a/miden-lib/asm/miden/tx.masm b/miden-lib/asm/miden/tx.masm index 8f1e61b41..e9cf33d7e 100644 --- a/miden-lib/asm/miden/tx.masm +++ b/miden-lib/asm/miden/tx.masm @@ -1,3 +1,5 @@ +use.miden::kernels::tx::memory + #! Returns the block number of the last known block at the time of transaction execution. #! #! Inputs: [] @@ -8,7 +10,8 @@ export.get_block_number push.0 # => [0] - syscall.get_block_number + exec.memory::get_block_number_ptr + syscall.exec_kernel_proc # => [num] end @@ -20,7 +23,9 @@ end #! Where: #! - BLOCK_HASH, reference block for the transaction execution. export.get_block_hash - padw syscall.get_block_hash + padw + exec.memory::get_block_hash_ptr + syscall.exec_kernel_proc # => [BLOCK_HASH] end @@ -34,7 +39,9 @@ end #! Where: #! - INPUT_NOTES_COMMITMENT is the input notes commitment hash. export.get_input_notes_commitment - padw syscall.get_input_notes_commitment + padw + exec.memory::get_input_notes_commitment_ptr + syscall.exec_kernel_proc # => [INPUT_NOTES_COMMITMENT] end @@ -49,7 +56,8 @@ export.get_output_notes_hash padw # => [0, 0, 0, 0] - syscall.get_output_notes_hash + exec.memory::get_output_notes_hash_ptr + syscall.exec_kernel_proc # => [COM] end @@ -70,7 +78,8 @@ export.create_note padw padw swapdw # => [tag, aux, note_type, execution_hint, RECIPIENT, PAD(8)] - syscall.create_note + exec.memory::create_note_ptr + syscall.exec_kernel_proc # => [note_idx, PAD(15)] # remove excess PADs from the stack @@ -91,7 +100,8 @@ export.add_asset_to_note push.0.0.0 padw padw swapdw movup.7 swapw movup.4 # => [note_idx, ASSET, PAD(11)] - syscall.add_asset_to_note + exec.memory::add_asset_to_note_ptr + syscall.exec_kernel_proc # => [note_idx, ASSET, PAD(11)] # remove excess PADs from the stack diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index c25c834f2..364dfe350 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -19,9 +19,10 @@ use miden_objects::{ pub(super) fn extend_advice_inputs( tx_inputs: &TransactionInputs, tx_args: &TransactionArgs, + kernel_procs: Vec, advice_inputs: &mut AdviceInputs, ) { - build_advice_stack(tx_inputs, tx_args.tx_script(), advice_inputs); + build_advice_stack(tx_inputs, tx_args.tx_script(), kernel_procs, advice_inputs); // build the advice map and Merkle store for relevant components add_chain_mmr_to_advice_inputs(tx_inputs.block_chain(), advice_inputs); @@ -38,6 +39,7 @@ pub(super) fn extend_advice_inputs( /// The following data is pushed to the advice stack: /// /// [ +/// [KERNEL_PROCS_HASHES], /// PREVIOUS_BLOCK_HASH, /// CHAIN_MMR_HASH, /// ACCOUNT_ROOT, @@ -57,8 +59,12 @@ pub(super) fn extend_advice_inputs( fn build_advice_stack( tx_inputs: &TransactionInputs, tx_script: Option<&TransactionScript>, + kernel_procs: Vec, inputs: &mut AdviceInputs, ) { + // push hashes of the kernel procedures to the advice stack + inputs.extend_stack(kernel_procs); + // push block header info into the stack // Note: keep in sync with the process_block_data kernel procedure let header = tx_inputs.block_header(); diff --git a/miden-lib/src/transaction/mod.rs b/miden-lib/src/transaction/mod.rs index 25963c53f..f92d99ec1 100644 --- a/miden-lib/src/transaction/mod.rs +++ b/miden-lib/src/transaction/mod.rs @@ -8,7 +8,7 @@ use miden_objects::{ }, utils::{group_slice_elements, serde::Deserializable}, vm::{AdviceInputs, AdviceMap, Program, ProgramInfo, StackInputs, StackOutputs}, - Digest, Felt, TransactionOutputError, Word, EMPTY_WORD, + Digest, Felt, TransactionOutputError, Word, EMPTY_WORD, Hasher, }; use miden_stdlib::StdLibrary; @@ -90,15 +90,25 @@ impl TransactionKernel { init_advice_inputs: Option, ) -> (StackInputs, AdviceInputs) { let account = tx_inputs.account(); + + let kernel = Self::kernel().kernel(); + // we need to get &[Felt] from &[Digest] + let kernel_procs_as_felts = Digest::digests_as_elements(kernel.proc_hashes().into_iter()) + .cloned() + .collect::>(); + // let aboba = kernel.proc_hashes().iter().flat_map(|digest| digest.as_elements().to_vec()).collect::>(); + let kernel_hash = Hasher::hash_elements(&kernel_procs_as_felts); + let stack_inputs = TransactionKernel::build_input_stack( account.id(), account.init_hash(), tx_inputs.input_notes().commitment(), tx_inputs.block_header().hash(), + (kernel.proc_hashes().len(), kernel_hash), ); let mut advice_inputs = init_advice_inputs.unwrap_or_default(); - inputs::extend_advice_inputs(tx_inputs, tx_args, &mut advice_inputs); + inputs::extend_advice_inputs(tx_inputs, tx_args, kernel_procs_as_felts, &mut advice_inputs); (stack_inputs, advice_inputs) } @@ -124,21 +134,35 @@ impl TransactionKernel { /// /// The initial stack is defined: /// - /// > [BLOCK_HASH, acct_id, INITIAL_ACCOUNT_HASH, INPUT_NOTES_COMMITMENT] + /// ```text + /// [ + /// BLOCK_HASH, + /// acct_id, + /// INITIAL_ACCOUNT_HASH, + /// INPUT_NOTES_COMMITMENT, + /// kernel_procs_len, + /// KERNEL_HASH + /// ] + /// ``` /// /// Where: /// - BLOCK_HASH, reference block for the transaction execution. /// - acct_id, the account that the transaction is being executed against. /// - INITIAL_ACCOUNT_HASH, account state prior to the transaction, EMPTY_WORD for new accounts. /// - INPUT_NOTES_COMMITMENT, see `transaction::api::get_input_notes_commitment`. + /// - kernel_procs_len, number of the procedures in the used kernel. + /// - KERNEL_HASH, hash of the entire kernel. pub fn build_input_stack( acct_id: AccountId, init_acct_hash: Digest, input_notes_hash: Digest, block_hash: Digest, + kernel: (usize, Digest), ) -> StackInputs { // Note: Must be kept in sync with the transaction's kernel prepare_transaction procedure - let mut inputs: Vec = Vec::with_capacity(13); + let mut inputs: Vec = Vec::with_capacity(18); + inputs.extend(kernel.1); + inputs.push(Felt::from(kernel.0 as u16)); inputs.extend(input_notes_hash); inputs.extend_from_slice(init_acct_hash.as_elements()); inputs.push(acct_id.into()); diff --git a/miden-tx/src/verifier/mod.rs b/miden-tx/src/verifier/mod.rs index af69ecbe9..5006d88ad 100644 --- a/miden-tx/src/verifier/mod.rs +++ b/miden-tx/src/verifier/mod.rs @@ -1,5 +1,7 @@ +use alloc::vec::Vec; + use miden_lib::transaction::TransactionKernel; -use miden_objects::{transaction::ProvenTransaction, vm::ProgramInfo}; +use miden_objects::{transaction::ProvenTransaction, vm::ProgramInfo, Digest, Felt, Hasher}; use miden_verifier::verify; use super::TransactionVerifierError; @@ -31,12 +33,21 @@ impl TransactionVerifier { /// - Transaction verification fails. /// - The security level of the verified proof is insufficient. pub fn verify(&self, transaction: ProvenTransaction) -> Result<(), TransactionVerifierError> { + // compute the kernel hash + let kernel = self.tx_program_info.kernel(); + // we need to get &[Felt] from &[Digest] + let kernel_procs_as_felts = Digest::digests_as_elements(kernel.proc_hashes().into_iter()) + .cloned() + .collect::>(); + let kernel_hash = Hasher::hash_elements(&kernel_procs_as_felts); + // build stack inputs and outputs let stack_inputs = TransactionKernel::build_input_stack( transaction.account_id(), transaction.account_update().init_state_hash(), transaction.input_notes().commitment(), transaction.block_ref(), + (kernel.proc_hashes().len(), kernel_hash) ); let stack_outputs = TransactionKernel::build_output_stack( transaction.account_update().final_state_hash(), From c7302379d26e1e7c2e8672bc1eb0bbf07044624e Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 28 Aug 2024 20:45:33 +0300 Subject: [PATCH 02/11] refactor: rework procs invocation --- CHANGELOG.md | 1 + docs/architecture/transactions/contexts.md | 2 +- miden-lib/asm/kernels/transaction/api.masm | 169 ++++++-- .../asm/kernels/transaction/lib/memory.masm | 380 +----------------- .../asm/kernels/transaction/lib/prologue.masm | 5 +- miden-lib/asm/miden/account.masm | 211 ++++++++-- miden-lib/asm/miden/faucet.masm | 41 +- miden-lib/asm/miden/kernel_invocation.masm | 375 +++++++++++++++++ miden-lib/asm/miden/note.masm | 55 ++- miden-lib/asm/miden/tx.masm | 74 +++- miden-lib/src/transaction/mod.rs | 10 +- .../src/tests/kernel_tests/test_prologue.rs | 2 +- miden-tx/src/verifier/mod.rs | 4 +- objects/src/testing/account_code.rs | 20 +- 14 files changed, 837 insertions(+), 512 deletions(-) create mode 100644 miden-lib/asm/miden/kernel_invocation.masm diff --git a/CHANGELOG.md b/CHANGELOG.md index dd7435f00..b3a4d0538 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Implemented offset based storage access (#843). - [BREAKING] `AccountStorageType` enum was renamed to `AccountStorageMode` along with its variants (#854). - [BREAKING] `AccountStub` structure was renamed to `AccountHeader` (#855). +- [BREAKING] Kernel procedures now have to be invoked using `dynexec` instruction (#803). ## 0.5.1 (2024-08-28) - `miden-objects` crate only diff --git a/docs/architecture/transactions/contexts.md b/docs/architecture/transactions/contexts.md index c37804da3..8ea1cbd89 100644 --- a/docs/architecture/transactions/contexts.md +++ b/docs/architecture/transactions/contexts.md @@ -70,7 +70,7 @@ The [account API](https://github.com/0xPolygonMiden/miden-base/blob/main/miden-l #! Add the specified asset to the vault. #! ... export.add_asset - exec.mem::account_vault_add_asset_ptr + exec.kernel_invocation::account_vault_add_asset_offset syscall.exec_kernel_proc end ``` diff --git a/miden-lib/asm/kernels/transaction/api.masm b/miden-lib/asm/kernels/transaction/api.masm index 7d02c1d46..ab05814bf 100644 --- a/miden-lib/asm/kernels/transaction/api.masm +++ b/miden-lib/asm/kernels/transaction/api.masm @@ -1,4 +1,5 @@ use.std::collections::smt +use.std::sys use.kernel::account use.kernel::asset_vault @@ -10,9 +11,11 @@ use.kernel::tx # NOTE # ================================================================================================= -# Procedures in this module are 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. # +# `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 only using a `dynexec` instruction by their hashes stored # +# in the memory. # # ================================================================================================= # ERRORS @@ -65,11 +68,14 @@ end #! Returns the account id. #! -#! Stack: [0] +#! Stack: [KERNEL_PROCEDURE_HASH, 0] #! Output: [acct_id] #! #! - acct_id is the account id. export.get_account_id + # drop the procedure's hash + dropw + # get the account id exec.account::get_id # => [acct_id, 0] @@ -80,11 +86,14 @@ end #! Returns the account nonce. #! -#! Stack: [0] +#! Stack: [KERNEL_PROCEDURE_HASH, 0] #! Output: [nonce] #! #! - nonce is the account nonce. export.get_account_nonce + # drop the procedure's hash + dropw + # get the account nonce exec.account::get_nonce # => [0, nonce] @@ -95,11 +104,14 @@ end #! Returns the initial account hash. #! -#! Stack: [0, 0, 0, 0] +#! Stack: [KERNEL_PROCEDURE_HASH, 0, 0, 0, 0] #! Output: [H] #! #! - H is the initial account hash. export.get_initial_account_hash + # drop the procedure's hash + dropw + # get the initial account hash exec.account::get_initial_hash # => [H, 0, 0, 0, 0] @@ -110,11 +122,14 @@ end #! Computes and returns the account hash from account data stored in memory. #! -#! Stack: [0, 0, 0, 0] +#! Stack: [KERNEL_PROCEDURE_HASH, 0, 0, 0, 0] #! Output: [ACCT_HASH] #! #! - ACCT_HASH is the hash of the account data. export.get_current_account_hash + # drop the procedure's hash + dropw + # get the current account hash exec.account::get_current_hash # => [ACCT_HASH, 0, 0, 0, 0] @@ -125,12 +140,15 @@ end #! Increments the account nonce by the provided value. #! -#! Stack: [value] +#! Stack: [KERNEL_PROCEDURE_HASH, value] #! Output: [0] #! #! - value is the value to increment the nonce by. value can be at most 2^32 - 1 otherwise this #! procedure panics. export.incr_account_nonce + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop # => [value] @@ -146,12 +164,15 @@ end #! Gets an item from the account storage. Panics if the index is out of bounds. #! -#! Stack: [index, 0, 0, 0] +#! Stack: [KERNEL_PROCEDURE_HASH, index, 0, 0, 0] #! Output: [VALUE] #! #! - index is the index of the item to get. #! - VALUE is the value of the item. export.get_account_item + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin # => [storage_offset, index, 0, 0, 0] @@ -171,7 +192,7 @@ end #! Sets an item in the account storage. Panics if the index is out of bounds. #! -#! Stack: [index, V', 0, 0, 0] +#! Stack: [KERNEL_PROCEDURE_HASH, index, V', 0, 0, 0] #! Output: [R', V] #! #! - index is the index of the item to set. @@ -179,6 +200,9 @@ end #! - V is the previous value of the item. #! - R' is the new storage root. export.set_account_item + # drop the procedure's hash + dropw + # 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 @@ -208,12 +232,15 @@ end #! - the index is out of bounds (>255). #! - the requested storage slot type is not map #! -#! Stack: [index, KEY, ...] +#! Stack: [KERNEL_PROCEDURE_HASH, index, KEY, ...] #! Output: [VALUE, 0] #! #! - index is the index of the item to get. #! - VALUE is the value of the item. export.get_account_map_item + # drop the procedure's hash + dropw + # check if storage type is map dup exec.account::get_storage_slot_type_info drop # => [slot_type, index, KEY, ...] @@ -249,7 +276,7 @@ end #! - the requested storage slot type is not map #! - the procedure is called from a non-account context #! -#! Stack: [index, KEY, NEW_VALUE, ...] +#! Stack: [KERNEL_PROCEDURE_HASH, index, KEY, NEW_VALUE, ...] #! Output: [OLD_MAP_ROOT, OLD_MAP_VALUE, 0] #! #! - index is the index of the item to get. @@ -259,6 +286,9 @@ end #! - OLD_MAP_ROOT is the root of the old map before insertion #! - NEW_MAP_ROOT is the root of the new map after insertion. export.set_account_map_item.1 + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin # => [storage_offset, index, KEY, NEW_VALUE, ...] @@ -287,11 +317,14 @@ end #! Sets the code of the account the transaction is being executed against. This procedure can only #! executed on regular accounts with updatable code. Otherwise, this procedure fails. #! -#! Stack: [CODE_COMMITMENT] +#! Stack: [KERNEL_PROCEDURE_HASH, CODE_COMMITMENT] #! Output: [0, 0, 0, 0] #! #! - CODE_COMMITMENT is the hash of the code to set. export.set_account_code + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop # => [CODE_COMMITMENT] @@ -308,12 +341,15 @@ end #! Returns the balance of a fungible asset associated with a faucet_id. #! Panics if the asset is not a fungible asset. #! -#! Stack: [faucet_id] +#! Stack: [KERNEL_PROCEDURE_HASH, faucet_id] #! Output: [balance] #! #! - faucet_id is the faucet id of the fungible asset of interest. #! - balance is the vault balance of the fungible asset. export.account_vault_get_balance + # drop the procedure's hash + dropw + # get the vault root exec.memory::get_acct_vault_root_ptr swap # => [faucet_id, acct_vault_root_ptr] @@ -326,12 +362,15 @@ end #! Returns a boolean indicating whether the non-fungible asset is present in the vault. #! Panics if the ASSET is a fungible asset. #! -#! Stack: [ASSET] +#! Stack: [KERNEL_PROCEDURE_HASH, ASSET] #! Output: [has_asset, 0, 0, 0] #! #! - ASSET is the non-fungible asset of interest #! - has_asset is a boolean indicating whether the account vault has the asset of interest export.account_vault_has_non_fungible_asset + # drop the procedure's hash + dropw + # 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] @@ -348,7 +387,7 @@ end #! - If the total value of two fungible assets is greater than or equal to 2^63. #! - If the vault already contains the same non-fungible asset. #! -#! Stack: [ASSET] +#! Stack: [KERNEL_PROCEDURE_HASH, ASSET] #! Output: [ASSET'] #! #! - ASSET is the asset to add to the vault. @@ -357,6 +396,9 @@ end #! - If ASSET is a fungible asset, then ASSET' is the total fungible asset in the account vault #! after ASSET was added to it. export.account_vault_add_asset + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop # => [ASSET] @@ -391,11 +433,14 @@ end #! - 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. #! -#! Stack: [ASSET] +#! Stack: [KERNEL_PROCEDURE_HASH, ASSET] #! Output: [ASSET] #! #! - ASSET is the asset to remove from the vault. export.account_vault_remove_asset + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop # => [ASSET] @@ -421,12 +466,15 @@ end #! Returns the number of assets and the assets hash of the note currently being processed. Panics #! if a note is not being processed. #! -#! Inputs: [0, 0, 0, 0, 0] +#! Inputs: [KERNEL_PROCEDURE_HASH, 0, 0, 0, 0, 0] #! Outputs: [ASSETS_HASH, num_assets] #! #! - 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. export.get_note_assets_info + # drop the procedure's hash + dropw + # get the assets info exec.note::get_assets_info # => [ASSETS_HASH, num_assets, 0, 0, 0, 0, 0] @@ -438,12 +486,15 @@ end #! Returns the current note's inputs hash. #! -#! Inputs: [EMPTY_WORD] +#! Inputs: [KERNEL_PROCEDURE_HASH, EMPTY_WORD] #! Outputs: [NOTE_INPUTS_HASH] #! #! Where: #! - NOTE_INPUTS_HASH, is the current note's inputs hash. export.get_note_inputs_hash + # drop the procedure's hash + dropw + exec.note::get_note_inputs_hash # => [NOTE_INPUTS_HASH, EMPTY_WORD] @@ -454,23 +505,29 @@ end #! Returns the sender of the note currently being processed. Panics if a note is not being #! processed. #! -#! Inputs: [0] +#! Inputs: [KERNEL_PROCEDURE_HASH, 0] #! Outputs: [sender] #! #! Where: #! - sender is the sender of the note currently being processed. export.get_note_sender + # drop the procedure's hash + dropw + 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] +#! Inputs: [KERNEL_PROCEDURE_HASH, 0] #! Outputs: [num] #! #! num is the last known block number. export.get_block_number + # drop the procedure's hash + dropw + # get the block number exec.tx::get_block_number # => [num, 0] @@ -482,12 +539,15 @@ end #! Returns the block hash of the reference block. #! -#! Stack: [EMPTY_WORD] +#! Stack: [KERNEL_PROCEDURE_HASH, EMPTY_WORD] #! Output: [BLOCK_HASH] #! #! Where: #! - BLOCK_HASH, reference block for the transaction execution. export.get_block_hash + # drop the procedure's hash + dropw + dropw exec.tx::get_block_hash # => [BLOCK_HASH] end @@ -500,12 +560,15 @@ end #! 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] +#! Inputs: [KERNEL_PROCEDURE_HASH, 0, 0, 0, 0] #! Outputs: [INPUT_NOTES_COMMITMENT] #! #! Where: #! - INPUT_NOTES_COMMITMENT is the input notes commitment hash. export.get_input_notes_commitment + # drop the procedure's hash + dropw + exec.tx::get_input_notes_commitment # => [COM, 0, 0, 0, 0] @@ -516,11 +579,14 @@ 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] +#! Inputs: [KERNEL_PROCEDURE_HASH, 0, 0, 0, 0] #! Outputs: [COM] #! #! COM is the output notes hash. export.get_output_notes_hash + # drop the procedure's hash + dropw + # get the output notes hash exec.tx::get_output_notes_hash # => [COM, 0, 0, 0, 0] @@ -532,7 +598,7 @@ end #! Creates a new note and returns the index of the note. #! -#! Inputs: [tag, aux, note_type, execution_hint, RECIPIENT, PAD(8)] +#! Inputs: [KERNEL_PROCEDURE_HASH, tag, aux, note_type, execution_hint, RECIPIENT, PAD(4)] #! Outputs: [note_idx, PAD(15)] #! #! tag is the tag to be included in the note. @@ -542,6 +608,9 @@ end #! RECIPIENT is the recipient of the note. #! note_idx is the index of the crated note. export.create_note + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop # => [tag, aux, note_type, execution_hint, RECIPIENT, PAD(8)] @@ -552,12 +621,15 @@ end #! Adds the ASSET to the note specified by the index. #! -#! Inputs: [note_idx, ASSET, PAD(11)] +#! Inputs: [KERNEL_PROCEDURE_HASH, note_idx, ASSET, PAD(7)] #! Outputs: [note_idx, ASSET, PAD(11)] #! #! note_idx is the index of the the note to which the asset is added. #! ASSET can be a fungible or non-fungible asset. export.add_asset_to_note + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop # => [note_idx, ASSET] @@ -572,11 +644,14 @@ end #! Returns a commitment to the account vault the transaction is being executed against. #! -#! Stack: [0, 0, 0, 0] +#! Stack: [KERNEL_PROCEDURE_HASH, 0, 0, 0, 0] #! Outputs: [COM] #! #! - COM is the commitment to the account vault. export.get_account_vault_commitment + # drop the procedure's hash + dropw + # fetch the account vault root exec.memory::get_acct_vault_root # => [COM, 0, 0, 0, 0] @@ -597,11 +672,14 @@ end #! allowed. #! - For non-fungible faucets if the non-fungible asset being minted already exists. #! -#! Stack: [ASSET] +#! Stack: [KERNEL_PROCEDURE_HASH, ASSET] #! Outputs: [ASSET] #! #! - ASSET is the asset that was minted. export.mint_asset + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop # => [ASSET] @@ -623,11 +701,14 @@ end #! - 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. #! -#! Stack: [ASSET] +#! Stack: [KERNEL_PROCEDURE_HASH, ASSET] #! Outputs: [ASSET] #! #! - ASSET is the asset that was burned. export.burn_asset + # drop the procedure's hash + dropw + # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop # => [ASSET] @@ -642,12 +723,15 @@ end #! Panics: #! - If the transaction is not being executed against a fungible faucet. #! -#! Stack: [0] +#! Stack: [KERNEL_PROCEDURE_HASH, 0] #! Outputs: [total_issuance] #! #! - total_issuance is the total issuance of the fungible faucet the transaction is being executed #! against. export.get_fungible_faucet_total_issuance + # drop the procedure's hash + dropw + # 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_ACCT_MUST_BE_A_FAUCET # => [0] @@ -664,11 +748,14 @@ end #! Returns the serial number of the note currently being processed. #! Panics if no note is not being processed. #! -#! Inputs: [] +#! Inputs: [KERNEL_PROCEDURE_HASH] #! Outputs: [SERIAL_NUMBER] #! #! - SERIAL_NUMBER is the serial number of the note currently being processed. export.get_note_serial_number + # drop the procedure's hash + dropw + exec.note::get_serial_number # => [SERIAL_NUMBER] @@ -677,21 +764,29 @@ export.get_note_serial_number # => [SERIAL_NUMBER] end -#! Executes a kernel procedure specified by its memory pointer +#! Executes a kernel procedure specified by its offset. #! -#! Inputs: [procedure_ptr] -#! Outputs: [*executed_procedure_output*] +#! Inputs: [procedure_offset, *executed_procedure_input*, PAD(*)] +#! Outputs: [*executed_procedure_output*, PAD(*)] #! -#! - procedure_ptr is a pointer to the memory where hash of the desired kernel procedure is stored. +#! - procedure_offset is an offset of the kernel procedure, specified in the +#! `miden/kernel_invocation.masm` file. export.exec_kernel_proc + # compute the memory pointer at which desired procedure is stored + exec.memory::get_kernel_procedures_ptr add + # => [procedure_pointer, *executed_procedure_input*, PAD(*)] + # prepare stack for procedure hash obtaining padw movup.4 - # => [procedure_ptr, 0, 0, 0, 0] + # => [procedure_pointer, 0, 0, 0, 0, *executed_procedure_input*, PAD(*)] # load kernel procedure hash mem_loadw - # => [KERNEL_PROCEDURE_HASH] + # => [KERNEL_PROCEDURE_HASH, *executed_procedure_input*, PAD(*)] # execute loaded procedure dynexec + # => [*executed_procedure_output*, PAD(*)] + + exec.sys::truncate_stack end diff --git a/miden-lib/asm/kernels/transaction/lib/memory.masm b/miden-lib/asm/kernels/transaction/lib/memory.masm index 92bc6a233..adc891027 100644 --- a/miden-lib/asm/kernels/transaction/lib/memory.masm +++ b/miden-lib/asm/kernels/transaction/lib/memory.masm @@ -131,37 +131,7 @@ const.ACCT_PROCEDURES_SECTION_OFFSET=1000 # The memory address at which the hashes of kernel procedures begin. # TODO: choose the proper memory location for the kernel procedures. -const.KERNEL_PROCEDURES_PTR=1500 - -# The offsets at which hash of the corresponding procedure is stored. -const.GET_ACCOUNT_ID_PTR=KERNEL_PROCEDURES_PTR -const.GET_ACCOUNT_NONCE_PTR=KERNEL_PROCEDURES_PTR+1 -const.GET_INITIAL_ACCOUNT_HASH_PTR=KERNEL_PROCEDURES_PTR+2 -const.GET_CURRENT_ACCOUNT_HASH_PTR=KERNEL_PROCEDURES_PTR+3 -const.INCR_ACCOUNT_NONCE_PTR=KERNEL_PROCEDURES_PTR+4 -const.GET_ACCOUNT_ITEM_PTR=KERNEL_PROCEDURES_PTR+5 -const.SET_ACCOUNT_ITEM_PTR=KERNEL_PROCEDURES_PTR+6 -const.GET_ACCOUNT_MAP_ITEM_PTR=KERNEL_PROCEDURES_PTR+7 -const.SET_ACCOUNT_MAP_ITEM_PTR=KERNEL_PROCEDURES_PTR+8 -const.SET_ACCOUNT_CODE_PTR=KERNEL_PROCEDURES_PTR+9 -const.ACCOUNT_VAULT_GET_BALANCE_PTR=KERNEL_PROCEDURES_PTR+10 -const.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_PTR=KERNEL_PROCEDURES_PTR+11 -const.ACCOUNT_VAULT_ADD_ASSET_PTR=KERNEL_PROCEDURES_PTR+12 -const.ACCOUNT_VAULT_REMOVE_ASSET_PTR=KERNEL_PROCEDURES_PTR+13 -const.GET_NOTE_ASSETS_INFO_PTR=KERNEL_PROCEDURES_PTR+14 -const.GET_NOTE_INPUTS_HASH_PTR=KERNEL_PROCEDURES_PTR+15 -const.GET_NOTE_SENDER_PTR=KERNEL_PROCEDURES_PTR+16 -const.GET_BLOCK_NUMBER_PTR=KERNEL_PROCEDURES_PTR+17 -const.GET_BLOCK_HASH_PTR=KERNEL_PROCEDURES_PTR+18 -const.GET_INPUT_NOTES_COMMITMENT_PTR=KERNEL_PROCEDURES_PTR+19 -const.GET_OUTPUT_NOTES_HASH_PTR=KERNEL_PROCEDURES_PTR+20 -const.CREATE_NOTE_PTR=KERNEL_PROCEDURES_PTR+21 -const.ADD_ASSET_TO_NOTE_PTR=KERNEL_PROCEDURES_PTR+22 -const.GET_ACCOUNT_VAULT_COMMITMENT_PTR=KERNEL_PROCEDURES_PTR+23 -const.MINT_ASSET_PTR=KERNEL_PROCEDURES_PTR+24 -const.BURN_ASSET_PTR=KERNEL_PROCEDURES_PTR+25 -const.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_PTR=KERNEL_PROCEDURES_PTR+26 -const.GET_NOTE_SERIAL_NUMBER_PTR=KERNEL_PROCEDURES_PTR+27 +const.KERNEL_PROCEDURES_PTR=10000 # INPUT NOTES DATA # ------------------------------------------------------------------------------------------------- @@ -471,10 +441,10 @@ end #! Returns the previous block hash of the last known block. #! #! Stack: [] -#! Output: [PRV_BLK_HASH] +#! Output: [PREV_BLOCK_HASH] #! #! Where: -#! - PRV_BLK_HASH is the previous block hash of the last known block. +#! - PREV_BLOCK_HASH is the previous block hash of the last known block. export.get_prv_blk_hash padw push.PREV_BLOCK_HASH_PTR mem_loadw end @@ -512,7 +482,6 @@ export.get_blk_timestamp padw push.BLOCK_METADATA_PTR mem_loadw drop movdn.2 drop drop end - #! Returns the chain root of the last known block. #! #! Stack: [] @@ -1212,11 +1181,11 @@ end #! Stack: [note_ptr, num_assets] #! Output: [] #! -#! Panics: if the number of assets exceeds the maximum allowed number of assets per note. -#! #! Where: #! - note_ptr is the memory address at which the output note data begins. #! - num_assets is the number of assets in the output note. +#! +#! Panics: if the number of assets exceeds the maximum allowed number of assets per note. export.set_output_note_num_assets push.OUTPUT_NOTE_NUM_ASSETS_OFFSET add # => [note_ptr + offset, num_assets] @@ -1258,343 +1227,10 @@ end #! Returns a pointer to the memory where hashes of the kernel procedures are stored. #! #! Stack: [] -#! Output: [kernel_procs_ptr] +#! Output: [kernel_procedures_ptr] #! #! Where: -#! - kernel_procs_ptr is the memory address where the hashes of the kernel procedures are stored. -export.get_kernel_procs_ptr +#! - kernel_procedures_ptr is the memory address where the hashes of the kernel procedures are stored. +export.get_kernel_procedures_ptr push.KERNEL_PROCEDURES_PTR end - -#! Returns a pointer to the hash of the `get_account_id` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_account_id` kernel procedure is -#! stored. -export.get_account_id_ptr - push.GET_ACCOUNT_ID_PTR -end - -#! Returns a pointer to the hash of the `get_account_nonce` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_account_nonce` kernel procedure is -#! stored. -export.get_account_nonce_ptr - push.GET_ACCOUNT_NONCE_PTR -end - -#! Returns a pointer to the hash of the `get_initial_account_hash` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_initial_account_hash` kernel -#! procedure is stored. -export.get_initial_account_hash_ptr - push.GET_INITIAL_ACCOUNT_HASH_PTR -end - -#! Returns a pointer to the hash of the `get_current_account_hash` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_current_account_hash` kernel -#! procedure is stored. -export.get_current_account_hash_ptr - push.GET_CURRENT_ACCOUNT_HASH_PTR -end - -#! Returns a pointer to the hash of the `incr_account_nonce` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `incr_account_nonce` kernel procedure is -#! stored. -export.incr_account_nonce_ptr - push.INCR_ACCOUNT_NONCE_PTR -end - -#! Returns a pointer to the hash of the `get_account_item` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_account_item` kernel procedure is -#! stored. -export.get_account_item_ptr - push.GET_ACCOUNT_ITEM_PTR -end - -#! Returns a pointer to the hash of the `set_account_item` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `set_account_item` kernel procedure is -#! stored. -export.set_account_item_ptr - push.SET_ACCOUNT_ITEM_PTR -end - -#! Returns a pointer to the hash of the `get_account_map_item` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_account_map_item` kernel procedure is -#! stored. -export.get_account_map_item_ptr - push.GET_ACCOUNT_MAP_ITEM_PTR -end - -#! Returns a pointer to the hash of the `set_account_map_item` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `set_account_map_item` kernel procedure is -#! stored. -export.set_account_map_item_ptr - push.SET_ACCOUNT_MAP_ITEM_PTR -end - -#! Returns a pointer to the hash of the `set_account_code` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `set_account_code` kernel procedure is -#! stored. -export.set_account_code_item_ptr - push.SET_ACCOUNT_CODE_PTR -end - -#! Returns a pointer to the hash of the `account_vault_get_balance` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `account_vault_get_balance` kernel -#! procedure is stored. -export.account_vault_get_balance_ptr - push.ACCOUNT_VAULT_GET_BALANCE_PTR -end - -#! Returns a pointer to the hash of the `account_vault_has_non_fungible_asset` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `account_vault_has_non_fungible_asset` -#! kernel procedure is stored. -export.account_vault_has_non_fungible_asset_ptr - push.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_PTR -end - -#! Returns a pointer to the hash of the `account_vault_add_asset` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `account_vault_add_asset` kernel procedure -#! is stored. -export.account_vault_add_asset_ptr - push.ACCOUNT_VAULT_ADD_ASSET_PTR -end - -#! Returns a pointer to the hash of the `account_vault_remove_asset` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `account_vault_remove_asset` kernel -#! procedure is stored. -export.account_vault_remove_asset_ptr - push.ACCOUNT_VAULT_REMOVE_ASSET_PTR -end - -#! Returns a pointer to the hash of the `get_note_assets_info` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_note_assets_info` kernel procedure -#! is stored. -export.get_note_assets_info_ptr - push.GET_NOTE_ASSETS_INFO_PTR -end - -#! Returns a pointer to the hash of the `get_note_inputs_hash` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_note_inputs_hash` kernel procedure -#! is stored. -export.get_note_inputs_hash_ptr - push.GET_NOTE_INPUTS_HASH_PTR -end - -#! Returns a pointer to the hash of the `get_note_sender` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_note_sender` kernel procedure is -#! stored. -export.get_note_sender_ptr - push.GET_NOTE_SENDER_PTR -end - -#! Returns a pointer to the hash of the `get_block_number` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_block_number` kernel procedure is -#! stored. -export.get_block_number_ptr - push.GET_BLOCK_NUMBER_PTR -end - -#! Returns a pointer to the hash of the `get_block_hash` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_block_hash` kernel procedure is -#! stored. -export.get_block_hash_ptr - push.GET_BLOCK_HASH_PTR -end - -#! Returns a pointer to the hash of the `get_input_notes_commitment` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_input_notes_commitment` kernel -#! procedure is stored. -export.get_input_notes_commitment_ptr - push.GET_INPUT_NOTES_COMMITMENT_PTR -end - -#! Returns a pointer to the hash of the `get_output_notes_hash` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_output_notes_hash` kernel procedure -#! is stored. -export.get_output_notes_hash_ptr - push.GET_OUTPUT_NOTES_HASH_PTR -end - -#! Returns a pointer to the hash of the `create_note` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `create_note` kernel procedure is stored. -export.create_note_ptr - push.CREATE_NOTE_PTR -end - -#! Returns a pointer to the hash of the `add_asset_to_note` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `add_asset_to_note` kernel procedure is -#! stored. -export.add_asset_to_note_ptr - push.ADD_ASSET_TO_NOTE_PTR -end - -#! Returns a pointer to the hash of the `get_account_vault_commitment` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_account_vault_commitment` kernel -#! procedure is stored. -export.get_account_vault_commitment_ptr - push.GET_ACCOUNT_VAULT_COMMITMENT_PTR -end - -#! Returns a pointer to the hash of the `mint_asset` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `mint_asset` kernel procedure is stored. -export.mint_asset_ptr - push.MINT_ASSET_PTR -end - -#! Returns a pointer to the hash of the `burn_asset` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `burn_asset` kernel procedure is stored. -export.burn_asset_ptr - push.BURN_ASSET_PTR -end - -#! Returns a pointer to the hash of the `get_fungible_faucet_total_issuance` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_fungible_faucet_total_issuance` -#! kernel procedure is stored. -export.get_fungible_faucet_total_issuance_ptr - push.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_PTR -end - -#! Returns a pointer to the hash of the `get_note_serial_number` kernel procedure. -#! -#! Stack: [] -#! Output: [proc_ptr] -#! -#! Where: -#! - proc_ptr is the memory address where the hash of the `get_note_serial_number` kernel procedure -#! is stored. -export.get_note_serial_number_ptr - push.GET_NOTE_SERIAL_NUMBER_PTR -end diff --git a/miden-lib/asm/kernels/transaction/lib/prologue.masm b/miden-lib/asm/kernels/transaction/lib/prologue.masm index 8b02991f8..98d63ad65 100644 --- a/miden-lib/asm/kernels/transaction/lib/prologue.masm +++ b/miden-lib/asm/kernels/transaction/lib/prologue.masm @@ -116,7 +116,7 @@ end #! - [KERNEL_PROCS], array of hashes of the kernel procedures. proc.process_kernel_data # get the pointer to the memory where hashes of the kernel procedures will be stored - exec.memory::get_kernel_procs_ptr swap + exec.memory::get_kernel_procedures_ptr swap # => [kernel_procs_len, kernel_procs_ptr, KERNEL_HASH] # store the kernel procedures to the memory @@ -125,9 +125,6 @@ proc.process_kernel_data drop # => [] - - # kernel hash - # 14953775620698834032, 17523231931899419664, 4825234885919677706, 11125827748116184971 end # BLOCK DATA diff --git a/miden-lib/asm/miden/account.masm b/miden-lib/asm/miden/account.masm index 63c8687d5..c4399c3ee 100644 --- a/miden-lib/asm/miden/account.masm +++ b/miden-lib/asm/miden/account.masm @@ -1,4 +1,4 @@ -use.kernel::transaction::lib::memory +use.miden::kernel_invocation #! Returns the account id. #! @@ -10,8 +10,21 @@ export.get_id push.0 # => [0] - exec.memory::get_account_id_ptr + # start padding the stack + push.0.0 + + exec.kernel_invocation::get_account_id_offset + # => [offset, 0, 0, 0] + + # pad the stack + padw swapw padw padw swapdw + # => [offset, 0, PAD(14)] + syscall.exec_kernel_proc + # => [acct_id, PAD(15)] + + # clean the stack + swapdw dropw dropw swapw dropw movdn.3 drop drop drop # => [acct_id] end @@ -25,8 +38,21 @@ export.get_nonce push.0 # => [0] - exec.memory::get_account_nonce_ptr + # start padding the stack + push.0.0 + + exec.kernel_invocation::get_account_nonce_offset + # => [offset, 0, 0, 0] + + # pad the stack + padw swapw padw padw swapdw + # => [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 @@ -37,11 +63,18 @@ end #! #! - H is the initial account hash. export.get_initial_hash - padw - # => [0, 0, 0, 0] + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_initial_account_hash_offset + # => [offset, PAD(15)] - exec.memory::get_initial_account_hash_ptr syscall.exec_kernel_proc + # => [H, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw # => [H] end @@ -52,11 +85,18 @@ end #! #! - ACCT_HASH is the hash of the account data. export.get_current_hash - padw - # => [0, 0, 0, 0] + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_current_account_hash_offset + # => [offset, PAD(15)] - exec.memory::get_current_account_hash_ptr syscall.exec_kernel_proc + # => [ACCT_HASH, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw # => [ACCT_HASH] end @@ -68,12 +108,21 @@ end #! - value is the value to increment the nonce by. value can be at most 2^32 - 1 otherwise this #! procedure panics. export.incr_nonce - exec.memory::incr_account_nonce_ptr + # start padding the stack + push.0.0 movup.2 + # => [value, 0, 0] + + exec.kernel_invocation::incr_account_nonce_offset + # => [offset, value, 0, 0] + + # pad the stack + padw swapw padw padw swapdw + # => [offset, value, PAD(14)] + syscall.exec_kernel_proc - # => [0] + # => [PAD(16)] - drop - # => [] + dropw dropw dropw dropw end #! Gets an item from the account storage. Panics if the index is out of bounds. @@ -84,11 +133,21 @@ end #! - index is the index of the item to get. #! - VALUE is the value of the item. export.get_item - push.0.0.0 movup.3 - # => [index, 0, 0, 0] + push.0.0 movup.2 + # => [index, 0, 0] + + exec.kernel_invocation::get_account_item_offset + # => [offset, index, 0, 0] + + # pad the stack + padw swapw padw padw swapdw + # => [offset, index, PAD(14)] - exec.memory::get_account_item_ptr syscall.exec_kernel_proc + # => [VALUE, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw # => [VALUE] end @@ -102,12 +161,18 @@ end #! - V is the previous value of the item. #! - R' is the new storage root. export.set_item - push.0 movdn.5 push.0 movdn.5 push.0 movdn.5 - # => [index, V', 0, 0, 0] + exec.kernel_invocation::set_account_item_offset + # => [offset, index, V'] - exec.memory::set_account_item_ptr + # pad the stack + push.0.0 movdn.7 movdn.7 padw padw swapdw + # => [offset, index, V', PAD(10)] + syscall.exec_kernel_proc - # => [R', V] + # => [R', V, PAD(8)] + + # clean the stack + swapdw dropw dropw end #! Gets a map item from the account storage. Panics if @@ -121,13 +186,19 @@ end #! - KEY is the key of the item to get. #! - VALUE is the value of the item. export.get_map_item - exec.memory::get_account_map_item_ptr + exec.kernel_invocation::get_account_map_item_offset + # => [offset, index, KEY] + + # pad the stack + push.0.0 movdn.7 movdn.7 padw padw swapdw + # => [offset, index, KEY, PAD(10)] + syscall.exec_kernel_proc - # => [VALUE] + # => [VALUE, PAD(12)] - # prepare stack for return - movup.5 drop - # => [VALUE, 0] + # clean the stack + swapdw dropw dropw swapw dropw + # => [VALUE] end #! Sets a map item in the account storage. Panics if @@ -143,11 +214,18 @@ end #! - OLD_MAP_ROOT is the old map root. #! - OLD_MAP_VALUE is the old value at KEY. export.set_map_item - exec.memory::set_account_map_item_ptr + exec.kernel_invocation::set_account_map_item_offset + # => [offset, index, KEY, VALUE] + + # pad the stack + push.0.0 movdn.11 movdn.11 padw movdnw.3 + # => [offset, index, KEY, VALUE, PAD(6)] + syscall.exec_kernel_proc - # => [OLD_MAP_ROOT, OLD_MAP_VALUE, 0] + # => [OLD_MAP_ROOT, OLD_MAP_VALUE, PAD(8)] - movup.8 drop + # clean the stack + swapdw dropw dropw # => [OLD_MAP_ROOT, OLD_MAP_VALUE] end @@ -159,11 +237,18 @@ end #! #! - CODE_COMMITMENT is the hash of the code to set. export.set_code - exec.memory::set_account_code_ptr + exec.kernel_invocation::set_account_code_offset + # => [offset, CODE_COMMITMENT] + + # pad the stack + push.0.0.0 movdn.7 movdn.7 movdn.7 padw padw swapdw + # => [offset, CODE_COMMITMENT, PAD(11)] + syscall.exec_kernel_proc - # => [0, 0, 0, 0] + # => [PAD(16)] - dropw + # clean the stack + dropw dropw dropw dropw # => [] end @@ -176,8 +261,18 @@ end #! - faucet_id is the faucet id of the fungible asset of interest. #! - balance is the vault balance of the fungible asset. export.get_balance - exec.memory::account_vault_get_balance_ptr + exec.kernel_invocation::account_vault_get_balance_offset + # => [offset, faucet_id] + + # pad the stack + push.0.0 movdn.3 movdn.3 padw swapw padw padw swapdw + # => [offset, faucet_id, PAD(14)] + syscall.exec_kernel_proc + # => [balance, PAD(15)] + + # clean the stack + swapdw dropw dropw swapw dropw movdn.3 drop drop drop # => [balance] end @@ -190,11 +285,18 @@ end #! - ASSET is the non-fungible asset of interest #! - has_asset is a boolean indicating whether the account vault has the asset of interest export.has_non_fungible_asset - exec.memory::account_vault_has_non_fungible_asset_ptr + exec.kernel_invocation::account_vault_has_non_fungible_asset_offset + # => [offset, ASSET] + + # pad the stack + push.0.0.0 movdn.7 movdn.7 movdn.7 padw padw swapdw + # => [offset, ASSET, PAD(11)] + syscall.exec_kernel_proc - # => [has_asset, 0, 0, 0] + # => [has_asset, PAD(15)] - swap drop swap drop swap drop + # clean the stack + swapdw dropw dropw swapw dropw movdn.3 drop drop drop # => [has_asset] end @@ -213,8 +315,19 @@ end #! - If ASSET is a fungible asset, then ASSET' is the total fungible asset in the account vault #! after ASSET was added to it. export.add_asset - exec.memory::account_vault_add_asset_ptr + exec.kernel_invocation::account_vault_add_asset_offset + # => [offset, ASSET] + + # pad the stack + push.0.0.0 movdn.7 movdn.7 movdn.7 padw padw swapdw + # => [offset, ASSET, PAD(11)] + syscall.exec_kernel_proc + # => [ASSET', PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw + # => [ASSET'] end #! Remove the specified asset from the vault. @@ -229,8 +342,19 @@ end #! #! - ASSET is the asset to remove from the vault. export.remove_asset - exec.memory::account_vault_remove_asset_ptr + exec.kernel_invocation::account_vault_remove_asset_offset + # => [offset, ASSET] + + # pad the stack + push.0.0.0 movdn.7 movdn.7 movdn.7 padw padw swapdw + # => [offset, ASSET, PAD(11)] + syscall.exec_kernel_proc + # => [ASSET, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw + # => [ASSET] end #! Returns a commitment to the account vault. @@ -241,12 +365,17 @@ end #! - COM is a commitment to the account vault. export.get_vault_commitment # pad the stack for syscall invocation - padw - # => [0, 0, 0, 0] + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_account_vault_commitment_offset + # => [offset, PAD(15)] - # invoke the syscall - exec.memory::get_account_vault_commitment_ptr syscall.exec_kernel_proc + # => [COM, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw # => [COM] end diff --git a/miden-lib/asm/miden/faucet.masm b/miden-lib/asm/miden/faucet.masm index 2a2640757..f7b333072 100644 --- a/miden-lib/asm/miden/faucet.masm +++ b/miden-lib/asm/miden/faucet.masm @@ -1,4 +1,4 @@ -use.miden::kernels::tx::memory +use.miden::kernel_invocation #! Mint an asset from the faucet the transaction is being executed against. #! @@ -16,8 +16,18 @@ use.miden::kernels::tx::memory #! #! - ASSET is the asset that was minted. export.mint - exec.memory::mint_asset_ptr + exec.kernel_invocation::mint_asset_offset + # => [offset, ASSET] + + # pad the stack + push.0.0.0 movdn.7 movdn.7 movdn.7 padw padw swapdw + # => [offset, ASSET, PAD(11)] + syscall.exec_kernel_proc + # => [ASSET, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw # => [ASSET] end @@ -38,8 +48,18 @@ end #! #! - ASSET is the asset that was burned. export.burn - exec.memory::burn_asset_ptr + exec.kernel_invocation::burn_asset_offset + # => [offset, ASSET] + + # pad the stack + push.0.0.0 movdn.7 movdn.7 movdn.7 padw padw swapdw + # => [offset, ASSET, PAD(11)] + syscall.exec_kernel_proc + # => [ASSET, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw # => [ASSET] end @@ -54,12 +74,17 @@ end #! - total_issuance is the total issuance of the fungible faucet the transaction is being executed #! against. export.get_total_issuance - # add padding to the stack for kernel invocation - push.0 - # => [0] + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_fungible_faucet_total_issuance_offset + # => [offset, PAD(15)] - # invoke the `get_fungible_faucet_total_issuance` kernel procedure - exec.memory::get_fungible_faucet_total_issuance_ptr syscall.exec_kernel_proc + # => [total_issuance, PAD(15)] + + # clean the stack + swapdw dropw dropw swapw dropw movdn.3 drop drop drop # => [total_issuance] end diff --git a/miden-lib/asm/miden/kernel_invocation.masm b/miden-lib/asm/miden/kernel_invocation.masm new file mode 100644 index 000000000..1db22ab12 --- /dev/null +++ b/miden-lib/asm/miden/kernel_invocation.masm @@ -0,0 +1,375 @@ +# KERNEL PROCEDURE OFFSETS +# ================================================================================================= + +# OFFSET CONSTANTS +# ------------------------------------------------------------------------------------------------- + +# The offsets at which hash of the corresponding procedure is stored. +# const.EXEC_KERNEL_PROC_OFFSET=0 +const.ACCOUNT_VAULT_GET_BALANCE_OFFSET=1 +const.GET_ACCOUNT_MAP_ITEM_OFFSET=2 +const.GET_ACCOUNT_ITEM_OFFSET=3 +const.GET_CURRENT_ACCOUNT_HASH_OFFSET=4 +const.GET_ACCOUNT_NONCE_OFFSET=5 +const.SET_ACCOUNT_ITEM_OFFSET=6 +const.GET_INITIAL_ACCOUNT_HASH_OFFSET=7 +const.MINT_ASSET_OFFSET=8 +const.GET_ACCOUNT_ID_OFFSET=9 +const.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_OFFSET=10 +const.BURN_ASSET_OFFSET=11 +const.INCR_ACCOUNT_NONCE_OFFSET=12 +const.CREATE_NOTE_OFFSET=13 +const.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_OFFSET=14 +const.GET_BLOCK_HASH_OFFSET=15 +const.GET_BLOCK_NUMBER_OFFSET=16 +const.ACCOUNT_VAULT_ADD_ASSET_OFFSET=17 +const.GET_NOTE_SERIAL_NUMBER_OFFSET=18 +const.GET_ACCOUNT_VAULT_COMMITMENT_OFFSET=19 +const.ACCOUNT_VAULT_REMOVE_ASSET_OFFSET=20 +const.SET_ACCOUNT_CODE_OFFSET=21 +const.GET_NOTE_ASSETS_INFO_OFFSET=22 +const.GET_NOTE_SENDER_OFFSET=23 +const.SET_ACCOUNT_MAP_ITEM_OFFSET=24 +const.GET_NOTE_INPUTS_HASH_OFFSET=25 +const.ADD_ASSET_TO_NOTE_OFFSET=26 +const.GET_OUTPUT_NOTES_HASH_OFFSET=27 +const.GET_INPUT_NOTES_COMMITMENT_OFFSET=28 + +# ACCESSORS +# ------------------------------------------------------------------------------------------------- + +#! Returns an offset of the `get_account_id` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_account_id` kernel procedure required to get the address +#! where this procedure is stored. +export.get_account_id_offset + push.GET_ACCOUNT_ID_OFFSET +end + +#! Returns an offset of the `get_account_nonce` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_account_nonce` kernel procedure required to get the +#! address where this procedure is stored. +export.get_account_nonce_offset + push.GET_ACCOUNT_NONCE_OFFSET +end + +#! Returns an offset of the `get_initial_account_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_initial_account_hash` kernel procedure required to get +#! the address where this procedure is stored. +export.get_initial_account_hash_offset + push.GET_INITIAL_ACCOUNT_HASH_OFFSET +end + +#! Returns an offset of the `get_current_account_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_current_account_hash` kernel procedure required to get +#! the address where this procedure is stored. +export.get_current_account_hash_offset + push.GET_CURRENT_ACCOUNT_HASH_OFFSET +end + +#! Returns an offset of the `incr_account_nonce` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `incr_account_nonce` kernel procedure required to get the +#! address where this procedure is stored. +export.incr_account_nonce_offset + push.INCR_ACCOUNT_NONCE_OFFSET +end + +#! Returns an offset of the `get_account_item` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_account_item` kernel procedure required to get the +#! address where this procedure is stored. +export.get_account_item_offset + push.GET_ACCOUNT_ITEM_OFFSET +end + +#! Returns an offset of the `set_account_item` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `set_account_item` kernel procedure required to get the +#! address where this procedure is stored. +export.set_account_item_offset + push.SET_ACCOUNT_ITEM_OFFSET +end + +#! Returns an offset of the `get_account_map_item` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_account_map_item` kernel procedure required to get the +#! address where this procedure is stored. +export.get_account_map_item_offset + push.GET_ACCOUNT_MAP_ITEM_OFFSET +end + +#! Returns an offset of the `set_account_map_item` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `set_account_map_item` kernel procedure required to get the +#! address where this procedure is stored. +export.set_account_map_item_offset + push.SET_ACCOUNT_MAP_ITEM_OFFSET +end + +#! Returns an offset of the `set_account_code` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `set_account_code` kernel procedure required to get the +#! address where this procedure is stored. +export.set_account_code_offset + push.SET_ACCOUNT_CODE_OFFSET +end + +#! Returns an offset of the `account_vault_get_balance` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `account_vault_get_balance` kernel procedure required to get +#! the address where this procedure is stored. +export.account_vault_get_balance_offset + push.ACCOUNT_VAULT_GET_BALANCE_OFFSET +end + +#! Returns an offset of the `account_vault_has_non_fungible_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `account_vault_has_non_fungible_asset` kernel procedure +#! required to get the address where this procedure is stored. +export.account_vault_has_non_fungible_asset_offset + push.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_OFFSET +end + +#! Returns an offset of the `account_vault_add_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `account_vault_add_asset` kernel procedure required to get the +#! address where this procedure is stored. +export.account_vault_add_asset_offset + push.ACCOUNT_VAULT_ADD_ASSET_OFFSET +end + +#! Returns an offset of the `account_vault_remove_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `account_vault_remove_asset` kernel procedure required to get +#! the address where this procedure is stored. +export.account_vault_remove_asset_offset + push.ACCOUNT_VAULT_REMOVE_ASSET_OFFSET +end + +#! Returns an offset of the `get_note_assets_info` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_note_assets_info` kernel procedure required to get the +#! address where this procedure is stored. +export.get_note_assets_info_offset + push.GET_NOTE_ASSETS_INFO_OFFSET +end + +#! Returns an offset of the `get_note_inputs_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_note_inputs_hash` kernel procedure required to get the +#! address where this procedure is stored. +export.get_note_inputs_hash_offset + push.GET_NOTE_INPUTS_HASH_OFFSET +end + +#! Returns an offset of the `get_note_sender` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_note_sender` kernel procedure required to get the address +#! where this procedure is stored. +export.get_note_sender_offset + push.GET_NOTE_SENDER_OFFSET +end + +#! Returns an offset of the `get_block_number` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_block_number` kernel procedure required to get the +#! address where this procedure is stored. +export.get_block_number_offset + push.GET_BLOCK_NUMBER_OFFSET +end + +#! Returns an offset of the `get_block_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_block_hash` kernel procedure required to get the address +#! where this procedure is stored. +export.get_block_hash_offset + push.GET_BLOCK_HASH_OFFSET +end + +#! Returns an offset of the `get_input_notes_commitment` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_input_notes_commitment` kernel procedure required to get +#! the address where this procedure is stored. +export.get_input_notes_commitment_offset + push.GET_INPUT_NOTES_COMMITMENT_OFFSET +end + +#! Returns an offset of the `get_output_notes_hash` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_output_notes_hash` kernel procedure required to get the +#! address where this procedure is stored. +export.get_output_notes_hash_offset + push.GET_OUTPUT_NOTES_HASH_OFFSET +end + +#! Returns an offset of the `create_note` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `create_note` kernel procedure required to get the address +#! where this procedure is stored. +export.create_note_offset + push.CREATE_NOTE_OFFSET +end + +#! Returns an offset of the `add_asset_to_note` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `add_asset_to_note` kernel procedure required to get the +#! address where this procedure is stored. +export.add_asset_to_note_offset + push.ADD_ASSET_TO_NOTE_OFFSET +end + +#! Returns an offset of the `get_account_vault_commitment` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_account_vault_commitment` kernel procedure required to +#! get the address where this procedure is stored. +export.get_account_vault_commitment_offset + push.GET_ACCOUNT_VAULT_COMMITMENT_OFFSET +end + +#! Returns an offset of the `mint_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `mint_asset` kernel procedure required to get the address +#! where this procedure is stored. +export.mint_asset_offset + push.MINT_ASSET_OFFSET +end + +#! Returns an offset of the `burn_asset` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `burn_asset` kernel procedure required to get the address +#! where this procedure is stored. +export.burn_asset_offset + push.BURN_ASSET_OFFSET +end + +#! Returns an offset of the `get_fungible_faucet_total_issuance` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_fungible_faucet_total_issuance` kernel procedure required +#! to get the address where this procedure is stored. +export.get_fungible_faucet_total_issuance_offset + push.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_OFFSET +end + +#! Returns an offset of the `get_note_serial_number` kernel procedure. +#! +#! Stack: [] +#! Output: [proc_offset] +#! +#! Where: +#! - proc_offset is the offset of the `get_note_serial_number` kernel procedure required to get the +#! address where this procedure is stored. +export.get_note_serial_number_offset + push.GET_NOTE_SERIAL_NUMBER_OFFSET +end \ No newline at end of file diff --git a/miden-lib/asm/miden/note.masm b/miden-lib/asm/miden/note.masm index ca9da2fd5..1b67227cc 100644 --- a/miden-lib/asm/miden/note.masm +++ b/miden-lib/asm/miden/note.masm @@ -1,4 +1,4 @@ -use.miden::kernels::tx::memory +use.miden::kernel_invocation use.std::crypto::hashes::native use.std::mem @@ -46,12 +46,18 @@ end #! - dest_ptr is the memory address to write the assets. #! - num_assets is the number of assets in the currently executing note. export.get_assets - padw push.0 - # => [0, 0, 0, 0, 0, dest_ptr] + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15), dest_ptr] + + exec.kernel_invocation::get_note_assets_info_offset + # => [offset, PAD(15), dest_ptr] - # get the current input note assets info - exec.memory::get_note_assets_info_ptr syscall.exec_kernel_proc + # => [ASSETS_HASH, num_assets, PAD(11), dest_ptr] + + # clean the stack + swapdw dropw dropw movup.7 movup.7 movup.7 drop drop drop # => [ASSETS_HASH, num_assets, dest_ptr] # load the asset data from the advice map to the advice stack @@ -85,9 +91,18 @@ end #! - inputs_len, the note's input count. #! - INPUTS, the data corresponding to the note's inputs. export.get_inputs - padw - exec.memory::get_note_inputs_hash_ptr + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15), dest_ptr] + + exec.kernel_invocation::get_note_inputs_hash_offset + # => [offset, PAD(15), dest_ptr] + syscall.exec_kernel_proc + # => [INPUTS_HASH, PAD(12), dest_ptr] + + # clean the stack + swapdw dropw dropw swapw dropw # => [INPUTS_HASH, dest_ptr] # load the inputs from the advice map to the advice stack @@ -126,11 +141,18 @@ end #! #! - sender is the sender of the note currently being processed. export.get_sender - push.0 - # => [0] + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_note_sender_offset + # => [offset, PAD(15)] - exec.memory::get_note_sender_ptr syscall.exec_kernel_proc + # => [sender, PAD(15)] + + # clean the stack + swapdw dropw dropw swapw dropw movdn.3 drop drop drop # => [sender] end @@ -142,11 +164,18 @@ end #! #! - SERIAL_NUMBER is the serial number of the note currently being processed. export.get_serial_number - padw - # => [0, 0, 0, 0] + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_note_serial_number_offset + # => [offset, PAD(15)] - exec.memory::get_note_serial_number_ptr syscall.exec_kernel_proc + # => [SERIAL_NUMBER, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw # => [SERIAL_NUMBER] end diff --git a/miden-lib/asm/miden/tx.masm b/miden-lib/asm/miden/tx.masm index e9cf33d7e..8178d300f 100644 --- a/miden-lib/asm/miden/tx.masm +++ b/miden-lib/asm/miden/tx.masm @@ -1,4 +1,4 @@ -use.miden::kernels::tx::memory +use.miden::kernel_invocation #! Returns the block number of the last known block at the time of transaction execution. #! @@ -7,11 +7,18 @@ use.miden::kernels::tx::memory #! #! num is the last known block number. export.get_block_number - push.0 - # => [0] + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_block_number_offset + # => [offset, PAD(15)] - exec.memory::get_block_number_ptr syscall.exec_kernel_proc + # => [num, PAD(15)] + + # clean the stack + swapdw dropw dropw swapw dropw movdn.3 drop drop drop # => [num] end @@ -23,9 +30,18 @@ end #! Where: #! - BLOCK_HASH, reference block for the transaction execution. export.get_block_hash - padw - exec.memory::get_block_hash_ptr + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_block_hash_offset + # => [offset, PAD(15)] + syscall.exec_kernel_proc + # => [BLOCK_HASH, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw # => [BLOCK_HASH] end @@ -39,10 +55,19 @@ end #! Where: #! - INPUT_NOTES_COMMITMENT is the input notes commitment hash. export.get_input_notes_commitment - padw - exec.memory::get_input_notes_commitment_ptr + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_input_notes_commitment_offset + # => [offset, PAD(15)] + syscall.exec_kernel_proc - # => [INPUT_NOTES_COMMITMENT] + # => [INPUT_NOTES_COMMITMENT, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw + # => [INPUT_NOTES_COMMITMENT] end #! Returns the output notes hash. This is computed as a sequential hash of (note_id, note_metadata) @@ -53,12 +78,19 @@ end #! #! COM is the output notes hash. export.get_output_notes_hash - padw - # => [0, 0, 0, 0] + # pad the stack + padw padw padw push.0.0.0 + # => [PAD(15)] + + exec.kernel_invocation::get_output_notes_hash_offset + # => [offset, PAD(15)] - exec.memory::get_output_notes_hash_ptr syscall.exec_kernel_proc - # => [COM] + # => [COM, PAD(12)] + + # clean the stack + swapdw dropw dropw swapw dropw + # => [COM] end #! Creates a new note and returns the index of the note. @@ -75,10 +107,12 @@ end export.create_note # pad the stack before the syscall to prevent accidental modification of the deeper stack # elements - padw padw swapdw - # => [tag, aux, note_type, execution_hint, RECIPIENT, PAD(8)] + padw padw swapdw movup.8 drop + # => [tag, aux, note_type, execution_hint, RECIPIENT, PAD(7)] + + exec.kernel_invocation::create_note_offset + # => [offset, tag, aux, note_type, execution_hint, RECIPIENT, PAD(7)] - exec.memory::create_note_ptr syscall.exec_kernel_proc # => [note_idx, PAD(15)] @@ -95,12 +129,14 @@ end #! note_idx is the index of the note to which the asset is added. #! ASSET can be a fungible or non-fungible asset. export.add_asset_to_note + movup.4 exec.kernel_invocation::add_asset_to_note_offset + # => [offset, note_idx, ASSET] + # pad the stack before the syscall to prevent accidental modification of the deeper stack # elements - push.0.0.0 padw padw swapdw movup.7 swapw movup.4 - # => [note_idx, ASSET, PAD(11)] + push.0.0 movdn.7 movdn.7 padw padw swapdw + # => [offset, note_idx, ASSET, PAD(10)] - exec.memory::add_asset_to_note_ptr syscall.exec_kernel_proc # => [note_idx, ASSET, PAD(11)] diff --git a/miden-lib/src/transaction/mod.rs b/miden-lib/src/transaction/mod.rs index f92d99ec1..3cac87e15 100644 --- a/miden-lib/src/transaction/mod.rs +++ b/miden-lib/src/transaction/mod.rs @@ -8,7 +8,7 @@ use miden_objects::{ }, utils::{group_slice_elements, serde::Deserializable}, vm::{AdviceInputs, AdviceMap, Program, ProgramInfo, StackInputs, StackOutputs}, - Digest, Felt, TransactionOutputError, Word, EMPTY_WORD, Hasher, + Digest, Felt, Hasher, TransactionOutputError, Word, EMPTY_WORD, }; use miden_stdlib::StdLibrary; @@ -91,12 +91,13 @@ impl TransactionKernel { ) -> (StackInputs, AdviceInputs) { let account = tx_inputs.account(); - let kernel = Self::kernel().kernel(); + let kernel_lib = Self::kernel(); + let kernel = kernel_lib.kernel(); + // we need to get &[Felt] from &[Digest] - let kernel_procs_as_felts = Digest::digests_as_elements(kernel.proc_hashes().into_iter()) + let kernel_procs_as_felts = Digest::digests_as_elements(kernel.proc_hashes().iter()) .cloned() .collect::>(); - // let aboba = kernel.proc_hashes().iter().flat_map(|digest| digest.as_elements().to_vec()).collect::>(); let kernel_hash = Hasher::hash_elements(&kernel_procs_as_felts); let stack_inputs = TransactionKernel::build_input_stack( @@ -302,5 +303,6 @@ impl TransactionKernel { .expect("failed to load miden-lib") .with_library(kernel_library) .expect("failed to load kernel library (/lib)") + .with_debug_mode(true) } } diff --git a/miden-tx/src/tests/kernel_tests/test_prologue.rs b/miden-tx/src/tests/kernel_tests/test_prologue.rs index b0f405ee4..88455da79 100644 --- a/miden-tx/src/tests/kernel_tests/test_prologue.rs +++ b/miden-tx/src/tests/kernel_tests/test_prologue.rs @@ -366,7 +366,7 @@ pub fn test_prologue_create_account() { use.kernel::prologue begin - call.prologue::prepare_transaction + exec.prologue::prepare_transaction end "; diff --git a/miden-tx/src/verifier/mod.rs b/miden-tx/src/verifier/mod.rs index 5006d88ad..bf1485473 100644 --- a/miden-tx/src/verifier/mod.rs +++ b/miden-tx/src/verifier/mod.rs @@ -36,7 +36,7 @@ impl TransactionVerifier { // compute the kernel hash let kernel = self.tx_program_info.kernel(); // we need to get &[Felt] from &[Digest] - let kernel_procs_as_felts = Digest::digests_as_elements(kernel.proc_hashes().into_iter()) + let kernel_procs_as_felts = Digest::digests_as_elements(kernel.proc_hashes().iter()) .cloned() .collect::>(); let kernel_hash = Hasher::hash_elements(&kernel_procs_as_felts); @@ -47,7 +47,7 @@ impl TransactionVerifier { transaction.account_update().init_state_hash(), transaction.input_notes().commitment(), transaction.block_ref(), - (kernel.proc_hashes().len(), kernel_hash) + (kernel.proc_hashes().len(), kernel_hash), ); let stack_outputs = TransactionKernel::build_output_stack( transaction.account_update().final_state_hash(), diff --git a/objects/src/testing/account_code.rs b/objects/src/testing/account_code.rs index 0129baec5..f25fe9c23 100644 --- a/objects/src/testing/account_code.rs +++ b/objects/src/testing/account_code.rs @@ -7,16 +7,16 @@ use crate::accounts::AccountCode; const MASTS: [&str; 12] = [ "0xff06b90f849c4b262cbfbea67042c4ea017ea0e9c558848a951d44b23370bec5", "0x8ef0092134469a1330e3c468f57c7f085ce611645d09cc7516c786fefc71d794", - "0xed87fcbdaf52f9d544d6362c0177f7294d917dfdbf48ee31b3df7b28be6f4ea0", - "0xf26ab9001bbe615e3f39e6bf5c12dd32754b99d9476c6dd003881c3c52a6bfc1", - "0x3f4b2dadf8a08e963898bc172f3fb1f4cbd7c560cb1d5f88eec582d0f9819edb", - "0x31c806646881424c912cf5af6ad8002fe1f24cdc83e769525dd6c68df94a8f3b", - "0x1b4fd4fc6d711276c4b25dc9e9b8dff6feb8f3762562fcecf45b85c7e4ed2437", - "0x8197f4791b030c86bd4e3e4a241de840de47fa1ec338b8668ddb37052eee00a6", - "0x16d574d4d5a70f83c86843a62a19ca647d2110c11cfd5cb2fc93a149f3c9c2c5", - "0x70573a57c1b809e6feacf3bfeda3c6a22e4ef018979d2a0f9d466e54ed9c44a5", - "0x60cc189b72db5eae2de193245a5c979bc8c322a98d3980bff068e1c80c066306", - "0x875149b782d20eeda59477e260c173fbb477d1f6f755820d0bfb214ce0ebe78b", + "0xa69d960467d9484c79812394587b81b13258a8c76ce7e458229323c734136bf0", + "0x68d503aba05d48bfb8ed4647a54df4e2f4f3f380868300710f991e201407ae36", + "0x18af4d279042d8042eadb854bb58e546bc7546a0b37f34dfd2fc7f995f8f33ce", + "0xaeeed1fe7453d66dd0f175fa1e4a9534eaa9928ee4ba6cc41ea27f41ec619038", + "0x5a600fe00f66dd29083a2985e310da0f85cfc90e5faf4c7661a5c2a91ebcde69", + "0x5c739834a3f5d34fc4c27bc78fd72939a9fa98cce7c5d6bb477624e3431b22ee", + "0xfb2afc65a25b322cdf51bf5450e4c32b93fdde19da351ac8cf28145f19969016", + "0xe1d6c52a75a15cee295e9f787a8bd0c73996b878b746f9c9f7ea9a7af83e6e50", + "0x1798f2959f525fc9b55b0307542600fb987afd965533c993cffa73461e1a1be2", + "0x0651c2b7081d29268e28fe2b99da0cebccd9515d228974a1b3959b12b3a4a448", ]; pub const ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT: &str = MASTS[2]; From 338cd45e9128a3a7b7faf96f919ff7dcd6697d93 Mon Sep 17 00:00:00 2001 From: Andrey Date: Mon, 2 Sep 2024 19:09:40 +0300 Subject: [PATCH 03/11] refactor: create proc hash array, move kernel inputs from op stack to advice stack --- bench-tx/bench-tx.json | 16 +- miden-lib/asm/kernels/transaction/api.masm | 19 +- .../asm/kernels/transaction/lib/prologue.masm | 23 +- miden-lib/asm/miden/account.masm | 10 +- miden-lib/asm/miden/kernel_invocation.masm | 57 +++-- miden-lib/src/transaction/inputs.rs | 19 +- miden-lib/src/transaction/mod.rs | 28 +-- miden-lib/src/transaction/procedures.rs | 204 ++++++++++++++++++ miden-tx/src/verifier/mod.rs | 13 +- objects/src/testing/account_code.rs | 18 +- 10 files changed, 306 insertions(+), 101 deletions(-) create mode 100644 miden-lib/src/transaction/procedures.rs diff --git a/bench-tx/bench-tx.json b/bench-tx/bench-tx.json index 353a35003..ea67a51ea 100644 --- a/bench-tx/bench-tx.json +++ b/bench-tx/bench-tx.json @@ -1,21 +1,21 @@ { "simple": { - "prologue": 3833, - "notes_processing": 2178, + "prologue": 4065, + "notes_processing": 2526, "note_execution": { - "0x8cb51db3dbec8fab6c0ce3ac3e332aaa28fc99de07ae5a52dd93047a1fe459c2": 1401, - "0xed95b651bebd558f84ece32c4e7b8ac7b0fff9d845d3bff86037b64e9f9c7245": 735 + "0x5c5e81a3c7b9950283a3e63e3526cdf189728a8f63d5459c6e43567ff22cc683": 851, + "0x8c3f1ace49f9b66d75c27e4b38a0082ddb8b8c5d1475e02399188c54eed5df32": 1633 }, "tx_script_processing": 44, "epilogue": 2287 }, "p2id": { - "prologue": 2141, - "notes_processing": 1012, + "prologue": 2373, + "notes_processing": 1357, "note_execution": { - "0xc1299ce481078310e6b4cf09f005bd898468019bb4cf7a03f5ded4b9e518790f": 977 + "0x0105f1a0142b9ebc6bfba0b09de88807eac595b46b70f0fea403ce01aee1fe54": 1322 }, - "tx_script_processing": 88460, + "tx_script_processing": 88989, "epilogue": 291 } } \ No newline at end of file diff --git a/miden-lib/asm/kernels/transaction/api.masm b/miden-lib/asm/kernels/transaction/api.masm index ab05814bf..0ce04a3b3 100644 --- a/miden-lib/asm/kernels/transaction/api.masm +++ b/miden-lib/asm/kernels/transaction/api.masm @@ -766,27 +766,32 @@ end #! Executes a kernel procedure specified by its offset. #! -#! Inputs: [procedure_offset, *executed_procedure_input*, PAD(*)] -#! Outputs: [*executed_procedure_output*, PAD(*)] +#! Inputs: [procedure_offset, procedure_inputs, PAD(*)] +#! Outputs: [procedure_outputs, PAD(*)] #! +#! Where: #! - procedure_offset is an offset of the kernel procedure, specified in the -#! `miden/kernel_invocation.masm` file. +#! `miden/kernel_invocation.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 12 elements, since the +#! first word on the stack will be occupied by the procedure hash. +#! - procedure_outputs are the outputs of the procedure to be executed. export.exec_kernel_proc # compute the memory pointer at which desired procedure is stored exec.memory::get_kernel_procedures_ptr add - # => [procedure_pointer, *executed_procedure_input*, PAD(*)] + # => [procedure_pointer, procedure_inputs, PAD(*)] # prepare stack for procedure hash obtaining padw movup.4 - # => [procedure_pointer, 0, 0, 0, 0, *executed_procedure_input*, PAD(*)] + # => [procedure_pointer, 0, 0, 0, 0, procedure_inputs, PAD(*)] # load kernel procedure hash mem_loadw - # => [KERNEL_PROCEDURE_HASH, *executed_procedure_input*, PAD(*)] + # => [KERNEL_PROCEDURE_HASH, procedure_inputs, PAD(*)] # execute loaded procedure dynexec - # => [*executed_procedure_output*, PAD(*)] + # => [procedure_outputs, PAD(*)] exec.sys::truncate_stack end diff --git a/miden-lib/asm/kernels/transaction/lib/prologue.masm b/miden-lib/asm/kernels/transaction/lib/prologue.masm index 98d63ad65..ac642a1f6 100644 --- a/miden-lib/asm/kernels/transaction/lib/prologue.masm +++ b/miden-lib/asm/kernels/transaction/lib/prologue.masm @@ -104,23 +104,32 @@ end #! Saves the hashes of the kernel procedures to memory and verifies that it matches the KERNEL_HASH #! public input. #! -#! Stack: [kernel_procs_len, KERNEL_HASH] #! Advice stack: [ -#! [KERNEL_PROCS] +#! kernel_procs_len, +#! [KERNEL_PROCS], +#! KERNEL_HASH #! ] #! Output: [] #! #! Where: #! - kernel_procs_len, number of kernel procedures. -#! - KERNEL_HASH, hash of all kernel procedures. #! - [KERNEL_PROCS], array of hashes of the kernel procedures. +#! - KERNEL_HASH, hash of all kernel procedures. proc.process_kernel_data + # get the number of kernel procedures + adv_push.1 + # => [kernel_procs_len] + # get the pointer to the memory where hashes of the kernel procedures will be stored exec.memory::get_kernel_procedures_ptr swap - # => [kernel_procs_len, kernel_procs_ptr, KERNEL_HASH] + # => [kernel_procs_len, kernel_procs_ptr] # store the kernel procedures to the memory - exec.mem::pipe_preimage_to_memory + exec.mem::pipe_words_to_memory + # => [SEQ_HASH, kernel_procs_ptr'] + + # get the precomputed hash and assert that it matches the computed one + padw adv_loadw assert_eqw # => [kernel_procs_ptr'] drop @@ -1124,11 +1133,11 @@ end #! account_id, #! INITIAL_ACCOUNT_HASH, #! INPUT_NOTES_COMMITMENT, -#! kernel_procs_len, -#! KERNEL_HASH #! ] #! Advice stack: [ +#! kernel_procs_len, #! [KERNEL_PROCS] +#! KERNEL_HASH #! PREVIOUS_BLOCK_HASH, #! CHAIN_MMR_HASH, #! ACCOUNT_ROOT, diff --git a/miden-lib/asm/miden/account.masm b/miden-lib/asm/miden/account.masm index c4399c3ee..15a7e83d3 100644 --- a/miden-lib/asm/miden/account.masm +++ b/miden-lib/asm/miden/account.masm @@ -7,11 +7,8 @@ use.miden::kernel_invocation #! #! - acct_id is the account id. export.get_id - push.0 - # => [0] - # start padding the stack - push.0.0 + push.0.0.0 exec.kernel_invocation::get_account_id_offset # => [offset, 0, 0, 0] @@ -35,11 +32,8 @@ end #! #! - nonce is the account nonce. export.get_nonce - push.0 - # => [0] - # start padding the stack - push.0.0 + push.0.0.0 exec.kernel_invocation::get_account_nonce_offset # => [offset, 0, 0, 0] diff --git a/miden-lib/asm/miden/kernel_invocation.masm b/miden-lib/asm/miden/kernel_invocation.masm index 1db22ab12..f262b6911 100644 --- a/miden-lib/asm/miden/kernel_invocation.masm +++ b/miden-lib/asm/miden/kernel_invocation.masm @@ -4,36 +4,35 @@ # OFFSET CONSTANTS # ------------------------------------------------------------------------------------------------- -# The offsets at which hash of the corresponding procedure is stored. -# const.EXEC_KERNEL_PROC_OFFSET=0 -const.ACCOUNT_VAULT_GET_BALANCE_OFFSET=1 -const.GET_ACCOUNT_MAP_ITEM_OFFSET=2 -const.GET_ACCOUNT_ITEM_OFFSET=3 -const.GET_CURRENT_ACCOUNT_HASH_OFFSET=4 -const.GET_ACCOUNT_NONCE_OFFSET=5 +const.GET_ACCOUNT_ID_OFFSET=0 +const.GET_ACCOUNT_NONCE_OFFSET=1 +const.GET_INITIAL_ACCOUNT_HASH_OFFSET=2 +const.GET_CURRENT_ACCOUNT_HASH_OFFSET=3 +const.INCR_ACCOUNT_NONCE_OFFSET=4 +const.GET_ACCOUNT_ITEM_OFFSET=5 const.SET_ACCOUNT_ITEM_OFFSET=6 -const.GET_INITIAL_ACCOUNT_HASH_OFFSET=7 -const.MINT_ASSET_OFFSET=8 -const.GET_ACCOUNT_ID_OFFSET=9 -const.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_OFFSET=10 -const.BURN_ASSET_OFFSET=11 -const.INCR_ACCOUNT_NONCE_OFFSET=12 -const.CREATE_NOTE_OFFSET=13 -const.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_OFFSET=14 -const.GET_BLOCK_HASH_OFFSET=15 -const.GET_BLOCK_NUMBER_OFFSET=16 -const.ACCOUNT_VAULT_ADD_ASSET_OFFSET=17 -const.GET_NOTE_SERIAL_NUMBER_OFFSET=18 -const.GET_ACCOUNT_VAULT_COMMITMENT_OFFSET=19 -const.ACCOUNT_VAULT_REMOVE_ASSET_OFFSET=20 -const.SET_ACCOUNT_CODE_OFFSET=21 -const.GET_NOTE_ASSETS_INFO_OFFSET=22 -const.GET_NOTE_SENDER_OFFSET=23 -const.SET_ACCOUNT_MAP_ITEM_OFFSET=24 -const.GET_NOTE_INPUTS_HASH_OFFSET=25 -const.ADD_ASSET_TO_NOTE_OFFSET=26 -const.GET_OUTPUT_NOTES_HASH_OFFSET=27 -const.GET_INPUT_NOTES_COMMITMENT_OFFSET=28 +const.GET_ACCOUNT_MAP_ITEM_OFFSET=7 +const.SET_ACCOUNT_MAP_ITEM_OFFSET=8 +const.SET_ACCOUNT_CODE_OFFSET=9 +const.ACCOUNT_VAULT_GET_BALANCE_OFFSET=10 +const.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_OFFSET=11 +const.ACCOUNT_VAULT_ADD_ASSET_OFFSET=12 +const.ACCOUNT_VAULT_REMOVE_ASSET_OFFSET=13 +const.GET_NOTE_ASSETS_INFO_OFFSET=14 +const.GET_NOTE_INPUTS_HASH_OFFSET=15 +const.GET_NOTE_SENDER_OFFSET=16 +const.GET_BLOCK_NUMBER_OFFSET=17 +const.GET_BLOCK_HASH_OFFSET=18 +const.GET_INPUT_NOTES_COMMITMENT_OFFSET=19 +const.GET_OUTPUT_NOTES_HASH_OFFSET=20 +const.CREATE_NOTE_OFFSET=21 +const.ADD_ASSET_TO_NOTE_OFFSET=22 +const.GET_ACCOUNT_VAULT_COMMITMENT_OFFSET=23 +const.MINT_ASSET_OFFSET=24 +const.BURN_ASSET_OFFSET=25 +const.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_OFFSET=26 +const.GET_NOTE_SERIAL_NUMBER_OFFSET=27 +const.EXEC_KERNEL_PROC_OFFSET=28 # ACCESSORS # ------------------------------------------------------------------------------------------------- diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index 364dfe350..238bc0620 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -4,7 +4,7 @@ use miden_objects::{ accounts::Account, transaction::{ChainMmr, InputNote, TransactionArgs, TransactionInputs, TransactionScript}, vm::AdviceInputs, - Felt, FieldElement, Word, EMPTY_WORD, ZERO, + Felt, FieldElement, Hasher, Word, EMPTY_WORD, ZERO, }; // ADVICE INPUTS @@ -19,7 +19,7 @@ use miden_objects::{ pub(super) fn extend_advice_inputs( tx_inputs: &TransactionInputs, tx_args: &TransactionArgs, - kernel_procs: Vec, + kernel_procs: (usize, Vec), advice_inputs: &mut AdviceInputs, ) { build_advice_stack(tx_inputs, tx_args.tx_script(), kernel_procs, advice_inputs); @@ -39,7 +39,9 @@ pub(super) fn extend_advice_inputs( /// The following data is pushed to the advice stack: /// /// [ +/// number_of_kernel_procedures, /// [KERNEL_PROCS_HASHES], +/// KERNEL_HASH, /// PREVIOUS_BLOCK_HASH, /// CHAIN_MMR_HASH, /// ACCOUNT_ROOT, @@ -59,11 +61,20 @@ pub(super) fn extend_advice_inputs( fn build_advice_stack( tx_inputs: &TransactionInputs, tx_script: Option<&TransactionScript>, - kernel_procs: Vec, + kernel_procs: (usize, Vec), inputs: &mut AdviceInputs, ) { + // compute the kernel procs hash + let kernel_hash = Hasher::hash_elements(&kernel_procs.1); + + // push the number of kernel procedures to the advice stack + inputs.extend_stack([Felt::new(kernel_procs.0 as u64)]); + // push hashes of the kernel procedures to the advice stack - inputs.extend_stack(kernel_procs); + inputs.extend_stack(kernel_procs.1); + + // push the hash of the kernel to the advice stack + inputs.extend_stack(kernel_hash); // push block header info into the stack // Note: keep in sync with the process_block_data kernel procedure diff --git a/miden-lib/src/transaction/mod.rs b/miden-lib/src/transaction/mod.rs index 3cac87e15..df8a7a4c2 100644 --- a/miden-lib/src/transaction/mod.rs +++ b/miden-lib/src/transaction/mod.rs @@ -8,7 +8,7 @@ use miden_objects::{ }, utils::{group_slice_elements, serde::Deserializable}, vm::{AdviceInputs, AdviceMap, Program, ProgramInfo, StackInputs, StackOutputs}, - Digest, Felt, Hasher, TransactionOutputError, Word, EMPTY_WORD, + Digest, Felt, TransactionOutputError, Word, EMPTY_WORD, }; use miden_stdlib::StdLibrary; @@ -31,6 +31,8 @@ pub use errors::{ TransactionEventParsingError, TransactionKernelError, TransactionTraceParsingError, }; +mod procedures; + // CONSTANTS // ================================================================================================ @@ -91,25 +93,24 @@ impl TransactionKernel { ) -> (StackInputs, AdviceInputs) { let account = tx_inputs.account(); - let kernel_lib = Self::kernel(); - let kernel = kernel_lib.kernel(); - - // we need to get &[Felt] from &[Digest] - let kernel_procs_as_felts = Digest::digests_as_elements(kernel.proc_hashes().iter()) + let kernel_procs_as_felts = Digest::digests_as_elements(Self::PROCEDURES.iter()) .cloned() .collect::>(); - let kernel_hash = Hasher::hash_elements(&kernel_procs_as_felts); let stack_inputs = TransactionKernel::build_input_stack( account.id(), account.init_hash(), tx_inputs.input_notes().commitment(), tx_inputs.block_header().hash(), - (kernel.proc_hashes().len(), kernel_hash), ); let mut advice_inputs = init_advice_inputs.unwrap_or_default(); - inputs::extend_advice_inputs(tx_inputs, tx_args, kernel_procs_as_felts, &mut advice_inputs); + inputs::extend_advice_inputs( + tx_inputs, + tx_args, + (Self::PROCEDURES.len(), kernel_procs_as_felts), + &mut advice_inputs, + ); (stack_inputs, advice_inputs) } @@ -141,8 +142,6 @@ impl TransactionKernel { /// acct_id, /// INITIAL_ACCOUNT_HASH, /// INPUT_NOTES_COMMITMENT, - /// kernel_procs_len, - /// KERNEL_HASH /// ] /// ``` /// @@ -151,19 +150,14 @@ impl TransactionKernel { /// - acct_id, the account that the transaction is being executed against. /// - INITIAL_ACCOUNT_HASH, account state prior to the transaction, EMPTY_WORD for new accounts. /// - INPUT_NOTES_COMMITMENT, see `transaction::api::get_input_notes_commitment`. - /// - kernel_procs_len, number of the procedures in the used kernel. - /// - KERNEL_HASH, hash of the entire kernel. pub fn build_input_stack( acct_id: AccountId, init_acct_hash: Digest, input_notes_hash: Digest, block_hash: Digest, - kernel: (usize, Digest), ) -> StackInputs { // Note: Must be kept in sync with the transaction's kernel prepare_transaction procedure - let mut inputs: Vec = Vec::with_capacity(18); - inputs.extend(kernel.1); - inputs.push(Felt::from(kernel.0 as u16)); + let mut inputs: Vec = Vec::with_capacity(13); inputs.extend(input_notes_hash); inputs.extend_from_slice(init_acct_hash.as_elements()); inputs.push(acct_id.into()); diff --git a/miden-lib/src/transaction/procedures.rs b/miden-lib/src/transaction/procedures.rs new file mode 100644 index 000000000..095b6942e --- /dev/null +++ b/miden-lib/src/transaction/procedures.rs @@ -0,0 +1,204 @@ +use miden_objects::{Digest, Felt}; + +use super::TransactionKernel; + +impl TransactionKernel { + pub const PROCEDURES: [Digest; 28] = [ + // get_account_id + Digest::new([ + Felt::new(8040261465733444704), + Felt::new(11111141085375373880), + Felt::new(7423929485586361344), + Felt::new(4119214601469502087), + ]), + // get_account_nonce + Digest::new([ + Felt::new(7949369589472998218), + Felt::new(13470489034885204869), + Felt::new(7657993556512253706), + Felt::new(4189240183103072865), + ]), + // get_initial_account_hash + Digest::new([ + Felt::new(16301123123708038227), + Felt::new(8835228777116955671), + Felt::new(1233594748884564040), + Felt::new(17497683909577038473), + ]), + // get_current_account_hash + Digest::new([ + Felt::new(18067387847945059633), + Felt::new(4630780713348682492), + Felt::new(16252299253975780120), + Felt::new(12604901563870135002), + ]), + // incr_account_nonce + Digest::new([ + Felt::new(11251993684560653453), + Felt::new(5231315954748375505), + Felt::new(6829555386766719516), + Felt::new(861981902332051880), + ]), + // get_account_item + Digest::new([ + Felt::new(6804600891105189676), + Felt::new(16357628444217998414), + Felt::new(9431845352605151209), + Felt::new(15608374733320272356), + ]), + // set_account_item + Digest::new([ + Felt::new(16244037745099512397), + Felt::new(16681829146325299211), + Felt::new(1331329308944150161), + Felt::new(16938907804846009042), + ]), + // get_account_map_item + Digest::new([ + Felt::new(3623586774841825559), + Felt::new(3709840750311142467), + Felt::new(12112504263612227679), + Felt::new(7718484063050107365), + ]), + // set_account_map_item + Digest::new([ + Felt::new(17054146566056119736), + Felt::new(16675792548721351168), + Felt::new(17840066796402754003), + Felt::new(4494493169083431642), + ]), + // set_account_code + Digest::new([ + Felt::new(4526386433602912172), + Felt::new(15601621292843281722), + Felt::new(6836940574893007865), + Felt::new(4561881232782527243), + ]), + // account_vault_get_balance + Digest::new([ + Felt::new(7035484340365940230), + Felt::new(17797159859808856495), + Felt::new(10586583242494928923), + Felt::new(9763511907089065699), + ]), + // account_vault_has_non_fungible_asset + Digest::new([ + Felt::new(3461454265989980777), + Felt::new(16222005807253493271), + Felt::new(5019331476826215138), + Felt::new(8747291997159999285), + ]), + // account_vault_add_asset + Digest::new([ + Felt::new(2077165816463172772), + Felt::new(6872053568248293880), + Felt::new(11884643902037361372), + Felt::new(11504756226677395192), + ]), + // account_vault_remove_asset + Digest::new([ + Felt::new(14790659034050634409), + Felt::new(10792738914573874947), + Felt::new(15240944025598720155), + Felt::new(12388802549660890868), + ]), + // get_note_assets_info + Digest::new([ + Felt::new(12346411220238036656), + Felt::new(18027533406091104744), + Felt::new(14723639276543495147), + Felt::new(11542458885879781389), + ]), + // get_note_inputs_hash + Digest::new([ + Felt::new(17186028199923932877), + Felt::new(2563818256742276816), + Felt::new(8351223767950877211), + Felt::new(11379249881600223287), + ]), + // get_note_sender + Digest::new([ + Felt::new(15233821980580537524), + Felt::new(8874650687593596380), + Felt::new(14910554371357890324), + Felt::new(11945045801206913876), + ]), + // get_block_number + Digest::new([ + Felt::new(16172105872838937242), + Felt::new(15451169972362006388), + Felt::new(10194691898988719168), + Felt::new(4396119213036826856), + ]), + // get_block_hash + Digest::new([ + Felt::new(15575368355470837910), + Felt::new(13483490255982391120), + Felt::new(5407999307430887046), + Felt::new(13895912493177462699), + ]), + // get_input_notes_commitment + Digest::new([ + Felt::new(2019728671844693749), + Felt::new(18222437788741437389), + Felt::new(12821100448410084889), + Felt::new(17418670035031233675), + ]), + // get_output_notes_hash + Digest::new([ + Felt::new(4412523757021344747), + Felt::new(8883378993868597671), + Felt::new(16885133168375194469), + Felt::new(15472424727696440458), + ]), + // create_note + Digest::new([ + Felt::new(14929021903257629840), + Felt::new(8604463029064930594), + Felt::new(988290775185352928), + Felt::new(8754535948183372308), + ]), + // add_asset_to_note + Digest::new([ + Felt::new(1388074421163142360), + Felt::new(9875906781970083545), + Felt::new(11032933281715356329), + Felt::new(6589288277095637140), + ]), + // get_account_vault_commitment + Digest::new([ + Felt::new(15827173769627914405), + Felt::new(8397707743192029429), + Felt::new(7205844492194182641), + Felt::new(1677433344562532693), + ]), + // mint_asset + Digest::new([ + Felt::new(7447962799646185052), + Felt::new(2576161227455352778), + Felt::new(17024702477581969886), + Felt::new(1577277405866978216), + ]), + // burn_asset + Digest::new([ + Felt::new(4798014337306650503), + Felt::new(9491313619529755262), + Felt::new(9813790657994357862), + Felt::new(18320657353147964360), + ]), + // get_fungible_faucet_total_issuance + Digest::new([ + Felt::new(5567752045855424912), + Felt::new(1313115426050254227), + Felt::new(12797601829399057688), + Felt::new(10963909072124913328), + ]), + // get_note_serial_number + Digest::new([ + Felt::new(203467101694736292), + Felt::new(1871816977533069235), + Felt::new(11026610821411620572), + Felt::new(8345006103126977916), + ]), + ]; +} diff --git a/miden-tx/src/verifier/mod.rs b/miden-tx/src/verifier/mod.rs index bf1485473..af69ecbe9 100644 --- a/miden-tx/src/verifier/mod.rs +++ b/miden-tx/src/verifier/mod.rs @@ -1,7 +1,5 @@ -use alloc::vec::Vec; - use miden_lib::transaction::TransactionKernel; -use miden_objects::{transaction::ProvenTransaction, vm::ProgramInfo, Digest, Felt, Hasher}; +use miden_objects::{transaction::ProvenTransaction, vm::ProgramInfo}; use miden_verifier::verify; use super::TransactionVerifierError; @@ -33,21 +31,12 @@ impl TransactionVerifier { /// - Transaction verification fails. /// - The security level of the verified proof is insufficient. pub fn verify(&self, transaction: ProvenTransaction) -> Result<(), TransactionVerifierError> { - // compute the kernel hash - let kernel = self.tx_program_info.kernel(); - // we need to get &[Felt] from &[Digest] - let kernel_procs_as_felts = Digest::digests_as_elements(kernel.proc_hashes().iter()) - .cloned() - .collect::>(); - let kernel_hash = Hasher::hash_elements(&kernel_procs_as_felts); - // build stack inputs and outputs let stack_inputs = TransactionKernel::build_input_stack( transaction.account_id(), transaction.account_update().init_state_hash(), transaction.input_notes().commitment(), transaction.block_ref(), - (kernel.proc_hashes().len(), kernel_hash), ); let stack_outputs = TransactionKernel::build_output_stack( transaction.account_update().final_state_hash(), diff --git a/objects/src/testing/account_code.rs b/objects/src/testing/account_code.rs index f25fe9c23..1164b5382 100644 --- a/objects/src/testing/account_code.rs +++ b/objects/src/testing/account_code.rs @@ -7,16 +7,16 @@ use crate::accounts::AccountCode; const MASTS: [&str; 12] = [ "0xff06b90f849c4b262cbfbea67042c4ea017ea0e9c558848a951d44b23370bec5", "0x8ef0092134469a1330e3c468f57c7f085ce611645d09cc7516c786fefc71d794", - "0xa69d960467d9484c79812394587b81b13258a8c76ce7e458229323c734136bf0", - "0x68d503aba05d48bfb8ed4647a54df4e2f4f3f380868300710f991e201407ae36", - "0x18af4d279042d8042eadb854bb58e546bc7546a0b37f34dfd2fc7f995f8f33ce", - "0xaeeed1fe7453d66dd0f175fa1e4a9534eaa9928ee4ba6cc41ea27f41ec619038", - "0x5a600fe00f66dd29083a2985e310da0f85cfc90e5faf4c7661a5c2a91ebcde69", - "0x5c739834a3f5d34fc4c27bc78fd72939a9fa98cce7c5d6bb477624e3431b22ee", - "0xfb2afc65a25b322cdf51bf5450e4c32b93fdde19da351ac8cf28145f19969016", - "0xe1d6c52a75a15cee295e9f787a8bd0c73996b878b746f9c9f7ea9a7af83e6e50", + "0x9500d49982f77c1b2eb66b2b688231fe10016a4b3cdcabfb2166dad6f1010197", + "0x58f266daa7521633681586a39e57d2d9ae5e7198bc958eaef001e523b38310ef", + "0x50e3fd0680161b1e48d5039c063903330330d6a5d8475be4d98e2c72c2b160d6", + "0x1b9dd32a282bd3bec1c192f1cb054b2e70d590372f6cd49ef0676cc09313b722", + "0x35004c7db85e6ac2471626db24c08da5e72532a8347dea8ed99d60419db4a78f", + "0x096b2c2bec8f88ef1f303d33bac07356f900515463bc9de72733451cc1b32b11", + "0xcd8d4567204fbf42c169fe88de615989de598f164a418736dfd5c2d833c7be04", + "0x812682907302f1070be8a7f920c168ba217429d3ba5b07bae30ceda234d18095", "0x1798f2959f525fc9b55b0307542600fb987afd965533c993cffa73461e1a1be2", - "0x0651c2b7081d29268e28fe2b99da0cebccd9515d228974a1b3959b12b3a4a448", + "0x79cbe48ff495c041b985f2dc6a0e1455e8f571354e8121a2eef0764d366c5f02", ]; pub const ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT: &str = MASTS[2]; From d55599289e6084b1cc097331146e2ee6b33d0158 Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 4 Sep 2024 19:20:07 +0300 Subject: [PATCH 04/11] refactor: add kernel root to the block header --- .../asm/kernels/transaction/lib/memory.masm | 9 +- .../asm/kernels/transaction/lib/prologue.masm | 104 +++++++++++++----- miden-lib/src/transaction/inputs.rs | 51 +++++---- miden-lib/src/transaction/memory.rs | 11 +- miden-lib/src/transaction/mod.rs | 18 ++- miden-lib/src/transaction/procedures.rs | 21 +++- miden-tx/src/testing/mock_chain.rs | 4 + .../src/tests/kernel_tests/test_prologue.rs | 17 ++- miden-tx/src/verifier/mod.rs | 2 + objects/src/block/header.rs | 16 +++ objects/src/testing/block.rs | 40 ++++++- objects/src/transaction/chain_mmr.rs | 1 + 12 files changed, 218 insertions(+), 76 deletions(-) diff --git a/miden-lib/asm/kernels/transaction/lib/memory.masm b/miden-lib/asm/kernels/transaction/lib/memory.masm index adc891027..c010d6306 100644 --- a/miden-lib/asm/kernels/transaction/lib/memory.masm +++ b/miden-lib/asm/kernels/transaction/lib/memory.masm @@ -70,14 +70,17 @@ const.NULLIFIER_ROOT_PTR=203 # The memory address at which the tx hash is stored const.TX_HASH_PTR=204 +# The memory address at which the kernel root is stored +const.KERNEL_ROOT_PTR=205 + # The memory address at which the proof hash is stored -const.PROOF_HASH_PTR=205 +const.PROOF_HASH_PTR=206 # The memory address at which the block metadata is stored [block_number, version, timestamp, 0] -const.BLOCK_METADATA_PTR=206 +const.BLOCK_METADATA_PTR=207 # The memory address at which the note root is stored -const.NOTE_ROOT_PTR=207 +const.NOTE_ROOT_PTR=208 # CHAIN MMR # ------------------------------------------------------------------------------------------------- diff --git a/miden-lib/asm/kernels/transaction/lib/prologue.masm b/miden-lib/asm/kernels/transaction/lib/prologue.masm index ac642a1f6..df9732011 100644 --- a/miden-lib/asm/kernels/transaction/lib/prologue.masm +++ b/miden-lib/asm/kernels/transaction/lib/prologue.masm @@ -104,36 +104,84 @@ end #! Saves the hashes of the kernel procedures to memory and verifies that it matches the KERNEL_HASH #! public input. #! -#! Advice stack: [ -#! kernel_procs_len, -#! [KERNEL_PROCS], -#! KERNEL_HASH -#! ] +#! Stack: [kernel_offset] +#! Advice Stack: [KERNEL_ROOT] +#! Advice Map: { +#! KERNEL_ROOT: [KERNEL_HASHES] +#! KERNEL_HASH: [KERNEL_PROCEDURE_HASHES] +#! } #! Output: [] #! #! Where: -#! - kernel_procs_len, number of kernel procedures. -#! - [KERNEL_PROCS], array of hashes of the kernel procedures. -#! - KERNEL_HASH, hash of all kernel procedures. +#! - kernel_offset, index of the desired kernel in the array of all kernels available for the +#! current transaction +#! - KERNEL_ROOT, accumulative hash from all kernel hashes. +#! - [KERNEL_HASHES], array of each kernel hash +#! - [KERNEL_PROCEDURE_HASHES], array of procedure hashes of the current kernel proc.process_kernel_data - # get the number of kernel procedures - adv_push.1 - # => [kernel_procs_len] + # move the kernel root to the stack + adv_loadw + # S => [KERNEL_ROOT, kernel_offset] + # AS => [] + + # push the kernel hashes from the advice map to the advice stack + adv.push_mapvaln + # S => [KERNEL_ROOT, kernel_offset] + # AS => [len_felts, [KERNEL_HASHES]] + + # move the number of felt elements in the [KERNEL_HASHES] array to the stack and get the + # number of Words from it + adv_push.1 div.4 + # S => [len_words, KERNEL_ROOT, kernel_offset] + # AS => [[KERNEL_HASHES]] + + # get the pointer to the memory where kernel hashes will be stored + # Note: for now we use the same address for kernel hash and for kernel procedures since there is + # only one kernel and its hash will be overwritten by the procedures anyway. + exec.memory::get_kernel_procedures_ptr swap + # S => [len_words, kernel_mem_ptr, KERNEL_ROOT, kernel_offset] + # AS => [[KERNEL_HASHES]] + + # store the kernel hashes in memory + exec.mem::pipe_words_to_memory + # S => [SEQ_HASH, kernel_mem_ptr', KERNEL_ROOT, kernel_offset] + # AS => [] + + # assert that sequential hash matches the precomputed kernel root + movup.4 drop assert_eqw + # S => [kernel_offset] + + # get the hash of the kernel which will be used in the current transaction + exec.memory::get_kernel_procedures_ptr add + # S => [kernel_ptr] + + padw movup.4 mem_loadw + # S => [KERNEL_HASH] + + # push the procedure hashes of the chosen kernel from the advice map to the advice stack + adv.push_mapvaln + # S => [KERNEL_HASH] + # AS => [len_felts, [PROC_HASHES]] + + # move the number of felt elements in the [PROC_HASHES] array to the stack and get the + # number of Words from it + adv_push.1 div.4 + # S => [len_words, KERNEL_HASH] + # AS => [[PROC_HASHES]] # get the pointer to the memory where hashes of the kernel procedures will be stored exec.memory::get_kernel_procedures_ptr swap - # => [kernel_procs_len, kernel_procs_ptr] + # S => [len_words, kernel_procs_ptr, KERNEL_HASH] + # AS => [[PROC_HASHES]] # store the kernel procedures to the memory exec.mem::pipe_words_to_memory - # => [SEQ_HASH, kernel_procs_ptr'] - - # get the precomputed hash and assert that it matches the computed one - padw adv_loadw assert_eqw - # => [kernel_procs_ptr'] + # S => [SEQ_HASH, kernel_procs_ptr', KERNEL_HASH] + # AS => [] - drop - # => [] + # assert that the precomputed hash matches the computed one + movup.4 drop assert_eqw + # S => [] end # BLOCK DATA @@ -148,9 +196,9 @@ end #! ACCOUNT_ROOT, #! NULLIFIER_ROOT, #! TX_HASH, +#! KERNEL_ROOT #! PROOF_HASH, #! [block_num, version, timestamp, 0], -#! EMPTY_WORD, #! NOTE_ROOT, #! ] #! Output: [] @@ -161,6 +209,7 @@ end #! - ACCOUNT_ROOT, root of the tree with latest account states for all accounts. #! - NULLIFIER_ROOT, root of the tree with nullifiers of all notes that have ever been consumed. #! - TX_HASH, commitment to a set of IDs of transactions which affected accounts in the block. +#! - KERNEL_ROOT, accumulative hash from all kernel hashes. #! - PROOF_HASH, hash of the block's stark proof. #! - block_num, the reference block number. #! - version, current protocol version. @@ -1133,19 +1182,18 @@ end #! account_id, #! INITIAL_ACCOUNT_HASH, #! INPUT_NOTES_COMMITMENT, +#! kernel_offset, #! ] #! Advice stack: [ -#! kernel_procs_len, -#! [KERNEL_PROCS] -#! KERNEL_HASH +#! KERNEL_ROOT #! PREVIOUS_BLOCK_HASH, #! CHAIN_MMR_HASH, #! ACCOUNT_ROOT, #! NULLIFIER_ROOT, #! TX_HASH, +#! KERNEL_ROOT #! PROOF_HASH, #! [block_num, version, timestamp, 0], -#! EMPTY_WORD, #! NOTE_ROOT, #! [account_id, 0, 0, account_nonce], #! ACCOUNT_VAULT_ROOT, @@ -1157,6 +1205,8 @@ end #! Advice map: { #! CHAIN_MMR_HASH: MMR_PEAKS, #! INPUT_NOTES_COMMITMENT => NOTE_DATA, +#! KERNEL_ROOT => KERNEL_HASHES +#! KERNEL_HASH => KERNEL_PROCEDURE_HASHES #! } #! Output: [] #! @@ -1165,9 +1215,9 @@ end #! - account_id, the account that the transaction is being executed against. #! - INITIAL_ACCOUNT_HASH, account state prior to the transaction, EMPTY_WORD for new accounts. #! - INPUT_NOTES_COMMITMENT, see `transaction::api::get_input_notes_commitment`. -#! - kernel_procs_len, number of kernel procedures. -#! - KERNEL_HASH, hash of all kernel procedures. -#! - [KERNEL_PROCS], array of hashes of the kernel procedures. +#! - kernel_offset, index of the desired kernel in the array of all kernels available for the +#! current transaction. +#! - KERNEL_ROOT, accumulative hash from all kernel hashes. #! - PREVIOUS_BLOCK_HASH, hash of the previous block. #! - CHAIN_MMR_HASH, sequential hash of the reference MMR. #! - ACCOUNT_ROOT, root of the tree with latest account states for all accounts. diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index 238bc0620..17e787520 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -4,9 +4,11 @@ use miden_objects::{ accounts::Account, transaction::{ChainMmr, InputNote, TransactionArgs, TransactionInputs, TransactionScript}, vm::AdviceInputs, - Felt, FieldElement, Hasher, Word, EMPTY_WORD, ZERO, + Felt, FieldElement, Word, EMPTY_WORD, ZERO, }; +use super::TransactionKernel; + // ADVICE INPUTS // ================================================================================================ @@ -19,12 +21,12 @@ use miden_objects::{ pub(super) fn extend_advice_inputs( tx_inputs: &TransactionInputs, tx_args: &TransactionArgs, - kernel_procs: (usize, Vec), advice_inputs: &mut AdviceInputs, ) { - build_advice_stack(tx_inputs, tx_args.tx_script(), kernel_procs, advice_inputs); + build_advice_stack(tx_inputs, tx_args.tx_script(), advice_inputs); // build the advice map and Merkle store for relevant components + add_kernel_hashes_to_advice_inputs(advice_inputs); add_chain_mmr_to_advice_inputs(tx_inputs.block_chain(), advice_inputs); add_account_to_advice_inputs(tx_inputs.account(), tx_inputs.account_seed(), advice_inputs); add_input_notes_to_advice_inputs(tx_inputs, tx_args, advice_inputs); @@ -39,17 +41,15 @@ pub(super) fn extend_advice_inputs( /// The following data is pushed to the advice stack: /// /// [ -/// number_of_kernel_procedures, -/// [KERNEL_PROCS_HASHES], -/// KERNEL_HASH, +/// KERNEL_ROOT /// PREVIOUS_BLOCK_HASH, /// CHAIN_MMR_HASH, /// ACCOUNT_ROOT, /// NULLIFIER_ROOT, /// TX_HASH, +/// KERNEL_ROOT /// PROOF_HASH, /// [block_num, version, timestamp, 0], -/// ZERO, /// NOTE_ROOT, /// [account_id, 0, 0, account_nonce], /// ACCOUNT_VAULT_ROOT, @@ -61,29 +61,21 @@ pub(super) fn extend_advice_inputs( fn build_advice_stack( tx_inputs: &TransactionInputs, tx_script: Option<&TransactionScript>, - kernel_procs: (usize, Vec), inputs: &mut AdviceInputs, ) { - // compute the kernel procs hash - let kernel_hash = Hasher::hash_elements(&kernel_procs.1); - - // push the number of kernel procedures to the advice stack - inputs.extend_stack([Felt::new(kernel_procs.0 as u64)]); - - // push hashes of the kernel procedures to the advice stack - inputs.extend_stack(kernel_procs.1); + let header = tx_inputs.block_header(); - // push the hash of the kernel to the advice stack - inputs.extend_stack(kernel_hash); + // push the accumulative hash of all kernels to the advice stack + inputs.extend_stack(header.kernel_root()); // push block header info into the stack // Note: keep in sync with the process_block_data kernel procedure - let header = tx_inputs.block_header(); inputs.extend_stack(header.prev_hash()); inputs.extend_stack(header.chain_root()); inputs.extend_stack(header.account_root()); inputs.extend_stack(header.nullifier_root()); inputs.extend_stack(header.tx_hash()); + inputs.extend_stack(header.kernel_root()); inputs.extend_stack(header.proof_hash()); inputs.extend_stack([ header.block_num().into(), @@ -91,7 +83,6 @@ fn build_advice_stack( header.timestamp().into(), ZERO, ]); - inputs.extend_stack(EMPTY_WORD); inputs.extend_stack(header.note_root()); // push core account items onto the stack @@ -307,3 +298,23 @@ fn add_input_notes_to_advice_inputs( // NOTE: keep map in sync with the `prologue::process_input_notes_data` kernel procedure inputs.extend_map([(tx_inputs.input_notes().commitment(), note_data)]); } + +// KERNEL HASHES INJECTOR +// ------------------------------------------------------------------------------------------------ + +/// Inserts kernel hashes and hashes of their procedures into the provided advice inputs. +/// +/// Inserts the following entries into the advice map: +/// - The accumulative hash of all kernels |-> array of each kernel hash. +/// - The hash of the kernel `i` (for every `i`) |-> array of the current kernel's procedure hashes. +pub fn add_kernel_hashes_to_advice_inputs(inputs: &mut AdviceInputs) { + let kernel_hashes = [TransactionKernel::kernel_hash().as_elements()].concat(); + + // insert kernels root with kernel hashes into the advice map + inputs.extend_map([(TransactionKernel::kernel_root(), kernel_hashes)]); + + // insert kernel hash with procedure hashes into the advice map + // TODO: insert kernel procedures iterating over kernels + inputs + .extend_map([(TransactionKernel::kernel_hash(), TransactionKernel::procedures_as_felts())]); +} diff --git a/miden-lib/src/transaction/memory.rs b/miden-lib/src/transaction/memory.rs index 6c10089ce..345111c7c 100644 --- a/miden-lib/src/transaction/memory.rs +++ b/miden-lib/src/transaction/memory.rs @@ -14,7 +14,7 @@ pub type StorageSlot = u8; // | ------------- | :------------:| :-----------:| // | Bookkeeping | 0 | 4 | // | Global inputs | 100 | 105 | -// | Block header | 200 | 207 | +// | Block header | 200 | 208 | // | Chain MMR | 300 | 332? | // | Account data | 400 | 651? | // | Account procedures| 999 | ? | @@ -97,11 +97,14 @@ pub const NULLIFIER_DB_ROOT_PTR: MemoryAddress = 203; /// The memory address at which the TX hash is stored pub const TX_HASH_PTR: MemoryAddress = 204; +/// The memory address at which the kernel root is stored +pub const KERNEL_ROOT_PTR: MemoryAddress = 205; + /// The memory address at which the proof hash is stored -pub const PROOF_HASH_PTR: MemoryAddress = 205; +pub const PROOF_HASH_PTR: MemoryAddress = 206; /// The memory address at which the block number is stored -pub const BLOCK_METADATA_PTR: MemoryAddress = 206; +pub const BLOCK_METADATA_PTR: MemoryAddress = 207; /// The index of the block number within the block metadata pub const BLOCK_NUMBER_IDX: DataIndex = 0; @@ -113,7 +116,7 @@ pub const PROTOCOL_VERSION_IDX: DataIndex = 1; pub const TIMESTAMP_IDX: DataIndex = 2; /// The memory address at which the note root is stored -pub const NOTE_ROOT_PTR: MemoryAddress = 207; +pub const NOTE_ROOT_PTR: MemoryAddress = 208; // CHAIN DATA // ------------------------------------------------------------------------------------------------ diff --git a/miden-lib/src/transaction/mod.rs b/miden-lib/src/transaction/mod.rs index df8a7a4c2..4ff6ce53a 100644 --- a/miden-lib/src/transaction/mod.rs +++ b/miden-lib/src/transaction/mod.rs @@ -93,24 +93,17 @@ impl TransactionKernel { ) -> (StackInputs, AdviceInputs) { let account = tx_inputs.account(); - let kernel_procs_as_felts = Digest::digests_as_elements(Self::PROCEDURES.iter()) - .cloned() - .collect::>(); - let stack_inputs = TransactionKernel::build_input_stack( account.id(), account.init_hash(), tx_inputs.input_notes().commitment(), tx_inputs.block_header().hash(), + // TODO: change the hardcoded offset to the kernel index provided by user + 0, ); let mut advice_inputs = init_advice_inputs.unwrap_or_default(); - inputs::extend_advice_inputs( - tx_inputs, - tx_args, - (Self::PROCEDURES.len(), kernel_procs_as_felts), - &mut advice_inputs, - ); + inputs::extend_advice_inputs(tx_inputs, tx_args, &mut advice_inputs); (stack_inputs, advice_inputs) } @@ -142,6 +135,7 @@ impl TransactionKernel { /// acct_id, /// INITIAL_ACCOUNT_HASH, /// INPUT_NOTES_COMMITMENT, + /// kernel_offset /// ] /// ``` /// @@ -150,14 +144,18 @@ impl TransactionKernel { /// - acct_id, the account that the transaction is being executed against. /// - INITIAL_ACCOUNT_HASH, account state prior to the transaction, EMPTY_WORD for new accounts. /// - INPUT_NOTES_COMMITMENT, see `transaction::api::get_input_notes_commitment`. + /// - kernel_offset, index of the desired kernel in the array of all kernels available for the + /// current transaction. pub fn build_input_stack( acct_id: AccountId, init_acct_hash: Digest, input_notes_hash: Digest, block_hash: Digest, + kernel_offset: u8, ) -> StackInputs { // Note: Must be kept in sync with the transaction's kernel prepare_transaction procedure let mut inputs: Vec = Vec::with_capacity(13); + inputs.push(Felt::from(kernel_offset)); inputs.extend(input_notes_hash); inputs.extend_from_slice(init_acct_hash.as_elements()); inputs.push(acct_id.into()); diff --git a/miden-lib/src/transaction/procedures.rs b/miden-lib/src/transaction/procedures.rs index 095b6942e..dfa530415 100644 --- a/miden-lib/src/transaction/procedures.rs +++ b/miden-lib/src/transaction/procedures.rs @@ -1,8 +1,11 @@ -use miden_objects::{Digest, Felt}; +use alloc::vec::Vec; + +use miden_objects::{Digest, Felt, Hasher}; use super::TransactionKernel; impl TransactionKernel { + /// Hashes of all dynamically executed kernel procedures. pub const PROCEDURES: [Digest; 28] = [ // get_account_id Digest::new([ @@ -201,4 +204,20 @@ impl TransactionKernel { Felt::new(8345006103126977916), ]), ]; + + pub fn procedures_as_felts() -> Vec { + Digest::digests_as_elements(Self::PROCEDURES.iter()) + .cloned() + .collect::>() + } + + /// Computes the accumulative hash of all kernel procedures. + pub fn kernel_hash() -> Digest { + Hasher::hash_elements(&Self::procedures_as_felts()) + } + + /// Computes a hash from all kernel hashes. + pub fn kernel_root() -> Digest { + Hasher::hash_elements(&[Self::kernel_hash().as_elements()].concat()) + } } diff --git a/miden-tx/src/testing/mock_chain.rs b/miden-tx/src/testing/mock_chain.rs index 3a6110911..97f45460f 100644 --- a/miden-tx/src/testing/mock_chain.rs +++ b/miden-tx/src/testing/mock_chain.rs @@ -512,6 +512,9 @@ impl MockChain { let tx_hash = compute_tx_hash(self.pending_objects.included_transactions.clone().into_iter()); + // get the hash of all kernels + let kernel_root = TransactionKernel::kernel_root(); + // TODO: Set `proof_hash` to the correct value once the kernel is available. let proof_hash = Digest::default(); @@ -524,6 +527,7 @@ impl MockChain { nullifier_root, note_root, tx_hash, + kernel_root, proof_hash, timestamp, ); diff --git a/miden-tx/src/tests/kernel_tests/test_prologue.rs b/miden-tx/src/tests/kernel_tests/test_prologue.rs index 88455da79..34e918222 100644 --- a/miden-tx/src/tests/kernel_tests/test_prologue.rs +++ b/miden-tx/src/tests/kernel_tests/test_prologue.rs @@ -10,8 +10,9 @@ use miden_lib::transaction::{ INPUT_NOTE_ASSETS_HASH_OFFSET, INPUT_NOTE_ASSETS_OFFSET, INPUT_NOTE_ID_OFFSET, INPUT_NOTE_INPUTS_HASH_OFFSET, INPUT_NOTE_METADATA_OFFSET, INPUT_NOTE_NUM_ASSETS_OFFSET, INPUT_NOTE_SCRIPT_ROOT_OFFSET, INPUT_NOTE_SECTION_OFFSET, INPUT_NOTE_SERIAL_NUM_OFFSET, - NOTE_ROOT_PTR, NULLIFIER_DB_ROOT_PTR, NUM_ACCT_PROCEDURES_PTR, PREV_BLOCK_HASH_PTR, - PROOF_HASH_PTR, PROTOCOL_VERSION_IDX, TIMESTAMP_IDX, TX_HASH_PTR, TX_SCRIPT_ROOT_PTR, + KERNEL_ROOT_PTR, NOTE_ROOT_PTR, NULLIFIER_DB_ROOT_PTR, NUM_ACCT_PROCEDURES_PTR, + PREV_BLOCK_HASH_PTR, PROOF_HASH_PTR, PROTOCOL_VERSION_IDX, TIMESTAMP_IDX, TX_HASH_PTR, + TX_SCRIPT_ROOT_PTR, }, TransactionKernel, }; @@ -165,9 +166,9 @@ fn block_data_memory_assertions(process: &Process, inputs: &Transactio ); assert_eq!( - read_root_mem_value(process, NOTE_ROOT_PTR), - inputs.tx_inputs().block_header().note_root().as_elements(), - "The note root should be stored at the NOTE_ROOT_PTR" + read_root_mem_value(process, KERNEL_ROOT_PTR), + inputs.tx_inputs().block_header().kernel_root().as_elements(), + "The kernel root should be stored at the KERNEL_ROOT_PTR" ); assert_eq!( @@ -193,6 +194,12 @@ fn block_data_memory_assertions(process: &Process, inputs: &Transactio inputs.tx_inputs().block_header().timestamp().into(), "The timestamp should be stored at BLOCK_METADATA_PTR[TIMESTAMP_IDX]" ); + + assert_eq!( + read_root_mem_value(process, NOTE_ROOT_PTR), + inputs.tx_inputs().block_header().note_root().as_elements(), + "The note root should be stored at the NOTE_ROOT_PTR" + ); } fn chain_mmr_memory_assertions(process: &Process, prepared_tx: &TransactionContext) { diff --git a/miden-tx/src/verifier/mod.rs b/miden-tx/src/verifier/mod.rs index af69ecbe9..704c82d0a 100644 --- a/miden-tx/src/verifier/mod.rs +++ b/miden-tx/src/verifier/mod.rs @@ -37,6 +37,8 @@ impl TransactionVerifier { transaction.account_update().init_state_hash(), transaction.input_notes().commitment(), transaction.block_ref(), + // TODO: change the hardcoded offset to the kernel index used in the current transaction + 0, ); let stack_outputs = TransactionKernel::build_output_stack( transaction.account_update().final_state_hash(), diff --git a/objects/src/block/header.rs b/objects/src/block/header.rs index 171422b75..a403668a6 100644 --- a/objects/src/block/header.rs +++ b/objects/src/block/header.rs @@ -35,6 +35,7 @@ pub struct BlockHeader { nullifier_root: Digest, note_root: Digest, tx_hash: Digest, + kernel_root: Digest, proof_hash: Digest, timestamp: u32, sub_hash: Digest, @@ -53,6 +54,7 @@ impl BlockHeader { nullifier_root: Digest, note_root: Digest, tx_hash: Digest, + kernel_root: Digest, proof_hash: Digest, timestamp: u32, ) -> Self { @@ -64,6 +66,7 @@ impl BlockHeader { account_root, nullifier_root, tx_hash, + kernel_root, proof_hash, timestamp, block_num, @@ -84,6 +87,7 @@ impl BlockHeader { nullifier_root, note_root, tx_hash, + kernel_root, proof_hash, timestamp, sub_hash, @@ -151,6 +155,13 @@ impl BlockHeader { self.tx_hash } + /// Returns the kernel root. + /// + /// Kernel root is computed as a sequential hash of all kernel hashes. + pub fn kernel_root(&self) -> Digest { + self.kernel_root + } + /// Returns the proof hash. pub fn proof_hash(&self) -> Digest { self.proof_hash @@ -177,6 +188,7 @@ impl BlockHeader { account_root: Digest, nullifier_root: Digest, tx_hash: Digest, + kernel_root: Digest, proof_hash: Digest, timestamp: u32, block_num: u32, @@ -187,6 +199,7 @@ impl BlockHeader { elements.extend_from_slice(account_root.as_elements()); elements.extend_from_slice(nullifier_root.as_elements()); elements.extend_from_slice(tx_hash.as_elements()); + elements.extend_from_slice(kernel_root.as_elements()); elements.extend_from_slice(proof_hash.as_elements()); elements.extend([block_num.into(), version.into(), timestamp.into(), ZERO]); elements.resize(32, ZERO); @@ -204,6 +217,7 @@ impl Serializable for BlockHeader { self.nullifier_root.write_into(target); self.note_root.write_into(target); self.tx_hash.write_into(target); + self.kernel_root.write_into(target); self.proof_hash.write_into(target); self.timestamp.write_into(target); } @@ -219,6 +233,7 @@ impl Deserializable for BlockHeader { let nullifier_root = source.read()?; let note_root = source.read()?; let tx_hash = source.read()?; + let kernel_root = source.read()?; let proof_hash = source.read()?; let timestamp = source.read()?; @@ -231,6 +246,7 @@ impl Deserializable for BlockHeader { nullifier_root, note_root, tx_hash, + kernel_root, proof_hash, timestamp, )) diff --git a/objects/src/testing/block.rs b/objects/src/testing/block.rs index d09bc5193..f8133ccf5 100644 --- a/objects/src/testing/block.rs +++ b/objects/src/testing/block.rs @@ -35,34 +35,62 @@ impl BlockHeader { .collect::>(), ) .expect("failed to create account db"); - let acct_root = acct_db.root(); + let account_root = acct_db.root(); #[cfg(not(target_family = "wasm"))] - let (prev_hash, chain_root, nullifier_root, note_root, tx_hash, proof_hash, timestamp) = { + let ( + prev_hash, + chain_root, + nullifier_root, + note_root, + tx_hash, + kernel_root, + proof_hash, + timestamp, + ) = { let prev_hash = rand_array::().into(); let chain_root = chain_root.unwrap_or(rand_array::().into()); let nullifier_root = rand_array::().into(); let note_root = note_root.unwrap_or(rand_array::().into()); let tx_hash = rand_array::().into(); + let kernel_root = rand_array::().into(); let proof_hash = rand_array::().into(); let timestamp = rand_value(); - (prev_hash, chain_root, nullifier_root, note_root, tx_hash, proof_hash, timestamp) + ( + prev_hash, + chain_root, + nullifier_root, + note_root, + tx_hash, + kernel_root, + proof_hash, + timestamp, + ) }; #[cfg(target_family = "wasm")] - let (prev_hash, chain_root, nullifier_root, note_root, tx_hash, proof_hash, timestamp) = - Default::default(); + let ( + prev_hash, + chain_root, + nullifier_root, + note_root, + tx_hash, + kernel_root, + proof_hash, + timestamp, + ) = Default::default(); BlockHeader::new( 0, prev_hash, block_num, chain_root, - acct_root, + account_root, nullifier_root, note_root, tx_hash, + kernel_root, proof_hash, timestamp, ) diff --git a/objects/src/transaction/chain_mmr.rs b/objects/src/transaction/chain_mmr.rs index 1020cf622..048e53072 100644 --- a/objects/src/transaction/chain_mmr.rs +++ b/objects/src/transaction/chain_mmr.rs @@ -181,6 +181,7 @@ mod tests { Digest::default(), Digest::default(), Digest::default(), + Digest::default(), 0, ) } From 55bc052d8f152dffeb8ae812246ec826e4fe197b Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 5 Sep 2024 15:59:19 +0300 Subject: [PATCH 05/11] test: fix bug to make P2IDR pass --- miden-lib/src/transaction/procedures.rs | 8 ++++---- miden-tx/tests/integration/scripts/p2idr.rs | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/miden-lib/src/transaction/procedures.rs b/miden-lib/src/transaction/procedures.rs index dfa530415..5d1ece6a1 100644 --- a/miden-lib/src/transaction/procedures.rs +++ b/miden-lib/src/transaction/procedures.rs @@ -128,10 +128,10 @@ impl TransactionKernel { ]), // get_block_number Digest::new([ - Felt::new(16172105872838937242), - Felt::new(15451169972362006388), - Felt::new(10194691898988719168), - Felt::new(4396119213036826856), + Felt::new(957081505105679725), + Felt::new(18012382143736246386), + Felt::new(13337406348155951825), + Felt::new(4537613255382865554), ]), // get_block_hash Digest::new([ diff --git a/miden-tx/tests/integration/scripts/p2idr.rs b/miden-tx/tests/integration/scripts/p2idr.rs index 3a1fb1fb9..83724d5dc 100644 --- a/miden-tx/tests/integration/scripts/p2idr.rs +++ b/miden-tx/tests/integration/scripts/p2idr.rs @@ -90,7 +90,7 @@ fn p2idr_script() { // consume the note. // // Case "reclaimable": block height is 4, reclaim block height is 3. Target and sender account - // can consume the note. The malicious account should never be able to consume the note. + // can consume the note. The malicious account should never be able to consume the note. // -------------------------------------------------------------------------------------------- // CONSTRUCT AND EXECUTE TX (Case "in time" - Target Account Execution Success) // -------------------------------------------------------------------------------------------- @@ -233,7 +233,6 @@ fn p2idr_script() { // CONSTRUCT AND EXECUTE TX (Case "too late" - Malicious Account Failure) // -------------------------------------------------------------------------------------------- - let tx_context_6 = TransactionContextBuilder::new(malicious_account.clone()) .input_notes(vec![note_reclaimable.clone()]) .build(); From eabf4da7b4ae12a3bba6b51b087688bf898170b6 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 5 Sep 2024 16:24:06 +0300 Subject: [PATCH 06/11] refactor: update kenrel proc hashes after rebase --- Cargo.lock | 20 +++--- miden-lib/src/transaction/procedures.rs | 96 ++++++++++++------------- miden-tx/src/verifier/mod.rs | 3 +- 3 files changed, 60 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 604b8ed17..03af73bba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -146,9 +146,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.15" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6" +checksum = "e9d013ecb737093c0e86b151a7b837993cf9ec6c502946cfb44bedc392421e0b" dependencies = [ "jobserver", "libc", @@ -190,18 +190,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstyle", "clap_lex", @@ -1472,9 +1472,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.127" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "indexmap", "itoa", @@ -1574,9 +1574,9 @@ dependencies = [ [[package]] name = "supports-color" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9829b314621dfc575df4e409e79f9d6a66a3bd707ab73f23cb4aa3a854ac854f" +checksum = "8775305acf21c96926c900ad056abeef436701108518cf890020387236ac5a77" dependencies = [ "is_ci", ] diff --git a/miden-lib/src/transaction/procedures.rs b/miden-lib/src/transaction/procedures.rs index 5d1ece6a1..79f234f83 100644 --- a/miden-lib/src/transaction/procedures.rs +++ b/miden-lib/src/transaction/procedures.rs @@ -37,45 +37,45 @@ impl TransactionKernel { ]), // incr_account_nonce Digest::new([ - Felt::new(11251993684560653453), - Felt::new(5231315954748375505), - Felt::new(6829555386766719516), - Felt::new(861981902332051880), + Felt::new(6166980265541679115), + Felt::new(14180799872462142156), + Felt::new(2778474088493363690), + Felt::new(1238401418236321485), ]), // get_account_item Digest::new([ - Felt::new(6804600891105189676), - Felt::new(16357628444217998414), - Felt::new(9431845352605151209), - Felt::new(15608374733320272356), + Felt::new(8242100606610843280), + Felt::new(12256919645951393204), + Felt::new(2951068718765716503), + Felt::new(8986453979900819291), ]), // set_account_item Digest::new([ - Felt::new(16244037745099512397), - Felt::new(16681829146325299211), - Felt::new(1331329308944150161), - Felt::new(16938907804846009042), + Felt::new(7498941893890508814), + Felt::new(5585745677648937735), + Felt::new(13176054907168595727), + Felt::new(14561446422739981128), ]), // get_account_map_item Digest::new([ - Felt::new(3623586774841825559), - Felt::new(3709840750311142467), - Felt::new(12112504263612227679), - Felt::new(7718484063050107365), + Felt::new(5940336313866490980), + Felt::new(9709935953040633522), + Felt::new(2215378650076306714), + Felt::new(7584412679403612847), ]), // set_account_map_item Digest::new([ - Felt::new(17054146566056119736), - Felt::new(16675792548721351168), - Felt::new(17840066796402754003), - Felt::new(4494493169083431642), + Felt::new(9257525779338879284), + Felt::new(5994228928952574041), + Felt::new(3477745056362616903), + Felt::new(1514247258411024664), ]), // set_account_code Digest::new([ - Felt::new(4526386433602912172), - Felt::new(15601621292843281722), - Felt::new(6836940574893007865), - Felt::new(4561881232782527243), + Felt::new(4083640213314520131), + Felt::new(11866061748990108757), + Felt::new(7174634238671132507), + Felt::new(16972174329470134023), ]), // account_vault_get_balance Digest::new([ @@ -93,17 +93,17 @@ impl TransactionKernel { ]), // account_vault_add_asset Digest::new([ - Felt::new(2077165816463172772), - Felt::new(6872053568248293880), - Felt::new(11884643902037361372), - Felt::new(11504756226677395192), + Felt::new(441011557193836424), + Felt::new(14128779488787237713), + Felt::new(9097945909079837843), + Felt::new(1927790173066110370), ]), // account_vault_remove_asset Digest::new([ - Felt::new(14790659034050634409), - Felt::new(10792738914573874947), - Felt::new(15240944025598720155), - Felt::new(12388802549660890868), + Felt::new(6000868439702831595), + Felt::new(9778474833766934115), + Felt::new(1146161010038681475), + Felt::new(1950819778618127304), ]), // get_note_assets_info Digest::new([ @@ -156,17 +156,17 @@ impl TransactionKernel { ]), // create_note Digest::new([ - Felt::new(14929021903257629840), - Felt::new(8604463029064930594), - Felt::new(988290775185352928), - Felt::new(8754535948183372308), + Felt::new(14778603067944873506), + Felt::new(14071319835769664212), + Felt::new(13946705703761691189), + Felt::new(68248535266635199), ]), // add_asset_to_note Digest::new([ - Felt::new(1388074421163142360), - Felt::new(9875906781970083545), - Felt::new(11032933281715356329), - Felt::new(6589288277095637140), + Felt::new(14950372948135486500), + Felt::new(16795936443880575519), + Felt::new(10590371208545379138), + Felt::new(3493796503081669802), ]), // get_account_vault_commitment Digest::new([ @@ -177,17 +177,17 @@ impl TransactionKernel { ]), // mint_asset Digest::new([ - Felt::new(7447962799646185052), - Felt::new(2576161227455352778), - Felt::new(17024702477581969886), - Felt::new(1577277405866978216), + Felt::new(11833462197234963951), + Felt::new(521365474344899632), + Felt::new(12219339115593432087), + Felt::new(3026752009521887157), ]), // burn_asset Digest::new([ - Felt::new(4798014337306650503), - Felt::new(9491313619529755262), - Felt::new(9813790657994357862), - Felt::new(18320657353147964360), + Felt::new(2613729911428583836), + Felt::new(3409713366391106845), + Felt::new(4618787175150657117), + Felt::new(13550289764852635265), ]), // get_fungible_faucet_total_issuance Digest::new([ diff --git a/miden-tx/src/verifier/mod.rs b/miden-tx/src/verifier/mod.rs index 704c82d0a..d97856209 100644 --- a/miden-tx/src/verifier/mod.rs +++ b/miden-tx/src/verifier/mod.rs @@ -37,7 +37,8 @@ impl TransactionVerifier { transaction.account_update().init_state_hash(), transaction.input_notes().commitment(), transaction.block_ref(), - // TODO: change the hardcoded offset to the kernel index used in the current transaction + // TODO: change the hardcoded offset to the kernel index used in the current + // transaction 0, ); let stack_outputs = TransactionKernel::build_output_stack( From 64723f41ebd4aabfc2885400e35ef9ced004fa3b Mon Sep 17 00:00:00 2001 From: Andrey Date: Wed, 11 Sep 2024 18:52:14 +0300 Subject: [PATCH 07/11] refactor: optimize inputs, improve docs and comments, impl digest! macro --- docs/architecture/transactions/contexts.md | 2 +- miden-lib/asm/kernels/transaction/api.masm | 32 +- .../asm/kernels/transaction/lib/memory.masm | 11 + .../asm/kernels/transaction/lib/prologue.masm | 67 +-- miden-lib/asm/miden/account.masm | 32 +- miden-lib/asm/miden/faucet.masm | 8 +- ...vocation.masm => kernel_proc_offsets.masm} | 62 +-- miden-lib/asm/miden/note.masm | 10 +- miden-lib/asm/miden/tx.masm | 14 +- miden-lib/src/transaction/inputs.rs | 32 +- miden-lib/src/transaction/memory.rs | 8 + miden-lib/src/transaction/mod.rs | 7 +- miden-lib/src/transaction/procedures.rs | 408 +++++++++--------- miden-tx/src/verifier/mod.rs | 3 - objects/src/block/header.rs | 5 +- objects/src/testing/account_code.rs | 20 +- 16 files changed, 387 insertions(+), 334 deletions(-) rename miden-lib/asm/miden/{kernel_invocation.masm => kernel_proc_offsets.masm} (90%) diff --git a/docs/architecture/transactions/contexts.md b/docs/architecture/transactions/contexts.md index 8ea1cbd89..e7ca0412d 100644 --- a/docs/architecture/transactions/contexts.md +++ b/docs/architecture/transactions/contexts.md @@ -70,7 +70,7 @@ The [account API](https://github.com/0xPolygonMiden/miden-base/blob/main/miden-l #! Add the specified asset to the vault. #! ... export.add_asset - exec.kernel_invocation::account_vault_add_asset_offset + exec.kernel_proc_offsets::account_vault_add_asset_offset syscall.exec_kernel_proc end ``` diff --git a/miden-lib/asm/kernels/transaction/api.masm b/miden-lib/asm/kernels/transaction/api.masm index 0ce04a3b3..ecd6442d8 100644 --- a/miden-lib/asm/kernels/transaction/api.masm +++ b/miden-lib/asm/kernels/transaction/api.masm @@ -12,10 +12,10 @@ 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 # +# 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 only using a `dynexec` instruction by their hashes stored # -# in the memory. # +# All other procedures must be invoked using a `dynexec` instruction by their hashes stored in # +# the memory. # # ================================================================================================= # ERRORS @@ -598,8 +598,8 @@ end #! Creates a new note and returns the index of the note. #! -#! Inputs: [KERNEL_PROCEDURE_HASH, tag, aux, note_type, execution_hint, RECIPIENT, PAD(4)] -#! Outputs: [note_idx, PAD(15)] +#! Inputs: [KERNEL_PROCEDURE_HASH, tag, aux, note_type, execution_hint, RECIPIENT, pad(4)] +#! Outputs: [note_idx, pad(15)] #! #! tag is the tag to be included in the note. #! aux is the auxiliary metadata to be included in the note. @@ -613,16 +613,16 @@ export.create_note # authenticate that the procedure invocation originates from the account context exec.authenticate_account_origin drop - # => [tag, aux, note_type, execution_hint, RECIPIENT, PAD(8)] + # => [tag, aux, note_type, execution_hint, RECIPIENT, pad(8)] exec.tx::create_note - # => [note_idx, PAD(15)] + # => [note_idx, pad(15)] end #! Adds the ASSET to the note specified by the index. #! -#! Inputs: [KERNEL_PROCEDURE_HASH, note_idx, ASSET, PAD(7)] -#! Outputs: [note_idx, ASSET, PAD(11)] +#! Inputs: [KERNEL_PROCEDURE_HASH, note_idx, ASSET, pad(7)] +#! Outputs: [note_idx, ASSET, pad(11)] #! #! note_idx is the index of the the note to which the asset is added. #! ASSET can be a fungible or non-fungible asset. @@ -766,12 +766,12 @@ end #! Executes a kernel procedure specified by its offset. #! -#! Inputs: [procedure_offset, procedure_inputs, PAD(*)] -#! Outputs: [procedure_outputs, PAD(*)] +#! Inputs: [procedure_offset, , ] +#! Outputs: [, ] #! #! Where: #! - procedure_offset is an offset of the kernel procedure, specified in the -#! `miden/kernel_invocation.masm` file. +#! `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 12 elements, since the #! first word on the stack will be occupied by the procedure hash. @@ -779,19 +779,19 @@ end export.exec_kernel_proc # compute the memory pointer at which desired procedure is stored exec.memory::get_kernel_procedures_ptr add - # => [procedure_pointer, procedure_inputs, PAD(*)] + # => [procedure_pointer, , ] # prepare stack for procedure hash obtaining padw movup.4 - # => [procedure_pointer, 0, 0, 0, 0, procedure_inputs, PAD(*)] + # => [procedure_pointer, 0, 0, 0, 0, , ] # load kernel procedure hash mem_loadw - # => [KERNEL_PROCEDURE_HASH, procedure_inputs, PAD(*)] + # => [KERNEL_PROCEDURE_HASH, , ] # execute loaded procedure dynexec - # => [procedure_outputs, PAD(*)] + # => [, ] exec.sys::truncate_stack end diff --git a/miden-lib/asm/kernels/transaction/lib/memory.masm b/miden-lib/asm/kernels/transaction/lib/memory.masm index c010d6306..7f1a9135d 100644 --- a/miden-lib/asm/kernels/transaction/lib/memory.masm +++ b/miden-lib/asm/kernels/transaction/lib/memory.masm @@ -529,6 +529,17 @@ export.get_tx_hash padw push.TX_HASH_PTR mem_loadw end +#! Returns the kernel root used in the last known block. +#! +#! Stack: [] +#! Output: [KERNEL_ROOT] +#! +#! Where: +#! - KERNEL_ROOT is an accumulative hash from all kernel hashes. +export.get_kernel_root + padw push.KERNEL_ROOT_PTR mem_loadw +end + #! Returns the proof hash of the last known block. #! #! Stack: [] diff --git a/miden-lib/asm/kernels/transaction/lib/prologue.masm b/miden-lib/asm/kernels/transaction/lib/prologue.masm index df9732011..9778bb583 100644 --- a/miden-lib/asm/kernels/transaction/lib/prologue.masm +++ b/miden-lib/asm/kernels/transaction/lib/prologue.masm @@ -101,16 +101,21 @@ end # KERNEL DATA # ================================================================================================= -#! Saves the hashes of the kernel procedures to memory and verifies that it matches the KERNEL_HASH -#! public input. + +#! Saves the procedure hashes of the chosen kernel to memory. Verifies that kernel root and kernel +#! hash match the sequential hash of all kernels and sequential hash of kernel procedures +#! respectively. #! -#! Stack: [kernel_offset] -#! Advice Stack: [KERNEL_ROOT] -#! Advice Map: { +#! Inputs: +#! Stack: [] +#! Advice stack: [kernel_offset] +#! Advice map: { #! KERNEL_ROOT: [KERNEL_HASHES] #! KERNEL_HASH: [KERNEL_PROCEDURE_HASHES] -#! } -#! Output: [] +#! } +#! Outputs: +#! Stack: [] +#! Advice stack: [] #! #! Where: #! - kernel_offset, index of the desired kernel in the array of all kernels available for the @@ -119,69 +124,78 @@ end #! - [KERNEL_HASHES], array of each kernel hash #! - [KERNEL_PROCEDURE_HASHES], array of procedure hashes of the current kernel proc.process_kernel_data - # move the kernel root to the stack - adv_loadw - # S => [KERNEL_ROOT, kernel_offset] + # move the kernel offset to the operand stack + adv_push.1 + # OS => [kernel_offset] + # AS => [] + + # load the kernel root from the memory + exec.memory::get_kernel_root + # OS => [KERNEL_ROOT, kernel_offset] # AS => [] # push the kernel hashes from the advice map to the advice stack adv.push_mapvaln - # S => [KERNEL_ROOT, kernel_offset] + # OS => [KERNEL_ROOT, kernel_offset] # AS => [len_felts, [KERNEL_HASHES]] # move the number of felt elements in the [KERNEL_HASHES] array to the stack and get the # number of Words from it adv_push.1 div.4 - # S => [len_words, KERNEL_ROOT, kernel_offset] + # OS => [len_words, KERNEL_ROOT, kernel_offset] # AS => [[KERNEL_HASHES]] # get the pointer to the memory where kernel hashes will be stored # Note: for now we use the same address for kernel hash and for kernel procedures since there is # only one kernel and its hash will be overwritten by the procedures anyway. exec.memory::get_kernel_procedures_ptr swap - # S => [len_words, kernel_mem_ptr, KERNEL_ROOT, kernel_offset] + # OS => [len_words, kernel_mem_ptr, KERNEL_ROOT, kernel_offset] # AS => [[KERNEL_HASHES]] # store the kernel hashes in memory exec.mem::pipe_words_to_memory - # S => [SEQ_HASH, kernel_mem_ptr', KERNEL_ROOT, kernel_offset] + # OS => [SEQ_HASH, kernel_mem_ptr', KERNEL_ROOT, kernel_offset] # AS => [] # assert that sequential hash matches the precomputed kernel root movup.4 drop assert_eqw - # S => [kernel_offset] + # OS => [kernel_offset] + # AS => [] # get the hash of the kernel which will be used in the current transaction exec.memory::get_kernel_procedures_ptr add - # S => [kernel_ptr] + # OS => [kernel_ptr] + # AS => [] padw movup.4 mem_loadw - # S => [KERNEL_HASH] + # OS => [KERNEL_HASH] + # AS => [] # push the procedure hashes of the chosen kernel from the advice map to the advice stack adv.push_mapvaln - # S => [KERNEL_HASH] + # OS => [KERNEL_HASH] # AS => [len_felts, [PROC_HASHES]] # move the number of felt elements in the [PROC_HASHES] array to the stack and get the # number of Words from it adv_push.1 div.4 - # S => [len_words, KERNEL_HASH] + # OS => [len_words, KERNEL_HASH] # AS => [[PROC_HASHES]] # get the pointer to the memory where hashes of the kernel procedures will be stored exec.memory::get_kernel_procedures_ptr swap - # S => [len_words, kernel_procs_ptr, KERNEL_HASH] + # OS => [len_words, kernel_procs_ptr, KERNEL_HASH] # AS => [[PROC_HASHES]] # store the kernel procedures to the memory exec.mem::pipe_words_to_memory - # S => [SEQ_HASH, kernel_procs_ptr', KERNEL_HASH] + # OS => [SEQ_HASH, kernel_procs_ptr', KERNEL_HASH] # AS => [] # assert that the precomputed hash matches the computed one movup.4 drop assert_eqw - # S => [] + # OS => [] + # AS => [] end # BLOCK DATA @@ -1182,10 +1196,8 @@ end #! account_id, #! INITIAL_ACCOUNT_HASH, #! INPUT_NOTES_COMMITMENT, -#! kernel_offset, #! ] #! Advice stack: [ -#! KERNEL_ROOT #! PREVIOUS_BLOCK_HASH, #! CHAIN_MMR_HASH, #! ACCOUNT_ROOT, @@ -1195,6 +1207,7 @@ end #! PROOF_HASH, #! [block_num, version, timestamp, 0], #! NOTE_ROOT, +#! kernel_offset #! [account_id, 0, 0, account_nonce], #! ACCOUNT_VAULT_ROOT, #! ACCOUNT_STORAGE_ROOT, @@ -1215,8 +1228,6 @@ end #! - account_id, the account that the transaction is being executed against. #! - INITIAL_ACCOUNT_HASH, account state prior to the transaction, EMPTY_WORD for new accounts. #! - INPUT_NOTES_COMMITMENT, see `transaction::api::get_input_notes_commitment`. -#! - kernel_offset, index of the desired kernel in the array of all kernels available for the -#! current transaction. #! - KERNEL_ROOT, accumulative hash from all kernel hashes. #! - PREVIOUS_BLOCK_HASH, hash of the previous block. #! - CHAIN_MMR_HASH, sequential hash of the reference MMR. @@ -1228,6 +1239,8 @@ end #! - version, the current protocol version. #! - timestamp, the current timestamp. #! - NOTE_ROOT, root of the tree with all notes created in the block. +#! - kernel_offset, index of the desired kernel in the array of all kernels available for the +#! current transaction. #! - account_nonce, account's nonce. #! - ACCOUNT_VAULT_ROOT, account's vault root. #! - ACCOUNT_STORAGE_ROOT, account's storage root. @@ -1240,8 +1253,8 @@ export.prepare_transaction exec.process_global_inputs # => [] - exec.process_kernel_data exec.process_block_data + exec.process_kernel_data exec.process_chain_data exec.process_account_data exec.process_input_notes_data diff --git a/miden-lib/asm/miden/account.masm b/miden-lib/asm/miden/account.masm index 15a7e83d3..6cfa851c8 100644 --- a/miden-lib/asm/miden/account.masm +++ b/miden-lib/asm/miden/account.masm @@ -1,4 +1,4 @@ -use.miden::kernel_invocation +use.miden::kernel_proc_offsets #! Returns the account id. #! @@ -10,7 +10,7 @@ export.get_id # start padding the stack push.0.0.0 - exec.kernel_invocation::get_account_id_offset + exec.kernel_proc_offsets::get_account_id_offset # => [offset, 0, 0, 0] # pad the stack @@ -35,7 +35,7 @@ export.get_nonce # start padding the stack push.0.0.0 - exec.kernel_invocation::get_account_nonce_offset + exec.kernel_proc_offsets::get_account_nonce_offset # => [offset, 0, 0, 0] # pad the stack @@ -61,7 +61,7 @@ export.get_initial_hash padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_initial_account_hash_offset + exec.kernel_proc_offsets::get_initial_account_hash_offset # => [offset, PAD(15)] syscall.exec_kernel_proc @@ -83,7 +83,7 @@ export.get_current_hash padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_current_account_hash_offset + exec.kernel_proc_offsets::get_current_account_hash_offset # => [offset, PAD(15)] syscall.exec_kernel_proc @@ -106,7 +106,7 @@ export.incr_nonce push.0.0 movup.2 # => [value, 0, 0] - exec.kernel_invocation::incr_account_nonce_offset + exec.kernel_proc_offsets::incr_account_nonce_offset # => [offset, value, 0, 0] # pad the stack @@ -130,7 +130,7 @@ export.get_item push.0.0 movup.2 # => [index, 0, 0] - exec.kernel_invocation::get_account_item_offset + exec.kernel_proc_offsets::get_account_item_offset # => [offset, index, 0, 0] # pad the stack @@ -155,7 +155,7 @@ end #! - V is the previous value of the item. #! - R' is the new storage root. export.set_item - exec.kernel_invocation::set_account_item_offset + exec.kernel_proc_offsets::set_account_item_offset # => [offset, index, V'] # pad the stack @@ -180,7 +180,7 @@ end #! - KEY is the key of the item to get. #! - VALUE is the value of the item. export.get_map_item - exec.kernel_invocation::get_account_map_item_offset + exec.kernel_proc_offsets::get_account_map_item_offset # => [offset, index, KEY] # pad the stack @@ -208,7 +208,7 @@ end #! - OLD_MAP_ROOT is the old map root. #! - OLD_MAP_VALUE is the old value at KEY. export.set_map_item - exec.kernel_invocation::set_account_map_item_offset + exec.kernel_proc_offsets::set_account_map_item_offset # => [offset, index, KEY, VALUE] # pad the stack @@ -231,7 +231,7 @@ end #! #! - CODE_COMMITMENT is the hash of the code to set. export.set_code - exec.kernel_invocation::set_account_code_offset + exec.kernel_proc_offsets::set_account_code_offset # => [offset, CODE_COMMITMENT] # pad the stack @@ -255,7 +255,7 @@ end #! - faucet_id is the faucet id of the fungible asset of interest. #! - balance is the vault balance of the fungible asset. export.get_balance - exec.kernel_invocation::account_vault_get_balance_offset + exec.kernel_proc_offsets::account_vault_get_balance_offset # => [offset, faucet_id] # pad the stack @@ -279,7 +279,7 @@ end #! - ASSET is the non-fungible asset of interest #! - has_asset is a boolean indicating whether the account vault has the asset of interest export.has_non_fungible_asset - exec.kernel_invocation::account_vault_has_non_fungible_asset_offset + exec.kernel_proc_offsets::account_vault_has_non_fungible_asset_offset # => [offset, ASSET] # pad the stack @@ -309,7 +309,7 @@ end #! - If ASSET is a fungible asset, then ASSET' is the total fungible asset in the account vault #! after ASSET was added to it. export.add_asset - exec.kernel_invocation::account_vault_add_asset_offset + exec.kernel_proc_offsets::account_vault_add_asset_offset # => [offset, ASSET] # pad the stack @@ -336,7 +336,7 @@ end #! #! - ASSET is the asset to remove from the vault. export.remove_asset - exec.kernel_invocation::account_vault_remove_asset_offset + exec.kernel_proc_offsets::account_vault_remove_asset_offset # => [offset, ASSET] # pad the stack @@ -362,7 +362,7 @@ export.get_vault_commitment padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_account_vault_commitment_offset + exec.kernel_proc_offsets::get_account_vault_commitment_offset # => [offset, PAD(15)] syscall.exec_kernel_proc diff --git a/miden-lib/asm/miden/faucet.masm b/miden-lib/asm/miden/faucet.masm index f7b333072..4ec4fec3c 100644 --- a/miden-lib/asm/miden/faucet.masm +++ b/miden-lib/asm/miden/faucet.masm @@ -1,4 +1,4 @@ -use.miden::kernel_invocation +use.miden::kernel_proc_offsets #! Mint an asset from the faucet the transaction is being executed against. #! @@ -16,7 +16,7 @@ use.miden::kernel_invocation #! #! - ASSET is the asset that was minted. export.mint - exec.kernel_invocation::mint_asset_offset + exec.kernel_proc_offsets::mint_asset_offset # => [offset, ASSET] # pad the stack @@ -48,7 +48,7 @@ end #! #! - ASSET is the asset that was burned. export.burn - exec.kernel_invocation::burn_asset_offset + exec.kernel_proc_offsets::burn_asset_offset # => [offset, ASSET] # pad the stack @@ -78,7 +78,7 @@ export.get_total_issuance padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_fungible_faucet_total_issuance_offset + exec.kernel_proc_offsets::get_fungible_faucet_total_issuance_offset # => [offset, PAD(15)] syscall.exec_kernel_proc diff --git a/miden-lib/asm/miden/kernel_invocation.masm b/miden-lib/asm/miden/kernel_proc_offsets.masm similarity index 90% rename from miden-lib/asm/miden/kernel_invocation.masm rename to miden-lib/asm/miden/kernel_proc_offsets.masm index f262b6911..16bc1deaa 100644 --- a/miden-lib/asm/miden/kernel_invocation.masm +++ b/miden-lib/asm/miden/kernel_proc_offsets.masm @@ -4,35 +4,41 @@ # OFFSET CONSTANTS # ------------------------------------------------------------------------------------------------- -const.GET_ACCOUNT_ID_OFFSET=0 -const.GET_ACCOUNT_NONCE_OFFSET=1 -const.GET_INITIAL_ACCOUNT_HASH_OFFSET=2 -const.GET_CURRENT_ACCOUNT_HASH_OFFSET=3 -const.INCR_ACCOUNT_NONCE_OFFSET=4 +# Current account +const.ACCOUNT_VAULT_ADD_ASSET_OFFSET=0 +const.ACCOUNT_VAULT_GET_BALANCE_OFFSET=1 +const.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_OFFSET=2 +const.ACCOUNT_VAULT_REMOVE_ASSET_OFFSET=3 +const.GET_ACCOUNT_ID_OFFSET=4 const.GET_ACCOUNT_ITEM_OFFSET=5 -const.SET_ACCOUNT_ITEM_OFFSET=6 -const.GET_ACCOUNT_MAP_ITEM_OFFSET=7 -const.SET_ACCOUNT_MAP_ITEM_OFFSET=8 -const.SET_ACCOUNT_CODE_OFFSET=9 -const.ACCOUNT_VAULT_GET_BALANCE_OFFSET=10 -const.ACCOUNT_VAULT_HAS_NON_FUNGIBLE_ASSET_OFFSET=11 -const.ACCOUNT_VAULT_ADD_ASSET_OFFSET=12 -const.ACCOUNT_VAULT_REMOVE_ASSET_OFFSET=13 -const.GET_NOTE_ASSETS_INFO_OFFSET=14 -const.GET_NOTE_INPUTS_HASH_OFFSET=15 -const.GET_NOTE_SENDER_OFFSET=16 -const.GET_BLOCK_NUMBER_OFFSET=17 -const.GET_BLOCK_HASH_OFFSET=18 -const.GET_INPUT_NOTES_COMMITMENT_OFFSET=19 -const.GET_OUTPUT_NOTES_HASH_OFFSET=20 -const.CREATE_NOTE_OFFSET=21 -const.ADD_ASSET_TO_NOTE_OFFSET=22 -const.GET_ACCOUNT_VAULT_COMMITMENT_OFFSET=23 -const.MINT_ASSET_OFFSET=24 -const.BURN_ASSET_OFFSET=25 -const.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_OFFSET=26 -const.GET_NOTE_SERIAL_NUMBER_OFFSET=27 -const.EXEC_KERNEL_PROC_OFFSET=28 +const.GET_ACCOUNT_MAP_ITEM_OFFSET=6 +const.GET_ACCOUNT_NONCE_OFFSET=7 +const.GET_ACCOUNT_VAULT_COMMITMENT_OFFSET=8 +const.GET_CURRENT_ACCOUNT_HASH_OFFSET=9 +const.GET_INITIAL_ACCOUNT_HASH_OFFSET=10 +const.INCR_ACCOUNT_NONCE_OFFSET=11 +const.SET_ACCOUNT_CODE_OFFSET=12 +const.SET_ACCOUNT_ITEM_OFFSET=13 +const.SET_ACCOUNT_MAP_ITEM_OFFSET=14 + +# Current faucet +const.BURN_ASSET_OFFSET=15 +const.GET_FUNGIBLE_FAUCET_TOTAL_ISSUANCE_OFFSET=16 +const.MINT_ASSET_OFFSET=17 + +# Current note +const.ADD_ASSET_TO_NOTE_OFFSET=18 +const.CREATE_NOTE_OFFSET=19 +const.GET_INPUT_NOTES_COMMITMENT_OFFSET=20 +const.GET_NOTE_ASSETS_INFO_OFFSET=21 +const.GET_NOTE_INPUTS_HASH_OFFSET=22 +const.GET_NOTE_SENDER_OFFSET=23 +const.GET_NOTE_SERIAL_NUMBER_OFFSET=24 +const.GET_OUTPUT_NOTES_HASH_OFFSET=25 + +# Transaction +const.GET_BLOCK_HASH_OFFSET=26 +const.GET_BLOCK_NUMBER_OFFSET=27 # ACCESSORS # ------------------------------------------------------------------------------------------------- diff --git a/miden-lib/asm/miden/note.masm b/miden-lib/asm/miden/note.masm index 1b67227cc..d2c6b8b66 100644 --- a/miden-lib/asm/miden/note.masm +++ b/miden-lib/asm/miden/note.masm @@ -1,4 +1,4 @@ -use.miden::kernel_invocation +use.miden::kernel_proc_offsets use.std::crypto::hashes::native use.std::mem @@ -50,7 +50,7 @@ export.get_assets padw padw padw push.0.0.0 # => [PAD(15), dest_ptr] - exec.kernel_invocation::get_note_assets_info_offset + exec.kernel_proc_offsets::get_note_assets_info_offset # => [offset, PAD(15), dest_ptr] syscall.exec_kernel_proc @@ -95,7 +95,7 @@ export.get_inputs padw padw padw push.0.0.0 # => [PAD(15), dest_ptr] - exec.kernel_invocation::get_note_inputs_hash_offset + exec.kernel_proc_offsets::get_note_inputs_hash_offset # => [offset, PAD(15), dest_ptr] syscall.exec_kernel_proc @@ -145,7 +145,7 @@ export.get_sender padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_note_sender_offset + exec.kernel_proc_offsets::get_note_sender_offset # => [offset, PAD(15)] syscall.exec_kernel_proc @@ -168,7 +168,7 @@ export.get_serial_number padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_note_serial_number_offset + exec.kernel_proc_offsets::get_note_serial_number_offset # => [offset, PAD(15)] syscall.exec_kernel_proc diff --git a/miden-lib/asm/miden/tx.masm b/miden-lib/asm/miden/tx.masm index 8178d300f..ffb6728e8 100644 --- a/miden-lib/asm/miden/tx.masm +++ b/miden-lib/asm/miden/tx.masm @@ -1,4 +1,4 @@ -use.miden::kernel_invocation +use.miden::kernel_proc_offsets #! Returns the block number of the last known block at the time of transaction execution. #! @@ -11,7 +11,7 @@ export.get_block_number padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_block_number_offset + exec.kernel_proc_offsets::get_block_number_offset # => [offset, PAD(15)] syscall.exec_kernel_proc @@ -34,7 +34,7 @@ export.get_block_hash padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_block_hash_offset + exec.kernel_proc_offsets::get_block_hash_offset # => [offset, PAD(15)] syscall.exec_kernel_proc @@ -59,7 +59,7 @@ export.get_input_notes_commitment padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_input_notes_commitment_offset + exec.kernel_proc_offsets::get_input_notes_commitment_offset # => [offset, PAD(15)] syscall.exec_kernel_proc @@ -82,7 +82,7 @@ export.get_output_notes_hash padw padw padw push.0.0.0 # => [PAD(15)] - exec.kernel_invocation::get_output_notes_hash_offset + exec.kernel_proc_offsets::get_output_notes_hash_offset # => [offset, PAD(15)] syscall.exec_kernel_proc @@ -110,7 +110,7 @@ export.create_note padw padw swapdw movup.8 drop # => [tag, aux, note_type, execution_hint, RECIPIENT, PAD(7)] - exec.kernel_invocation::create_note_offset + exec.kernel_proc_offsets::create_note_offset # => [offset, tag, aux, note_type, execution_hint, RECIPIENT, PAD(7)] syscall.exec_kernel_proc @@ -129,7 +129,7 @@ end #! note_idx is the index of the note to which the asset is added. #! ASSET can be a fungible or non-fungible asset. export.add_asset_to_note - movup.4 exec.kernel_invocation::add_asset_to_note_offset + movup.4 exec.kernel_proc_offsets::add_asset_to_note_offset # => [offset, note_idx, ASSET] # pad the stack before the syscall to prevent accidental modification of the deeper stack diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index 17e787520..315ea243c 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -23,10 +23,13 @@ pub(super) fn extend_advice_inputs( tx_args: &TransactionArgs, advice_inputs: &mut AdviceInputs, ) { - build_advice_stack(tx_inputs, tx_args.tx_script(), advice_inputs); + // TODO: remove this value and use a user input instead + let kernel_offset = 0; + + build_advice_stack(tx_inputs, tx_args.tx_script(), advice_inputs, kernel_offset); // build the advice map and Merkle store for relevant components - add_kernel_hashes_to_advice_inputs(advice_inputs); + add_kernel_hashes_to_advice_inputs(advice_inputs, kernel_offset); add_chain_mmr_to_advice_inputs(tx_inputs.block_chain(), advice_inputs); add_account_to_advice_inputs(tx_inputs.account(), tx_inputs.account_seed(), advice_inputs); add_input_notes_to_advice_inputs(tx_inputs, tx_args, advice_inputs); @@ -41,7 +44,6 @@ pub(super) fn extend_advice_inputs( /// The following data is pushed to the advice stack: /// /// [ -/// KERNEL_ROOT /// PREVIOUS_BLOCK_HASH, /// CHAIN_MMR_HASH, /// ACCOUNT_ROOT, @@ -51,6 +53,7 @@ pub(super) fn extend_advice_inputs( /// PROOF_HASH, /// [block_num, version, timestamp, 0], /// NOTE_ROOT, +/// kernel_offset /// [account_id, 0, 0, account_nonce], /// ACCOUNT_VAULT_ROOT, /// ACCOUNT_STORAGE_ROOT, @@ -62,12 +65,10 @@ fn build_advice_stack( tx_inputs: &TransactionInputs, tx_script: Option<&TransactionScript>, inputs: &mut AdviceInputs, + kernel_offset: u8, ) { let header = tx_inputs.block_header(); - // push the accumulative hash of all kernels to the advice stack - inputs.extend_stack(header.kernel_root()); - // push block header info into the stack // Note: keep in sync with the process_block_data kernel procedure inputs.extend_stack(header.prev_hash()); @@ -85,6 +86,10 @@ fn build_advice_stack( ]); inputs.extend_stack(header.note_root()); + // push the offset of the kernel which will be used for this transaction + // Note: keep in sync with the process_kernel_data kernel procedure + inputs.extend_stack([Felt::from(kernel_offset)]); + // push core account items onto the stack // Note: keep in sync with the process_account_data kernel procedure let account = tx_inputs.account(); @@ -306,15 +311,16 @@ fn add_input_notes_to_advice_inputs( /// /// Inserts the following entries into the advice map: /// - The accumulative hash of all kernels |-> array of each kernel hash. -/// - The hash of the kernel `i` (for every `i`) |-> array of the current kernel's procedure hashes. -pub fn add_kernel_hashes_to_advice_inputs(inputs: &mut AdviceInputs) { - let kernel_hashes = [TransactionKernel::kernel_hash().as_elements()].concat(); +/// - The hash of the selected kernel |-> array of the kernel's procedure hashes. +pub fn add_kernel_hashes_to_advice_inputs(inputs: &mut AdviceInputs, kernel_offset: u8) { + let kernel_hashes = [TransactionKernel::kernel_hash(kernel_offset).as_elements()].concat(); // insert kernels root with kernel hashes into the advice map inputs.extend_map([(TransactionKernel::kernel_root(), kernel_hashes)]); - // insert kernel hash with procedure hashes into the advice map - // TODO: insert kernel procedures iterating over kernels - inputs - .extend_map([(TransactionKernel::kernel_hash(), TransactionKernel::procedures_as_felts())]); + // insert the selected kernel hash with its procedure hashes into the advice map + inputs.extend_map([( + TransactionKernel::kernel_hash(kernel_offset), + TransactionKernel::procedures_as_elements(kernel_offset), + )]); } diff --git a/miden-lib/src/transaction/memory.rs b/miden-lib/src/transaction/memory.rs index 345111c7c..068cebdf1 100644 --- a/miden-lib/src/transaction/memory.rs +++ b/miden-lib/src/transaction/memory.rs @@ -18,6 +18,7 @@ pub type StorageSlot = u8; // | Chain MMR | 300 | 332? | // | Account data | 400 | 651? | // | Account procedures| 999 | ? | +// | Kernel data | 10_000 | 10_028? | // | Input notes | 1_048_576 | ? | // | Output notes | 4_194_304 | ? | @@ -195,6 +196,13 @@ pub const NUM_ACCT_PROCEDURES_PTR: MemoryAddress = 999; /// The memory address at which the account procedures section begins. pub const ACCT_PROCEDURES_SECTION_OFFSET: MemoryAddress = 1000; +// KERNEL DATA +// ------------------------------------------------------------------------------------------------ + +/// The memory address at which the section, where the hashes of the kernel procedures are stored, +/// begins +pub const KERNEL_PROCEDURES_PTR: MemoryAddress = 10000; + // NOTES DATA // ================================================================================================ diff --git a/miden-lib/src/transaction/mod.rs b/miden-lib/src/transaction/mod.rs index 4ff6ce53a..22c7945af 100644 --- a/miden-lib/src/transaction/mod.rs +++ b/miden-lib/src/transaction/mod.rs @@ -98,8 +98,6 @@ impl TransactionKernel { account.init_hash(), tx_inputs.input_notes().commitment(), tx_inputs.block_header().hash(), - // TODO: change the hardcoded offset to the kernel index provided by user - 0, ); let mut advice_inputs = init_advice_inputs.unwrap_or_default(); @@ -151,11 +149,9 @@ impl TransactionKernel { init_acct_hash: Digest, input_notes_hash: Digest, block_hash: Digest, - kernel_offset: u8, ) -> StackInputs { // Note: Must be kept in sync with the transaction's kernel prepare_transaction procedure - let mut inputs: Vec = Vec::with_capacity(13); - inputs.push(Felt::from(kernel_offset)); + let mut inputs: Vec = Vec::with_capacity(12); inputs.extend(input_notes_hash); inputs.extend_from_slice(init_acct_hash.as_elements()); inputs.push(acct_id.into()); @@ -295,6 +291,5 @@ impl TransactionKernel { .expect("failed to load miden-lib") .with_library(kernel_library) .expect("failed to load kernel library (/lib)") - .with_debug_mode(true) } } diff --git a/miden-lib/src/transaction/procedures.rs b/miden-lib/src/transaction/procedures.rs index 79f234f83..fb0acec51 100644 --- a/miden-lib/src/transaction/procedures.rs +++ b/miden-lib/src/transaction/procedures.rs @@ -4,220 +4,236 @@ use miden_objects::{Digest, Felt, Hasher}; use super::TransactionKernel; +macro_rules! digest { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + Digest::new([Felt::new($a), Felt::new($b), Felt::new($c), Felt::new($d)]) + }; +} + impl TransactionKernel { - /// Hashes of all dynamically executed kernel procedures. - pub const PROCEDURES: [Digest; 28] = [ + /// Hashes of all dynamically executed procedures from the kernel 0. + pub const KERNEL0_PROCEDURES: [Digest; 28] = [ + // account_vault_add_asset + digest!( + 441011557193836424, + 14128779488787237713, + 9097945909079837843, + 1927790173066110370 + ), + // account_vault_get_balance + digest!( + 7035484340365940230, + 17797159859808856495, + 10586583242494928923, + 9763511907089065699 + ), + // account_vault_has_non_fungible_asset + digest!( + 3461454265989980777, + 16222005807253493271, + 5019331476826215138, + 8747291997159999285 + ), + // account_vault_remove_asset + digest!( + 6000868439702831595, + 9778474833766934115, + 1146161010038681475, + 1950819778618127304 + ), // get_account_id - Digest::new([ - Felt::new(8040261465733444704), - Felt::new(11111141085375373880), - Felt::new(7423929485586361344), - Felt::new(4119214601469502087), - ]), + digest!( + 8040261465733444704, + 11111141085375373880, + 7423929485586361344, + 4119214601469502087 + ), + // get_account_item + digest!( + 8242100606610843280, + 12256919645951393204, + 2951068718765716503, + 8986453979900819291 + ), + // get_account_map_item + digest!( + 5940336313866490980, + 9709935953040633522, + 2215378650076306714, + 7584412679403612847 + ), // get_account_nonce - Digest::new([ - Felt::new(7949369589472998218), - Felt::new(13470489034885204869), - Felt::new(7657993556512253706), - Felt::new(4189240183103072865), - ]), - // get_initial_account_hash - Digest::new([ - Felt::new(16301123123708038227), - Felt::new(8835228777116955671), - Felt::new(1233594748884564040), - Felt::new(17497683909577038473), - ]), + digest!( + 7949369589472998218, + 13470489034885204869, + 7657993556512253706, + 4189240183103072865 + ), + // get_account_vault_commitment + digest!( + 15827173769627914405, + 8397707743192029429, + 7205844492194182641, + 1677433344562532693 + ), // get_current_account_hash - Digest::new([ - Felt::new(18067387847945059633), - Felt::new(4630780713348682492), - Felt::new(16252299253975780120), - Felt::new(12604901563870135002), - ]), + digest!( + 18067387847945059633, + 4630780713348682492, + 16252299253975780120, + 12604901563870135002 + ), + // get_initial_account_hash + digest!( + 16301123123708038227, + 8835228777116955671, + 1233594748884564040, + 17497683909577038473 + ), // incr_account_nonce - Digest::new([ - Felt::new(6166980265541679115), - Felt::new(14180799872462142156), - Felt::new(2778474088493363690), - Felt::new(1238401418236321485), - ]), - // get_account_item - Digest::new([ - Felt::new(8242100606610843280), - Felt::new(12256919645951393204), - Felt::new(2951068718765716503), - Felt::new(8986453979900819291), - ]), + digest!( + 6166980265541679115, + 14180799872462142156, + 2778474088493363690, + 1238401418236321485 + ), + // set_account_code + digest!( + 4083640213314520131, + 11866061748990108757, + 7174634238671132507, + 16972174329470134023 + ), // set_account_item - Digest::new([ - Felt::new(7498941893890508814), - Felt::new(5585745677648937735), - Felt::new(13176054907168595727), - Felt::new(14561446422739981128), - ]), - // get_account_map_item - Digest::new([ - Felt::new(5940336313866490980), - Felt::new(9709935953040633522), - Felt::new(2215378650076306714), - Felt::new(7584412679403612847), - ]), + digest!( + 7498941893890508814, + 5585745677648937735, + 13176054907168595727, + 14561446422739981128 + ), // set_account_map_item - Digest::new([ - Felt::new(9257525779338879284), - Felt::new(5994228928952574041), - Felt::new(3477745056362616903), - Felt::new(1514247258411024664), - ]), - // set_account_code - Digest::new([ - Felt::new(4083640213314520131), - Felt::new(11866061748990108757), - Felt::new(7174634238671132507), - Felt::new(16972174329470134023), - ]), - // account_vault_get_balance - Digest::new([ - Felt::new(7035484340365940230), - Felt::new(17797159859808856495), - Felt::new(10586583242494928923), - Felt::new(9763511907089065699), - ]), - // account_vault_has_non_fungible_asset - Digest::new([ - Felt::new(3461454265989980777), - Felt::new(16222005807253493271), - Felt::new(5019331476826215138), - Felt::new(8747291997159999285), - ]), - // account_vault_add_asset - Digest::new([ - Felt::new(441011557193836424), - Felt::new(14128779488787237713), - Felt::new(9097945909079837843), - Felt::new(1927790173066110370), - ]), - // account_vault_remove_asset - Digest::new([ - Felt::new(6000868439702831595), - Felt::new(9778474833766934115), - Felt::new(1146161010038681475), - Felt::new(1950819778618127304), - ]), + digest!( + 9257525779338879284, + 5994228928952574041, + 3477745056362616903, + 1514247258411024664 + ), + // burn_asset + digest!( + 2613729911428583836, + 3409713366391106845, + 4618787175150657117, + 13550289764852635265 + ), + // get_fungible_faucet_total_issuance + digest!( + 5567752045855424912, + 1313115426050254227, + 12797601829399057688, + 10963909072124913328 + ), + // mint_asset + digest!( + 11833462197234963951, + 521365474344899632, + 12219339115593432087, + 3026752009521887157 + ), + // add_asset_to_note + digest!( + 14950372948135486500, + 16795936443880575519, + 10590371208545379138, + 3493796503081669802 + ), + // create_note + digest!( + 14778603067944873506, + 14071319835769664212, + 13946705703761691189, + 68248535266635199 + ), + // get_input_notes_commitment + digest!( + 2019728671844693749, + 18222437788741437389, + 12821100448410084889, + 17418670035031233675 + ), // get_note_assets_info - Digest::new([ - Felt::new(12346411220238036656), - Felt::new(18027533406091104744), - Felt::new(14723639276543495147), - Felt::new(11542458885879781389), - ]), + digest!( + 12346411220238036656, + 18027533406091104744, + 14723639276543495147, + 11542458885879781389 + ), // get_note_inputs_hash - Digest::new([ - Felt::new(17186028199923932877), - Felt::new(2563818256742276816), - Felt::new(8351223767950877211), - Felt::new(11379249881600223287), - ]), + digest!( + 17186028199923932877, + 2563818256742276816, + 8351223767950877211, + 11379249881600223287 + ), // get_note_sender - Digest::new([ - Felt::new(15233821980580537524), - Felt::new(8874650687593596380), - Felt::new(14910554371357890324), - Felt::new(11945045801206913876), - ]), - // get_block_number - Digest::new([ - Felt::new(957081505105679725), - Felt::new(18012382143736246386), - Felt::new(13337406348155951825), - Felt::new(4537613255382865554), - ]), - // get_block_hash - Digest::new([ - Felt::new(15575368355470837910), - Felt::new(13483490255982391120), - Felt::new(5407999307430887046), - Felt::new(13895912493177462699), - ]), - // get_input_notes_commitment - Digest::new([ - Felt::new(2019728671844693749), - Felt::new(18222437788741437389), - Felt::new(12821100448410084889), - Felt::new(17418670035031233675), - ]), - // get_output_notes_hash - Digest::new([ - Felt::new(4412523757021344747), - Felt::new(8883378993868597671), - Felt::new(16885133168375194469), - Felt::new(15472424727696440458), - ]), - // create_note - Digest::new([ - Felt::new(14778603067944873506), - Felt::new(14071319835769664212), - Felt::new(13946705703761691189), - Felt::new(68248535266635199), - ]), - // add_asset_to_note - Digest::new([ - Felt::new(14950372948135486500), - Felt::new(16795936443880575519), - Felt::new(10590371208545379138), - Felt::new(3493796503081669802), - ]), - // get_account_vault_commitment - Digest::new([ - Felt::new(15827173769627914405), - Felt::new(8397707743192029429), - Felt::new(7205844492194182641), - Felt::new(1677433344562532693), - ]), - // mint_asset - Digest::new([ - Felt::new(11833462197234963951), - Felt::new(521365474344899632), - Felt::new(12219339115593432087), - Felt::new(3026752009521887157), - ]), - // burn_asset - Digest::new([ - Felt::new(2613729911428583836), - Felt::new(3409713366391106845), - Felt::new(4618787175150657117), - Felt::new(13550289764852635265), - ]), - // get_fungible_faucet_total_issuance - Digest::new([ - Felt::new(5567752045855424912), - Felt::new(1313115426050254227), - Felt::new(12797601829399057688), - Felt::new(10963909072124913328), - ]), + digest!( + 15233821980580537524, + 8874650687593596380, + 14910554371357890324, + 11945045801206913876 + ), // get_note_serial_number - Digest::new([ - Felt::new(203467101694736292), - Felt::new(1871816977533069235), - Felt::new(11026610821411620572), - Felt::new(8345006103126977916), - ]), + digest!( + 203467101694736292, + 1871816977533069235, + 11026610821411620572, + 8345006103126977916 + ), + // get_output_notes_hash + digest!( + 4412523757021344747, + 8883378993868597671, + 16885133168375194469, + 15472424727696440458 + ), + // get_block_hash + digest!( + 15575368355470837910, + 13483490255982391120, + 5407999307430887046, + 13895912493177462699 + ), + // get_block_number + digest!( + 957081505105679725, + 18012382143736246386, + 13337406348155951825, + 4537613255382865554 + ), ]; - pub fn procedures_as_felts() -> Vec { - Digest::digests_as_elements(Self::PROCEDURES.iter()) - .cloned() - .collect::>() + /// Array of all available kernels. + pub const PROCEDURES: [&'static [Digest]; 1] = [&Self::KERNEL0_PROCEDURES]; + + /// Returns procedures of the kernel specified by the `kernel_offset` as vector of Felts. + pub fn procedures_as_elements(kernel_offset: u8) -> Vec { + Digest::digests_as_elements( + Self::PROCEDURES + .get(kernel_offset as usize) + .expect("provided kernel index is out of bounds") + .iter(), + ) + .cloned() + .collect::>() } - /// Computes the accumulative hash of all kernel procedures. - pub fn kernel_hash() -> Digest { - Hasher::hash_elements(&Self::procedures_as_felts()) + /// Computes the accumulative hash of all procedures of the kernel specified by the + /// `kernel_offset`. + pub fn kernel_hash(kernel_offset: u8) -> Digest { + Hasher::hash_elements(&Self::procedures_as_elements(kernel_offset)) } /// Computes a hash from all kernel hashes. pub fn kernel_root() -> Digest { - Hasher::hash_elements(&[Self::kernel_hash().as_elements()].concat()) + Hasher::hash_elements(&[Self::kernel_hash(0).as_elements()].concat()) } } diff --git a/miden-tx/src/verifier/mod.rs b/miden-tx/src/verifier/mod.rs index d97856209..af69ecbe9 100644 --- a/miden-tx/src/verifier/mod.rs +++ b/miden-tx/src/verifier/mod.rs @@ -37,9 +37,6 @@ impl TransactionVerifier { transaction.account_update().init_state_hash(), transaction.input_notes().commitment(), transaction.block_ref(), - // TODO: change the hardcoded offset to the kernel index used in the current - // transaction - 0, ); let stack_outputs = TransactionKernel::build_output_stack( transaction.account_update().final_state_hash(), diff --git a/objects/src/block/header.rs b/objects/src/block/header.rs index a403668a6..8eddb8b26 100644 --- a/objects/src/block/header.rs +++ b/objects/src/block/header.rs @@ -19,6 +19,7 @@ use crate::utils::serde::{ /// - `note_root` is a commitment to all notes created in the current block. /// - `tx_hash` is a commitment to a set of IDs of transactions which affected accounts in the /// block. +/// - `kernel_root` is an accumulative hash from all kernel hashes. /// - `proof_hash` is a hash of a STARK proof attesting to the correct state transition. /// - `timestamp` is the time when the block was created, in seconds since UNIX epoch. Current /// representation is sufficient to represent time up to year 2106. @@ -179,7 +180,8 @@ impl BlockHeader { /// /// The sub hash is computed as a sequential hash of the following fields: /// `prev_hash`, `chain_root`, `account_root`, `nullifier_root`, `note_root`, `tx_hash`, - /// `proof_hash`, `version`, `timestamp`, `block_num` (all fields except the `note_root`). + /// `kernel_root`, `proof_hash`, `version`, `timestamp`, `block_num` (all fields except the + /// `note_root`). #[allow(clippy::too_many_arguments)] fn compute_sub_hash( version: u32, @@ -202,7 +204,6 @@ impl BlockHeader { elements.extend_from_slice(kernel_root.as_elements()); elements.extend_from_slice(proof_hash.as_elements()); elements.extend([block_num.into(), version.into(), timestamp.into(), ZERO]); - elements.resize(32, ZERO); Hasher::hash_elements(&elements) } } diff --git a/objects/src/testing/account_code.rs b/objects/src/testing/account_code.rs index 1164b5382..6043c8419 100644 --- a/objects/src/testing/account_code.rs +++ b/objects/src/testing/account_code.rs @@ -7,16 +7,16 @@ use crate::accounts::AccountCode; const MASTS: [&str; 12] = [ "0xff06b90f849c4b262cbfbea67042c4ea017ea0e9c558848a951d44b23370bec5", "0x8ef0092134469a1330e3c468f57c7f085ce611645d09cc7516c786fefc71d794", - "0x9500d49982f77c1b2eb66b2b688231fe10016a4b3cdcabfb2166dad6f1010197", - "0x58f266daa7521633681586a39e57d2d9ae5e7198bc958eaef001e523b38310ef", - "0x50e3fd0680161b1e48d5039c063903330330d6a5d8475be4d98e2c72c2b160d6", - "0x1b9dd32a282bd3bec1c192f1cb054b2e70d590372f6cd49ef0676cc09313b722", - "0x35004c7db85e6ac2471626db24c08da5e72532a8347dea8ed99d60419db4a78f", - "0x096b2c2bec8f88ef1f303d33bac07356f900515463bc9de72733451cc1b32b11", - "0xcd8d4567204fbf42c169fe88de615989de598f164a418736dfd5c2d833c7be04", - "0x812682907302f1070be8a7f920c168ba217429d3ba5b07bae30ceda234d18095", - "0x1798f2959f525fc9b55b0307542600fb987afd965533c993cffa73461e1a1be2", - "0x79cbe48ff495c041b985f2dc6a0e1455e8f571354e8121a2eef0764d366c5f02", + "0xccc3cadc32c201f1d6c95a7d0889256fe2fc2f97a690c98514f3671fde08c085", + "0x101389fca3b637faeec7dd016cdb049e3abb3047e94887efc740d42add684ec0", + "0x7b5fc2ffc46aaaf368faeb951d42f7208cbf699700cd472a3a400396c302512b", + "0x69775174df01ca390b305ad4648a48a2990cc0fae413eea85760361911755cba", + "0x543cb5ae38244e39505278166261b14ee40c70c3a457e06189df9426bbcdaa95", + "0xbe3bc60c05b4b279aa51d68840c2ca9932425ba36a21345e168d21b822bdaab2", + "0x290ac6c64247538cf332f79db404c084214c5f9b631a4825b795976935cf072c", + "0x0ac3968e24e701d45c74eb48e19b61e07552b1c55911684e04dfc91107f67bae", + "0x7368ef24e0e7076b06439cefcfbdcc68bc673df47f30d329b8a15227f542092a", + "0x833a729f3a8770457076a0307fab9593333374705242945fbb8c35eb82902976", ]; pub const ACCOUNT_ADD_ASSET_TO_NOTE_MAST_ROOT: &str = MASTS[2]; From 88cfeab3ae91d11c731178798091f12c386c6096 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 12 Sep 2024 20:05:09 +0300 Subject: [PATCH 08/11] refactor: add number of kernel procs to memory, minor code improvements --- miden-lib/asm/kernels/transaction/api.masm | 8 + .../asm/kernels/transaction/lib/memory.masm | 25 + .../asm/kernels/transaction/lib/prologue.masm | 31 +- miden-lib/asm/miden/kernel_proc_offsets.masm | 3 - miden-lib/src/transaction/inputs.rs | 39 +- miden-lib/src/transaction/memory.rs | 5 +- miden-lib/src/transaction/mod.rs | 5 +- miden-lib/src/transaction/procedures.rs | 427 +++++++++--------- miden-tx/src/error.rs | 6 +- 9 files changed, 305 insertions(+), 244 deletions(-) diff --git a/miden-lib/asm/kernels/transaction/api.masm b/miden-lib/asm/kernels/transaction/api.masm index ecd6442d8..cda74e3cd 100644 --- a/miden-lib/asm/kernels/transaction/api.masm +++ b/miden-lib/asm/kernels/transaction/api.masm @@ -30,6 +30,9 @@ const.ERR_ACCT_MUST_BE_A_FAUCET=0x00020001 # Getting a map item on a non-map slot const.ERR_READING_MAP_VALUE_FROM_NON_MAP_SLOT=0x00020049 +# Provided kernel procedure offset is out of bounds +const.ERR_KERNEL_PROCEDURE_OFFSET_OUT_OF_BOUNDS=0x0002004F + # EVENTS # ================================================================================================= @@ -777,6 +780,11 @@ end #! first word on the stack will be occupied by the procedure hash. #! - procedure_outputs are the outputs of the procedure to be executed. 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_pointer, , ] + # compute the memory pointer at which desired procedure is stored exec.memory::get_kernel_procedures_ptr add # => [procedure_pointer, , ] diff --git a/miden-lib/asm/kernels/transaction/lib/memory.masm b/miden-lib/asm/kernels/transaction/lib/memory.masm index 7f1a9135d..8f4fb9339 100644 --- a/miden-lib/asm/kernels/transaction/lib/memory.masm +++ b/miden-lib/asm/kernels/transaction/lib/memory.masm @@ -132,6 +132,9 @@ const.ACCT_PROCEDURES_SECTION_OFFSET=1000 # KERNEL DATA # ------------------------------------------------------------------------------------------------- +# The memory address at which the number of the procedures of the selected kernel is stored. +const.NUM_KERNEL_PROCEDURES_PTR=9999 + # The memory address at which the hashes of kernel procedures begin. # TODO: choose the proper memory location for the kernel procedures. const.KERNEL_PROCEDURES_PTR=10000 @@ -1238,6 +1241,28 @@ end # KERNEL DATA # ------------------------------------------------------------------------------------------------- +#! Sets the number of of the procedures of the selected kernel. +#! +#! Stack: [num_kernel_procedures] +#! Output: [] +#! +#! Where: +#! - num_kernel_procedures is the number of the procedures of the selected kernel. +export.set_num_kernel_procedures + push.NUM_KERNEL_PROCEDURES_PTR mem_store +end + +#! Returns the number of the procedures of the selected kernel. +#! +#! Stack: [] +#! Output: [num_kernel_procedures] +#! +#! Where: +#! - num_kernel_procedures is the number of the procedures of the selected kernel. +export.get_num_kernel_procedures + push.NUM_KERNEL_PROCEDURES_PTR mem_load +end + #! Returns a pointer to the memory where hashes of the kernel procedures are stored. #! #! Stack: [] diff --git a/miden-lib/asm/kernels/transaction/lib/prologue.masm b/miden-lib/asm/kernels/transaction/lib/prologue.masm index 9778bb583..2014e5f92 100644 --- a/miden-lib/asm/kernels/transaction/lib/prologue.masm +++ b/miden-lib/asm/kernels/transaction/lib/prologue.masm @@ -107,18 +107,18 @@ end #! respectively. #! #! Inputs: -#! Stack: [] -#! Advice stack: [kernel_offset] +#! Operand stack: [] +#! Advice stack: [kernel_version] #! Advice map: { #! KERNEL_ROOT: [KERNEL_HASHES] #! KERNEL_HASH: [KERNEL_PROCEDURE_HASHES] #! } #! Outputs: -#! Stack: [] +#! Operand stack: [] #! Advice stack: [] #! #! Where: -#! - kernel_offset, index of the desired kernel in the array of all kernels available for the +#! - kernel_version, index of the desired kernel in the array of all kernels available for the #! current transaction #! - KERNEL_ROOT, accumulative hash from all kernel hashes. #! - [KERNEL_HASHES], array of each kernel hash @@ -126,40 +126,40 @@ end proc.process_kernel_data # move the kernel offset to the operand stack adv_push.1 - # OS => [kernel_offset] + # OS => [kernel_version] # AS => [] # load the kernel root from the memory exec.memory::get_kernel_root - # OS => [KERNEL_ROOT, kernel_offset] + # OS => [KERNEL_ROOT, kernel_version] # AS => [] # push the kernel hashes from the advice map to the advice stack adv.push_mapvaln - # OS => [KERNEL_ROOT, kernel_offset] + # OS => [KERNEL_ROOT, kernel_version] # AS => [len_felts, [KERNEL_HASHES]] # move the number of felt elements in the [KERNEL_HASHES] array to the stack and get the # number of Words from it adv_push.1 div.4 - # OS => [len_words, KERNEL_ROOT, kernel_offset] + # OS => [len_words, KERNEL_ROOT, kernel_version] # AS => [[KERNEL_HASHES]] # get the pointer to the memory where kernel hashes will be stored # Note: for now we use the same address for kernel hash and for kernel procedures since there is # only one kernel and its hash will be overwritten by the procedures anyway. exec.memory::get_kernel_procedures_ptr swap - # OS => [len_words, kernel_mem_ptr, KERNEL_ROOT, kernel_offset] + # OS => [len_words, kernel_mem_ptr, KERNEL_ROOT, kernel_version] # AS => [[KERNEL_HASHES]] # store the kernel hashes in memory exec.mem::pipe_words_to_memory - # OS => [SEQ_HASH, kernel_mem_ptr', KERNEL_ROOT, kernel_offset] + # OS => [SEQ_HASH, kernel_mem_ptr', KERNEL_ROOT, kernel_version] # AS => [] # assert that sequential hash matches the precomputed kernel root movup.4 drop assert_eqw - # OS => [kernel_offset] + # OS => [kernel_version] # AS => [] # get the hash of the kernel which will be used in the current transaction @@ -182,6 +182,11 @@ proc.process_kernel_data # OS => [len_words, KERNEL_HASH] # AS => [[PROC_HASHES]] + # store the number of the procedures of the chosen kernel to the memory + dup exec.memory::set_num_kernel_procedures + # OS => [len_words, KERNEL_HASH] + # AS => [[PROC_HASHES]] + # get the pointer to the memory where hashes of the kernel procedures will be stored exec.memory::get_kernel_procedures_ptr swap # OS => [len_words, kernel_procs_ptr, KERNEL_HASH] @@ -1207,7 +1212,7 @@ end #! PROOF_HASH, #! [block_num, version, timestamp, 0], #! NOTE_ROOT, -#! kernel_offset +#! kernel_version #! [account_id, 0, 0, account_nonce], #! ACCOUNT_VAULT_ROOT, #! ACCOUNT_STORAGE_ROOT, @@ -1239,7 +1244,7 @@ end #! - version, the current protocol version. #! - timestamp, the current timestamp. #! - NOTE_ROOT, root of the tree with all notes created in the block. -#! - kernel_offset, index of the desired kernel in the array of all kernels available for the +#! - kernel_version, index of the desired kernel in the array of all kernels available for the #! current transaction. #! - account_nonce, account's nonce. #! - ACCOUNT_VAULT_ROOT, account's vault root. diff --git a/miden-lib/asm/miden/kernel_proc_offsets.masm b/miden-lib/asm/miden/kernel_proc_offsets.masm index 16bc1deaa..57f336b46 100644 --- a/miden-lib/asm/miden/kernel_proc_offsets.masm +++ b/miden-lib/asm/miden/kernel_proc_offsets.masm @@ -1,6 +1,3 @@ -# KERNEL PROCEDURE OFFSETS -# ================================================================================================= - # OFFSET CONSTANTS # ------------------------------------------------------------------------------------------------- diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index 315ea243c..b572f89d1 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -4,7 +4,7 @@ use miden_objects::{ accounts::Account, transaction::{ChainMmr, InputNote, TransactionArgs, TransactionInputs, TransactionScript}, vm::AdviceInputs, - Felt, FieldElement, Word, EMPTY_WORD, ZERO, + Digest, Felt, FieldElement, Word, EMPTY_WORD, WORD_SIZE, ZERO, }; use super::TransactionKernel; @@ -24,12 +24,12 @@ pub(super) fn extend_advice_inputs( advice_inputs: &mut AdviceInputs, ) { // TODO: remove this value and use a user input instead - let kernel_offset = 0; + let kernel_version = 0; - build_advice_stack(tx_inputs, tx_args.tx_script(), advice_inputs, kernel_offset); + build_advice_stack(tx_inputs, tx_args.tx_script(), advice_inputs, kernel_version); // build the advice map and Merkle store for relevant components - add_kernel_hashes_to_advice_inputs(advice_inputs, kernel_offset); + add_kernel_hashes_to_advice_inputs(advice_inputs, kernel_version); add_chain_mmr_to_advice_inputs(tx_inputs.block_chain(), advice_inputs); add_account_to_advice_inputs(tx_inputs.account(), tx_inputs.account_seed(), advice_inputs); add_input_notes_to_advice_inputs(tx_inputs, tx_args, advice_inputs); @@ -53,7 +53,7 @@ pub(super) fn extend_advice_inputs( /// PROOF_HASH, /// [block_num, version, timestamp, 0], /// NOTE_ROOT, -/// kernel_offset +/// kernel_version /// [account_id, 0, 0, account_nonce], /// ACCOUNT_VAULT_ROOT, /// ACCOUNT_STORAGE_ROOT, @@ -65,7 +65,7 @@ fn build_advice_stack( tx_inputs: &TransactionInputs, tx_script: Option<&TransactionScript>, inputs: &mut AdviceInputs, - kernel_offset: u8, + kernel_version: u8, ) { let header = tx_inputs.block_header(); @@ -86,9 +86,9 @@ fn build_advice_stack( ]); inputs.extend_stack(header.note_root()); - // push the offset of the kernel which will be used for this transaction + // push the version of the kernel which will be used for this transaction // Note: keep in sync with the process_kernel_data kernel procedure - inputs.extend_stack([Felt::from(kernel_offset)]); + inputs.extend_stack([Felt::from(kernel_version)]); // push core account items onto the stack // Note: keep in sync with the process_account_data kernel procedure @@ -312,15 +312,24 @@ fn add_input_notes_to_advice_inputs( /// Inserts the following entries into the advice map: /// - The accumulative hash of all kernels |-> array of each kernel hash. /// - The hash of the selected kernel |-> array of the kernel's procedure hashes. -pub fn add_kernel_hashes_to_advice_inputs(inputs: &mut AdviceInputs, kernel_offset: u8) { - let kernel_hashes = [TransactionKernel::kernel_hash(kernel_offset).as_elements()].concat(); - - // insert kernels root with kernel hashes into the advice map - inputs.extend_map([(TransactionKernel::kernel_root(), kernel_hashes)]); +pub fn add_kernel_hashes_to_advice_inputs(inputs: &mut AdviceInputs, kernel_version: u8) { + let mut kernel_hashes: Vec = + Vec::with_capacity(TransactionKernel::KERNEL_VERSION_NUMBER * WORD_SIZE); + for version in 0..TransactionKernel::KERNEL_VERSION_NUMBER { + kernel_hashes + .extend_from_slice(TransactionKernel::kernel_hash(version as u8).as_elements()); + } // insert the selected kernel hash with its procedure hashes into the advice map inputs.extend_map([( - TransactionKernel::kernel_hash(kernel_offset), - TransactionKernel::procedures_as_elements(kernel_offset), + Digest::new( + kernel_hashes[kernel_version as usize..kernel_version as usize + WORD_SIZE] + .try_into() + .expect("invalid kernel offset"), + ), + TransactionKernel::procedures_as_elements(kernel_version), )]); + + // insert kernels root with kernel hashes into the advice map + inputs.extend_map([(TransactionKernel::kernel_root(), kernel_hashes)]); } diff --git a/miden-lib/src/transaction/memory.rs b/miden-lib/src/transaction/memory.rs index 068cebdf1..1f9c3123d 100644 --- a/miden-lib/src/transaction/memory.rs +++ b/miden-lib/src/transaction/memory.rs @@ -18,7 +18,7 @@ pub type StorageSlot = u8; // | Chain MMR | 300 | 332? | // | Account data | 400 | 651? | // | Account procedures| 999 | ? | -// | Kernel data | 10_000 | 10_028? | +// | Kernel data | 9_999 | 10_028? | // | Input notes | 1_048_576 | ? | // | Output notes | 4_194_304 | ? | @@ -199,6 +199,9 @@ pub const ACCT_PROCEDURES_SECTION_OFFSET: MemoryAddress = 1000; // KERNEL DATA // ------------------------------------------------------------------------------------------------ +/// The memory address at which the number of the procedures of the selected kernel is stored. +pub const NUM_KERNEL_PROCEDURES_PTR: MemoryAddress = 9999; + /// The memory address at which the section, where the hashes of the kernel procedures are stored, /// begins pub const KERNEL_PROCEDURES_PTR: MemoryAddress = 10000; diff --git a/miden-lib/src/transaction/mod.rs b/miden-lib/src/transaction/mod.rs index 369986cb1..a34b4842c 100644 --- a/miden-lib/src/transaction/mod.rs +++ b/miden-lib/src/transaction/mod.rs @@ -133,7 +133,6 @@ impl TransactionKernel { /// acct_id, /// INITIAL_ACCOUNT_HASH, /// INPUT_NOTES_COMMITMENT, - /// kernel_offset /// ] /// ``` /// @@ -142,8 +141,6 @@ impl TransactionKernel { /// - acct_id, the account that the transaction is being executed against. /// - INITIAL_ACCOUNT_HASH, account state prior to the transaction, EMPTY_WORD for new accounts. /// - INPUT_NOTES_COMMITMENT, see `transaction::api::get_input_notes_commitment`. - /// - kernel_offset, index of the desired kernel in the array of all kernels available for the - /// current transaction. pub fn build_input_stack( acct_id: AccountId, init_acct_hash: Digest, @@ -151,7 +148,7 @@ impl TransactionKernel { block_hash: Digest, ) -> StackInputs { // Note: Must be kept in sync with the transaction's kernel prepare_transaction procedure - let mut inputs: Vec = Vec::with_capacity(12); + let mut inputs: Vec = Vec::with_capacity(13); inputs.extend(input_notes_hash); inputs.extend_from_slice(init_acct_hash.as_elements()); inputs.push(acct_id.into()); diff --git a/miden-lib/src/transaction/procedures.rs b/miden-lib/src/transaction/procedures.rs index fb0acec51..4db16bf4e 100644 --- a/miden-lib/src/transaction/procedures.rs +++ b/miden-lib/src/transaction/procedures.rs @@ -10,215 +10,27 @@ macro_rules! digest { }; } +// TRANSACTION KERNEL +// ================================================================================================ + impl TransactionKernel { - /// Hashes of all dynamically executed procedures from the kernel 0. - pub const KERNEL0_PROCEDURES: [Digest; 28] = [ - // account_vault_add_asset - digest!( - 441011557193836424, - 14128779488787237713, - 9097945909079837843, - 1927790173066110370 - ), - // account_vault_get_balance - digest!( - 7035484340365940230, - 17797159859808856495, - 10586583242494928923, - 9763511907089065699 - ), - // account_vault_has_non_fungible_asset - digest!( - 3461454265989980777, - 16222005807253493271, - 5019331476826215138, - 8747291997159999285 - ), - // account_vault_remove_asset - digest!( - 6000868439702831595, - 9778474833766934115, - 1146161010038681475, - 1950819778618127304 - ), - // get_account_id - digest!( - 8040261465733444704, - 11111141085375373880, - 7423929485586361344, - 4119214601469502087 - ), - // get_account_item - digest!( - 8242100606610843280, - 12256919645951393204, - 2951068718765716503, - 8986453979900819291 - ), - // get_account_map_item - digest!( - 5940336313866490980, - 9709935953040633522, - 2215378650076306714, - 7584412679403612847 - ), - // get_account_nonce - digest!( - 7949369589472998218, - 13470489034885204869, - 7657993556512253706, - 4189240183103072865 - ), - // get_account_vault_commitment - digest!( - 15827173769627914405, - 8397707743192029429, - 7205844492194182641, - 1677433344562532693 - ), - // get_current_account_hash - digest!( - 18067387847945059633, - 4630780713348682492, - 16252299253975780120, - 12604901563870135002 - ), - // get_initial_account_hash - digest!( - 16301123123708038227, - 8835228777116955671, - 1233594748884564040, - 17497683909577038473 - ), - // incr_account_nonce - digest!( - 6166980265541679115, - 14180799872462142156, - 2778474088493363690, - 1238401418236321485 - ), - // set_account_code - digest!( - 4083640213314520131, - 11866061748990108757, - 7174634238671132507, - 16972174329470134023 - ), - // set_account_item - digest!( - 7498941893890508814, - 5585745677648937735, - 13176054907168595727, - 14561446422739981128 - ), - // set_account_map_item - digest!( - 9257525779338879284, - 5994228928952574041, - 3477745056362616903, - 1514247258411024664 - ), - // burn_asset - digest!( - 2613729911428583836, - 3409713366391106845, - 4618787175150657117, - 13550289764852635265 - ), - // get_fungible_faucet_total_issuance - digest!( - 5567752045855424912, - 1313115426050254227, - 12797601829399057688, - 10963909072124913328 - ), - // mint_asset - digest!( - 11833462197234963951, - 521365474344899632, - 12219339115593432087, - 3026752009521887157 - ), - // add_asset_to_note - digest!( - 14950372948135486500, - 16795936443880575519, - 10590371208545379138, - 3493796503081669802 - ), - // create_note - digest!( - 14778603067944873506, - 14071319835769664212, - 13946705703761691189, - 68248535266635199 - ), - // get_input_notes_commitment - digest!( - 2019728671844693749, - 18222437788741437389, - 12821100448410084889, - 17418670035031233675 - ), - // get_note_assets_info - digest!( - 12346411220238036656, - 18027533406091104744, - 14723639276543495147, - 11542458885879781389 - ), - // get_note_inputs_hash - digest!( - 17186028199923932877, - 2563818256742276816, - 8351223767950877211, - 11379249881600223287 - ), - // get_note_sender - digest!( - 15233821980580537524, - 8874650687593596380, - 14910554371357890324, - 11945045801206913876 - ), - // get_note_serial_number - digest!( - 203467101694736292, - 1871816977533069235, - 11026610821411620572, - 8345006103126977916 - ), - // get_output_notes_hash - digest!( - 4412523757021344747, - 8883378993868597671, - 16885133168375194469, - 15472424727696440458 - ), - // get_block_hash - digest!( - 15575368355470837910, - 13483490255982391120, - 5407999307430887046, - 13895912493177462699 - ), - // get_block_number - digest!( - 957081505105679725, - 18012382143736246386, - 13337406348155951825, - 4537613255382865554 - ), - ]; + // CONSTANTS + // -------------------------------------------------------------------------------------------- + + /// Number of currently used kernel versions. + pub const KERNEL_VERSION_NUMBER: usize = 1; /// Array of all available kernels. - pub const PROCEDURES: [&'static [Digest]; 1] = [&Self::KERNEL0_PROCEDURES]; + pub const PROCEDURES: [&'static [Digest]; Self::KERNEL_VERSION_NUMBER] = [&KERNEL0_PROCEDURES]; + + // PUBLIC ACCESSORS + // -------------------------------------------------------------------------------------------- - /// Returns procedures of the kernel specified by the `kernel_offset` as vector of Felts. - pub fn procedures_as_elements(kernel_offset: u8) -> Vec { + /// Returns procedures of the kernel specified by the `kernel_version` as vector of Felts. + pub fn procedures_as_elements(kernel_version: u8) -> Vec { Digest::digests_as_elements( Self::PROCEDURES - .get(kernel_offset as usize) + .get(kernel_version as usize) .expect("provided kernel index is out of bounds") .iter(), ) @@ -227,9 +39,9 @@ impl TransactionKernel { } /// Computes the accumulative hash of all procedures of the kernel specified by the - /// `kernel_offset`. - pub fn kernel_hash(kernel_offset: u8) -> Digest { - Hasher::hash_elements(&Self::procedures_as_elements(kernel_offset)) + /// `kernel_version`. + pub fn kernel_hash(kernel_version: u8) -> Digest { + Hasher::hash_elements(&Self::procedures_as_elements(kernel_version)) } /// Computes a hash from all kernel hashes. @@ -237,3 +49,206 @@ impl TransactionKernel { Hasher::hash_elements(&[Self::kernel_hash(0).as_elements()].concat()) } } + +// KERNEL V0 PROCEDURES +// ================================================================================================ + +/// Hashes of all dynamically executed procedures from the kernel 0. +const KERNEL0_PROCEDURES: [Digest; 28] = [ + // account_vault_add_asset + digest!( + 441011557193836424, + 14128779488787237713, + 9097945909079837843, + 1927790173066110370 + ), + // account_vault_get_balance + digest!( + 7035484340365940230, + 17797159859808856495, + 10586583242494928923, + 9763511907089065699 + ), + // account_vault_has_non_fungible_asset + digest!( + 3461454265989980777, + 16222005807253493271, + 5019331476826215138, + 8747291997159999285 + ), + // account_vault_remove_asset + digest!( + 6000868439702831595, + 9778474833766934115, + 1146161010038681475, + 1950819778618127304 + ), + // get_account_id + digest!( + 8040261465733444704, + 11111141085375373880, + 7423929485586361344, + 4119214601469502087 + ), + // get_account_item + digest!( + 8242100606610843280, + 12256919645951393204, + 2951068718765716503, + 8986453979900819291 + ), + // get_account_map_item + digest!( + 5940336313866490980, + 9709935953040633522, + 2215378650076306714, + 7584412679403612847 + ), + // get_account_nonce + digest!( + 7949369589472998218, + 13470489034885204869, + 7657993556512253706, + 4189240183103072865 + ), + // get_account_vault_commitment + digest!( + 15827173769627914405, + 8397707743192029429, + 7205844492194182641, + 1677433344562532693 + ), + // get_current_account_hash + digest!( + 18067387847945059633, + 4630780713348682492, + 16252299253975780120, + 12604901563870135002 + ), + // get_initial_account_hash + digest!( + 16301123123708038227, + 8835228777116955671, + 1233594748884564040, + 17497683909577038473 + ), + // incr_account_nonce + digest!( + 6166980265541679115, + 14180799872462142156, + 2778474088493363690, + 1238401418236321485 + ), + // set_account_code + digest!( + 4083640213314520131, + 11866061748990108757, + 7174634238671132507, + 16972174329470134023 + ), + // set_account_item + digest!( + 7498941893890508814, + 5585745677648937735, + 13176054907168595727, + 14561446422739981128 + ), + // set_account_map_item + digest!( + 9257525779338879284, + 5994228928952574041, + 3477745056362616903, + 1514247258411024664 + ), + // burn_asset + digest!( + 2613729911428583836, + 3409713366391106845, + 4618787175150657117, + 13550289764852635265 + ), + // get_fungible_faucet_total_issuance + digest!( + 5567752045855424912, + 1313115426050254227, + 12797601829399057688, + 10963909072124913328 + ), + // mint_asset + digest!( + 11833462197234963951, + 521365474344899632, + 12219339115593432087, + 3026752009521887157 + ), + // add_asset_to_note + digest!( + 14950372948135486500, + 16795936443880575519, + 10590371208545379138, + 3493796503081669802 + ), + // create_note + digest!( + 14778603067944873506, + 14071319835769664212, + 13946705703761691189, + 68248535266635199 + ), + // get_input_notes_commitment + digest!( + 2019728671844693749, + 18222437788741437389, + 12821100448410084889, + 17418670035031233675 + ), + // get_note_assets_info + digest!( + 12346411220238036656, + 18027533406091104744, + 14723639276543495147, + 11542458885879781389 + ), + // get_note_inputs_hash + digest!( + 17186028199923932877, + 2563818256742276816, + 8351223767950877211, + 11379249881600223287 + ), + // get_note_sender + digest!( + 15233821980580537524, + 8874650687593596380, + 14910554371357890324, + 11945045801206913876 + ), + // get_note_serial_number + digest!( + 203467101694736292, + 1871816977533069235, + 11026610821411620572, + 8345006103126977916 + ), + // get_output_notes_hash + digest!( + 4412523757021344747, + 8883378993868597671, + 16885133168375194469, + 15472424727696440458 + ), + // get_block_hash + digest!( + 15575368355470837910, + 13483490255982391120, + 5407999307430887046, + 13895912493177462699 + ), + // get_block_number + digest!( + 957081505105679725, + 18012382143736246386, + 13337406348155951825, + 4537613255382865554 + ), +]; diff --git a/miden-tx/src/error.rs b/miden-tx/src/error.rs index b2d41f71f..6f2786dca 100644 --- a/miden-tx/src/error.rs +++ b/miden-tx/src/error.rs @@ -266,8 +266,9 @@ const ERR_PROC_INDEX_OUT_OF_BOUNDS: u32 = 131147; const ERR_ACCT_CODE_HASH_MISMATCH: u32 = 131148; const ERR_ACCT_TOO_MANY_PROCEDURES: u32 = 131149; const ERR_STORAGE_SLOT_INDEX_OUT_OF_BOUNDS: u32 = 131150; +const ERR_KERNEL_PROCEDURE_OFFSET_OUT_OF_BOUNDS: u32 = 131151; -pub const KERNEL_ERRORS: [(u32, &str); 80] = [ +pub const KERNEL_ERRORS: [(u32, &str); 81] = [ (ERR_FAUCET_RESERVED_DATA_SLOT, "For faucets, storage slot 254 is reserved and can not be used with set_account_item procedure"), (ERR_ACCT_MUST_BE_A_FAUCET, "Procedure can only be called from faucet accounts"), (ERR_P2ID_WRONG_NUMBER_OF_INPUTS, "P2ID scripts expect exactly 1 note input"), @@ -347,5 +348,6 @@ pub const KERNEL_ERRORS: [(u32, &str); 80] = [ (ERR_PROC_INDEX_OUT_OF_BOUNDS, "Provided procedure index is out of bounds"), (ERR_ACCT_CODE_HASH_MISMATCH, "Provided account hash does not match stored account hash"), (ERR_ACCT_TOO_MANY_PROCEDURES, "Number of account procedures exceeded the maximum limit of 256"), - (ERR_STORAGE_SLOT_INDEX_OUT_OF_BOUNDS, "Provided storage slot index is out of bounds") + (ERR_STORAGE_SLOT_INDEX_OUT_OF_BOUNDS, "Provided storage slot index is out of bounds"), + (ERR_KERNEL_PROCEDURE_OFFSET_OUT_OF_BOUNDS, "Provided kernel procedure offset is out of bounds"), ]; From dda26069fd5d2d803ec18165e40741b5f60bcd79 Mon Sep 17 00:00:00 2001 From: Andrey Date: Thu, 12 Sep 2024 20:42:18 +0300 Subject: [PATCH 09/11] chore: remove debug lines --- miden-lib/src/transaction/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/miden-lib/src/transaction/mod.rs b/miden-lib/src/transaction/mod.rs index 096245197..5703ca79a 100644 --- a/miden-lib/src/transaction/mod.rs +++ b/miden-lib/src/transaction/mod.rs @@ -91,9 +91,6 @@ impl TransactionKernel { tx_args: &TransactionArgs, init_advice_inputs: Option, ) -> (StackInputs, AdviceInputs) { - let (_, aboba, _) = Self::kernel().into_parts(); - std::println!("{:?}", aboba); - let account = tx_inputs.account(); let stack_inputs = TransactionKernel::build_input_stack( From 304027f929e0b5871b26378fe893534c74d1fc50 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 13 Sep 2024 14:58:41 +0300 Subject: [PATCH 10/11] refactor: move macro to utils, rename variables, remove excess error --- miden-lib/src/transaction/inputs.rs | 4 ++-- miden-lib/src/transaction/procedures.rs | 12 +++--------- miden-tx/src/errors/tx_kernel_errors.rs | 7 +------ objects/src/lib.rs | 8 ++++++++ 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/miden-lib/src/transaction/inputs.rs b/miden-lib/src/transaction/inputs.rs index fb232e894..91d749c7a 100644 --- a/miden-lib/src/transaction/inputs.rs +++ b/miden-lib/src/transaction/inputs.rs @@ -308,8 +308,8 @@ fn add_input_notes_to_advice_inputs( /// - The hash of the selected kernel |-> array of the kernel's procedure hashes. pub fn add_kernel_hashes_to_advice_inputs(inputs: &mut AdviceInputs, kernel_version: u8) { let mut kernel_hashes: Vec = - Vec::with_capacity(TransactionKernel::KERNEL_VERSION_NUMBER * WORD_SIZE); - for version in 0..TransactionKernel::KERNEL_VERSION_NUMBER { + Vec::with_capacity(TransactionKernel::NUM_VERSIONS * WORD_SIZE); + for version in 0..TransactionKernel::NUM_VERSIONS { kernel_hashes .extend_from_slice(TransactionKernel::kernel_hash(version as u8).as_elements()); } diff --git a/miden-lib/src/transaction/procedures.rs b/miden-lib/src/transaction/procedures.rs index 0593532f5..7920d8c6a 100644 --- a/miden-lib/src/transaction/procedures.rs +++ b/miden-lib/src/transaction/procedures.rs @@ -1,15 +1,9 @@ use alloc::vec::Vec; -use miden_objects::{Digest, Felt, Hasher}; +use miden_objects::{digest, Digest, Felt, Hasher}; use super::TransactionKernel; -macro_rules! digest { - ($a:expr, $b:expr, $c:expr, $d:expr) => { - Digest::new([Felt::new($a), Felt::new($b), Felt::new($c), Felt::new($d)]) - }; -} - // TRANSACTION KERNEL // ================================================================================================ @@ -18,10 +12,10 @@ impl TransactionKernel { // -------------------------------------------------------------------------------------------- /// Number of currently used kernel versions. - pub const KERNEL_VERSION_NUMBER: usize = 1; + pub const NUM_VERSIONS: usize = 1; /// Array of all available kernels. - pub const PROCEDURES: [&'static [Digest]; Self::KERNEL_VERSION_NUMBER] = [&KERNEL0_PROCEDURES]; + pub const PROCEDURES: [&'static [Digest]; Self::NUM_VERSIONS] = [&KERNEL0_PROCEDURES]; // PUBLIC ACCESSORS // -------------------------------------------------------------------------------------------- diff --git a/miden-tx/src/errors/tx_kernel_errors.rs b/miden-tx/src/errors/tx_kernel_errors.rs index 69ab5c8c4..52d8f81e4 100644 --- a/miden-tx/src/errors/tx_kernel_errors.rs +++ b/miden-tx/src/errors/tx_kernel_errors.rs @@ -70,11 +70,7 @@ pub const ERR_ASSET_NOT_FUNGIBLE_ID: u32 = 131137; pub const ERR_ASSET_INVALID_AMOUNT: u32 = 131138; pub const ERR_ASSET_NOT_NON_FUNGIBLE_ID: u32 = 131139; pub const ERR_INVALID_NOTE_TYPE: u32 = 131140; - -// TODO: fix the error values pub const ERR_NOTE_INVALID_TYPE_FOR_TAG: u32 = 131141; -pub const ERR_NOTE_INVALID_TAG_PREFIX_FOR_TYPE: u32 = 131141; - pub const ERR_NOTE_TAG_MUST_BE_U32: u32 = 131142; pub const ERR_SETTING_NON_VALUE_ITEM_ON_VALUE_SLOT: u32 = 131143; pub const ERR_SETTING_MAP_ITEM_ON_NON_MAP_SLOT: u32 = 131144; @@ -90,7 +86,7 @@ pub const ERR_NON_FUNGIBLE_ASSET_ALREADY_EXISTS: u32 = 131153; pub const ERR_INVALID_NOTE_IDX: u32 = 131154; pub const ERR_KERNEL_PROCEDURE_OFFSET_OUT_OF_BOUNDS: u32 = 131155; -pub const KERNEL_ERRORS: [(u32, &str); 84] = [ +pub const KERNEL_ERRORS: [(u32, &str); 83] = [ (ERR_FAUCET_RESERVED_DATA_SLOT, "For faucets, storage slot 254 is reserved and can not be used with set_account_item procedure"), (ERR_ACCT_MUST_BE_A_FAUCET, "Procedure can only be called from faucet accounts"), (ERR_P2ID_WRONG_NUMBER_OF_INPUTS, "P2ID scripts expect exactly 1 note input"), @@ -164,7 +160,6 @@ pub const KERNEL_ERRORS: [(u32, &str); 84] = [ (ERR_NOTE_INVALID_TYPE_FOR_TAG, "Provided note tag type is invalid"), (ERR_NOTE_FUNGIBLE_MAX_AMOUNT_EXCEEDED, "Adding a fungible asset to a note cannot exceed the maximum_amount"), (ERR_NON_FUNGIBLE_ASSET_ALREADY_EXISTS, "Non-fungible asset that already exists in the note cannot be added again"), - (ERR_NOTE_INVALID_TAG_PREFIX_FOR_TYPE, "The note's tag failed the most significant validation"), (ERR_NOTE_TAG_MUST_BE_U32, "The note's tag high bits must be set to 0"), (ERR_SETTING_NON_VALUE_ITEM_ON_VALUE_SLOT, "Setting a non-value item on a value slot"), (ERR_SETTING_MAP_ITEM_ON_NON_MAP_SLOT, "Setting a map item on a non-map slot"), diff --git a/objects/src/lib.rs b/objects/src/lib.rs index c42731b67..f6dd42d11 100644 --- a/objects/src/lib.rs +++ b/objects/src/lib.rs @@ -52,6 +52,14 @@ pub mod utils { ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, }; } + + /// Construct a new [Digest] from four `u64` values. + #[macro_export] + macro_rules! digest { + ($a:expr, $b:expr, $c:expr, $d:expr) => { + Digest::new([Felt::new($a), Felt::new($b), Felt::new($c), Felt::new($d)]) + }; + } } pub mod vm { From 06c72bff2308a0526a80e5c4856c62abe26c255b Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 13 Sep 2024 15:10:29 +0300 Subject: [PATCH 11/11] docs: fix macro doc, update documentation --- docs/architecture/transactions/contexts.md | 2 +- objects/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/architecture/transactions/contexts.md b/docs/architecture/transactions/contexts.md index e7ca0412d..e398d6515 100644 --- a/docs/architecture/transactions/contexts.md +++ b/docs/architecture/transactions/contexts.md @@ -64,7 +64,7 @@ export.receive_asset end ``` -The [account API](https://github.com/0xPolygonMiden/miden-base/blob/main/miden-lib/asm/miden/account.masm#L162) exposes procedures to manage accounts. This particular procedure that was called by the wallet invokes a `syscall` to return back to the root context **(3)**, where the account vault is stored in memory (see prologue). `syscall` can invoke all procedures defined in the [Kernel API](https://github.com/0xPolygonMiden/miden-base/blob/main/miden-lib/asm/kernels/transaction/api.masm). +The [account API](https://github.com/0xPolygonMiden/miden-base/blob/main/miden-lib/asm/miden/account.masm#L162) exposes procedures to manage accounts. This particular procedure that was called by the wallet invokes a `syscall` to return back to the root context **(3)**, where the account vault is stored in memory (see prologue). Procedures defined in the [Kernel API](https://github.com/0xPolygonMiden/miden-base/blob/main/miden-lib/asm/kernels/transaction/api.masm) should be invoked with `syscall` using the corresponding [procedure offset](https://github.com/0xPolygonMiden/miden-base/blob/main/miden-lib/asm/miden/kernel_proc_offsets.masm) and the `exec_kernel_proc` kernel procedure. ```arduino #! Add the specified asset to the vault. diff --git a/objects/src/lib.rs b/objects/src/lib.rs index f6dd42d11..2fdd810c8 100644 --- a/objects/src/lib.rs +++ b/objects/src/lib.rs @@ -53,7 +53,7 @@ pub mod utils { }; } - /// Construct a new [Digest] from four `u64` values. + /// Construct a new `Digest` from four `u64` values. #[macro_export] macro_rules! digest { ($a:expr, $b:expr, $c:expr, $d:expr) => {