pub mod property_tests;
mod tests;
use alloc::{collections::BTreeMap, string::ToString};
use miden_field::Word;
use miden_serde_utils::{
ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
};
use crate::merkle::{
EmptySubtreeRoots, NodeIndex,
smt::{LeafIndex, SMT_DEPTH, SmtLeaf},
};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UniqueNodes {
pub root: Word,
pub nodes: BTreeMap<NodeIndex, Word>,
pub leaves: BTreeMap<u64, SmtLeaf>,
pub value_only_leaves: BTreeMap<u64, Word>,
}
impl UniqueNodes {
pub fn empty() -> Self {
Self {
root: *EmptySubtreeRoots::entry(SMT_DEPTH, 0),
nodes: BTreeMap::new(),
leaves: BTreeMap::new(),
value_only_leaves: BTreeMap::new(),
}
}
pub fn get_leaf_hash(&self, position: u64) -> Word {
self.leaves
.get(&position)
.map(SmtLeaf::hash)
.or_else(|| self.value_only_leaves.get(&position).copied())
.unwrap_or_else(|| SmtLeaf::new_empty(LeafIndex::new_max_depth(position)).hash())
}
pub fn get_node_hash(&self, index: NodeIndex) -> Word {
self.nodes
.get(&index)
.copied()
.unwrap_or_else(|| *EmptySubtreeRoots::entry(SMT_DEPTH, index.depth()))
}
pub(super) fn validate(&self) -> Result<(), DeserializationError> {
for (&position, leaf) in &self.leaves {
if position != leaf.index().position() {
return Err(DeserializationError::InvalidValue(format!(
"Node index {position} did not match the embedded leaf index {}",
leaf.index().position()
)));
}
}
Ok(())
}
}
impl Default for UniqueNodes {
fn default() -> Self {
Self::empty()
}
}
impl Serializable for UniqueNodes {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.root.write_into(target);
let mut levels = self.nodes.iter().peekable();
let level_count = self
.nodes
.keys()
.map(NodeIndex::depth)
.fold((0, None), |(count, previous), depth| {
(count + u64::from(previous != Some(depth)), Some(depth))
})
.0;
target.write(level_count);
while let Some((index, _)) = levels.peek() {
let depth = index.depth();
target.write(depth);
let level_node_count =
levels.clone().take_while(|(index, _)| index.depth() == depth).count();
target.write(level_node_count as u64);
for (index, value) in levels.by_ref().take(level_node_count) {
target.write(index.position());
target.write(value);
}
}
let leaf_count = self.leaves.len() as u64;
target.write(leaf_count);
target.write_many(self.leaves.iter());
let value_only_leaf_count = self.value_only_leaves.len() as u64;
target.write(value_only_leaf_count);
target.write_many(self.value_only_leaves.iter());
}
}
impl Deserializable for UniqueNodes {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let root = Word::read_from(source)?;
let level_count = source.read_u64()?;
let mut nodes = BTreeMap::new();
for _ in 0..level_count {
let depth = source.read_u8()?;
let node_count = source.read_u64()?;
for _ in 0..node_count {
let position = source.read_u64()?;
let index = NodeIndex::new(depth, position)
.map_err(|err| DeserializationError::InvalidValue(err.to_string()))?;
let value = source.read()?;
nodes.insert(index, value);
}
}
let leaf_count = source.read_u64()?;
let mut leaves = BTreeMap::new();
for _ in 0..leaf_count {
let (position, leaf) = source.read()?;
leaves.insert(position, leaf);
}
let value_only_leaf_count = source.read_u64()?;
let mut value_only_leaves = BTreeMap::new();
for _ in 0..value_only_leaf_count {
let (position, value) = source.read()?;
value_only_leaves.insert(position, value);
}
let unique_nodes = Self { root, nodes, leaves, value_only_leaves };
unique_nodes.validate()?;
Ok(unique_nodes)
}
}