diff --git a/CHANGELOG.md b/CHANGELOG.md index d5b31db43a..90c79f681a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ - Added support for environment variables to set up the `miden-proving-service` worker (#1281). - Added field identifier structs for component metadata (#1292). - Move `NullifierTree` and `BlockChain` from node to base (#1304). +- Rename `ChainMmr` to `PartialBlockchain` (#1305). ## 0.8.2 (2025-04-18) - `miden-proving-service` crate only diff --git a/crates/miden-block-prover/src/local_block_prover.rs b/crates/miden-block-prover/src/local_block_prover.rs index b11c5a2072..cd3ab106be 100644 --- a/crates/miden-block-prover/src/local_block_prover.rs +++ b/crates/miden-block-prover/src/local_block_prover.rs @@ -10,7 +10,7 @@ use miden_objects::{ ProposedBlock, ProvenBlock, }, note::Nullifier, - transaction::ChainMmr, + transaction::PartialBlockchain, }; use crate::errors::ProvenBlockError; @@ -86,7 +86,7 @@ impl LocalBlockProver { account_updated_witnesses, output_note_batches, created_nullifiers, - chain_mmr, + partial_blockchain, prev_block_header, ) = proposed_block.into_parts(); @@ -111,11 +111,11 @@ impl LocalBlockProver { let new_account_root = compute_account_root(&account_updated_witnesses, &prev_block_header)?; - // Insert the previous block header into the block chain MMR to get the new chain + // Insert the previous block header into the block partial blockchain to get the new chain // commitment. // -------------------------------------------------------------------------------------------- - let new_chain_commitment = compute_chain_commitment(chain_mmr, prev_block_header); + let new_chain_commitment = compute_chain_commitment(partial_blockchain, prev_block_header); // Transform the account update witnesses into block account updates. // -------------------------------------------------------------------------------------------- @@ -229,13 +229,16 @@ fn compute_nullifiers( Ok((nullifiers, partial_nullifier_tree.root())) } -/// Adds the commitment of the previous block header to the chain MMR to compute the new chain -/// commitment. -fn compute_chain_commitment(mut chain_mmr: ChainMmr, prev_block_header: BlockHeader) -> Digest { +/// Adds the commitment of the previous block header to the partial blockchain to compute the new +/// chain commitment. +fn compute_chain_commitment( + mut partial_blockchain: PartialBlockchain, + prev_block_header: BlockHeader, +) -> Digest { // SAFETY: This does not panic as long as the block header we're adding is the next one in the // chain which is validated as part of constructing a `ProposedBlock`. - chain_mmr.add_block(prev_block_header, true); - chain_mmr.peaks().hash_peaks() + partial_blockchain.add_block(prev_block_header, true); + partial_blockchain.peaks().hash_peaks() } /// Computes the new account tree root after the given updates. diff --git a/crates/miden-block-prover/src/tests/proposed_block_errors.rs b/crates/miden-block-prover/src/tests/proposed_block_errors.rs index 19fd2a5f5f..0f699b110e 100644 --- a/crates/miden-block-prover/src/tests/proposed_block_errors.rs +++ b/crates/miden-block-prover/src/tests/proposed_block_errors.rs @@ -40,7 +40,7 @@ fn proposed_block_fails_on_too_many_batches() -> anyhow::Result<()> { let block_inputs = BlockInputs::new( chain.latest_block_header(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), BTreeMap::default(), BTreeMap::default(), @@ -64,7 +64,7 @@ fn proposed_block_fails_on_duplicate_batches() -> anyhow::Result<()> { let block_inputs = BlockInputs::new( chain.latest_block_header(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), BTreeMap::default(), BTreeMap::default(), @@ -124,7 +124,7 @@ fn proposed_block_fails_on_timestamp_not_increasing_monotonically() -> anyhow::R // Mock BlockInputs. let block_inputs = BlockInputs::new( chain.latest_block_header(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), BTreeMap::default(), BTreeMap::default(), @@ -143,22 +143,23 @@ fn proposed_block_fails_on_timestamp_not_increasing_monotonically() -> anyhow::R Ok(()) } -/// Tests that a chain MMR that is not at the state of the previous block header produces an error. +/// Tests that a partial blockchain that is not at the state of the previous block header produces +/// an error. #[test] -fn proposed_block_fails_on_chain_mmr_and_prev_block_inconsistency() -> anyhow::Result<()> { +fn proposed_block_fails_on_partial_blockchain_and_prev_block_inconsistency() -> anyhow::Result<()> { let TestSetup { mut chain, mut txs, .. } = setup_chain(1); let proven_tx0 = txs.remove(&0).unwrap(); let batch0 = generate_batch(&mut chain, vec![proven_tx0]); let batches = vec![batch0]; - // Select the chain MMR which is valid for the current block but pass the next block in the - // chain, which is an inconsistent combination. - let mut chain_mmr = chain.latest_chain_mmr(); + // Select the partial blockchain which is valid for the current block but pass the next block in + // the chain, which is an inconsistent combination. + let mut partial_blockchain = chain.latest_partial_blockchain(); let block2 = chain.clone().seal_next_block(); let block_inputs = BlockInputs::new( block2.header().clone(), - chain_mmr.clone(), + partial_blockchain.clone(), BTreeMap::default(), BTreeMap::default(), BTreeMap::default(), @@ -170,17 +171,17 @@ fn proposed_block_fails_on_chain_mmr_and_prev_block_inconsistency() -> anyhow::R ProposedBlockError::ChainLengthNotEqualToPreviousBlockNumber { chain_length, prev_block_num - } if chain_length == chain_mmr.chain_length() && + } if chain_length == partial_blockchain.chain_length() && prev_block_num == block2.header().block_num() ); // Add an invalid value making the chain length equal to block2's number, but resulting in a // different chain commitment. - chain_mmr.partial_mmr_mut().add(block2.header().nullifier_root(), true); + partial_blockchain.partial_mmr_mut().add(block2.header().nullifier_root(), true); let block_inputs = BlockInputs::new( block2.header().clone(), - chain_mmr.clone(), + partial_blockchain.clone(), BTreeMap::default(), BTreeMap::default(), BTreeMap::default(), @@ -195,8 +196,8 @@ fn proposed_block_fails_on_chain_mmr_and_prev_block_inconsistency() -> anyhow::R Ok(()) } -/// Tests that a chain MMR that does not contain all reference blocks of the batches produces an -/// error. +/// Tests that a partial blockchain that does not contain all reference blocks of the batches +/// produces an error. #[test] fn proposed_block_fails_on_missing_batch_reference_block() -> anyhow::Result<()> { let TestSetup { mut chain, mut txs, .. } = setup_chain(1); @@ -208,13 +209,13 @@ fn proposed_block_fails_on_missing_batch_reference_block() -> anyhow::Result<()> let block2 = chain.seal_next_block(); - let (_, chain_mmr) = chain.latest_selective_chain_mmr([BlockNumber::from(0)]); + let (_, partial_blockchain) = chain.latest_selective_partial_blockchain([BlockNumber::from(0)]); - // The proposed block references block 2 but the chain MMR only contains block 0 but not - // block 1 which is referenced by the batch. + // The proposed block references block 2 but the partial blockchain only contains block 0 but + // not block 1 which is referenced by the batch. let block_inputs = BlockInputs::new( block2.header().clone(), - chain_mmr.clone(), + partial_blockchain.clone(), BTreeMap::default(), BTreeMap::default(), BTreeMap::default(), @@ -307,7 +308,7 @@ fn proposed_block_fails_on_duplicate_output_note() -> anyhow::Result<()> { /// Tests that a missing note inclusion proof produces an error. /// Also tests that an error is produced if the block that the note inclusion proof references is -/// not in the chain MMR. +/// not in the partial blockchain. #[test] fn proposed_block_fails_on_invalid_proof_or_missing_note_inclusion_reference_block() -> anyhow::Result<()> { @@ -337,22 +338,22 @@ fn proposed_block_fails_on_invalid_proof_or_missing_note_inclusion_reference_blo let original_block_inputs = chain.get_block_inputs(&batches); - // Error: Block referenced by note inclusion proof is not in chain MMR. + // Error: Block referenced by note inclusion proof is not in partial blockchain. // -------------------------------------------------------------------------------------------- let mut invalid_block_inputs = original_block_inputs.clone(); invalid_block_inputs - .chain_mmr_mut() + .partial_blockchain_mut() .partial_mmr_mut() .untrack(block2.header().block_num().as_usize()); invalid_block_inputs - .chain_mmr_mut() + .partial_blockchain_mut() .block_headers_mut() .remove(&block2.header().block_num()) .expect("block2 should have been fetched"); let error = ProposedBlock::new(invalid_block_inputs, batches.clone()).unwrap_err(); - assert_matches!(error, ProposedBlockError::UnauthenticatedInputNoteBlockNotInChainMmr { block_number, note_id } if block_number == block2.header().block_num() && note_id == note0.id()); + assert_matches!(error, ProposedBlockError::UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number, note_id } if block_number == block2.header().block_num() && note_id == note0.id()); // Error: Invalid note inclusion proof. // -------------------------------------------------------------------------------------------- diff --git a/crates/miden-block-prover/src/tests/proposed_block_success.rs b/crates/miden-block-prover/src/tests/proposed_block_success.rs index 92cc9db1c5..5e2bcfb570 100644 --- a/crates/miden-block-prover/src/tests/proposed_block_success.rs +++ b/crates/miden-block-prover/src/tests/proposed_block_success.rs @@ -21,7 +21,7 @@ fn proposed_block_succeeds_with_empty_batches() -> anyhow::Result<()> { let block_inputs = BlockInputs::new( chain.latest_block_header(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), BTreeMap::default(), BTreeMap::default(), diff --git a/crates/miden-block-prover/src/tests/proven_block_success.rs b/crates/miden-block-prover/src/tests/proven_block_success.rs index 558ee9e499..7645658aff 100644 --- a/crates/miden-block-prover/src/tests/proven_block_success.rs +++ b/crates/miden-block-prover/src/tests/proven_block_success.rs @@ -129,7 +129,7 @@ fn proven_block_success() -> anyhow::Result<()> { // The Mmr in MockChain adds a new block after it is sealed, so at this point the chain contains // block2 and has length 3. // This means the chain commitment of the mock chain must match the chain commitment of the - // ChainMmr with chain length 2 when the prev block (block2) is added. + // PartialBlockchain with chain length 2 when the prev block (block2) is added. assert_eq!( proven_block.header().chain_commitment(), chain.block_chain().peaks().hash_peaks() @@ -369,12 +369,12 @@ fn proven_block_succeeds_with_empty_batches() -> anyhow::Result<()> { assert_ne!(latest_block_header.account_root(), AccountTree::new().root()); assert_ne!(latest_block_header.nullifier_root(), Smt::new().root()); - let (_, empty_chain_mmr) = chain.latest_selective_chain_mmr([]); - assert_eq!(empty_chain_mmr.block_headers().count(), 0); + let (_, empty_partial_blockchain) = chain.latest_selective_partial_blockchain([]); + assert_eq!(empty_partial_blockchain.block_headers().count(), 0); let block_inputs = BlockInputs::new( latest_block_header.clone(), - empty_chain_mmr.clone(), + empty_partial_blockchain.clone(), BTreeMap::default(), BTreeMap::default(), BTreeMap::default(), diff --git a/crates/miden-lib/asm/kernels/transaction/lib/account.masm b/crates/miden-lib/asm/kernels/transaction/lib/account.masm index 2f775f7d8d..8e4b6cfc3f 100644 --- a/crates/miden-lib/asm/kernels/transaction/lib/account.masm +++ b/crates/miden-lib/asm/kernels/transaction/lib/account.masm @@ -750,7 +750,7 @@ end #! #! Validation is performed via the following steps: #! 1. Retrieve the anchor block commitment by computing the block number of the anchor block and -#! retrieving it from the chain mmr. +#! retrieving it from the partial blockchain. #! 2. Compute the hash of (SEED, CODE_COMMITMENT, STORAGE_COMMITMENT, ANCHOR_BLOCK_COMMITMENT). #! 3. Assert the two least significant elements of the digest are equal to the account ID of the #! account the transaction is being executed against. @@ -758,7 +758,7 @@ end #! Inputs: [] #! Outputs: [] export.validate_seed - # Load the block commitment of the anchor block from the chain mmr. + # Load the block commitment of the anchor block from the partial blockchain. # This is the block commitment to which the account ID is anchored and is derived from. # --------------------------------------------------------------------------------------------- @@ -770,8 +770,8 @@ export.validate_seed dup.3 exec.account_id::id_anchor_block_num # => [anchor_block_num, 0, 0, account_id_prefix, account_id_suffix] - exec.memory::get_chain_mmr_ptr swap - # => [anchor_block_num, chain_mmr_ptr, 0, 0, account_id_prefix, account_id_suffix] + exec.memory::get_partial_blockchain_ptr swap + # => [anchor_block_num, partial_blockchain_ptr, 0, 0, account_id_prefix, account_id_suffix] exec.mmr::get # => [ANCHOR_BLOCK_COMMITMENT, 0, 0, account_id_prefix, account_id_suffix] diff --git a/crates/miden-lib/asm/kernels/transaction/lib/memory.masm b/crates/miden-lib/asm/kernels/transaction/lib/memory.masm index 097bb475c8..9c77c3b3ec 100644 --- a/crates/miden-lib/asm/kernels/transaction/lib/memory.masm +++ b/crates/miden-lib/asm/kernels/transaction/lib/memory.masm @@ -113,17 +113,17 @@ const.BLOCK_METADATA_PTR=828 # The memory address at which the note root is stored const.NOTE_ROOT_PTR=832 -# CHAIN MMR +# PARTIAL BLOCKCHAIN # ------------------------------------------------------------------------------------------------- # The memory address at which the chain data section begins -const.CHAIN_MMR_PTR=1200 +const.PARTIAL_BLOCKCHAIN_PTR=1200 -# The memory address at which the total number of leaves in the chain MMR is stored -const.CHAIN_MMR_NUM_LEAVES_PTR=1200 +# The memory address at which the total number of leaves in the partial blockchain is stored +const.PARTIAL_BLOCKCHAIN_NUM_LEAVES_PTR=1200 -# The memory address at which the chain mmr peaks are stored -const.CHAIN_MMR_PEAKS_PTR=1204 +# The memory address at which the partial blockchain peaks are stored +const.PARTIAL_BLOCKCHAIN_PEAKS_PTR=1204 # KERNEL DATA # ------------------------------------------------------------------------------------------------- @@ -618,37 +618,37 @@ end # CHAIN DATA # ------------------------------------------------------------------------------------------------- -#! Returns a pointer to the chain MMR section. +#! Returns a pointer to the partial blockchain section. #! #! Inputs: [] #! Outputs: [ptr] #! #! Where: -#! - ptr is the pointer to the chain MMR section. -export.get_chain_mmr_ptr - push.CHAIN_MMR_PTR +#! - ptr is the pointer to the partial blockchain section. +export.get_partial_blockchain_ptr + push.PARTIAL_BLOCKCHAIN_PTR end -#! Sets the number of leaves in the chain MMR. +#! Sets the number of leaves in the partial blockchain. #! #! Inputs: [num_leaves] #! Outputs: [] #! #! Where: -#! - num_leaves is the number of leaves in the chain MMR. -export.set_chain_mmr_num_leaves - push.CHAIN_MMR_NUM_LEAVES_PTR mem_store +#! - num_leaves is the number of leaves in the partial blockchain. +export.set_partial_blockchain_num_leaves + push.PARTIAL_BLOCKCHAIN_NUM_LEAVES_PTR mem_store end -#! Returns a pointer to start of the chain MMR peaks section. +#! Returns a pointer to start of the partial blockchain peaks section. #! #! Inputs: [] #! Outputs: [ptr] #! #! Where: -#! - ptr is the pointer to the start of the chain MMR peaks section. -export.get_chain_mmr_peaks_ptr - push.CHAIN_MMR_PEAKS_PTR +#! - ptr is the pointer to the start of the partial blockchain peaks section. +export.get_partial_blockchain_peaks_ptr + push.PARTIAL_BLOCKCHAIN_PEAKS_PTR end # ACCOUNT DATA diff --git a/crates/miden-lib/asm/kernels/transaction/lib/prologue.masm b/crates/miden-lib/asm/kernels/transaction/lib/prologue.masm index 2956ee7a9e..7c29e139be 100644 --- a/crates/miden-lib/asm/kernels/transaction/lib/prologue.masm +++ b/crates/miden-lib/asm/kernels/transaction/lib/prologue.masm @@ -216,7 +216,7 @@ end #! Operand stack: [block_num] #! Advice stack: [ #! PREV_BLOCK_COMMITMENT, -#! CHAIN_MMR_HASH, +#! PARTIAL_BLOCKCHAIN_COMMITMENT, #! ACCOUNT_ROOT, #! NULLIFIER_ROOT, #! TX_COMMITMENT, @@ -230,7 +230,7 @@ end #! #! Where: #! - PREV_BLOCK_COMMITMENT is the commitment to the previous block. -#! - CHAIN_MMR_HASH is the sequential hash of the reference MMR. +#! - PARTIAL_BLOCKCHAIN_COMMITMENT 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 #! consumed. @@ -278,7 +278,7 @@ end # CHAIN DATA # ================================================================================================= -#! Saves the MMR peaks to memory and verifies that it matches the reference block's CHAIN_MMR_HASH. +#! Saves the MMR peaks to memory and verifies that it matches the reference block's PARTIAL_BLOCKCHAIN_COMMITMENT. #! #! This procedure loads the MMR peaks from the advice provider, verifies their hash matches the #! reference block, and insert the reference block in the MMR. The reference block is added to the @@ -289,23 +289,23 @@ end #! Inputs: #! Operand stack: [] #! Advice map: { -#! CHAIN_MMR_HASH: [[num_blocks, 0, 0, 0], PEAK_1, ..., PEAK_N] +#! PARTIAL_BLOCKCHAIN_COMMITMENT: [[num_blocks, 0, 0, 0], PEAK_1, ..., PEAK_N] #! } #! Outputs: #! Operand stack: [] #! #! Where: -#! - CHAIN_MMR_HASH is the sequential hash of the padded MMR peaks. +#! - PARTIAL_BLOCKCHAIN_COMMITMENT is the sequential hash of the padded MMR peaks. #! - num_blocks is the number of blocks in the MMR. #! - PEAK_1 .. PEAK_N are the MMR peaks. proc.process_chain_data - exec.memory::get_chain_mmr_ptr dup - # => [chain_mmr_ptr, chain_mmr_ptr] + exec.memory::get_partial_blockchain_ptr dup + # => [partial_blockchain_ptr, partial_blockchain_ptr] # save the MMR peaks to memory and verify it matches the block's CHAIN_COMMITMENT exec.memory::get_chain_commitment exec.mmr::unpack - # => [chain_mmr_ptr] + # => [partial_blockchain_ptr] # add the current block's commitment to the MMR, enabling authentication of notes created in it exec.memory::get_block_commitment @@ -566,11 +566,11 @@ end #! - NOTE_ROOT is the merkle root of the notes tree containing the input note. #! - note_index is the input note's position in the notes tree. proc.authenticate_note.8 - # Load the BLOCK_COMMITMENT from the CHAIN_MMR + # Load the BLOCK_COMMITMENT from the PARTIAL_BLOCKCHAIN # --------------------------------------------------------------------------------------------- - exec.memory::get_chain_mmr_ptr adv_push.1 - # => [block_num, chain_mmr_ptr, NOTE_COMMITMENT] + exec.memory::get_partial_blockchain_ptr adv_push.1 + # => [block_num, partial_blockchain_ptr, NOTE_COMMITMENT] exec.mmr::get # => [BLOCK_COMMITMENT, NOTE_COMMITMENT] @@ -1103,7 +1103,7 @@ end #! ] #! Advice stack: [ #! PREV_BLOCK_COMMITMENT, -#! CHAIN_MMR_HASH, +#! PARTIAL_BLOCKCHAIN_COMMITMENT, #! ACCOUNT_ROOT, #! NULLIFIER_ROOT, #! TX_COMMITMENT, @@ -1120,7 +1120,7 @@ end #! TX_SCRIPT_ROOT, #! ] #! Advice map: { -#! CHAIN_MMR_HASH: [MMR_PEAKS], +#! PARTIAL_BLOCKCHAIN_COMMITMENT: [MMR_PEAKS], #! INPUT_NOTES_COMMITMENT: [NOTE_DATA], #! TX_KERNEL_COMMITMENT: [KERNEL_COMMITMENTS], #! KERNEL_COMMITMENT: [KERNEL_PROCEDURE_ROOTS], @@ -1140,7 +1140,7 @@ end #! - INPUT_NOTES_COMMITMENT, see `transaction::api::get_input_notes_commitment`. #! - TX_KERNEL_COMMITMENT is the accumulative hash from all kernel commitments. #! - PREV_BLOCK_COMMITMENT is the commitment to the previous block. -#! - CHAIN_MMR_HASH is the sequential hash of the reference MMR. +#! - PARTIAL_BLOCKCHAIN_COMMITMENT 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 #! consumed. diff --git a/crates/miden-lib/src/transaction/inputs.rs b/crates/miden-lib/src/transaction/inputs.rs index d5395e5671..21244939dd 100644 --- a/crates/miden-lib/src/transaction/inputs.rs +++ b/crates/miden-lib/src/transaction/inputs.rs @@ -3,7 +3,9 @@ use alloc::vec::Vec; use miden_objects::{ Digest, EMPTY_WORD, Felt, FieldElement, TransactionInputError, WORD_SIZE, Word, ZERO, account::{Account, StorageSlot}, - transaction::{ChainMmr, InputNote, TransactionArgs, TransactionInputs, TransactionScript}, + transaction::{ + InputNote, PartialBlockchain, TransactionArgs, TransactionInputs, TransactionScript, + }, vm::AdviceInputs, }; @@ -17,7 +19,7 @@ use super::TransactionKernel; /// /// This includes the initial account, an optional account seed (required for new accounts), and /// the input note data, including core note data + authentication paths all the way to the root -/// of one of chain MMR peaks. +/// of one of partial blockchain peaks. pub(super) fn extend_advice_inputs( tx_inputs: &TransactionInputs, tx_args: &TransactionArgs, @@ -30,7 +32,7 @@ pub(super) fn extend_advice_inputs( // build the advice map and Merkle store for relevant components add_kernel_commitments_to_advice_inputs(advice_inputs, kernel_version); - add_chain_mmr_to_advice_inputs(tx_inputs.block_chain(), advice_inputs); + add_partial_blockchain_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)?; for foreign_account in tx_args.foreign_accounts() { @@ -50,7 +52,7 @@ pub(super) fn extend_advice_inputs( /// /// [ /// PARENT_BLOCK_COMMITMENT, -/// CHAIN_MMR_HASH, +/// PARTIAL_BLOCKCHAIN_COMMITMENT, /// ACCOUNT_ROOT, /// NULLIFIER_ROOT, /// TX_COMMITMENT, @@ -115,13 +117,13 @@ fn build_advice_stack( inputs.extend_stack(tx_script.map_or(Word::default(), |script| *script.root())); } -// CHAIN MMR INJECTOR +// PARTIAL BLOCKCHAIN INJECTOR // ------------------------------------------------------------------------------------------------ -/// Inserts the chain MMR data into the provided advice inputs. +/// Inserts the partial blockchain data into the provided advice inputs. /// /// Inserts the following items into the Merkle store: -/// - Inner nodes of all authentication paths contained in the chain MMR. +/// - Inner nodes of all authentication paths contained in the partial blockchain. /// /// Inserts the following data to the advice map: /// @@ -131,7 +133,7 @@ fn build_advice_stack( /// - MMR_ROOT, is the sequential hash of the padded MMR peaks /// - num_blocks, is the number of blocks in the MMR. /// - PEAK_1 .. PEAK_N, are the MMR peaks. -fn add_chain_mmr_to_advice_inputs(mmr: &ChainMmr, inputs: &mut AdviceInputs) { +fn add_partial_blockchain_to_advice_inputs(mmr: &PartialBlockchain, inputs: &mut AdviceInputs) { // NOTE: keep this code in sync with the `process_chain_data` kernel procedure // add authentication paths from the MMR to the Merkle store @@ -273,7 +275,7 @@ fn add_input_notes_to_advice_inputs( tx_inputs .block_chain() .get_block(block_num) - .expect("block not found in chain MMR") + .expect("block not found in partial blockchain") }; // NOTE: keep in sync with the `prologue::process_input_note` kernel procedure diff --git a/crates/miden-lib/src/transaction/memory.rs b/crates/miden-lib/src/transaction/memory.rs index 510bed5db1..55711f1f79 100644 --- a/crates/miden-lib/src/transaction/memory.rs +++ b/crates/miden-lib/src/transaction/memory.rs @@ -19,7 +19,7 @@ pub type StorageSlot = u8; // | Bookkeeping | 0 (0) | 287 (71) | | // | Global inputs | 400 (100) | 423 (105) | | // | Block header | 800 (200) | 835 (208) | | -// | Chain MMR | 1_200 (300) | 1_331? (332?) | | +// | Partial blockchain | 1_200 (300) | 1_331? (332?) | | // | Kernel data | 1_600 (400) | 1_739 (434) | 34 procedures in total, 4 elements each | // | Accounts data | 8_192 (2048) | 532_479 (133_119) | 64 accounts max, 8192 elements each | // | Input notes | 4_194_304 (1_048_576) | ? | | @@ -162,13 +162,13 @@ pub const NOTE_ROOT_PTR: MemoryAddress = 832; // ------------------------------------------------------------------------------------------------ /// The memory address at which the chain data section begins -pub const CHAIN_MMR_PTR: MemoryAddress = 1200; +pub const PARTIAL_BLOCKCHAIN_PTR: MemoryAddress = 1200; -/// The memory address at which the total number of leaves in the chain MMR is stored -pub const CHAIN_MMR_NUM_LEAVES_PTR: MemoryAddress = 1200; +/// The memory address at which the total number of leaves in the partial blockchain is stored +pub const PARTIAL_BLOCKCHAIN_NUM_LEAVES_PTR: MemoryAddress = 1200; -/// The memory address at which the chain mmr peaks are stored -pub const CHAIN_MMR_PEAKS_PTR: MemoryAddress = 1204; +/// The memory address at which the partial blockchain peaks are stored +pub const PARTIAL_BLOCKCHAIN_PEAKS_PTR: MemoryAddress = 1204; // KERNEL DATA // ------------------------------------------------------------------------------------------------ diff --git a/crates/miden-objects/src/batch/input_output_note_tracker.rs b/crates/miden-objects/src/batch/input_output_note_tracker.rs index f66e6b10fd..58fbe76969 100644 --- a/crates/miden-objects/src/batch/input_output_note_tracker.rs +++ b/crates/miden-objects/src/batch/input_output_note_tracker.rs @@ -7,7 +7,9 @@ use crate::{ crypto::merkle::MerkleError, errors::ProposedBatchError, note::{NoteHeader, NoteId, NoteInclusionProof, Nullifier}, - transaction::{ChainMmr, InputNoteCommitment, OutputNote, ProvenTransaction, TransactionId}, + transaction::{ + InputNoteCommitment, OutputNote, PartialBlockchain, ProvenTransaction, TransactionId, + }, }; type BatchInputNotes = Vec; @@ -53,7 +55,7 @@ impl InputOutputNoteTracker { pub fn from_transactions<'a>( txs: impl Iterator + Clone, unauthenticated_note_proofs: &BTreeMap, - chain_mmr: &ChainMmr, + partial_blockchain: &PartialBlockchain, batch_reference_block: &BlockHeader, ) -> Result<(BatchInputNotes, BatchOutputNotes), ProposedBatchError> { let input_notes_iter = txs.clone().flat_map(|tx| { @@ -69,7 +71,7 @@ impl InputOutputNoteTracker { input_notes_iter, output_notes_iter, unauthenticated_note_proofs, - chain_mmr, + partial_blockchain, batch_reference_block, ) .map_err(ProposedBatchError::from)?; @@ -93,7 +95,7 @@ impl InputOutputNoteTracker { pub fn from_batches<'a>( batches: impl Iterator + Clone, unauthenticated_note_proofs: &BTreeMap, - chain_mmr: &ChainMmr, + partial_blockchain: &PartialBlockchain, prev_block: &BlockHeader, ) -> Result<(BlockInputNotes, ErasedNotes, BlockOutputNotes), ProposedBlockError> { let input_notes_iter = batches.clone().flat_map(|batch| { @@ -111,7 +113,7 @@ impl InputOutputNoteTracker { input_notes_iter, output_notes_iter, unauthenticated_note_proofs, - chain_mmr, + partial_blockchain, prev_block, ) .map_err(ProposedBlockError::from)?; @@ -133,7 +135,7 @@ impl InputOutputNoteTracker { input_notes_iter: impl Iterator, output_notes_iter: impl Iterator, unauthenticated_note_proofs: &BTreeMap, - chain_mmr: &ChainMmr, + partial_blockchain: &PartialBlockchain, reference_block: &BlockHeader, ) -> Result> { let mut input_notes = BTreeMap::new(); @@ -148,7 +150,7 @@ impl InputOutputNoteTracker { input_note_commitment.nullifier(), note_header, proof, - chain_mmr, + partial_blockchain, reference_block, )?; } @@ -261,7 +263,8 @@ impl InputOutputNoteTracker { } /// Verifies the note inclusion proof for the given input note commitment parts (nullifier and - /// note header). Uses the block header referenced by the inclusion proof from the chain MMR. + /// note header). Uses the block header referenced by the inclusion proof from the partial + /// blockchain. /// /// If the proof is valid, it means the note is part of the chain and it is "marked" as /// authenticated by returning an [`InputNoteCommitment`] without the note header. @@ -269,15 +272,15 @@ impl InputOutputNoteTracker { nullifier: Nullifier, note_header: &NoteHeader, proof: &NoteInclusionProof, - chain_mmr: &ChainMmr, + partial_blockchain: &PartialBlockchain, reference_block: &BlockHeader, ) -> Result> { let proof_reference_block = proof.location().block_num(); let note_block_header = if reference_block.block_num() == proof_reference_block { reference_block } else { - chain_mmr.get_block(proof.location().block_num()).ok_or_else(|| { - InputOutputNoteTrackerError::UnauthenticatedInputNoteBlockNotInChainMmr { + partial_blockchain.get_block(proof.location().block_num()).ok_or_else(|| { + InputOutputNoteTrackerError::UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number: proof.location().block_num(), note_id: note_header.id(), } @@ -323,7 +326,7 @@ enum InputOutputNoteTrackerError { input_commitment: Digest, output_commitment: Digest, }, - UnauthenticatedInputNoteBlockNotInChainMmr { + UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number: BlockNumber, note_id: NoteId, }, @@ -364,10 +367,10 @@ impl From> for ProposedBlockError { input_commitment, output_commitment, }, - InputOutputNoteTrackerError::UnauthenticatedInputNoteBlockNotInChainMmr { + InputOutputNoteTrackerError::UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number, note_id, - } => ProposedBlockError::UnauthenticatedInputNoteBlockNotInChainMmr { + } => ProposedBlockError::UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number, note_id, }, @@ -414,10 +417,10 @@ impl From> for ProposedBatchError { input_commitment, output_commitment, }, - InputOutputNoteTrackerError::UnauthenticatedInputNoteBlockNotInChainMmr { + InputOutputNoteTrackerError::UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number, note_id, - } => ProposedBatchError::UnauthenticatedInputNoteBlockNotInChainMmr { + } => ProposedBatchError::UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number, note_id, }, diff --git a/crates/miden-objects/src/batch/proposed_batch.rs b/crates/miden-objects/src/batch/proposed_batch.rs index b7568c6a71..a3bb50a172 100644 --- a/crates/miden-objects/src/batch/proposed_batch.rs +++ b/crates/miden-objects/src/batch/proposed_batch.rs @@ -12,7 +12,7 @@ use crate::{ errors::ProposedBatchError, note::{NoteId, NoteInclusionProof}, transaction::{ - ChainMmr, InputNoteCommitment, InputNotes, OrderedTransactionHeaders, OutputNote, + InputNoteCommitment, InputNotes, OrderedTransactionHeaders, OutputNote, PartialBlockchain, ProvenTransaction, TransactionHeader, }, utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}, @@ -29,10 +29,10 @@ pub struct ProposedBatch { transactions: Vec>, /// The header is boxed as it has a large stack size. reference_block_header: BlockHeader, - /// The chain MMR used to authenticate: + /// The partial blockchain used to authenticate: /// - all unauthenticated notes that can be authenticated, /// - all block commitments referenced by the transactions in the batch. - chain_mmr: ChainMmr, + partial_blockchain: PartialBlockchain, /// The note inclusion proofs for unauthenticated notes that were consumed in the batch which /// can be authenticated. unauthenticated_note_proofs: BTreeMap, @@ -67,8 +67,8 @@ impl ProposedBatch { /// matches the account state before any transactions are executed and B's initial account /// state commitment matches the final account state commitment of A, then A must come before /// B. - /// - The chain MMR's hashed peaks must match the reference block's `chain_commitment` and it - /// must contain all block headers: + /// - The partial blockchain's hashed peaks must match the reference block's `chain_commitment` + /// and it must contain all block headers: /// - that are referenced by note inclusion proofs in `unauthenticated_note_proofs`. /// - that are referenced by a transaction in the batch. /// - The `unauthenticated_note_proofs` should contain [`NoteInclusionProof`]s for any @@ -81,7 +81,7 @@ impl ProposedBatch { /// - The reference block of a batch must satisfy the following requirement: Its block number /// must be greater or equal to the highest block number referenced by any transaction. This /// is not verified explicitly, but will implicitly cause an error during the validation that - /// each reference block of a transaction is in the chain MMR. + /// each reference block of a transaction is in the partial blockchain. /// /// # Errors /// @@ -97,14 +97,14 @@ impl ProposedBatch { /// - Any note is created more than once. /// - The number of account updates exceeds [`MAX_ACCOUNTS_PER_BATCH`]. /// - Note that any number of transactions against the same account count as one update. - /// - The chain MMRs chain length does not match the block header's block number. This means the - /// chain MMR should not contain the block header itself as it is added to the MMR in the - /// batch kernel. - /// - The chain MMRs hashed peaks do not match the block header's chain commitment. - /// - The reference block of any transaction is not in the chain MMR. + /// - The partial blockchains chain length does not match the block header's block number. This + /// means the partial blockchain should not contain the block header itself as it is added to + /// the MMR in the batch kernel. + /// - The partial blockchains hashed peaks do not match the block header's chain commitment. + /// - The reference block of any transaction is not in the partial blockchain. /// - The note inclusion proof for an unauthenticated note fails to verify. /// - The block referenced by a note inclusion proof for an unauthenticated note is missing from - /// the chain MMR. + /// the partial blockchain. /// - The transactions in the proposed batch which update the same account are not correctly /// ordered. /// - The provided list of transactions is empty. An empty batch is pointless and would @@ -116,7 +116,7 @@ impl ProposedBatch { pub fn new( transactions: Vec>, reference_block_header: BlockHeader, - chain_mmr: ChainMmr, + partial_blockchain: PartialBlockchain, unauthenticated_note_proofs: BTreeMap, ) -> Result { // Check for empty or duplicate transactions. @@ -133,17 +133,17 @@ impl ProposedBatch { } } - // Verify block header and chain MMR match. + // Verify block header and partial blockchain match. // -------------------------------------------------------------------------------------------- - if chain_mmr.chain_length() != reference_block_header.block_num() { + if partial_blockchain.chain_length() != reference_block_header.block_num() { return Err(ProposedBatchError::InconsistentChainLength { expected: reference_block_header.block_num(), - actual: chain_mmr.chain_length(), + actual: partial_blockchain.chain_length(), }); } - let hashed_peaks = chain_mmr.peaks().hash_peaks(); + let hashed_peaks = partial_blockchain.peaks().hash_peaks(); if hashed_peaks != reference_block_header.chain_commitment() { return Err(ProposedBatchError::InconsistentChainRoot { expected: reference_block_header.chain_commitment(), @@ -151,29 +151,30 @@ impl ProposedBatch { }); } - // Verify all block references from the transactions are in the chain MMR, except for the - // batch's reference block. + // Verify all block references from the transactions are in the partial blockchain, except + // for the batch's reference block. // - // Note that some block X is only added to the blockchain MMR by block X + 1. This is - // because block X cannot compute its own block commitment and thus cannot add itself to the - // chain. So, more generally, a previous block is added to the blockchain by its child - // block. + // Note that some block X is only added to the blockchain by block X + 1. This + // is because block X cannot compute its own block commitment and thus cannot add + // itself to the chain. So, more generally, a previous block is added to the + // blockchain by its child block. // // The reference block of a batch may be the latest block in the chain and, as mentioned, - // block is not yet part of the blockchain MMR, so its inclusion cannot be proven. Since the - // inclusion cannot be proven in all cases, the batch kernel instead commits to this - // reference block's commitment as a public input, which means the block kernel will prove - // this block's inclusion when including this batch and verifying its ZK proof. + // block is not yet part of the blockchain, so its inclusion cannot be proven. + // Since the inclusion cannot be proven in all cases, the batch kernel instead + // commits to this reference block's commitment as a public input, which means the + // block kernel will prove this block's inclusion when including this batch and + // verifying its ZK proof. // // Finally, note that we don't verify anything cryptographically here. We have previously // verified that the batch reference block's chain commitment matches the hashed peaks of - // the `ChainMmr`, and so we only have to check if the chain MMR contains the block - // here. + // the `PartialBlockchain`, and so we only have to check if the partial blockchain contains + // the block here. // -------------------------------------------------------------------------------------------- for tx in transactions.iter() { if reference_block_header.block_num() != tx.ref_block_num() - && !chain_mmr.contains_block(tx.ref_block_num()) + && !partial_blockchain.contains_block(tx.ref_block_num()) { return Err(ProposedBatchError::MissingTransactionBlockReference { block_reference: tx.ref_block_commitment(), @@ -260,7 +261,7 @@ impl ProposedBatch { let (input_notes, output_notes) = InputOutputNoteTracker::from_transactions( transactions.iter().map(AsRef::as_ref), &unauthenticated_note_proofs, - &chain_mmr, + &partial_blockchain, &reference_block_header, )?; @@ -284,7 +285,7 @@ impl ProposedBatch { id, transactions, reference_block_header, - chain_mmr, + partial_blockchain, unauthenticated_note_proofs, account_updates, batch_expiration_block_num, @@ -356,7 +357,7 @@ impl ProposedBatch { ) -> ( Vec>, BlockHeader, - ChainMmr, + PartialBlockchain, BTreeMap, BatchId, BTreeMap, @@ -367,7 +368,7 @@ impl ProposedBatch { ( self.transactions, self.reference_block_header, - self.chain_mmr, + self.partial_blockchain, self.unauthenticated_note_proofs, self.id, self.account_updates, @@ -390,7 +391,7 @@ impl Serializable for ProposedBatch { .write_into(target); self.reference_block_header.write_into(target); - self.chain_mmr.write_into(target); + self.partial_blockchain.write_into(target); self.unauthenticated_note_proofs.write_into(target); } } @@ -403,16 +404,19 @@ impl Deserializable for ProposedBatch { .collect::>>(); let block_header = BlockHeader::read_from(source)?; - let chain_mmr = ChainMmr::read_from(source)?; + let partial_blockchain = PartialBlockchain::read_from(source)?; let unauthenticated_note_proofs = BTreeMap::::read_from(source)?; - ProposedBatch::new(transactions, block_header, chain_mmr, unauthenticated_note_proofs) - .map_err(|source| { - DeserializationError::UnknownError(format!( - "failed to create proposed batch: {source}" - )) - }) + ProposedBatch::new( + transactions, + block_header, + partial_blockchain, + unauthenticated_note_proofs, + ) + .map_err(|source| { + DeserializationError::UnknownError(format!("failed to create proposed batch: {source}")) + }) } } @@ -433,16 +437,16 @@ mod tests { #[test] fn proposed_batch_serialization() -> anyhow::Result<()> { - // create chain MMR with 3 blocks - i.e., 2 peaks + // create partial blockchain with 3 blocks - i.e., 2 peaks let mut mmr = Mmr::default(); for i in 0..3 { let block_header = BlockHeader::mock(i, None, None, &[], Digest::default()); mmr.add(block_header.commitment()); } let partial_mmr: PartialMmr = mmr.peaks().into(); - let chain_mmr = ChainMmr::new(partial_mmr, Vec::new()).unwrap(); + let partial_blockchain = PartialBlockchain::new(partial_mmr, Vec::new()).unwrap(); - let chain_commitment = chain_mmr.peaks().hash_peaks(); + let chain_commitment = partial_blockchain.peaks().hash_peaks(); let note_root: Word = rand_array(); let tx_kernel_commitment: Word = rand_array(); let reference_block_header = BlockHeader::mock( @@ -484,7 +488,7 @@ mod tests { let batch = ProposedBatch::new( vec![Arc::new(tx)], reference_block_header, - chain_mmr, + partial_blockchain, BTreeMap::new(), ) .context("failed to propose batch")?; @@ -496,7 +500,7 @@ mod tests { assert_eq!(batch.transactions(), batch2.transactions()); assert_eq!(batch.reference_block_header, batch2.reference_block_header); - assert_eq!(batch.chain_mmr, batch2.chain_mmr); + assert_eq!(batch.partial_blockchain, batch2.partial_blockchain); assert_eq!(batch.unauthenticated_note_proofs, batch2.unauthenticated_note_proofs); assert_eq!(batch.id, batch2.id); assert_eq!(batch.account_updates, batch2.account_updates); diff --git a/crates/miden-objects/src/block/block_inputs.rs b/crates/miden-objects/src/block/block_inputs.rs index deeb47f2b0..4a9bb72d1f 100644 --- a/crates/miden-objects/src/block/block_inputs.rs +++ b/crates/miden-objects/src/block/block_inputs.rs @@ -4,7 +4,7 @@ use crate::{ account::AccountId, block::{AccountWitness, BlockHeader, NullifierWitness}, note::{NoteId, NoteInclusionProof, Nullifier}, - transaction::ChainMmr, + transaction::PartialBlockchain, }; // BLOCK INPUTS @@ -19,7 +19,7 @@ pub struct BlockInputs { /// The chain state at the previous block with authentication paths for: /// - each block referenced by a batch in the block, /// - each block referenced by a note inclusion proof for an unauthenticated note. - chain_mmr: ChainMmr, + partial_blockchain: PartialBlockchain, /// The state commitments of the accounts in the block and their authentication paths. account_witnesses: BTreeMap, @@ -36,14 +36,14 @@ impl BlockInputs { /// Creates new [`BlockInputs`] from the provided parts. pub fn new( prev_block_header: BlockHeader, - chain_mmr: ChainMmr, + partial_blockchain: PartialBlockchain, account_witnesses: BTreeMap, nullifier_witnesses: BTreeMap, unauthenticated_note_proofs: BTreeMap, ) -> Self { Self { prev_block_header, - chain_mmr, + partial_blockchain, account_witnesses, nullifier_witnesses, unauthenticated_note_proofs, @@ -55,9 +55,9 @@ impl BlockInputs { &self.prev_block_header } - /// Returns a reference to the [`ChainMmr`]. - pub fn chain_mmr(&self) -> &ChainMmr { - &self.chain_mmr + /// Returns a reference to the [`PartialBlockchain`]. + pub fn partial_blockchain(&self) -> &PartialBlockchain { + &self.partial_blockchain } /// Returns a reference to the account witnesses. @@ -81,14 +81,14 @@ impl BlockInputs { self, ) -> ( BlockHeader, - ChainMmr, + PartialBlockchain, BTreeMap, BTreeMap, BTreeMap, ) { ( self.prev_block_header, - self.chain_mmr, + self.partial_blockchain, self.account_witnesses, self.nullifier_witnesses, self.unauthenticated_note_proofs, @@ -98,12 +98,12 @@ impl BlockInputs { // TESTING // -------------------------------------------------------------------------------------------- - /// Returns a mutable reference to the [`ChainMmr`]. + /// Returns a mutable reference to the [`PartialBlockchain`]. /// - /// Allows mutating the inner chain MMR for testing purposes. + /// Allows mutating the inner partial blockchain for testing purposes. #[cfg(any(feature = "testing", test))] - pub fn chain_mmr_mut(&mut self) -> &mut ChainMmr { - &mut self.chain_mmr + pub fn partial_blockchain_mut(&mut self) -> &mut PartialBlockchain { + &mut self.partial_blockchain } /// Returns a mutable reference to the note inclusion proofs. diff --git a/crates/miden-objects/src/block/blockchain.rs b/crates/miden-objects/src/block/blockchain.rs index 245146547f..dde61ae50a 100644 --- a/crates/miden-objects/src/block/blockchain.rs +++ b/crates/miden-objects/src/block/blockchain.rs @@ -135,8 +135,9 @@ impl Blockchain { let leaf = self.mmr.get(block_num.as_usize())?; let path = self.open_at(*block_num, checkpoint)?.merkle_path; - // SAFETY: We should be able to fill the partial MMR with data from the chain MMR - // without errors, otherwise it indicates the blockchain is invalid. + // SAFETY: We should be able to fill the partial MMR with data from the partial + // blockchain without errors, otherwise it indicates the blockchain is + // invalid. partial_mmr .track(block_num.as_usize(), leaf, &path) .expect("filling partial mmr with data from mmr should succeed"); diff --git a/crates/miden-objects/src/block/proposed_block.rs b/crates/miden-objects/src/block/proposed_block.rs index 1eb68461e5..279b5a4b83 100644 --- a/crates/miden-objects/src/block/proposed_block.rs +++ b/crates/miden-objects/src/block/proposed_block.rs @@ -14,7 +14,7 @@ use crate::{ }, errors::ProposedBlockError, note::{NoteId, Nullifier}, - transaction::{ChainMmr, InputNoteCommitment, OutputNote, TransactionHeader}, + transaction::{InputNoteCommitment, OutputNote, PartialBlockchain, TransactionHeader}, utils::serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable}, }; @@ -47,13 +47,13 @@ pub struct ProposedBlock { /// These are the nullifiers of all input notes after note erasure has been done, so these are /// the nullifiers of all _authenticated_ notes consumed in the block. created_nullifiers: BTreeMap, - /// The [`ChainMmr`] at the state of the previous block header. It is used to: + /// The [`PartialBlockchain`] at the state of the previous block header. It is used to: /// - authenticate unauthenticated notes whose note inclusion proof references a block. /// - authenticate all reference blocks of the batches in this block. - chain_mmr: ChainMmr, + partial_blockchain: PartialBlockchain, /// The previous block's header which this block builds on top of. /// - /// As part of proving the block, this header will be added to the next chain MMR. + /// As part of proving the block, this header will be added to the next partial blockchain. prev_block_header: BlockHeader, } @@ -81,10 +81,10 @@ impl ProposedBlock { /// /// ## Chain /// - /// - The length of the [`ChainMmr`] in the block inputs is not equal to the previous block - /// header in the block inputs. - /// - The [`ChainMmr`]'s chain commitment is not equal to the [`BlockHeader::chain_commitment`] - /// of the previous block header. + /// - The length of the [`PartialBlockchain`] in the block inputs is not equal to the previous + /// block header in the block inputs. + /// - The [`PartialBlockchain`]'s chain commitment is not equal to the + /// [`BlockHeader::chain_commitment`] of the previous block header. /// /// ## Notes /// @@ -96,7 +96,7 @@ impl ProposedBlock { /// - There is an unauthenticated input note and an output note with the same note ID but their /// note commitments are different (i.e. their metadata is different). /// - There is a note inclusion proof for an unauthenticated note whose referenced block is not - /// in the [`ChainMmr`]. + /// in the [`PartialBlockchain`]. /// - The note inclusion proof for an unauthenticated is invalid. /// - There are any unauthenticated notes for which no note inclusion proof is provided. /// - A [`NullifierWitness`] is missing for an authenticated note. @@ -146,19 +146,19 @@ impl ProposedBlock { check_batch_expiration(&batches, block_inputs.prev_block_header())?; - // Check for consistency between the chain MMR and the referenced previous block. + // Check for consistency between the partial blockchain and the referenced previous block. // -------------------------------------------------------------------------------------------- - check_reference_block_chain_mmr_consistency( - block_inputs.chain_mmr(), + check_reference_block_partial_blockchain_consistency( + block_inputs.partial_blockchain(), block_inputs.prev_block_header(), )?; - // Check every block referenced by a batch is in the chain MMR. + // Check every block referenced by a batch is in the partial blockchain. // -------------------------------------------------------------------------------------------- check_batch_reference_blocks( - block_inputs.chain_mmr(), + block_inputs.partial_blockchain(), block_inputs.prev_block_header(), &batches, )?; @@ -172,7 +172,7 @@ impl ProposedBlock { InputOutputNoteTracker::from_batches( batches.iter(), block_inputs.unauthenticated_note_proofs(), - block_inputs.chain_mmr(), + block_inputs.partial_blockchain(), block_inputs.prev_block_header(), )?; @@ -187,7 +187,7 @@ impl ProposedBlock { // Check for nullifiers proofs and unspent nullifiers. // -------------------------------------------------------------------------------------------- - let (prev_block_header, chain_mmr, account_witnesses, mut nullifier_witnesses, _) = + let (prev_block_header, partial_blockchain, account_witnesses, mut nullifier_witnesses, _) = block_inputs.into_parts(); // Remove nullifiers of erased notes, so we only add the nullifiers of actual input notes to @@ -221,7 +221,7 @@ impl ProposedBlock { account_updated_witnesses, output_note_batches, created_nullifiers: nullifier_witnesses, - chain_mmr, + partial_blockchain, prev_block_header, }) } @@ -265,7 +265,7 @@ impl ProposedBlock { pub fn block_num(&self) -> BlockNumber { // The chain length is the length at the state of the previous block header, so we have to // add one. - self.chain_mmr().chain_length() + 1 + self.partial_blockchain().chain_length() + 1 } /// Returns a reference to the slice of batches in this block. @@ -283,9 +283,9 @@ impl ProposedBlock { &self.prev_block_header } - /// Returns the [`ChainMmr`] that this block contains. - pub fn chain_mmr(&self) -> &ChainMmr { - &self.chain_mmr + /// Returns the [`PartialBlockchain`] that this block contains. + pub fn partial_blockchain(&self) -> &PartialBlockchain { + &self.partial_blockchain } /// Returns a reference to the slice of accounts updated in this block. @@ -315,7 +315,7 @@ impl ProposedBlock { Vec<(AccountId, AccountUpdateWitness)>, Vec, BTreeMap, - ChainMmr, + PartialBlockchain, BlockHeader, ) { ( @@ -323,7 +323,7 @@ impl ProposedBlock { self.account_updated_witnesses, self.output_note_batches, self.created_nullifiers, - self.chain_mmr, + self.partial_blockchain, self.prev_block_header, ) } @@ -339,7 +339,7 @@ impl Serializable for ProposedBlock { self.account_updated_witnesses.write_into(target); self.output_note_batches.write_into(target); self.created_nullifiers.write_into(target); - self.chain_mmr.write_into(target); + self.partial_blockchain.write_into(target); self.prev_block_header.write_into(target); } } @@ -352,7 +352,7 @@ impl Deserializable for ProposedBlock { account_updated_witnesses: >::read_from(source)?, output_note_batches: >::read_from(source)?, created_nullifiers: >::read_from(source)?, - chain_mmr: ChainMmr::read_from(source)?, + partial_blockchain: PartialBlockchain::read_from(source)?, prev_block_header: BlockHeader::read_from(source)?, }; @@ -449,27 +449,29 @@ fn remove_erased_nullifiers( } } -/// Checks consistency between the previous block header and the provided chain MMR. +/// Checks consistency between the previous block header and the provided partial blockchain. /// /// This checks that: -/// - the chain length of the chain MMR is equal to the block number of the previous block header, -/// i.e. the chain MMR's latest block is the previous' blocks reference block. The previous block -/// header will be added to the chain MMR as part of constructing the current block. -/// - the root of the chain MMR is equivalent to the chain commitment of the previous block header. -fn check_reference_block_chain_mmr_consistency( - chain_mmr: &ChainMmr, +/// - the chain length of the partial blockchain is equal to the block number of the previous block +/// header, i.e. the partial blockchain's latest block is the previous' blocks reference block. +/// The previous block header will be added to the partial blockchain as part of constructing the +/// current block. +/// - the root of the partial blockchain is equivalent to the chain commitment of the previous block +/// header. +fn check_reference_block_partial_blockchain_consistency( + partial_blockchain: &PartialBlockchain, prev_block_header: &BlockHeader, ) -> Result<(), ProposedBlockError> { - // Make sure that the current chain MMR has blocks up to prev_block_header - 1, i.e. its - // chain length is equal to the block number of the previous block header. - if chain_mmr.chain_length() != prev_block_header.block_num() { + // Make sure that the current partial blockchain has blocks up to prev_block_header - 1, i.e. + // its chain length is equal to the block number of the previous block header. + if partial_blockchain.chain_length() != prev_block_header.block_num() { return Err(ProposedBlockError::ChainLengthNotEqualToPreviousBlockNumber { - chain_length: chain_mmr.chain_length(), + chain_length: partial_blockchain.chain_length(), prev_block_num: prev_block_header.block_num(), }); } - let chain_commitment = chain_mmr.peaks().hash_peaks(); + let chain_commitment = partial_blockchain.peaks().hash_peaks(); if chain_commitment != prev_block_header.chain_commitment() { return Err(ProposedBlockError::ChainRootNotEqualToPreviousBlockChainCommitment { chain_commitment, @@ -481,17 +483,17 @@ fn check_reference_block_chain_mmr_consistency( Ok(()) } -/// Check that each block referenced by a batch in the block has an entry in the chain MMR, +/// Check that each block referenced by a batch in the block has an entry in the partial blockchain, /// except if the referenced block is the same as the previous block, referenced by the block. fn check_batch_reference_blocks( - chain_mmr: &ChainMmr, + partial_blockchain: &PartialBlockchain, prev_block_header: &BlockHeader, batches: &[ProvenBatch], ) -> Result<(), ProposedBlockError> { for batch in batches { let batch_reference_block_num = batch.reference_block_num(); if batch_reference_block_num != prev_block_header.block_num() - && !chain_mmr.contains_block(batch.reference_block_num()) + && !partial_blockchain.contains_block(batch.reference_block_num()) { return Err(ProposedBlockError::BatchReferenceBlockMissingFromChain { reference_block_num: batch.reference_block_num(), diff --git a/crates/miden-objects/src/errors.rs b/crates/miden-objects/src/errors.rs index 1346257cfa..98f278b0fa 100644 --- a/crates/miden-objects/src/errors.rs +++ b/crates/miden-objects/src/errors.rs @@ -403,23 +403,25 @@ pub enum NoteError { TooManyInputs(usize), } -// CHAIN MMR ERROR +// PARTIAL BLOCKCHAIN ERROR // ================================================================================================ #[derive(Debug, Error)] -pub enum ChainMmrError { - #[error("block num {block_num} exceeds chain length {chain_length} implied by the chain MMR")] +pub enum PartialBlockchainError { + #[error( + "block num {block_num} exceeds chain length {chain_length} implied by the partial blockchain" + )] BlockNumTooBig { chain_length: usize, block_num: BlockNumber, }, - #[error("duplicate block {block_num} in chain MMR")] + #[error("duplicate block {block_num} in partial blockchain")] DuplicateBlock { block_num: BlockNumber }, - #[error("chain MMR does not track authentication paths for block {block_num}")] + #[error("partial blockchain does not track authentication paths for block {block_num}")] UntrackedBlock { block_num: BlockNumber }, } -impl ChainMmrError { +impl PartialBlockchainError { pub fn block_num_too_big(chain_length: usize, block_num: BlockNumber) -> Self { Self::BlockNumTooBig { chain_length, block_num } } @@ -452,7 +454,7 @@ pub enum TransactionInputError { #[error("account seed must not be provided for existing accounts")] AccountSeedProvidedForExistingAccount, #[error( - "anchor block header for epoch {0} (block number = {block_number}) must be provided in the chain mmr for the new account", + "anchor block header for epoch {0} (block number = {block_number}) must be provided in the partial blockchain for the new account", block_number = BlockNumber::from_epoch(*.0), )] AnchorBlockHeaderNotProvidedForNewAccount(u16), @@ -462,17 +464,17 @@ pub enum TransactionInputError { "ID {expected} of the new account does not match the ID {actual} computed from the provided seed" )] InconsistentAccountSeed { expected: AccountId, actual: AccountId }, - #[error("chain mmr has length {actual} which does not match block number {expected}")] + #[error("partial blockchain has length {actual} which does not match block number {expected}")] InconsistentChainLength { expected: BlockNumber, actual: BlockNumber, }, #[error( - "chain mmr has commitment {actual} which does not match the block header's chain commitment {expected}" + "partial blockchain has commitment {actual} which does not match the block header's chain commitment {expected}" )] InconsistentChainCommitment { expected: Digest, actual: Digest }, - #[error("block in which input note with id {0} was created is not in chain mmr")] - InputNoteBlockNotInChainMmr(NoteId), + #[error("block in which input note with id {0} was created is not in partial blockchain")] + InputNoteBlockNotInPartialBlockchain(NoteId), #[error("input note with id {0} was not created in block {1}")] InputNoteNotInBlock(NoteId, BlockNumber), #[error("account ID computed from seed is invalid")] @@ -619,9 +621,9 @@ pub enum ProposedBatchError { }, #[error( - "unable to prove unauthenticated note inclusion because block {block_number} in which note with id {note_id} was created is not in chain mmr" + "unable to prove unauthenticated note inclusion because block {block_number} in which note with id {note_id} was created is not in partial blockchain" )] - UnauthenticatedInputNoteBlockNotInChainMmr { + UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number: BlockNumber, note_id: NoteId, }, @@ -635,17 +637,19 @@ pub enum ProposedBatchError { source: MerkleError, }, - #[error("chain mmr has length {actual} which does not match block number {expected}")] + #[error("partial blockchain has length {actual} which does not match block number {expected}")] InconsistentChainLength { expected: BlockNumber, actual: BlockNumber, }, - #[error("chain mmr has root {actual} which does not match block header's root {expected}")] + #[error( + "partial blockchain has root {actual} which does not match block header's root {expected}" + )] InconsistentChainRoot { expected: Digest, actual: Digest }, #[error( - "block {block_reference} referenced by transaction {transaction_id} is not in the chain mmr" + "block {block_reference} referenced by transaction {transaction_id} is not in the partial blockchain" )] MissingTransactionBlockReference { block_reference: Digest, @@ -732,7 +736,7 @@ pub enum ProposedBlockError { }, #[error( - "chain mmr has length {chain_length} which does not match the block number {prev_block_num} of the previous block referenced by the to-be-built block" + "partial blockchain has length {chain_length} which does not match the block number {prev_block_num} of the previous block referenced by the to-be-built block" )] ChainLengthNotEqualToPreviousBlockNumber { chain_length: BlockNumber, @@ -740,7 +744,7 @@ pub enum ProposedBlockError { }, #[error( - "chain mmr has commitment {chain_commitment} which does not match the chain commitment {prev_block_chain_commitment} of the previous block {prev_block_num}" + "partial blockchain has commitment {chain_commitment} which does not match the chain commitment {prev_block_chain_commitment} of the previous block {prev_block_num}" )] ChainRootNotEqualToPreviousBlockChainCommitment { chain_commitment: Digest, @@ -749,7 +753,7 @@ pub enum ProposedBlockError { }, #[error( - "chain mmr is missing block {reference_block_num} referenced by batch {batch_id} in the block" + "partial blockchain is missing block {reference_block_num} referenced by batch {batch_id} in the block" )] BatchReferenceBlockMissingFromChain { reference_block_num: BlockNumber, @@ -766,9 +770,9 @@ pub enum ProposedBlockError { }, #[error( - "failed to prove unauthenticated note inclusion because block {block_number} in which note with id {note_id} was created is not in chain mmr" + "failed to prove unauthenticated note inclusion because block {block_number} in which note with id {note_id} was created is not in partial blockchain" )] - UnauthenticatedInputNoteBlockNotInChainMmr { + UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number: BlockNumber, note_id: NoteId, }, diff --git a/crates/miden-objects/src/lib.rs b/crates/miden-objects/src/lib.rs index a1249cfba4..6147272147 100644 --- a/crates/miden-objects/src/lib.rs +++ b/crates/miden-objects/src/lib.rs @@ -25,7 +25,7 @@ mod errors; pub use constants::*; pub use errors::{ AccountDeltaError, AccountError, AccountIdError, AccountTreeError, AssetError, AssetVaultError, - BatchAccountUpdateError, ChainMmrError, NetworkIdError, NoteError, NullifierTreeError, + BatchAccountUpdateError, NetworkIdError, NoteError, NullifierTreeError, PartialBlockchainError, ProposedBatchError, ProposedBlockError, ProvenBatchError, ProvenTransactionError, TransactionInputError, TransactionOutputError, TransactionScriptError, }; diff --git a/crates/miden-objects/src/testing/mod.rs b/crates/miden-objects/src/testing/mod.rs index 63b60ad144..03a703a56b 100644 --- a/crates/miden-objects/src/testing/mod.rs +++ b/crates/miden-objects/src/testing/mod.rs @@ -4,7 +4,7 @@ pub mod account_component; pub mod account_id; pub mod asset; pub mod block; -pub mod chain_mmr; pub mod constants; pub mod note; +pub mod partial_blockchain; pub mod storage; diff --git a/crates/miden-objects/src/testing/partial_blockchain.rs b/crates/miden-objects/src/testing/partial_blockchain.rs new file mode 100644 index 0000000000..20598e5f7c --- /dev/null +++ b/crates/miden-objects/src/testing/partial_blockchain.rs @@ -0,0 +1,44 @@ +use alloc::vec::Vec; + +use crate::{ + PartialBlockchainError, + block::{BlockHeader, Blockchain}, + transaction::PartialBlockchain, +}; + +impl PartialBlockchain { + /// Converts the [`Blockchain`] into a [`PartialBlockchain`] by selectively copying all leaves + /// that are in the given `blocks` iterator. + /// + /// This tracks all blocks in the given iterator in the [`PartialBlockchain`] except for the + /// block whose block number equals [`Blockchain::chain_tip`], which is the current chain + /// tip. + /// + /// # Panics + /// + /// Due to being only available in test scenarios, this function panics when one of the given + /// blocks does not exist in the provided chain or if the chain does not contain at least the + /// genesis block. + pub fn from_blockchain( + chain: &Blockchain, + blocks: impl IntoIterator, + ) -> Result { + let block_headers: Vec<_> = blocks.into_iter().collect(); + + // We take the state at the latest block which will be used as the reference block by + // transaction or batch kernels. That way, the returned partial mmr's hash peaks will match + // the chain commitment of the reference block. + let latest_block = chain + .chain_tip() + .expect("block chain should contain at least the genesis block"); + + let partial_mmr = chain + .partial_mmr_from_blocks( + &block_headers.iter().map(BlockHeader::block_num).collect(), + latest_block, + ) + .expect("latest block should be in the chain and set of blocks should be valid"); + + PartialBlockchain::new(partial_mmr, block_headers) + } +} diff --git a/crates/miden-objects/src/transaction/inputs.rs b/crates/miden-objects/src/transaction/inputs.rs index b331bd80d4..128651adb1 100644 --- a/crates/miden-objects/src/transaction/inputs.rs +++ b/crates/miden-objects/src/transaction/inputs.rs @@ -3,7 +3,7 @@ use core::fmt::Debug; use miden_crypto::merkle::{SmtProof, SmtProofError}; -use super::{BlockHeader, ChainMmr, Digest, Felt, Hasher, Word}; +use super::{BlockHeader, Digest, Felt, Hasher, PartialBlockchain, Word}; use crate::{ MAX_INPUT_NOTES_PER_TX, TransactionInputError, account::{ @@ -23,7 +23,7 @@ pub struct TransactionInputs { account: Account, account_seed: Option, block_header: BlockHeader, - block_chain: ChainMmr, + block_chain: PartialBlockchain, input_notes: InputNotes, } @@ -40,7 +40,7 @@ impl TransactionInputs { account: Account, account_seed: Option, block_header: BlockHeader, - block_chain: ChainMmr, + block_chain: PartialBlockchain, input_notes: InputNotes, ) -> Result { // validate the seed @@ -70,9 +70,9 @@ impl TransactionInputs { let block_header = if note_block_num == block_num { &block_header } else { - block_chain - .get_block(note_block_num) - .ok_or(TransactionInputError::InputNoteBlockNotInChainMmr(note.id()))? + block_chain.get_block(note_block_num).ok_or( + TransactionInputError::InputNoteBlockNotInPartialBlockchain(note.id()), + )? }; validate_is_in_block(note, proof, block_header)?; @@ -106,9 +106,9 @@ impl TransactionInputs { &self.block_header } - /// Returns chain MMR containing authentication paths for all notes consumed by the + /// Returns partial blockchain containing authentication paths for all notes consumed by the /// transaction. - pub fn block_chain(&self) -> &ChainMmr { + pub fn block_chain(&self) -> &PartialBlockchain { &self.block_chain } @@ -123,7 +123,7 @@ impl TransactionInputs { /// Consumes these transaction inputs and returns their underlying components. pub fn into_parts( self, - ) -> (Account, Option, BlockHeader, ChainMmr, InputNotes) { + ) -> (Account, Option, BlockHeader, PartialBlockchain, InputNotes) { ( self.account, self.account_seed, @@ -149,7 +149,7 @@ impl Deserializable for TransactionInputs { let account = Account::read_from(source)?; let account_seed = source.read()?; let block_header = BlockHeader::read_from(source)?; - let block_chain = ChainMmr::read_from(source)?; + let block_chain = PartialBlockchain::read_from(source)?; let input_notes = InputNotes::read_from(source)?; Self::new(account, account_seed, block_header, block_chain, input_notes) .map_err(|err| DeserializationError::InvalidValue(format!("{}", err))) @@ -490,7 +490,7 @@ impl Deserializable for InputNote { pub fn validate_account_seed( account: &Account, block_header: &BlockHeader, - block_chain: &ChainMmr, + block_chain: &PartialBlockchain, account_seed: Option, ) -> Result<(), TransactionInputError> { match (account.is_new(), account_seed) { diff --git a/crates/miden-objects/src/transaction/mod.rs b/crates/miden-objects/src/transaction/mod.rs index fe9b51be61..9b19f0f532 100644 --- a/crates/miden-objects/src/transaction/mod.rs +++ b/crates/miden-objects/src/transaction/mod.rs @@ -6,24 +6,24 @@ use super::{ vm::AdviceInputs, }; -mod chain_mmr; mod executed_tx; mod inputs; mod ordered_transactions; mod outputs; +mod partial_blockchain; mod proven_tx; mod transaction_id; mod tx_args; mod tx_header; mod tx_witness; -pub use chain_mmr::ChainMmr; pub use executed_tx::{ExecutedTransaction, TransactionMeasurements}; pub use inputs::{ ForeignAccountInputs, InputNote, InputNotes, ToInputNoteCommitments, TransactionInputs, }; pub use ordered_transactions::OrderedTransactionHeaders; pub use outputs::{OutputNote, OutputNotes, TransactionOutputs}; +pub use partial_blockchain::PartialBlockchain; pub use proven_tx::{ InputNoteCommitment, ProvenTransaction, ProvenTransactionBuilder, TxAccountUpdate, }; diff --git a/crates/miden-objects/src/transaction/chain_mmr.rs b/crates/miden-objects/src/transaction/partial_blockchain.rs similarity index 68% rename from crates/miden-objects/src/transaction/chain_mmr.rs rename to crates/miden-objects/src/transaction/partial_blockchain.rs index 05d2bea84b..e801b32114 100644 --- a/crates/miden-objects/src/transaction/chain_mmr.rs +++ b/crates/miden-objects/src/transaction/partial_blockchain.rs @@ -1,40 +1,40 @@ use alloc::collections::BTreeMap; use crate::{ - ChainMmrError, + PartialBlockchainError, block::{BlockHeader, BlockNumber}, crypto::merkle::{InnerNodeInfo, MmrPeaks, PartialMmr}, utils::serde::{Deserializable, Serializable}, }; -// CHAIN MMR +// PARTIAL BLOCKCHAIN // ================================================================================================ /// A struct that represents the chain Merkle Mountain Range (MMR). /// /// The MMR allows for efficient authentication of input notes during transaction execution. /// Authentication is achieved by providing inclusion proofs for the notes consumed in the -/// transaction against the chain MMR root associated with the latest block known at the time -/// of transaction execution. +/// transaction against the partial blockchain root associated with the latest block known at the +/// time of transaction execution. /// -/// [ChainMmr] represents a partial view into the actual MMR and contains authentication paths -/// for a limited set of blocks. The intent is to include only the blocks relevant for execution -/// of a specific transaction (i.e., the blocks corresponding to all input notes and the one needed -/// to validate the seed of a new account, if applicable). +/// [PartialBlockchain] represents a partial view into the actual MMR and contains authentication +/// paths for a limited set of blocks. The intent is to include only the blocks relevant for +/// execution of a specific transaction (i.e., the blocks corresponding to all input notes and the +/// one needed to validate the seed of a new account, if applicable). #[derive(Debug, Clone, PartialEq, Eq)] -pub struct ChainMmr { - /// Partial view of the Chain MMR with authentication paths for the blocks listed below. +pub struct PartialBlockchain { + /// Partial view of the blockchain with authentication paths for the blocks listed below. mmr: PartialMmr, /// A map of block_num |-> block_header for all blocks for which the partial MMR contains /// authentication paths. blocks: BTreeMap, } -impl ChainMmr { +impl PartialBlockchain { // CONSTRUCTOR // -------------------------------------------------------------------------------------------- - /// Returns a new [ChainMmr] instantiated from the provided partial MMR and a list of block - /// headers. + /// Returns a new [PartialBlockchain] instantiated from the provided partial MMR and a list of + /// block headers. /// /// # Errors /// Returns an error if: @@ -45,21 +45,21 @@ impl ChainMmr { pub fn new( mmr: PartialMmr, blocks: impl IntoIterator, - ) -> Result { + ) -> Result { let chain_length = mmr.forest(); let mut block_map = BTreeMap::new(); for block in blocks { let block_num = block.block_num(); if block.block_num().as_usize() >= chain_length { - return Err(ChainMmrError::block_num_too_big(chain_length, block_num)); + return Err(PartialBlockchainError::block_num_too_big(chain_length, block_num)); } if !mmr.is_tracked(block_num.as_usize()) { - return Err(ChainMmrError::untracked_block(block_num)); + return Err(PartialBlockchainError::untracked_block(block_num)); } if block_map.insert(block_num, block).is_some() { - return Err(ChainMmrError::duplicate_block(block_num)); + return Err(PartialBlockchainError::duplicate_block(block_num)); } } @@ -83,22 +83,22 @@ impl ChainMmr { pub fn chain_length(&self) -> BlockNumber { BlockNumber::from( u32::try_from(self.mmr.forest()) - .expect("chain mmr should never contain more than u32::MAX blocks"), + .expect("partial blockchain should never contain more than u32::MAX blocks"), ) } - /// Returns true if the block is present in this chain MMR. + /// Returns true if the block is present in this partial blockchain. pub fn contains_block(&self, block_num: BlockNumber) -> bool { self.blocks.contains_key(&block_num) } /// Returns the block header for the specified block, or None if the block is not present in - /// this chain MMR. + /// this partial blockchain. pub fn get_block(&self, block_num: BlockNumber) -> Option<&BlockHeader> { self.blocks.get(&block_num) } - /// Returns an iterator over the block headers in this chain MMR. + /// Returns an iterator over the block headers in this partial blockchain. pub fn block_headers(&self) -> impl Iterator { self.blocks.values() } @@ -106,11 +106,11 @@ impl ChainMmr { // DATA MUTATORS // -------------------------------------------------------------------------------------------- - /// Appends the provided block header to this chain MMR. This method assumes that the provided - /// block header is for the next block in the chain. + /// Appends the provided block header to this partial blockchain. This method assumes that the + /// provided block header is for the next block in the chain. /// /// If `track` parameter is set to true, the authentication path for the provided block header - /// will be added to this chain MMR. + /// will be added to this partial blockchain. /// /// # Panics /// Panics if the `block_header.block_num` is not equal to the current chain length (i.e., the @@ -136,7 +136,8 @@ impl ChainMmr { // TESTING // -------------------------------------------------------------------------------------------- - /// Returns a mutable reference to the map of block numbers to block headers in this chain MMR. + /// Returns a mutable reference to the map of block numbers to block headers in this partial + /// blockchain. /// /// Allows mutating the inner map for testing purposes. #[cfg(any(feature = "testing", test))] @@ -144,7 +145,7 @@ impl ChainMmr { &mut self.blocks } - /// Returns a mutable reference to the partial MMR of this chain MMR. + /// Returns a mutable reference to the partial MMR of this partial blockchain. /// /// Allows mutating the inner partial MMR for testing purposes. #[cfg(any(feature = "testing", test))] @@ -153,14 +154,14 @@ impl ChainMmr { } } -impl Serializable for ChainMmr { +impl Serializable for PartialBlockchain { fn write_into(&self, target: &mut W) { self.mmr.write_into(target); self.blocks.write_into(target); } } -impl Deserializable for ChainMmr { +impl Deserializable for PartialBlockchain { fn read_from( source: &mut R, ) -> Result { @@ -176,7 +177,7 @@ impl Deserializable for ChainMmr { mod tests { use vm_core::utils::{Deserializable, Serializable}; - use super::ChainMmr; + use super::PartialBlockchain; use crate::{ Digest, alloc::vec::Vec, @@ -185,65 +186,65 @@ mod tests { }; #[test] - fn test_chain_mmr_add() { - // create chain MMR with 3 blocks - i.e., 2 peaks + fn test_partial_blockchain_add() { + // create partial blockchain with 3 blocks - i.e., 2 peaks let mut mmr = Mmr::default(); for i in 0..3 { let block_header = int_to_block_header(i); mmr.add(block_header.commitment()); } let partial_mmr: PartialMmr = mmr.peaks().into(); - let mut chain_mmr = ChainMmr::new(partial_mmr, Vec::new()).unwrap(); + let mut partial_blockchain = PartialBlockchain::new(partial_mmr, Vec::new()).unwrap(); - // add a new block to the chain MMR, this reduces the number of peaks to 1 + // add a new block to the partial blockchain, this reduces the number of peaks to 1 let block_num = 3; let bock_header = int_to_block_header(block_num); mmr.add(bock_header.commitment()); - chain_mmr.add_block(bock_header, true); + partial_blockchain.add_block(bock_header, true); assert_eq!( mmr.open(block_num as usize).unwrap(), - chain_mmr.mmr.open(block_num as usize).unwrap().unwrap() + partial_blockchain.mmr.open(block_num as usize).unwrap().unwrap() ); - // add one more block to the chain MMR, the number of peaks is again 2 + // add one more block to the partial blockchain, the number of peaks is again 2 let block_num = 4; let bock_header = int_to_block_header(block_num); mmr.add(bock_header.commitment()); - chain_mmr.add_block(bock_header, true); + partial_blockchain.add_block(bock_header, true); assert_eq!( mmr.open(block_num as usize).unwrap(), - chain_mmr.mmr.open(block_num as usize).unwrap().unwrap() + partial_blockchain.mmr.open(block_num as usize).unwrap().unwrap() ); - // add one more block to the chain MMR, the number of peaks is still 2 + // add one more block to the partial blockchain, the number of peaks is still 2 let block_num = 5; let bock_header = int_to_block_header(block_num); mmr.add(bock_header.commitment()); - chain_mmr.add_block(bock_header, true); + partial_blockchain.add_block(bock_header, true); assert_eq!( mmr.open(block_num as usize).unwrap(), - chain_mmr.mmr.open(block_num as usize).unwrap().unwrap() + partial_blockchain.mmr.open(block_num as usize).unwrap().unwrap() ); } #[test] - fn tst_chain_mmr_serialization() { - // create chain MMR with 3 blocks - i.e., 2 peaks + fn tst_partial_blockchain_serialization() { + // create partial blockchain with 3 blocks - i.e., 2 peaks let mut mmr = Mmr::default(); for i in 0..3 { let block_header = int_to_block_header(i); mmr.add(block_header.commitment()); } let partial_mmr: PartialMmr = mmr.peaks().into(); - let chain_mmr = ChainMmr::new(partial_mmr, Vec::new()).unwrap(); + let partial_blockchain = PartialBlockchain::new(partial_mmr, Vec::new()).unwrap(); - let bytes = chain_mmr.to_bytes(); - let deserialized = ChainMmr::read_from_bytes(&bytes).unwrap(); + let bytes = partial_blockchain.to_bytes(); + let deserialized = PartialBlockchain::read_from_bytes(&bytes).unwrap(); - assert_eq!(chain_mmr, deserialized); + assert_eq!(partial_blockchain, deserialized); } fn int_to_block_header(block_num: impl Into) -> BlockHeader { diff --git a/crates/miden-tx-batch-prover/src/tests/proposed_batch.rs b/crates/miden-tx-batch-prover/src/tests/proposed_batch.rs index 173aa811d4..2637718b4e 100644 --- a/crates/miden-tx-batch-prover/src/tests/proposed_batch.rs +++ b/crates/miden-tx-batch-prover/src/tests/proposed_batch.rs @@ -11,7 +11,7 @@ use miden_objects::{ block::BlockNumber, note::{Note, NoteType}, testing::{account_id::AccountIdBuilder, note::NoteBuilder}, - transaction::{ChainMmr, InputNote, InputNoteCommitment, OutputNote}, + transaction::{InputNote, InputNoteCommitment, OutputNote, PartialBlockchain}, }; use miden_tx::testing::{Auth, MockChain}; use rand::{SeedableRng, rngs::SmallRng}; @@ -57,8 +57,9 @@ fn empty_transaction_batch() -> anyhow::Result<()> { let TestSetup { chain, .. } = setup_chain(); let block1 = chain.block_header(1); - let error = ProposedBatch::new(vec![], block1, chain.latest_chain_mmr(), BTreeMap::default()) - .unwrap_err(); + let error = + ProposedBatch::new(vec![], block1, chain.latest_partial_blockchain(), BTreeMap::default()) + .unwrap_err(); assert_matches!(error, ProposedBatchError::EmptyTransactionBatch); @@ -88,7 +89,7 @@ fn note_created_and_consumed_in_same_batch() -> anyhow::Result<()> { let batch = ProposedBatch::new( [tx1, tx2].into_iter().map(Arc::new).collect(), block2.header().clone(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), )?; @@ -120,7 +121,7 @@ fn duplicate_unauthenticated_input_notes() -> anyhow::Result<()> { let error = ProposedBatch::new( [tx1.clone(), tx2.clone()].into_iter().map(Arc::new).collect(), block1, - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), ) .unwrap_err(); @@ -160,7 +161,7 @@ fn duplicate_authenticated_input_notes() -> anyhow::Result<()> { let error = ProposedBatch::new( [tx1.clone(), tx2.clone()].into_iter().map(Arc::new).collect(), block2.header().clone(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), ) .unwrap_err(); @@ -200,7 +201,7 @@ fn duplicate_mixed_input_notes() -> anyhow::Result<()> { let error = ProposedBatch::new( [tx1.clone(), tx2.clone()].into_iter().map(Arc::new).collect(), block2.header().clone(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), ) .unwrap_err(); @@ -239,7 +240,7 @@ fn duplicate_output_notes() -> anyhow::Result<()> { let error = ProposedBatch::new( [tx1.clone(), tx2.clone()].into_iter().map(Arc::new).collect(), block1, - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), ) .unwrap_err(); @@ -280,9 +281,9 @@ fn unauthenticated_note_converted_to_authenticated() -> anyhow::Result<()> { let input_note1 = chain.available_notes_map().get(¬e1.id()).expect("note not found"); let note_inclusion_proof1 = input_note1.proof().expect("note should be of type authenticated"); - // The chain MMR will contain all blocks in the mock chain, in particular block2 which both note - // inclusion proofs need for verification. - let chain_mmr = chain.latest_chain_mmr(); + // The partial blockchain will contain all blocks in the mock chain, in particular block2 which + // both note inclusion proofs need for verification. + let partial_blockchain = chain.latest_partial_blockchain(); // Case 1: Error: A wrong proof is passed. // -------------------------------------------------------------------------------------------- @@ -290,7 +291,7 @@ fn unauthenticated_note_converted_to_authenticated() -> anyhow::Result<()> { let error = ProposedBatch::new( [tx1.clone()].into_iter().map(Arc::new).collect(), block4.header().clone(), - chain_mmr.clone(), + partial_blockchain.clone(), BTreeMap::from_iter([(input_note1.id(), note_inclusion_proof0.clone())]), ) .unwrap_err(); @@ -306,10 +307,10 @@ fn unauthenticated_note_converted_to_authenticated() -> anyhow::Result<()> { // Case 2: Error: The block referenced by the (valid) note inclusion proof is missing. // -------------------------------------------------------------------------------------------- - // Make a clone of the chain mmr where block2 is missing. - let mut mmr = chain_mmr.mmr().clone(); + // Make a clone of the partial blockchain where block2 is missing. + let mut mmr = partial_blockchain.mmr().clone(); mmr.untrack(block2.header().block_num().as_usize()); - let blocks = chain_mmr + let blocks = partial_blockchain .block_headers() .filter(|header| header.block_num() != block2.header().block_num()) .cloned(); @@ -317,14 +318,15 @@ fn unauthenticated_note_converted_to_authenticated() -> anyhow::Result<()> { let error = ProposedBatch::new( [tx1.clone()].into_iter().map(Arc::new).collect(), block4.header().clone(), - ChainMmr::new(mmr, blocks).context("failed to build chain mmr with missing block")?, + PartialBlockchain::new(mmr, blocks) + .context("failed to build partial blockchain with missing block")?, BTreeMap::from_iter([(input_note1.id(), note_inclusion_proof1.clone())]), ) .unwrap_err(); assert_matches!( error, - ProposedBatchError::UnauthenticatedInputNoteBlockNotInChainMmr { + ProposedBatchError::UnauthenticatedInputNoteBlockNotInPartialBlockchain { block_number, note_id } if block_number == note_inclusion_proof1.location().block_num() && @@ -337,7 +339,7 @@ fn unauthenticated_note_converted_to_authenticated() -> anyhow::Result<()> { let batch = ProposedBatch::new( [tx1].into_iter().map(Arc::new).collect(), block4.header().clone(), - chain_mmr, + partial_blockchain, BTreeMap::from_iter([(input_note1.id(), note_inclusion_proof1.clone())]), )?; @@ -387,7 +389,7 @@ fn authenticated_note_created_in_same_batch() -> anyhow::Result<()> { let batch = ProposedBatch::new( [tx1, tx2].into_iter().map(Arc::new).collect(), block2.header().clone(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), )?; @@ -430,7 +432,7 @@ fn multiple_transactions_against_same_account() -> anyhow::Result<()> { let batch = ProposedBatch::new( [tx1.clone(), tx2.clone()].into_iter().map(Arc::new).collect(), block1.clone(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), )?; @@ -450,7 +452,7 @@ fn multiple_transactions_against_same_account() -> anyhow::Result<()> { let error = ProposedBatch::new( [tx2.clone(), tx1.clone()].into_iter().map(Arc::new).collect(), block1, - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), ) .unwrap_err(); @@ -498,7 +500,7 @@ fn input_and_output_notes_commitment() -> anyhow::Result<()> { let batch = ProposedBatch::new( [tx1.clone(), tx2.clone()].into_iter().map(Arc::new).collect(), block1, - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), )?; @@ -546,7 +548,7 @@ fn batch_expiration() -> anyhow::Result<()> { let batch = ProposedBatch::new( [tx1, tx2].into_iter().map(Arc::new).collect(), block1.clone(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), )?; @@ -570,7 +572,7 @@ fn duplicate_transaction() -> anyhow::Result<()> { let error = ProposedBatch::new( [tx1.clone(), tx1.clone()].into_iter().map(Arc::new).collect(), block1, - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), ) .unwrap_err(); @@ -607,7 +609,7 @@ fn circular_note_dependency() -> anyhow::Result<()> { let batch = ProposedBatch::new( [tx1, tx2].into_iter().map(Arc::new).collect(), block1, - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), )?; @@ -638,7 +640,7 @@ fn expired_transaction() -> anyhow::Result<()> { let error = ProposedBatch::new( [tx1.clone(), tx2].into_iter().map(Arc::new).collect(), block1.clone(), - chain.latest_chain_mmr(), + chain.latest_partial_blockchain(), BTreeMap::default(), ) .unwrap_err(); diff --git a/crates/miden-tx/src/executor/data_store.rs b/crates/miden-tx/src/executor/data_store.rs index f31dee7f59..ed9acbf32f 100644 --- a/crates/miden-tx/src/executor/data_store.rs +++ b/crates/miden-tx/src/executor/data_store.rs @@ -5,7 +5,7 @@ use alloc::collections::BTreeSet; use miden_objects::{ account::{Account, AccountId}, block::{BlockHeader, BlockNumber}, - transaction::ChainMmr, + transaction::PartialBlockchain, }; use vm_processor::{MastForestStore, Word}; use winter_maybe_async::*; @@ -37,5 +37,5 @@ pub trait DataStore: MastForestStore { &self, account_id: AccountId, ref_blocks: BTreeSet, - ) -> Result<(Account, Option, BlockHeader, ChainMmr), DataStoreError>; + ) -> Result<(Account, Option, BlockHeader, PartialBlockchain), DataStoreError>; } diff --git a/crates/miden-tx/src/testing/mock_chain/mod.rs b/crates/miden-tx/src/testing/mock_chain/mod.rs index 071add9635..6750e27288 100644 --- a/crates/miden-tx/src/testing/mock_chain/mod.rs +++ b/crates/miden-tx/src/testing/mock_chain/mod.rs @@ -25,9 +25,10 @@ use miden_objects::{ note::{Note, NoteHeader, NoteId, NoteInclusionProof, NoteType, Nullifier}, testing::account_code::DEFAULT_AUTH_SCRIPT, transaction::{ - ChainMmr, ExecutedTransaction, ForeignAccountInputs, InputNote, InputNotes, - OrderedTransactionHeaders, OutputNote, ProvenTransaction, ToInputNoteCommitments, - TransactionHeader, TransactionId, TransactionInputs, TransactionScript, + ExecutedTransaction, ForeignAccountInputs, InputNote, InputNotes, + OrderedTransactionHeaders, OutputNote, PartialBlockchain, ProvenTransaction, + ToInputNoteCommitments, TransactionHeader, TransactionId, TransactionInputs, + TransactionScript, }, }; use rand::{Rng, SeedableRng}; @@ -439,7 +440,7 @@ impl MockChain { { let transactions: Vec<_> = txs.into_iter().map(alloc::sync::Arc::new).collect(); - let (batch_reference_block, chain_mmr) = + let (batch_reference_block, partial_blockchain) = self.get_batch_inputs(transactions.iter().map(|tx| tx.ref_block_num())); // TODO: Get the actual proofs as part of get_batch_inputs. @@ -448,7 +449,7 @@ impl MockChain { ProposedBatch::new( transactions, batch_reference_block, - chain_mmr, + partial_blockchain, unauthenticated_note_proofs, ) } @@ -460,7 +461,7 @@ impl MockChain { let ( transactions, block_header, - _chain_mmr, + _partial_blockchain, _unauthenticated_note_proofs, id, account_updates, @@ -734,7 +735,7 @@ impl MockChain { } let block_headers = block_headers_map.values().cloned(); - let mmr = ChainMmr::from_blockchain(&self.chain, block_headers).unwrap(); + let mmr = PartialBlockchain::from_blockchain(&self.chain, block_headers).unwrap(); TransactionInputs::new( account, @@ -751,11 +752,11 @@ impl MockChain { pub fn get_batch_inputs( &self, tx_reference_blocks: impl IntoIterator, - ) -> (BlockHeader, ChainMmr) { - let (batch_reference_block, chain_mmr) = - self.latest_selective_chain_mmr(tx_reference_blocks); + ) -> (BlockHeader, PartialBlockchain) { + let (batch_reference_block, partial_blockchain) = + self.latest_selective_partial_blockchain(tx_reference_blocks); - (batch_reference_block, chain_mmr) + (batch_reference_block, partial_blockchain) } /// Gets foreign account inputs to execute FPI transactions. @@ -798,7 +799,7 @@ impl MockChain { batch.input_notes().iter().filter_map(|note| note.header().map(NoteHeader::id)) })); - let (block_reference_block, chain_mmr) = self.latest_selective_chain_mmr( + let (block_reference_block, partial_blockchain) = self.latest_selective_partial_blockchain( batch_iterator.clone().map(ProvenBatch::reference_block_num).chain( unauthenticated_note_proofs.values().map(|proof| proof.location().block_num()), ), @@ -812,7 +813,7 @@ impl MockChain { BlockInputs::new( block_reference_block, - chain_mmr, + partial_blockchain, account_witnesses, nullifier_proofs, unauthenticated_note_proofs, @@ -995,28 +996,28 @@ impl MockChain { &self.chain } - /// Gets the latest [ChainMmr]. - pub fn latest_chain_mmr(&self) -> ChainMmr { + /// Gets the latest [PartialBlockchain]. + pub fn latest_partial_blockchain(&self) -> PartialBlockchain { // We have to exclude the latest block because we need to fetch the state of the chain at // that latest block, which does not include itself. let block_headers = self.blocks.iter().map(|b| b.header()).take(self.blocks.len() - 1).cloned(); - ChainMmr::from_blockchain(&self.chain, block_headers).unwrap() + PartialBlockchain::from_blockchain(&self.chain, block_headers).unwrap() } - /// Creates a new [`ChainMmr`] with all reference blocks in the given iterator except for the - /// latest block header in the chain and returns that latest block header. + /// Creates a new [`PartialBlockchain`] with all reference blocks in the given iterator except + /// for the latest block header in the chain and returns that latest block header. /// /// The intended use is for the latest block header to become the reference block of a new /// transaction batch or block. - pub fn latest_selective_chain_mmr( + pub fn latest_selective_partial_blockchain( &self, reference_blocks: impl IntoIterator, - ) -> (BlockHeader, ChainMmr) { + ) -> (BlockHeader, PartialBlockchain) { let latest_block_header = self.latest_block_header().clone(); // Deduplicate block numbers so each header will be included just once. This is required so - // ChainMmr::from_blockchain does not panic. + // PartialBlockchain::from_blockchain does not panic. let reference_blocks: BTreeSet<_> = reference_blocks.into_iter().collect(); // Include all block headers of the reference blocks except the latest block. @@ -1026,9 +1027,10 @@ impl MockChain { .filter(|block_header| block_header.commitment() != latest_block_header.commitment()) .collect(); - let chain_mmr = ChainMmr::from_blockchain(&self.chain, block_headers).unwrap(); + let partial_blockchain = + PartialBlockchain::from_blockchain(&self.chain, block_headers).unwrap(); - (latest_block_header, chain_mmr) + (latest_block_header, partial_blockchain) } /// Returns the witnesses for the provided account IDs of the current account tree. diff --git a/crates/miden-tx/src/testing/tx_context/mod.rs b/crates/miden-tx/src/testing/tx_context/mod.rs index 641ef4744b..5043155b1f 100644 --- a/crates/miden-tx/src/testing/tx_context/mod.rs +++ b/crates/miden-tx/src/testing/tx_context/mod.rs @@ -10,7 +10,8 @@ use miden_objects::{ block::{BlockHeader, BlockNumber}, note::Note, transaction::{ - ChainMmr, ExecutedTransaction, InputNote, InputNotes, TransactionArgs, TransactionInputs, + ExecutedTransaction, InputNote, InputNotes, PartialBlockchain, TransactionArgs, + TransactionInputs, }, }; use rand_chacha::ChaCha20Rng; @@ -154,7 +155,7 @@ impl DataStore for TransactionContext { &self, account_id: AccountId, _ref_blocks: BTreeSet, - ) -> Result<(Account, Option, BlockHeader, ChainMmr), DataStoreError> { + ) -> Result<(Account, Option, BlockHeader, PartialBlockchain), DataStoreError> { assert_eq!(account_id, self.account().id()); let (account, seed, header, mmr, _) = self.tx_inputs.clone().into_parts(); 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 4000ed38d4..e30d66d15b 100644 --- a/crates/miden-tx/src/tests/kernel_tests/test_prologue.rs +++ b/crates/miden-tx/src/tests/kernel_tests/test_prologue.rs @@ -12,10 +12,9 @@ use miden_lib::{ TransactionKernel, memory::{ ACCT_DB_ROOT_PTR, ACCT_ID_PTR, BLOCK_COMMITMENT_PTR, BLOCK_METADATA_PTR, - BLOCK_NUMBER_IDX, CHAIN_COMMITMENT_PTR, CHAIN_MMR_NUM_LEAVES_PTR, CHAIN_MMR_PEAKS_PTR, - INIT_ACCT_COMMITMENT_PTR, INIT_NONCE_PTR, INPUT_NOTE_ARGS_OFFSET, - INPUT_NOTE_ASSETS_HASH_OFFSET, INPUT_NOTE_ASSETS_OFFSET, INPUT_NOTE_ID_OFFSET, - INPUT_NOTE_INPUTS_COMMITMENT_OFFSET, INPUT_NOTE_METADATA_OFFSET, + BLOCK_NUMBER_IDX, CHAIN_COMMITMENT_PTR, INIT_ACCT_COMMITMENT_PTR, INIT_NONCE_PTR, + INPUT_NOTE_ARGS_OFFSET, INPUT_NOTE_ASSETS_HASH_OFFSET, INPUT_NOTE_ASSETS_OFFSET, + INPUT_NOTE_ID_OFFSET, INPUT_NOTE_INPUTS_COMMITMENT_OFFSET, INPUT_NOTE_METADATA_OFFSET, INPUT_NOTE_NULLIFIER_SECTION_PTR, INPUT_NOTE_NUM_ASSETS_OFFSET, INPUT_NOTE_SCRIPT_ROOT_OFFSET, INPUT_NOTE_SECTION_PTR, INPUT_NOTE_SERIAL_NUM_OFFSET, INPUT_NOTES_COMMITMENT_PTR, MemoryOffset, NATIVE_ACCT_CODE_COMMITMENT_PTR, @@ -23,6 +22,7 @@ use miden_lib::{ NATIVE_ACCT_STORAGE_COMMITMENT_PTR, NATIVE_ACCT_STORAGE_SLOTS_SECTION_PTR, NATIVE_ACCT_VAULT_ROOT_PTR, NATIVE_NUM_ACCT_PROCEDURES_PTR, NATIVE_NUM_ACCT_STORAGE_SLOTS_PTR, NOTE_ROOT_PTR, NULLIFIER_DB_ROOT_PTR, + PARTIAL_BLOCKCHAIN_NUM_LEAVES_PTR, PARTIAL_BLOCKCHAIN_PEAKS_PTR, PREV_BLOCK_COMMITMENT_PTR, PROOF_COMMITMENT_PTR, PROTOCOL_VERSION_IDX, TIMESTAMP_IDX, TX_COMMITMENT_PTR, TX_KERNEL_COMMITMENT_PTR, TX_SCRIPT_ROOT_PTR, }, @@ -103,7 +103,7 @@ fn test_transaction_prologue() { global_input_memory_assertions(process, &tx_context); block_data_memory_assertions(process, &tx_context); - chain_mmr_memory_assertions(process, &tx_context); + partial_blockchain_memory_assertions(process, &tx_context); account_data_memory_assertions(process, &tx_context); input_notes_memory_assertions(process, &tx_context, ¬e_args); } @@ -225,23 +225,27 @@ fn block_data_memory_assertions(process: &Process, inputs: &TransactionContext) ); } -fn chain_mmr_memory_assertions(process: &Process, prepared_tx: &TransactionContext) { - // update the chain MMR to point to the block against which this transaction is being executed - let mut chain_mmr = prepared_tx.tx_inputs().block_chain().clone(); - chain_mmr.add_block(prepared_tx.tx_inputs().block_header().clone(), true); +fn partial_blockchain_memory_assertions(process: &Process, prepared_tx: &TransactionContext) { + // update the partial blockchain to point to the block against which this transaction is being + // executed + let mut partial_blockchain = prepared_tx.tx_inputs().block_chain().clone(); + partial_blockchain.add_block(prepared_tx.tx_inputs().block_header().clone(), true); assert_eq!( - read_root_mem_word(&process.into(), CHAIN_MMR_NUM_LEAVES_PTR)[0], - Felt::new(chain_mmr.chain_length().as_u64()), - "The number of leaves should be stored at the CHAIN_MMR_NUM_LEAVES_PTR" + read_root_mem_word(&process.into(), PARTIAL_BLOCKCHAIN_NUM_LEAVES_PTR)[0], + Felt::new(partial_blockchain.chain_length().as_u64()), + "The number of leaves should be stored at the PARTIAL_BLOCKCHAIN_NUM_LEAVES_PTR" ); - for (i, peak) in chain_mmr.peaks().peaks().iter().enumerate() { - // The peaks should be stored at the CHAIN_MMR_PEAKS_PTR + for (i, peak) in partial_blockchain.peaks().peaks().iter().enumerate() { + // The peaks should be stored at the PARTIAL_BLOCKCHAIN_PEAKS_PTR let i: u32 = i.try_into().expect( "Number of peaks is log2(number_of_leaves), this value won't be larger than 2**32", ); - assert_eq!(read_root_mem_word(&process.into(), CHAIN_MMR_PEAKS_PTR + i), Word::from(peak)); + assert_eq!( + read_root_mem_word(&process.into(), PARTIAL_BLOCKCHAIN_PEAKS_PTR + i), + Word::from(peak) + ); } }