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

feat!: apply hashing api to the mmr #4445

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ use tari_common_types::types::{Commitment, RangeProofService};
use tari_comms::{connectivity::ConnectivityRequester, peer_manager::NodeId};
use tari_crypto::{
commitment::HomomorphicCommitment,
hash::blake2::Blake256,
tari_utilities::{hex::Hex, Hashable},
};
use tari_mmr::{MerkleMountainRange, MutableMmr};
use tokio::task;

use super::error::HorizonSyncError;
Expand Down Expand Up @@ -75,6 +73,10 @@ use crate::{
TransactionOutput,
},
validation::{helpers, FinalHorizonStateValidation},
MutablePrunedOutputMmr,
PrunedKernelMmr,
PrunedOutputMmr,
PrunedWitnessMmr,
};

const LOG_TARGET: &str = "c::bn::state_machine_service::states::horizon_state_sync";
Expand Down Expand Up @@ -326,7 +328,7 @@ impl<'a, B: BlockchainBackend + 'static> HorizonStateSynchronization<'a, B> {
.fetch_block_accumulated_data(current_header.header().prev_hash.clone())
.await?;
let kernel_pruned_set = block_data.dissolve().0;
let mut kernel_mmr = MerkleMountainRange::<Blake256, _>::new(kernel_pruned_set);
let mut kernel_mmr = PrunedKernelMmr::new(kernel_pruned_set);

for hash in kernel_hashes.drain(..) {
kernel_mmr.push(hash)?;
Expand Down Expand Up @@ -487,8 +489,8 @@ impl<'a, B: BlockchainBackend + 'static> HorizonStateSynchronization<'a, B> {
.await?;
let (_, output_pruned_set, witness_pruned_set, _) = block_data.dissolve();

let mut output_mmr = MerkleMountainRange::<Blake256, _>::new(output_pruned_set);
let mut witness_mmr = MerkleMountainRange::<Blake256, _>::new(witness_pruned_set);
let mut output_mmr = PrunedOutputMmr::new(output_pruned_set);
let mut witness_mmr = PrunedWitnessMmr::new(witness_pruned_set);
let mut constants = self.rules.consensus_constants(current_header.height()).clone();
let mut last_sync_timer = Instant::now();
let mut avg_latency = RollingAverageTime::new(20);
Expand Down Expand Up @@ -596,7 +598,7 @@ impl<'a, B: BlockchainBackend + 'static> HorizonStateSynchronization<'a, B> {
bitmap.run_optimize();

let pruned_output_set = output_mmr.get_pruned_hash_set()?;
let output_mmr = MutableMmr::<Blake256, _>::new(pruned_output_set.clone(), bitmap.clone())?;
let output_mmr = MutablePrunedOutputMmr::new(pruned_output_set.clone(), bitmap.clone())?;

let mmr_root = output_mmr.get_merkle_root()?;
if mmr_root != current_header.header().output_mr {
Expand Down
103 changes: 54 additions & 49 deletions base_layer/core/src/blocks/genesis_block.rs

Large diffs are not rendered by default.

15 changes: 9 additions & 6 deletions base_layer/core/src/chain_storage/blockchain_database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ use tari_common_types::{
chain_metadata::ChainMetadata,
types::{BlockHash, Commitment, HashOutput, Signature},
};
use tari_crypto::hash::blake2::Blake256;
use tari_mmr::{pruned_hashset::PrunedHashSet, MerkleMountainRange, MutableMmr};
use tari_mmr::pruned_hashset::PrunedHashSet;
use tari_utilities::{epoch_time::EpochTime, hex::Hex, ByteArray, Hashable};

use crate::{
Expand Down Expand Up @@ -88,6 +87,10 @@ use crate::{
OrphanValidation,
PostOrphanBodyValidation,
},
MutablePrunedOutputMmr,
PrunedInputMmr,
PrunedKernelMmr,
PrunedWitnessMmr,
};

const LOG_TARGET: &str = "c::cs::database";
Expand Down Expand Up @@ -1215,10 +1218,10 @@ pub fn calculate_mmr_roots<T: BlockchainBackend>(db: &T, block: &Block) -> Resul
value: header.prev_hash.to_hex(),
})?;

let mut kernel_mmr = MerkleMountainRange::<Blake256, _>::new(kernels);
let mut output_mmr = MutableMmr::<Blake256, _>::new(outputs, deleted)?;
let mut witness_mmr = MerkleMountainRange::<Blake256, _>::new(range_proofs);
let mut input_mmr = MerkleMountainRange::<Blake256, _>::new(PrunedHashSet::default());
let mut kernel_mmr = PrunedKernelMmr::new(kernels);
let mut output_mmr = MutablePrunedOutputMmr::new(outputs, deleted)?;
let mut witness_mmr = PrunedWitnessMmr::new(range_proofs);
let mut input_mmr = PrunedInputMmr::new(PrunedHashSet::default());
let mut deleted_outputs = Vec::new();

