Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
51fecb2
feat: Only iterate if num leaves is different in account tree
PhilippGackstatter Apr 24, 2025
862eda2
chore: Add changelog entry
PhilippGackstatter Apr 24, 2025
7fdff8a
chore: Remove period from duplicate error message
PhilippGackstatter Apr 24, 2025
fe79ffe
Merge remote-tracking branch 'origin/next' into pgackst-account-tree-…
PhilippGackstatter Apr 25, 2025
29ce0ac
feat: Guarantee account ID prefix uniqueness in mutation set
PhilippGackstatter Apr 25, 2025
45d93f0
chore: Fix changelog
PhilippGackstatter Apr 25, 2025
8a8433d
feat: Add `NullifierTree` with tests
PhilippGackstatter Apr 25, 2025
3916599
feat: Add `BlockChain`
PhilippGackstatter Apr 25, 2025
66730b0
feat: Use `BlockChain` in `MockChain`
PhilippGackstatter Apr 25, 2025
6e74d3c
feat: Use `NullifierTree` in `MockChain`
PhilippGackstatter Apr 25, 2025
950d82c
chore: Add changelog entry
PhilippGackstatter Apr 25, 2025
ee04688
fix: changelog entry
PhilippGackstatter Apr 25, 2025
04e084e
feat: Rename `ChainMmr` -> `PartialBlockChain`
PhilippGackstatter Apr 25, 2025
543b4d5
chore: Add changelog entry
PhilippGackstatter Apr 25, 2025
732d98d
fix: search replace rename
PhilippGackstatter Apr 25, 2025
cb3337e
Merge branch 'next' into pgackst-nullifier-tree-blockchain
bobbinth May 3, 2025
e315e93
chore: Address review comments
PhilippGackstatter May 5, 2025
ff94435
chore: Add tests separator
PhilippGackstatter May 5, 2025
bf4988f
Merge branch 'pgackst-nullifier-tree-blockchain' into pgackst-partial…
PhilippGackstatter May 5, 2025
dc4d275
chore: Rename `PartialBlockChain` -> `PartialBlockchain`
PhilippGackstatter May 5, 2025
9ac9a6b
chore: Follow-up rename for block_chain -> blockchain
PhilippGackstatter May 5, 2025
3c345ac
chore: Rename blockchain hash to commitment
PhilippGackstatter May 5, 2025
1b75b1c
Merge remote-tracking branch 'origin/next' into pgackst-partial-block…
PhilippGackstatter May 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
21 changes: 12 additions & 9 deletions crates/miden-block-prover/src/local_block_prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use miden_objects::{
ProposedBlock, ProvenBlock,
},
note::Nullifier,
transaction::ChainMmr,
transaction::PartialBlockchain,
};

use crate::errors::ProvenBlockError;
Expand Down Expand Up @@ -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();

Expand All @@ -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.
// --------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -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.
Expand Down
47 changes: 24 additions & 23 deletions crates/miden-block-prover/src/tests/proposed_block_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand All @@ -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(),
Expand Down Expand Up @@ -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(),
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -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);
Expand All @@ -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(),
Expand Down Expand Up @@ -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<()> {
Expand Down Expand Up @@ -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.
// --------------------------------------------------------------------------------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
8 changes: 4 additions & 4 deletions crates/miden-block-prover/src/tests/proven_block_success.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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(),
Expand Down
8 changes: 4 additions & 4 deletions crates/miden-lib/asm/kernels/transaction/lib/account.masm
Original file line number Diff line number Diff line change
Expand Up @@ -750,15 +750,15 @@ 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.
#!
#! 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.
# ---------------------------------------------------------------------------------------------

Expand All @@ -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]
Expand Down
36 changes: 18 additions & 18 deletions crates/miden-lib/asm/kernels/transaction/lib/memory.masm
Original file line number Diff line number Diff line change
Expand Up @@ -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
# -------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -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
Expand Down
Loading