diff --git a/CHANGELOG.md b/CHANGELOG.md index 59f8f4f4b..ae5e4c23b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - [BREAKING] Renamed `AccountData` to `AccountFile` (#1116). - Implement transaction batch prover in Rust (#1112). - [BREAKING] Refactored config file for `miden-proving-service` to be based on environment variables (#1120). +- Added block number as a public input to the transaction kernel. Updated prologue logic to validate the global input block number is consistent with the commitment block number (#1126). ## 0.7.2 (2025-01-28) - `miden-objects` crate only diff --git a/crates/miden-lib/asm/kernels/transaction/lib/memory.masm b/crates/miden-lib/asm/kernels/transaction/lib/memory.masm index fd11e6d01..ec7be8704 100644 --- a/crates/miden-lib/asm/kernels/transaction/lib/memory.masm +++ b/crates/miden-lib/asm/kernels/transaction/lib/memory.masm @@ -43,25 +43,25 @@ const.TX_EXPIRATION_BLOCK_NUM_PTR=28 # GLOBAL INPUTS # ------------------------------------------------------------------------------------------------- -# The memory address at which the global inputs section begins +# The memory address at which the global inputs section begins. const.GLOBAL_INPUTS_SECTION_OFFSET=400 -# The memory address at which the latest known block hash is stored +# The memory address at which the latest known block hash is stored. const.BLK_HASH_PTR=400 # The memory address at which the account ID felts are stored. const.ACCT_ID_PTR=404 -# The memory address at which the initial account hash is stored +# The memory address at which the initial account hash is stored. const.INIT_ACCT_HASH_PTR=408 -# The memory address at which the input notes commitment is stored +# The memory address at which the input notes commitment is stored. const.INPUT_NOTES_COMMITMENT_PTR=412 -# The memory address at which the initial nonce is stored +# The memory address at which the initial nonce is stored. const.INIT_NONCE_PTR=416 -# The memory address at which the transaction script mast root is stored +# The memory address at which the transaction script mast root is stored. const.TX_SCRIPT_ROOT_PTR=420 # GLOBAL BLOCK DATA @@ -123,14 +123,14 @@ const.KERNEL_PROCEDURES_PTR=1604 # ------------------------------------------------------------------------------------------------- # The largest memory address which can be used to load the foreign account data. -# It is computed as `2048 * 64 * 4` -- this is the memory address where the data block of the 64th +# It is computed as `2048 * 64 * 4` -- this is the memory address where the data block of the 64th # account starts. const.MAX_FOREIGN_ACCOUNT_PTR=524288 # The memory address at which the native account data is stored. const.NATIVE_ACCOUNT_DATA_PTR=8192 -# The length of the memory interval that the account data occupies. +# The length of the memory interval that the account data occupies. const.ACCOUNT_DATA_LENGTH=8192 # The offsets at which the account data is stored relative to the start of the account data segment. @@ -241,7 +241,7 @@ end #! Outputs: [input_vault_root_ptr] #! #! Where: -#! - input_vault_root_ptr is a pointer to the memory address at which the input vault root is +#! - input_vault_root_ptr is a pointer to the memory address at which the input vault root is #! stored. export.get_input_vault_root_ptr push.INPUT_VAULT_ROOT_PTR @@ -649,7 +649,7 @@ export.get_native_account_data_ptr push.NATIVE_ACCOUNT_DATA_PTR end -#! Returns the length of the memory interval that the account data occupies. +#! Returns the length of the memory interval that the account data occupies. #! #! Inputs: [] #! Outputs: [acct_data_length] @@ -666,7 +666,7 @@ end #! Outputs: [max_foreign_acct_ptr] #! #! Where: -#! - max_foreign_acct_ptr is the largest memory address which can be used to load the foreign +#! - max_foreign_acct_ptr is the largest memory address which can be used to load the foreign #! account data. export.get_max_foreign_account_ptr push.MAX_FOREIGN_ACCOUNT_PTR @@ -1063,7 +1063,7 @@ export.set_input_note_id mem_storew end -#! Computes a pointer to the memory address at which the nullifier associated a note with `idx` is +#! Computes a pointer to the memory address at which the nullifier associated a note with `idx` is #! stored. #! #! Inputs: [idx] @@ -1221,7 +1221,7 @@ export.set_input_note_num_assets mem_store end -#! Returns a pointer to the start of the assets segment for the input note located at the specified +#! Returns a pointer to the start of the assets segment for the input note located at the specified #! memory address. #! #! Inputs: [note_ptr] @@ -1449,7 +1449,7 @@ end #! Outputs: [kernel_procedures_ptr] #! #! Where: -#! - kernel_procedures_ptr is the memory address where the hashes of the kernel procedures are +#! - 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 diff --git a/crates/miden-lib/asm/kernels/transaction/lib/prologue.masm b/crates/miden-lib/asm/kernels/transaction/lib/prologue.masm index 2fff6b96a..f52dc4baf 100644 --- a/crates/miden-lib/asm/kernels/transaction/lib/prologue.masm +++ b/crates/miden-lib/asm/kernels/transaction/lib/prologue.masm @@ -19,6 +19,9 @@ const.MAX_BLOCK_NUM=0xFFFFFFFF # The provided global inputs do not match the block hash commitment const.ERR_PROLOGUE_GLOBAL_INPUTS_PROVIDED_DO_NOT_MATCH_BLOCK_HASH_COMMITMENT=0x00020034 +# The provided global inputs do not match the block number commitment +const.ERR_PROLOGUE_GLOBAL_INPUTS_PROVIDED_DO_NOT_MATCH_BLOCK_NUMBER_COMMITMENT=0x00020134 + # New account must have an empty vault const.ERR_PROLOGUE_NEW_ACCOUNT_VAULT_MUST_BE_EMPTY=0x00020035 @@ -66,22 +69,23 @@ const.ERR_PROLOGUE_NEW_ACCOUNT_NONCE_MUST_BE_ZERO=0x0002005B #! Saves global inputs to memory. #! -#! Inputs: [BLOCK_HASH, account_id_prefix, account_id_suffix, INITIAL_ACCOUNT_HASH, INPUT_NOTES_COMMITMENT] -#! Outputs: [] +#! Inputs: [BLOCK_HASH, INITIAL_ACCOUNT_HASH, INPUT_NOTES_COMMITMENT, account_id_prefix, account_id_suffix, block_num] +#! Outputs: [block_num] #! #! Where: #! - BLOCK_HASH is the reference block for the transaction execution. -#! - account_id_{prefix,suffix} are the prefix and suffix felts of the account ID of the account +#! - block_num is the number of the reference block. +#! - account_id_{prefix,suffix} are the prefix and suffix felts of the account ID of the account #! that the transaction is being executed against. -#! - INITIAL_ACCOUNT_HASH is the account state prior to the transaction, EMPTY_WORD for new +#! - INITIAL_ACCOUNT_HASH is the account state prior to the transaction, EMPTY_WORD for new #! accounts. -#! - INPUT_NOTES_COMMITMENT is the commitment to the input notes. See the +#! - INPUT_NOTES_COMMITMENT is the commitment to the input notes. See the #! `tx_get_input_notes_commitment` kernel procedure for details. proc.process_global_inputs exec.memory::set_block_hash dropw - exec.memory::set_global_acct_id exec.memory::set_init_acct_hash dropw exec.memory::set_nullifier_commitment dropw + exec.memory::set_global_acct_id end # KERNEL DATA @@ -102,7 +106,7 @@ end #! Outputs: #! Operand stack: [] #! Advice stack: [] -#! +#! #! Where: #! - kernel_version is the index of the desired kernel in the array of all kernels available for the #! current transaction. @@ -154,7 +158,7 @@ proc.process_kernel_data # AS => [] # get the hash of the kernel which will be used in the current transaction - exec.memory::get_kernel_procedures_ptr add + exec.memory::get_kernel_procedures_ptr add # OS => [kernel_ptr] # AS => [] @@ -196,7 +200,7 @@ proc.process_kernel_data # assert that the precomputed hash matches the computed one movup.4 drop assert_eqw # OS => [] - # AS => [] + # AS => [] end # BLOCK DATA @@ -205,7 +209,7 @@ end #! Saves block data to memory and verifies that it matches the BLOCK_HASH public input. #! #! Inputs: -#! Operand stack: [] +#! Operand stack: [block_num] #! Advice stack: [ #! PREVIOUS_BLOCK_HASH, #! CHAIN_MMR_HASH, @@ -224,7 +228,7 @@ end #! - PREVIOUS_BLOCK_HASH is the hash of the previous block. #! - CHAIN_MMR_HASH is the sequential hash of the reference MMR. #! - ACCOUNT_ROOT is the root of the tree with latest account states for all accounts. -#! - NULLIFIER_ROOT is the root of the tree with nullifiers of all notes that have ever been +#! - NULLIFIER_ROOT is the root of the tree with nullifiers of all notes that have ever been #! consumed. #! - TX_HASH is the commitment to a set of IDs of transactions which affected accounts in the block. #! - KERNEL_ROOT is the accumulative hash from all kernel hashes. @@ -235,7 +239,7 @@ end #! - NOTE_ROOT is the root of the tree with all notes created in the block. proc.process_block_data exec.memory::get_block_data_ptr - # => [block_data_ptr] + # => [block_data_ptr, block_num] # read block data and compute its subhash. See `Advice stack` above for details. padw padw padw @@ -244,24 +248,27 @@ proc.process_block_data adv_pipe hperm adv_pipe hperm exec.rpo::squeeze_digest - # => [DIG, block_data_ptr'] + # => [DIG, block_data_ptr', block_num] # store the note root in memory padw adv_loadw dupw exec.memory::set_note_root dropw - # => [NOTE_ROOT, DIG, block_data_ptr'] + # => [NOTE_ROOT, DIG, block_data_ptr', block_num] # merge the note root with the block data digest hmerge - # => [BLOCK_HASH, block_data_ptr'] + # => [BLOCK_HASH, block_data_ptr', block_num] # assert that the block hash matches the hash in global inputs exec.memory::get_block_hash assert_eqw.err=ERR_PROLOGUE_GLOBAL_INPUTS_PROVIDED_DO_NOT_MATCH_BLOCK_HASH_COMMITMENT - # => [block_data_ptr'] + # => [block_data_ptr', block_num] drop - # => [] + # => [block_num] + + exec.memory::get_blk_num + assert_eq.err=ERR_PROLOGUE_GLOBAL_INPUTS_PROVIDED_DO_NOT_MATCH_BLOCK_NUMBER_COMMITMENT end # CHAIN DATA @@ -357,7 +364,7 @@ proc.validate_new_account if.true # assert the fungible faucet reserved slot is initialized correctly (EMPTY_WORD) # TODO: Switch to standard library implementation when available (miden-vm/#1483) - exec.is_empty_word_dropped not + exec.is_empty_word_dropped not assertz.err=ERR_PROLOGUE_NEW_FUNGIBLE_FAUCET_RESERVED_SLOT_MUST_BE_EMPTY # => [] @@ -366,13 +373,13 @@ proc.validate_new_account # => [slot_type] # assert the fungible faucet reserved slot type == value - exec.constants::get_storage_slot_type_value eq + exec.constants::get_storage_slot_type_value eq assert.err=ERR_PROLOGUE_NEW_FUNGIBLE_FAUCET_RESERVED_SLOT_INVALID_TYPE # => [] else # assert the non-fungible faucet reserved slot is initialized correctly (root of # empty SMT) - exec.constants::get_empty_smt_root + exec.constants::get_empty_smt_root assert_eqw.err=ERR_PROLOGUE_NEW_NON_FUNGIBLE_FAUCET_RESERVED_SLOT_MUST_BE_VALID_EMPY_SMT # => [] @@ -381,7 +388,7 @@ proc.validate_new_account # => [slot_type] # assert the non-fungible faucet reserved slot type == map - exec.constants::get_storage_slot_type_map eq + exec.constants::get_storage_slot_type_map eq assert.err=ERR_PROLOGUE_NEW_NON_FUNGIBLE_FAUCET_RESERVED_SLOT_INVALID_TYPE # => [] end @@ -421,7 +428,7 @@ end #! This procedure will: #! - Read the account data from the advice stack. #! - Save it to memory. -#! - For new accounts, signaled by having a INITIAL_ACCOUNT_HASH set to EMPTY_WORD as a global +#! - For new accounts, signaled by having a INITIAL_ACCOUNT_HASH set to EMPTY_WORD as a global #! input, validate the account's id and initial state. #! - For existing accounts, verify the INITIAL_ACCOUNT_HASH commitment matches the provided data, #! and the account nonce is not zero. @@ -439,7 +446,7 @@ end #! Advice stack: [] #! #! Where: -#! - account_id_{prefix,suffix} are the prefix and suffix felts of the ID of the account that the +#! - account_id_{prefix,suffix} are the prefix and suffix felts of the ID of the account that the #! transaction is being executed against. #! - account_nonce is the account's nonce. #! - ACCOUNT_VAULT_ROOT is the account's vault root. @@ -482,7 +489,7 @@ proc.process_account_data exec.account::save_account_storage_data # => [ACCT_HASH] - # set the new account code commitment to the initial account code root + # set the new account code commitment to the initial account code root # this is used for managing code commitment updates exec.memory::get_acct_code_commitment exec.memory::set_new_acct_code_commitment @@ -579,7 +586,7 @@ proc.authenticate_note.8 # => [COMPUTED_BLOCK_HASH, PERM, mem_ptr', BLOCK_HASH, NOTE_HASH] # assert the computed block hash matches - movup.8 drop movupw.2 + movup.8 drop movupw.2 assert_eqw.err=ERR_PROLOGUE_MISMATCH_OF_REFERENCE_BLOCK_MMR_AND_NOTE_AUTHENTICATION_MMR # => [PERM, NOTE_HASH] @@ -616,7 +623,7 @@ end #! INPUTS_HASH, #! ASSETS_HASH, #! ] -#! Outputs: +#! Outputs: #! Operand stack: [NULLIFIER] #! Advice stack: [] #! @@ -648,8 +655,8 @@ end #! - The note's ARGS are not authenticated, these are optional arguments the user can provide when #! consuming the note. #! - The note's metadata is authenticated, so the data is returned in the stack. The value is used -#! to compute the NOTE_HASH as `hash(NOTE_ID || NOTE_METADATA)`, which is the leaf value of the -#! note's tree in the contained in the block header. The NOTE_HASH is either verified by this +#! to compute the NOTE_HASH as `hash(NOTE_ID || NOTE_METADATA)`, which is the leaf value of the +#! note's tree in the contained in the block header. The NOTE_HASH is either verified by this #! kernel, or delayed to be verified by another kernel (e.g. block or batch kernels). #! #! Inputs: @@ -691,7 +698,7 @@ proc.process_note_assets adv_push.1 # => [assets_count, note_ptr] - dup exec.constants::get_max_assets_per_note lte + dup exec.constants::get_max_assets_per_note lte assert.err=ERR_PROLOGUE_NUMBER_OF_NOTE_ASSETS_EXCEEDS_LIMIT # => [assets_count, note_ptr] @@ -855,13 +862,13 @@ end #! NOTE_ROOT, #! )? #! ] -#! Outputs: +#! Outputs: #! Operand stack: [PERM, PERM, PERM] #! Advice stack: [] #! #! Where: #! - idx is the index of the input note. -#! - HASHER_CAPACITY is the state of the hasher capacity word, with the commitment to the previous +#! - HASHER_CAPACITY is the state of the hasher capacity word, with the commitment to the previous #! notes. #! - SERIAL_NUMBER is the note's serial. #! - SCRIPT_ROOT is the note's script root. @@ -954,10 +961,10 @@ end #! Inputs: #! Operand stack: [] #! Advice stack: [num_notes], -#! Advice map: { -#! INPUT_NOTES_COMMITMENT: [NOTE_DATA] +#! Advice map: { +#! INPUT_NOTES_COMMITMENT: [NOTE_DATA] #! } -#! Outputs: +#! Outputs: #! Operand stack: [] #! Advice stack: [] #! @@ -973,7 +980,7 @@ proc.process_input_notes_data # assert the number of input notes is within limits; since max number of input notes is # expected to be smaller than 2^32, we can use a more efficient u32 comparison dup - exec.constants::get_max_num_input_notes + exec.constants::get_max_num_input_notes u32assert2.err=ERR_PROLOGUE_NUMBER_OF_INPUT_NOTES_EXCEEDS_LIMIT u32lte assert.err=ERR_PROLOGUE_NUMBER_OF_INPUT_NOTES_EXCEEDS_LIMIT # => [num_notes] @@ -1086,9 +1093,9 @@ end #! Inputs: #! Operand stack: [ #! BLOCK_HASH, -#! account_id_prefix, account_id_suffix, #! INITIAL_ACCOUNT_HASH, #! INPUT_NOTES_COMMITMENT, +#! account_id_prefix, account_id_suffix, block_num, #! ] #! Advice stack: [ #! PREVIOUS_BLOCK_HASH, @@ -1122,16 +1129,16 @@ end #! #! Where: #! - BLOCK_HASH is the reference block for the transaction execution. -#! - account_id_{prefix,suffix} are the prefix and suffix felts of the account that the transaction +#! - account_id_{prefix,suffix} are the prefix and suffix felts of the account that the transaction #! is being executed against. -#! - INITIAL_ACCOUNT_HASH is the account state prior to the transaction, EMPTY_WORD for new +#! - INITIAL_ACCOUNT_HASH is the account state prior to the transaction, EMPTY_WORD for new #! accounts. #! - INPUT_NOTES_COMMITMENT, see `transaction::api::get_input_notes_commitment`. #! - KERNEL_ROOT is the accumulative hash from all kernel hashes. #! - PREVIOUS_BLOCK_HASH is the hash of the previous block. #! - CHAIN_MMR_HASH is the sequential hash of the reference MMR. #! - ACCOUNT_ROOT is the root of the tree with latest account states for all accounts. -#! - NULLIFIER_ROOT is the root of the tree with nullifiers of all notes that have ever been +#! - NULLIFIER_ROOT is the root of the tree with nullifiers of all notes that have ever been #! consumed. #! - TX_HASH is the commitment to a set of IDs of transactions which affected accounts in the block. #! - PROOF_HASH is the hash of the block's stark proof. @@ -1158,7 +1165,7 @@ end #! - any of the input notes do note exist in the note db. export.prepare_transaction exec.process_global_inputs - # => [] + # => [block_num] exec.process_block_data exec.process_kernel_data diff --git a/crates/miden-lib/src/errors/tx_kernel_errors.rs b/crates/miden-lib/src/errors/tx_kernel_errors.rs index e3e9441b0..40d07b4fa 100644 --- a/crates/miden-lib/src/errors/tx_kernel_errors.rs +++ b/crates/miden-lib/src/errors/tx_kernel_errors.rs @@ -83,6 +83,7 @@ pub const ERR_P2ID_WRONG_NUMBER_OF_INPUTS: u32 = 0x00020050; pub const ERR_PROLOGUE_EXISTING_ACCOUNT_MUST_HAVE_NON_ZERO_NONCE: u32 = 0x0002003B; pub const ERR_PROLOGUE_GLOBAL_INPUTS_PROVIDED_DO_NOT_MATCH_BLOCK_HASH_COMMITMENT: u32 = 0x00020034; +pub const ERR_PROLOGUE_GLOBAL_INPUTS_PROVIDED_DO_NOT_MATCH_BLOCK_NUMBER_COMMITMENT: u32 = 0x00020134; pub const ERR_PROLOGUE_INPUT_NOTES_COMMITMENT_MISMATCH: u32 = 0x00020041; pub const ERR_PROLOGUE_MISMATCH_OF_ACCOUNT_IDS_FROM_GLOBAL_INPUTS_AND_ADVICE_PROVIDER: u32 = 0x0002003C; pub const ERR_PROLOGUE_MISMATCH_OF_REFERENCE_BLOCK_MMR_AND_NOTE_AUTHENTICATION_MMR: u32 = 0x0002003D; @@ -115,7 +116,7 @@ pub const ERR_VAULT_NON_FUNGIBLE_ASSET_ALREADY_EXISTS: u32 = 0x0002001C; pub const ERR_VAULT_NON_FUNGIBLE_ASSET_TO_REMOVE_NOT_FOUND: u32 = 0x0002001F; pub const ERR_VAULT_REMOVE_FUNGIBLE_ASSET_FAILED_INITIAL_VALUE_INVALID: u32 = 0x0002001E; -pub const TX_KERNEL_ERRORS: [(u32, &str); 90] = [ +pub const TX_KERNEL_ERRORS: [(u32, &str); 91] = [ (ERR_ACCOUNT_ANCHOR_BLOCK_HASH_MUST_NOT_BE_EMPTY, "Anchor block hash must not be empty"), (ERR_ACCOUNT_CODE_COMMITMENT_MISMATCH, "Computed account code commitment does not match recorded account code commitment"), (ERR_ACCOUNT_CODE_IS_NOT_UPDATABLE, "Account code must be updatable for it to be possible to set new code"), @@ -189,6 +190,7 @@ pub const TX_KERNEL_ERRORS: [(u32, &str); 90] = [ (ERR_PROLOGUE_EXISTING_ACCOUNT_MUST_HAVE_NON_ZERO_NONCE, "Existing accounts must have a non-zero nonce"), (ERR_PROLOGUE_GLOBAL_INPUTS_PROVIDED_DO_NOT_MATCH_BLOCK_HASH_COMMITMENT, "The provided global inputs do not match the block hash commitment"), + (ERR_PROLOGUE_GLOBAL_INPUTS_PROVIDED_DO_NOT_MATCH_BLOCK_NUMBER_COMMITMENT, "The provided global inputs do not match the block number commitment"), (ERR_PROLOGUE_INPUT_NOTES_COMMITMENT_MISMATCH, "Note commitment computed from the input note data does not match given note commitment"), (ERR_PROLOGUE_MISMATCH_OF_ACCOUNT_IDS_FROM_GLOBAL_INPUTS_AND_ADVICE_PROVIDER, "Account IDs provided via global inputs and advice provider do not match"), (ERR_PROLOGUE_MISMATCH_OF_REFERENCE_BLOCK_MMR_AND_NOTE_AUTHENTICATION_MMR, "Reference block MMR and note's authentication MMR must match"), diff --git a/crates/miden-lib/src/transaction/mod.rs b/crates/miden-lib/src/transaction/mod.rs index 275007d13..6810144e0 100644 --- a/crates/miden-lib/src/transaction/mod.rs +++ b/crates/miden-lib/src/transaction/mod.rs @@ -99,6 +99,7 @@ impl TransactionKernel { account.init_hash(), tx_inputs.input_notes().commitment(), tx_inputs.block_header().hash(), + tx_inputs.block_header().block_num(), ); let mut advice_inputs = init_advice_inputs.unwrap_or_default(); @@ -131,14 +132,15 @@ impl TransactionKernel { /// ```text /// [ /// BLOCK_HASH, - /// acct_id, /// INITIAL_ACCOUNT_HASH, /// INPUT_NOTES_COMMITMENT, + /// acct_id_prefix, acct_id_suffix, block_num /// ] /// ``` /// /// Where: /// - BLOCK_HASH, reference block for the transaction execution. + /// - block_num, number of the reference block. /// - 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`. @@ -147,13 +149,15 @@ impl TransactionKernel { init_acct_hash: Digest, input_notes_hash: Digest, block_hash: Digest, + block_num: BlockNumber, ) -> StackInputs { // Note: Must be kept in sync with the transaction's kernel prepare_transaction procedure let mut inputs: Vec = Vec::with_capacity(14); - inputs.extend(input_notes_hash); - inputs.extend_from_slice(init_acct_hash.as_elements()); + inputs.push(Felt::from(block_num)); inputs.push(account_id.suffix()); inputs.push(account_id.prefix().as_felt()); + inputs.extend(input_notes_hash); + inputs.extend_from_slice(init_acct_hash.as_elements()); inputs.extend_from_slice(block_hash.as_elements()); StackInputs::new(inputs) .map_err(|e| e.to_string()) diff --git a/crates/miden-tx/src/tests/kernel_tests/test_prologue.rs b/crates/miden-tx/src/tests/kernel_tests/test_prologue.rs index 2e490c888..0fb99ae72 100644 --- a/crates/miden-tx/src/tests/kernel_tests/test_prologue.rs +++ b/crates/miden-tx/src/tests/kernel_tests/test_prologue.rs @@ -657,7 +657,7 @@ fn test_get_blk_version() { exec.prologue::prepare_transaction exec.memory::get_blk_version - # truncate the stack + # truncate the stack swap drop end "; @@ -678,7 +678,7 @@ fn test_get_blk_timestamp() { exec.prologue::prepare_transaction exec.memory::get_blk_timestamp - # truncate the stack + # truncate the stack swap drop end "; diff --git a/crates/miden-tx/src/verifier/mod.rs b/crates/miden-tx/src/verifier/mod.rs index d42b4944c..ce113c1db 100644 --- a/crates/miden-tx/src/verifier/mod.rs +++ b/crates/miden-tx/src/verifier/mod.rs @@ -37,6 +37,7 @@ impl TransactionVerifier { transaction.account_update().init_state_hash(), transaction.input_notes().commitment(), transaction.block_ref(), + transaction.block_num(), ); let stack_outputs = TransactionKernel::build_output_stack( transaction.account_update().final_state_hash(),