for kernel in body.kernels().iter() {
Expand Down
12 changes: 7 additions & 5 deletions base_layer/core/src/chain_storage/lmdb_db/lmdb_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@ use tari_common_types::{
chain_metadata::ChainMetadata,
types::{BlockHash, Commitment, HashOutput, Signature, BLOCK_HASH_LENGTH},
};
use tari_crypto::hash::blake2::Blake256;
use tari_mmr::{Hash, MerkleMountainRange, MutableMmr};
use tari_mmr::Hash;
use tari_storage::lmdb_store::{db, LMDBBuilder, LMDBConfig, LMDBStore};
use tari_utilities::{
hash::Hashable,
Expand Down Expand Up @@ -98,6 +97,9 @@ use crate::{
aggregated_body::AggregateBody,
transaction_components::{TransactionError, TransactionInput, TransactionKernel, TransactionOutput},
},
MutablePrunedOutputMmr,
PrunedKernelMmr,
PrunedWitnessMmr,
};

type DatabaseRef = Arc<Database<'static>>;
Expand Down Expand Up @@ -1155,7 +1157,7 @@ impl LMDBDatabase {
..
} = data;

let mut kernel_mmr = MerkleMountainRange::<Blake256, _>::new(pruned_kernel_set);
let mut kernel_mmr = PrunedKernelMmr::new(pruned_kernel_set);

for kernel in kernels {
total_kernel_sum = &total_kernel_sum + &kernel.excess;
Expand All @@ -1170,8 +1172,8 @@ impl LMDBDatabase {
})?;
self.insert_kernel(txn, &block_hash, &kernel, pos)?;
}
let mut output_mmr = MutableMmr::<Blake256, _>::new(pruned_output_set, Bitmap::create())?;
let mut witness_mmr = MerkleMountainRange::<Blake256, _>::new(pruned_proof_set);
let mut output_mmr = MutablePrunedOutputMmr::new(pruned_output_set, Bitmap::create())?;
let mut witness_mmr = PrunedWitnessMmr::new(pruned_proof_set);

let leaf_count = witness_mmr.get_leaf_count()?;

Expand Down
39 changes: 39 additions & 0 deletions base_layer/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,43 @@ pub mod large_ints {
pub struct U512(8);
}
}

pub use large_ints::{U256, U512};
use tari_crypto::{hash::blake2::Blake256, hash_domain, hashing::DomainSeparatedHasher};
use tari_mmr::{pruned_hashset::PrunedHashSet, Hash, MerkleMountainRange, MutableMmr};

hash_domain!(
KernelMmrHashDomain,
"com.tari.tari_project.base_layer.core.kernel_mmr",
1
);
pub type KernelMmrHasherBlake256 = DomainSeparatedHasher<Blake256, KernelMmrHashDomain>;
pub type KernelMmr = MerkleMountainRange<KernelMmrHasherBlake256, Vec<Hash>>;
pub type PrunedKernelMmr = MerkleMountainRange<KernelMmrHasherBlake256, PrunedHashSet>;

hash_domain!(
WitnessMmrHashDomain,
"com.tari.tari_project.base_layer.core.witness_mmr",
1
);
pub type WitnessMmrHasherBlake256 = DomainSeparatedHasher<Blake256, WitnessMmrHashDomain>;
pub type WitnessMmr = MerkleMountainRange<WitnessMmrHasherBlake256, Vec<Hash>>;
pub type PrunedWitnessMmr = MerkleMountainRange<WitnessMmrHasherBlake256, PrunedHashSet>;

hash_domain!(
OutputMmrHashDomain,
"com.tari.tari_project.base_layer.core.output_mmr",
1
);
pub type OutputMmrHasherBlake256 = DomainSeparatedHasher<Blake256, OutputMmrHashDomain>;
pub type MutableOutputMmr = MutableMmr<OutputMmrHasherBlake256, Vec<Hash>>;
pub type PrunedOutputMmr = MerkleMountainRange<OutputMmrHasherBlake256, PrunedHashSet>;
pub type MutablePrunedOutputMmr = MutableMmr<OutputMmrHasherBlake256, PrunedHashSet>;

