Skip to content

Commit

Permalink
Merge pull request #195 from 0xPolygonMiden/hacka-partial-mmr2
Browse files Browse the repository at this point in the history
mmr: added partial mmr
  • Loading branch information
hackaugusto authored Oct 19, 2023
2 parents 7f3d4b8 + bde20f9 commit 012ad5a
Show file tree
Hide file tree
Showing 13 changed files with 1,129 additions and 135 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* Implemented benchmarking for `TieredSmt` (#182).
* Added more leaf traversal methods for `MerkleStore` (#185).
* Added SVE acceleration for RPO hash function (#189).
* Implemented the `PartialMmr` datastructure (#195).

## 0.6.0 (2023-06-25)

Expand Down
28 changes: 26 additions & 2 deletions src/merkle/merkle_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ impl MerkleTree {
///
/// # Errors
/// Returns an error if the number of leaves is smaller than two or is not a power of two.
pub fn new(leaves: Vec<Word>) -> Result<Self, MerkleError> {
pub fn new<T>(leaves: T) -> Result<Self, MerkleError>
where
T: AsRef<[Word]>,
{
let leaves = leaves.as_ref();
let n = leaves.len();
if n <= 1 {
return Err(MerkleError::DepthTooSmall(n as u8));
Expand All @@ -34,7 +38,7 @@ impl MerkleTree {

// copy leaves into the second part of the nodes vector
nodes[n..].iter_mut().zip(leaves).for_each(|(node, leaf)| {
*node = RpoDigest::from(leaf);
*node = RpoDigest::from(*leaf);
});

// re-interpret nodes as an array of two nodes fused together
Expand Down Expand Up @@ -175,6 +179,26 @@ impl MerkleTree {
}
}

// CONVERSIONS
// ================================================================================================

impl TryFrom<&[Word]> for MerkleTree {
type Error = MerkleError;

fn try_from(value: &[Word]) -> Result<Self, Self::Error> {
MerkleTree::new(value)
}
}

impl TryFrom<&[RpoDigest]> for MerkleTree {
type Error = MerkleError;

fn try_from(value: &[RpoDigest]) -> Result<Self, Self::Error> {
let value: Vec<Word> = value.iter().map(|v| *v.deref()).collect();
MerkleTree::new(value)
}
}

// ITERATORS
// ================================================================================================

Expand Down
16 changes: 16 additions & 0 deletions src/merkle/mmr/delta.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use super::super::{RpoDigest, Vec};

/// Container for the update data of a [PartialMmr]
#[derive(Debug)]
pub struct MmrDelta {
/// The new version of the [Mmr]
pub forest: usize,

/// Update data.
///
/// The data is packed as follows:
/// 1. All the elements needed to perform authentication path updates. These are the right
/// siblings required to perform tree merges on the [PartialMmr].
/// 2. The new peaks.
pub data: Vec<RpoDigest>,
}
35 changes: 35 additions & 0 deletions src/merkle/mmr/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use crate::merkle::MerkleError;
use core::fmt::{Display, Formatter};

#[cfg(feature = "std")]
use std::error::Error;

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum MmrError {
InvalidPosition(usize),
InvalidPeaks,
InvalidPeak,
InvalidUpdate,
UnknownPeak,
MerkleError(MerkleError),
}

impl Display for MmrError {
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), core::fmt::Error> {
match self {
MmrError::InvalidPosition(pos) => write!(fmt, "Mmr does not contain position {pos}"),
MmrError::InvalidPeaks => write!(fmt, "Invalid peaks count"),
MmrError::InvalidPeak => {
write!(fmt, "Peak values does not match merkle path computed root")
}
MmrError::InvalidUpdate => write!(fmt, "Invalid mmr update"),
MmrError::UnknownPeak => {
write!(fmt, "Peak not in Mmr")
}
MmrError::MerkleError(err) => write!(fmt, "{}", err),
}
}
}

#[cfg(feature = "std")]
impl Error for MmrError {}
Loading

0 comments on commit 012ad5a

Please sign in to comment.