use crate::{
backend::ArrayLike,
common::node_index,
error::MerkleMountainRangeError,
mutable_mmr_leaf_nodes::MutableMmrLeafNodes,
Hash,
MerkleMountainRange,
};
use croaring::Bitmap;
use digest::Digest;
#[derive(Debug)]
pub struct MutableMmr<D, B>
where
D: Digest,
B: ArrayLike<Value = Hash>,
{
pub(crate) mmr: MerkleMountainRange<D, B>,
pub(crate) deleted: Bitmap,
pub(crate) size: u32,
}
impl<D, B> MutableMmr<D, B>
where
D: Digest,
B: ArrayLike<Value = Hash>,
{
pub fn new(mmr_backend: B, deleted: Bitmap) -> Result<MutableMmr<D, B>, MerkleMountainRangeError> {
let mmr = MerkleMountainRange::new(mmr_backend);
Ok(MutableMmr {
size: mmr.get_leaf_count()? as u32,
mmr,
deleted,
})
}
pub fn assign(&mut self, state: MutableMmrLeafNodes) -> Result<(), MerkleMountainRangeError> {
self.mmr.assign(state.leaf_hashes)?;
self.deleted = state.deleted;
self.size = self.mmr.get_leaf_count()? as u32;
Ok(())
}
#[allow(clippy::len_without_is_empty)]
#[inline(always)]
pub fn len(&self) -> u32 {
self.size - self.deleted.cardinality() as u32
}
pub fn is_empty(&self) -> Result<bool, MerkleMountainRangeError> {
Ok(self.mmr.is_empty()? || self.deleted.cardinality() == self.size as u64)
}
pub fn get_leaf_hash(&self, leaf_index: u32) -> Result<Option<Hash>, MerkleMountainRangeError> {
if self.deleted.contains(leaf_index) {
return Ok(None);
}
self.mmr.get_node_hash(node_index(leaf_index as usize))
}
pub fn get_leaf_status(&self, leaf_index: u32) -> Result<(Option<Hash>, bool), MerkleMountainRangeError> {
let hash = self.mmr.get_node_hash(node_index(leaf_index as usize))?;
let deleted = self.deleted.contains(leaf_index);
Ok((hash, deleted))
}
pub fn get_leaf_count(&self) -> usize {
self.size as usize
}
pub fn get_merkle_root(&self) -> Result<Hash, MerkleMountainRangeError> {
let mmr_root = self.mmr.get_merkle_root()?;
let mut hasher = D::new();
hasher.update(&mmr_root);
Ok(self.hash_deleted(hasher).finalize().to_vec())
}
pub fn get_mmr_only_root(&self) -> Result<Hash, MerkleMountainRangeError> {
self.mmr.get_merkle_root()
}
pub fn find_node_index(&self, hash: &[u8]) -> Result<Option<usize>, MerkleMountainRangeError> {
self.mmr.find_node_index(hash)
}
pub fn find_leaf_index(&self, hash: &[u8]) -> Result<Option<u32>, MerkleMountainRangeError> {
self.mmr.find_leaf_index(hash)
}
pub fn push(&mut self, hash: Hash) -> Result<usize, MerkleMountainRangeError> {
if self.size == u32::MAX {
return Err(MerkleMountainRangeError::MaximumSizeReached);
}
self.mmr.push(hash)?;
self.size += 1;
Ok(self.size as usize)
}
pub fn delete(&mut self, leaf_index: u32) -> bool {
if (leaf_index >= self.size) || self.deleted.contains(leaf_index) {
return false;
}
self.deleted.add(leaf_index);
true
}
pub fn compress(&mut self) -> bool {
self.deleted.run_optimize()
}
pub fn validate(&self) -> Result<(), MerkleMountainRangeError> {
self.mmr.validate()
}
fn hash_deleted(&self, mut hasher: D) -> D {
let bitmap_ser = self.deleted.serialize();
hasher.update(&bitmap_ser);
hasher
}
fn get_sub_bitmap(&self, leaf_index: usize, count: usize) -> Result<Bitmap, MerkleMountainRangeError> {
let mut deleted = self.deleted.clone();
if leaf_index > 0 {
deleted.remove_range_closed(0..(leaf_index - 1) as u32)
}
let leaf_count = self.mmr.get_leaf_count()?;
if leaf_count > 1 {
let last_index = leaf_index + count - 1;
if last_index < leaf_count - 1 {
deleted.remove_range_closed((last_index + 1) as u32..leaf_count as u32);
}
}
Ok(deleted)
}
pub fn to_leaf_nodes(
&self,
leaf_index: usize,
count: usize,
) -> Result<MutableMmrLeafNodes, MerkleMountainRangeError> {
Ok(MutableMmrLeafNodes {
leaf_hashes: self.mmr.get_leaf_hashes(leaf_index, count)?,
deleted: self.get_sub_bitmap(leaf_index, count)?,
})
}
pub fn mmr(&self) -> &MerkleMountainRange<D, B> {
&self.mmr
}
pub fn deleted(&self) -> &Bitmap {
&self.deleted
}
pub fn set_deleted(&mut self, deleted: Bitmap) {
self.deleted = deleted;
}
pub fn clear(&mut self) -> Result<(), MerkleMountainRangeError> {
self.mmr.clear()?;
self.deleted = Bitmap::create();
self.size = 0;
Ok(())
}
}
impl<D, B, B2> PartialEq<MutableMmr<D, B2>> for MutableMmr<D, B>
where
D: Digest,
B: ArrayLike<Value = Hash>,
B2: ArrayLike<Value = Hash>,
{
fn eq(&self, other: &MutableMmr<D, B2>) -> bool {
self.get_merkle_root() == other.get_merkle_root()
}
}