hash_domain!(
InputMmrHashDomain,
"com.tari.tari_project.base_layer.core.output_mmr",
1
);
pub type InputMmrHasherBlake256 = DomainSeparatedHasher<Blake256, InputMmrHashDomain>;
pub type PrunedInputMmr = MerkleMountainRange<InputMmrHasherBlake256, PrunedHashSet>;
23 changes: 15 additions & 8 deletions base_layer/core/tests/helpers/block_builders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,17 @@ use tari_core::{
},
CryptoFactories,
},
KernelMmr,
KernelMmrHasherBlake256,
MutableOutputMmr,
WitnessMmr,
WitnessMmrHasherBlake256,
};
use tari_crypto::{
hash::blake2::Blake256,
keys::PublicKey as PublicKeyTrait,
tari_utilities::{hash::Hashable, hex::Hex},
};
use tari_mmr::{MerkleMountainRange, MutableMmr};
use tari_mmr::{Hash, MutableMmr};
use tari_script::script;

pub fn create_coinbase(
Expand Down Expand Up @@ -151,12 +155,12 @@ fn print_new_genesis_block(network: Network) {
.build()
.unwrap();

let mut kernel_mmr = MerkleMountainRange::<Blake256, _>::new(Vec::new());
let mut kernel_mmr = KernelMmr::new(Vec::new());
kernel_mmr.push(kernel.hash()).unwrap();

let mut witness_mmr = MerkleMountainRange::<Blake256, _>::new(Vec::new());
let mut witness_mmr = WitnessMmr::new(Vec::new());
witness_mmr.push(utxo.witness_hash()).unwrap();
let mut output_mmr = MutableMmr::<Blake256, _>::new(Vec::new(), Bitmap::create()).unwrap();
let mut output_mmr = MutableOutputMmr::new(Vec::new(), Bitmap::create()).unwrap();
output_mmr.push(utxo.hash()).unwrap();

header.kernel_mr = kernel_mmr.get_merkle_root().unwrap();
Expand Down Expand Up @@ -235,6 +239,9 @@ pub fn create_genesis_block(

// Calculate the MMR Merkle roots for the genesis block template and update the header.
fn update_genesis_block_mmr_roots(template: NewBlockTemplate) -> Result<Block, ChainStorageError> {
type BaseLayerKernelMutableMmr = MutableMmr<KernelMmrHasherBlake256, Vec<Hash>>;
type BaseLayerWitnessMutableMmr = MutableMmr<WitnessMmrHasherBlake256, Vec<Hash>>;

let NewBlockTemplate { header, mut body, .. } = template;
// Make sure the body components are sorted. If they already are, this is a very cheap call.
body.sort();
Expand All @@ -243,13 +250,13 @@ fn update_genesis_block_mmr_roots(template: NewBlockTemplate) -> Result<Block, C
let rp_hashes: Vec<HashOutput> = body.outputs().iter().map(|out| out.witness_hash()).collect();

let mut header = BlockHeader::from(header);
header.kernel_mr = MutableMmr::<Blake256, _>::new(kernel_hashes, Bitmap::create())
header.kernel_mr = BaseLayerKernelMutableMmr::new(kernel_hashes, Bitmap::create())
.unwrap()
.get_merkle_root()?;
header.output_mr = MutableMmr::<Blake256, _>::new(out_hashes, Bitmap::create())
header.output_mr = MutableOutputMmr::new(out_hashes, Bitmap::create())
.unwrap()
.get_merkle_root()?;
header.witness_mr = MutableMmr::<Blake256, _>::new(rp_hashes, Bitmap::create())
header.witness_mr = BaseLayerWitnessMutableMmr::new(rp_hashes, Bitmap::create())
.unwrap()
.get_merkle_root()?;
Ok(Block { header, body })
Expand Down
13 changes: 11 additions & 2 deletions base_layer/mmr/benches/bench.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ mod benches {
use blake2::Blake2b;
use criterion::{criterion_group, BatchSize, Criterion};
use digest::Digest;
use tari_mmr::MerkleMountainRange;
use tari_crypto::{hash::blake2::Blake256, hash_domain, hashing::DomainSeparatedHasher};
use tari_mmr::{Hash, MerkleMountainRange};

hash_domain!(
MmrBenchTestHashDomain,
"com.tari.tari_project.base_layer.mmr.bemches",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hansieodendaal Just noticed a type-o here

Copy link
Member

@sdbondi sdbondi Aug 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nm just a test so it's not a problem :)

1
);
pub type MmrTestHasherBlake256 = DomainSeparatedHasher<Blake256, MmrBenchTestHashDomain>;
pub type TestMmr = MerkleMountainRange<MmrTestHasherBlake256, Vec<Hash>>;

fn get_hashes(n: usize) -> Vec<Vec<u8>> {
(0..n).map(|i| Blake2b::digest(&i.to_le_bytes()).to_vec()).collect()
Expand All @@ -43,7 +52,7 @@ mod benches {
fn build_mmr(c: &mut Criterion) {
c.bench_function("Build MMR", move |b| {
let hashes = get_hashes(1000);
let mut mmr = MerkleMountainRange::<Blake2b, _>::new(Vec::default());
let mut mmr = TestMmr::new(Vec::default());
b.iter_batched(
|| hashes.clone(),
|hashes| {
Expand Down
3 changes: 2 additions & 1 deletion base_layer/mmr/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use std::convert::TryInto;

use digest::Digest;
use tari_common::DomainDigest;

use crate::{error::MerkleMountainRangeError, Hash};

Expand Down Expand Up @@ -171,7 +172,7 @@ pub fn is_left_sibling(pos: usize) -> bool {
(peak_map & peak) == 0
}

pub fn hash_together<D: Digest>(left: &[u8], right: &[u8]) -> Hash {
pub fn hash_together<D: Digest + DomainDigest>(left: &[u8], right: &[u8]) -> Hash {
D::new().chain(left).chain(right).finalize().to_vec()
}

Expand Down
9 changes: 5 additions & 4 deletions base_layer/mmr/src/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use crate::{
};
use digest::Digest;
use std::{convert::TryFrom, marker::PhantomData};
use tari_common::DomainDigest;

pub type PrunedMmr<D> = MerkleMountainRange<D, PrunedHashSet>;
pub type PrunedMutableMmr<D> = MutableMmr<D, PrunedHashSet>;
Expand All @@ -41,7 +42,7 @@ pub type PrunedMutableMmr<D> = MutableMmr<D, PrunedHashSet>;
/// `validate` will throw an error.
pub fn prune_mmr<D, B>(mmr: &MerkleMountainRange<D, B>) -> Result<PrunedMmr<D>, MerkleMountainRangeError>
where
D: Digest,
D: Digest + DomainDigest,
B: ArrayLike<Value = Hash>,
{
let backend = PrunedHashSet::try_from(mmr)?;
Expand All @@ -54,7 +55,7 @@ where
/// A convenience function in the same vein as [prune_mmr], but applied to `MutableMmr` instances.
pub fn prune_mutable_mmr<D, B>(mmr: &MutableMmr<D, B>) -> Result<PrunedMutableMmr<D>, MerkleMountainRangeError>
where
D: Digest,
D: Digest + DomainDigest,
B: ArrayLike<Value = Hash>,
{
let backend = PrunedHashSet::try_from(&mmr.mmr)?;
Expand Down Expand Up @@ -84,7 +85,7 @@ pub fn calculate_pruned_mmr_root<D, B>(
deletions: Vec<u32>,
) -> Result<Hash, MerkleMountainRangeError>
where
D: Digest,
D: Digest + DomainDigest,
B: ArrayLike<Value = Hash>,
{
let mut pruned_mmr = prune_mutable_mmr(src)?;
Expand All @@ -103,7 +104,7 @@ pub fn calculate_mmr_root<D, B>(
additions: Vec<Hash>,
) -> Result<Hash, MerkleMountainRangeError>
where
D: Digest,
D: Digest + DomainDigest,
B: ArrayLike<Value = Hash>,
{
let mut mmr = prune_mmr(src)?;
Expand Down
3 changes: 2 additions & 1 deletion base_layer/mmr/src/merkle_checkpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use serde::{
de::{self, Deserialize, Deserializer, MapAccess, SeqAccess, Visitor},
ser::{Serialize, SerializeStruct, Serializer},
};
use tari_common::DomainDigest;

use crate::{backend::ArrayLike, error::MerkleMountainRangeError, mutable_mmr::MutableMmr, Hash};

Expand Down Expand Up @@ -55,7 +56,7 @@ impl MerkleCheckPoint {
/// from here.
pub fn apply<D, B2>(&self, mmr: &mut MutableMmr<D, B2>) -> Result<(), MerkleMountainRangeError>
where
D: Digest,
D: Digest + DomainDigest,
B2: ArrayLike<Value = Hash>,
{
for node in &self.nodes_added {
Expand Down
5 changes: 3 additions & 2 deletions base_layer/mmr/src/merkle_mountain_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use std::{
};

use digest::Digest;
use tari_common::DomainDigest;

use crate::{
backend::ArrayLike,
Expand Down Expand Up @@ -57,7 +58,7 @@ pub struct MerkleMountainRange<D, B> {

impl<D, B> MerkleMountainRange<D, B>
where
D: Digest,
D: Digest + DomainDigest,
B: ArrayLike<Value = Hash>,
{
/// Create a new Merkle mountain range using the given backend for storage
Expand Down Expand Up @@ -276,7 +277,7 @@ where

impl<D, B, B2> PartialEq<MerkleMountainRange<D, B2>> for MerkleMountainRange<D, B>
where
D: Digest,
D: Digest + DomainDigest,
B: ArrayLike<Value = Hash>,
B2: ArrayLike<Value = Hash>,
{
Expand Down