use std::marker::PhantomData;
use anyhow::{Context, Result};
use crate::compound_merkle_proof::CompoundMerkleProof;
use crate::hash::Algorithm;
use crate::merkle::{get_merkle_tree_len, Element, MerkleTree};
use crate::proof::Proof;
use crate::store::{Store, StoreConfig};
use typenum::marker_traits::Unsigned;
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct CompoundMerkleTree<T, A, K, B, N>
where
T: Element,
A: Algorithm<T>,
K: Store<T>,
B: Unsigned, N: Unsigned, {
trees: Vec<MerkleTree<T, A, K, B>>,
top_layer_nodes: usize,
len: usize,
leafs: usize,
height: usize,
root: T,
_n: PhantomData<N>,
}
impl<T: Element, A: Algorithm<T>, K: Store<T>, B: Unsigned, N: Unsigned>
CompoundMerkleTree<T, A, K, B, N>
{
pub fn from_trees(
trees: Vec<MerkleTree<T, A, K, B>>,
) -> Result<CompoundMerkleTree<T, A, K, B, N>> {
let top_layer_nodes = N::to_usize();
ensure!(
trees.len() == top_layer_nodes,
"Length of trees MUST equal the number of top layer nodes"
);
ensure!(
trees.iter().all(|ref mt| mt.height() == trees[0].height()),
"All passed in trees must have the same height"
);
ensure!(
trees.iter().all(|ref mt| mt.len() == trees[0].len()),
"All passed in trees must have the same length"
);
let leafs = trees.iter().fold(0, |leafs, mt| leafs + mt.leafs());
let len = trees.iter().fold(0, |len, mt| len + mt.len()) + 1;
let height = trees[0].height() + 1;
let roots: Vec<T> = trees.iter().map(|x| x.root()).collect();
let root = A::default().multi_node(&roots, 1);
Ok(CompoundMerkleTree {
trees,
top_layer_nodes,
len,
leafs,
height,
root,
_n: PhantomData,
})
}
pub fn from_slices(
tree_data: &[&[u8]],
leafs: usize,
) -> Result<CompoundMerkleTree<T, A, K, B, N>> {
let mut trees = Vec::with_capacity(tree_data.len());
for data in tree_data {
trees.push(MerkleTree::<T, A, K, B>::from_tree_slice(data, leafs)?);
}
CompoundMerkleTree::from_trees(trees)
}
pub fn from_slices_with_configs(
tree_data: &[&[u8]],
leafs: usize,
configs: &[StoreConfig],
) -> Result<CompoundMerkleTree<T, A, K, B, N>> {
let mut trees = Vec::with_capacity(tree_data.len());
for i in 0..tree_data.len() {
trees.push(MerkleTree::<T, A, K, B>::from_tree_slice_with_config(
tree_data[i],
leafs,
configs[i].clone(),
)?);
}
CompoundMerkleTree::from_trees(trees)
}
pub fn from_stores(leafs: usize, stores: Vec<K>) -> Result<CompoundMerkleTree<T, A, K, B, N>> {
let mut trees = Vec::with_capacity(stores.len());
for store in stores {
trees.push(MerkleTree::<T, A, K, B>::from_data_store(store, leafs)?);
}
CompoundMerkleTree::from_trees(trees)
}
pub fn from_store_configs(
leafs: usize,
configs: &[StoreConfig],
) -> Result<CompoundMerkleTree<T, A, K, B, N>> {
let branches = B::to_usize();
let mut trees = Vec::with_capacity(configs.len());
for config in configs {
let data = K::new_with_config(
get_merkle_tree_len(leafs, branches),
branches,
config.clone(),
)
.context("failed to create data store")?;
trees.push(MerkleTree::<T, A, K, B>::from_data_store(data, leafs)?);
}
CompoundMerkleTree::from_trees(trees)
}
pub fn gen_proof(&self, i: usize) -> Result<CompoundMerkleProof<T, B, N>> {
ensure!(
i < self.leafs,
"{} is out of bounds (max: {})",
i,
self.leafs
);
let tree_index = i / (self.leafs / self.top_layer_nodes);
let tree = &self.trees[tree_index];
let tree_leafs = tree.leafs();
let leaf_index = i % tree_leafs;
let sub_tree_proof: Proof<T, B> = tree.gen_proof(leaf_index)?;
let mut path: Vec<usize> = Vec::with_capacity(1); let mut lemma: Vec<T> = Vec::with_capacity(self.top_layer_nodes);
for i in 0..self.top_layer_nodes {
if i != tree_index {
lemma.push(self.trees[i].root())
}
}
lemma.push(self.root());
path.push(tree_index);
CompoundMerkleProof::new(sub_tree_proof, lemma, path)
}
pub fn top_layer_nodes(&self) -> usize {
self.top_layer_nodes
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn leafs(&self) -> usize {
self.leafs
}
pub fn height(&self) -> usize {
self.height
}
pub fn root(&self) -> T {
self.root.clone()
}
#[inline]
pub fn read_at(&self, i: usize) -> Result<T> {
ensure!(
i < self.leafs,
"{} is out of bounds (max: {})",
i,
self.leafs
);
let tree_index = i / (self.leafs / self.top_layer_nodes);
let tree = &self.trees[tree_index];
let tree_leafs = tree.leafs();
let leaf_index = i % tree_leafs;
tree.read_at(leaf_index)
}
}