use crate::{
error::MerkleMountainRangeError,
pruned_hashset::PrunedHashSet,
ArrayLike,
Hash,
MerkleMountainRange,
MutableMmr,
};
use digest::Digest;
use std::{convert::TryFrom, marker::PhantomData};
pub type PrunedMmr<D> = MerkleMountainRange<D, PrunedHashSet>;
pub type PrunedMutableMmr<D> = MutableMmr<D, PrunedHashSet>;
pub fn prune_mmr<D, B>(mmr: &MerkleMountainRange<D, B>) -> Result<PrunedMmr<D>, MerkleMountainRangeError>
where
D: Digest,
B: ArrayLike<Value = Hash>,
{
let backend = PrunedHashSet::try_from(mmr)?;
Ok(MerkleMountainRange {
hashes: backend,
_hasher: PhantomData,
})
}
pub fn prune_mutable_mmr<D, B>(mmr: &MutableMmr<D, B>) -> Result<PrunedMutableMmr<D>, MerkleMountainRangeError>
where
D: Digest,
B: ArrayLike<Value = Hash>,
{
let backend = PrunedHashSet::try_from(&mmr.mmr)?;
Ok(MutableMmr {
mmr: MerkleMountainRange::new(backend),
deleted: mmr.deleted.clone(),
size: mmr.size,
})
}
pub fn calculate_pruned_mmr_root<D, B>(
src: &MutableMmr<D, B>,
additions: Vec<Hash>,
deletions: Vec<u32>,
) -> Result<Hash, MerkleMountainRangeError>
where
D: Digest,
B: ArrayLike<Value = Hash>,
{
let mut pruned_mmr = prune_mutable_mmr(src)?;
for hash in additions {
pruned_mmr.push(hash)?;
}
for index in deletions {
pruned_mmr.delete(index);
}
pruned_mmr.compress();
pruned_mmr.get_merkle_root()
}
pub fn calculate_mmr_root<D, B>(
src: &MerkleMountainRange<D, B>,
additions: Vec<Hash>,
) -> Result<Hash, MerkleMountainRangeError>
where
D: Digest,
B: ArrayLike<Value = Hash>,
{
let mut mmr = prune_mmr(src)?;
for hash in additions {
mmr.push(hash)?;
}
mmr.get_merkle_root()
}