Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Stress-04] Create nested tree for finalize root #2170

Merged
merged 9 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 5 additions & 1 deletion console/program/src/state_path/configuration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,17 @@ use snarkvm_console_network::BHPMerkleTree;
pub const BLOCKS_DEPTH: u8 = 32;
/// The depth of the Merkle tree for the block header.
pub const HEADER_DEPTH: u8 = 3;
/// The depth of the Merkle tree for finalize operations in a transaction.
pub const FINALIZE_ID_DEPTH: u8 = TRANSACTION_DEPTH + 4; // '+ 4' is to support 16 finalize operations per transition.
/// The depth of the Merkle tree for finalize operations in a block.
pub const FINALIZE_OPERATIONS_DEPTH: u8 = 20;
pub const FINALIZE_OPERATIONS_DEPTH: u8 = TRANSACTIONS_DEPTH;
/// The depth of the Merkle tree for the ratifications in a block.
pub const RATIFICATIONS_DEPTH: u8 = 16;
/// The depth the Merkle tree for the subdag certificates in a block.
pub const SUBDAG_CERTIFICATES_DEPTH: u8 = 16;
/// The depth of the Merkle tree for transactions in a block.
/// Note: The technical limit is 2^16 - 1 transactions, to allow compatibility with the
/// finalize operations tree, which requires 1 leaf for the ratified finalize ID.
pub const TRANSACTIONS_DEPTH: u8 = 16;
/// The depth of the Merkle tree for the transaction.
pub const TRANSACTION_DEPTH: u8 = 5;
Expand Down
12 changes: 11 additions & 1 deletion ledger/block/src/transactions/confirmed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ mod serialize;
mod string;

use crate::{rejected::Rejected, Transaction};
use console::{network::prelude::*, types::Field};
use console::{network::prelude::*, program::FINALIZE_ID_DEPTH, types::Field};
use synthesizer_program::FinalizeOperation;

pub type NumFinalizeSize = u16;
Expand Down Expand Up @@ -261,6 +261,16 @@ impl<N: Network> ConfirmedTransaction<N> {
}
}

/// Returns the finalize ID, by computing the root of a (small) Merkle tree comprised of
/// the ordered finalize operations for the transaction.
pub fn to_finalize_id(&self) -> Result<Field<N>> {
// Prepare the leaves.
let leaves = self.finalize_operations().iter().map(ToBits::to_bits_le).collect::<Vec<_>>();
// Compute the finalize ID.
// Note: This call will ensure the number of finalize operations is within the size of the Merkle tree.
Ok(*N::merkle_tree_bhp::<FINALIZE_ID_DEPTH>(&leaves)?.root())
}

/// Returns the rejected ID, if the confirmed transaction is rejected.
pub fn to_rejected_id(&self) -> Result<Option<Field<N>>> {
match self {
Expand Down
30 changes: 22 additions & 8 deletions ledger/block/src/transactions/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,23 @@ use super::*;
impl<N: Network> Transactions<N> {
/// Returns the finalize root of the transactions.
pub fn to_finalize_root(&self, ratified_finalize_operations: Vec<FinalizeOperation<N>>) -> Result<Field<N>> {
// Prepare the leaves.
let leaves = self.finalize_operations().chain(&ratified_finalize_operations).map(ToBits::to_bits_le);
// Compute the finalize tree.
// Note: This call will check the number of finalize operations is within the size of the Merkle tree.
let tree = N::merkle_tree_bhp::<FINALIZE_OPERATIONS_DEPTH>(&leaves.collect::<Vec<_>>())?;
// Return the finalize root.
Ok(*tree.root())
// Prepare the ratified finalize ID - a Merkle tree composed of the ratified finalize operations.
let ratified_finalize_id = *N::merkle_tree_bhp::<FINALIZE_ID_DEPTH>(
&ratified_finalize_operations.iter().map(ToBits::to_bits_le).collect::<Vec<_>>(),
)?
.root();

// Prepare the leaves, composed of:
// | transaction_0 finalize ID, ..., transaction_n finalize ID | ratified finalize ID |
let leaves = self
.iter()
.map(|tx| tx.to_finalize_id().map(|id| id.to_bits_le()))
.chain(std::iter::once(Ok(ratified_finalize_id.to_bits_le())))
.collect::<Result<Vec<_>>>()?;

// Compute the finalize root.
// Note: This call will ensure the number of finalize operations is within the size of the Merkle tree.
Ok(*N::merkle_tree_bhp::<FINALIZE_OPERATIONS_DEPTH>(&leaves)?.root())
}
}

Expand Down Expand Up @@ -74,6 +84,10 @@ mod tests {
#[test]
fn test_transactions_depth() {
// Ensure the log2 relationship between depth and the maximum number of transactions.
assert_eq!(2usize.pow(TRANSACTIONS_DEPTH as u32), Transactions::<CurrentNetwork>::MAX_TRANSACTIONS);
// Note: This test uses 'checked_sub' to ensure the depth is not zero.
assert_eq!(
2usize.pow(TRANSACTIONS_DEPTH as u32).checked_sub(1).expect("Invalid depth"),
Transactions::<CurrentNetwork>::MAX_TRANSACTIONS
);
}
}
3 changes: 2 additions & 1 deletion ledger/block/src/transactions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use console::{
Record,
TransactionsPath,
TransactionsTree,
FINALIZE_ID_DEPTH,
FINALIZE_OPERATIONS_DEPTH,
TRANSACTIONS_DEPTH,
},
Expand Down Expand Up @@ -167,7 +168,7 @@ impl<N: Network> Transactions<N> {

impl<N: Network> Transactions<N> {
/// The maximum number of transactions allowed in a block.
pub const MAX_TRANSACTIONS: usize = usize::pow(2, TRANSACTIONS_DEPTH as u32);
pub const MAX_TRANSACTIONS: usize = usize::pow(2, TRANSACTIONS_DEPTH as u32).saturating_sub(1);

/// Returns an iterator over all transactions, for all transactions in `self`.
pub fn iter(&self) -> impl '_ + ExactSizeIterator<Item = &ConfirmedTransaction<N>> {
Expand Down
1 change: 1 addition & 0 deletions ledger/block/src/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ impl<N: Network> Block<N> {
previous_height: u32,
current_committee: &Committee<N>,
) -> Result<(u64, u32, i64)> {
// Note: Do not remove this. This ensures that all blocks after genesis are quorum blocks.
#[cfg(not(any(test, feature = "test")))]
ensure!(self.authority.is_quorum(), "The next block must be a quorum block");

Expand Down
2 changes: 1 addition & 1 deletion ledger/narwhal/batch-header/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<N: Network> BatchHeader<N> {
/// The maximum number of solutions in a batch.
pub const MAX_SOLUTIONS: usize = N::MAX_SOLUTIONS;
/// The maximum number of transactions in a batch.
pub const MAX_TRANSACTIONS: usize = usize::pow(2, console::program::TRANSACTIONS_DEPTH as u32);
pub const MAX_TRANSACTIONS: usize = usize::pow(2, console::program::TRANSACTIONS_DEPTH as u32).saturating_sub(1);
/// The maximum number of transmissions in a batch.
pub const MAX_TRANSMISSIONS: usize = Self::MAX_SOLUTIONS + Self::MAX_TRANSACTIONS;
}
Expand Down
Binary file modified parameters/src/testnet3/resources/block.genesis
Binary file not shown.