use std::marker::PhantomData;
use std::sync::{Arc, RwLock};
use anyhow::{Context, Result};
use log::debug;
use rayon::prelude::*;
use typenum::marker_traits::Unsigned;
use typenum::U2;
use crate::hash::{Algorithm, Hashable};
use crate::proof::Proof;
use crate::store::{Store, StoreConfig, VecStore, BUILD_CHUNK_NODES};
pub const BUILD_DATA_BLOCK_SIZE: usize = 64 * BUILD_CHUNK_NODES;
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct MerkleTree<T, A, K, U = U2>
where
T: Element,
A: Algorithm<T>,
K: Store<T>,
U: Unsigned,
{
data: K,
leafs: usize,
height: usize,
root: T,
_u: PhantomData<U>,
_a: PhantomData<A>,
_t: PhantomData<T>,
}
pub trait Element: Ord + Clone + AsRef<[u8]> + Sync + Send + Default + std::fmt::Debug {
fn byte_len() -> usize;
fn from_slice(bytes: &[u8]) -> Self;
fn copy_to_slice(&self, bytes: &mut [u8]);
}
impl<T: Element, A: Algorithm<T>, K: Store<T>, U: Unsigned> MerkleTree<T, A, K, U> {
pub fn new<I: IntoIterator<Item = T>>(data: I) -> Result<MerkleTree<T, A, K, U>> {
Self::try_from_iter(data.into_iter().map(Ok))
}
pub fn new_with_config<I: IntoIterator<Item = T>>(
data: I,
config: StoreConfig,
) -> Result<MerkleTree<T, A, K, U>> {
Self::try_from_iter_with_config(data.into_iter().map(Ok), config)
}
pub fn from_data<O: Hashable<A>, I: IntoIterator<Item = O>>(
data: I,
) -> Result<MerkleTree<T, A, K, U>> {
let mut a = A::default();
Self::try_from_iter(data.into_iter().map(|x| {
a.reset();
x.hash(&mut a);
Ok(a.hash())
}))
}
pub fn from_data_with_config<O: Hashable<A>, I: IntoIterator<Item = O>>(
data: I,
config: StoreConfig,
) -> Result<MerkleTree<T, A, K, U>> {
let mut a = A::default();
Self::try_from_iter_with_config(
data.into_iter().map(|x| {
a.reset();
x.hash(&mut a);
Ok(a.hash())
}),
config,
)
}
pub fn from_data_store(data: K, leafs: usize) -> Result<MerkleTree<T, A, K, U>> {
let branches = U::to_usize();
ensure!(next_pow2(leafs) == leafs, "leafs MUST be a power of 2");
ensure!(
next_pow2(branches) == branches,
"branches MUST be a power of 2"
);
let tree_len = get_merkle_tree_len(leafs, branches);
ensure!(tree_len == data.len(), "Inconsistent tree data");
ensure!(
is_merkle_tree_size_valid(leafs, branches),
"MerkleTree size is invalid given the arity"
);
let height = get_merkle_tree_height(leafs, branches);
let root = data.read_at(data.len() - 1)?;
Ok(MerkleTree {
data,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
pub fn from_tree_slice(data: &[u8], leafs: usize) -> Result<MerkleTree<T, A, K, U>> {
let branches = U::to_usize();
let height = get_merkle_tree_height(leafs, branches);
let tree_len = get_merkle_tree_len(leafs, branches);
ensure!(
tree_len == data.len() / T::byte_len(),
"Inconsistent tree data"
);
ensure!(
is_merkle_tree_size_valid(leafs, branches),
"MerkleTree size is invalid given the arity"
);
let store = K::new_from_slice(tree_len, &data).context("failed to create data store")?;
let root = store.read_at(data.len() - 1)?;
Ok(MerkleTree {
data: store,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
pub fn from_tree_slice_with_config(
data: &[u8],
leafs: usize,
config: StoreConfig,
) -> Result<MerkleTree<T, A, K, U>> {
let branches = U::to_usize();
let height = get_merkle_tree_height(leafs, branches);
let tree_len = get_merkle_tree_len(leafs, branches);
ensure!(
tree_len == data.len() / T::byte_len(),
"Inconsistent tree data"
);
ensure!(
is_merkle_tree_size_valid(leafs, branches),
"MerkleTree size is invalid given the arity"
);
let store = K::new_from_slice_with_config(tree_len, branches, &data, config)
.context("failed to create data store")?;
let root = store.read_at(data.len() - 1)?;
Ok(MerkleTree {
data: store,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
#[inline]
fn build_partial_tree(
mut data: VecStore<T>,
leafs: usize,
height: usize,
) -> Result<MerkleTree<T, A, VecStore<T>, U>> {
let root = VecStore::build::<A, U>(&mut data, leafs, height, None)?;
let branches = U::to_usize();
let tree_len = get_merkle_tree_len(leafs, branches);
ensure!(tree_len == Store::len(&data), "Inconsistent tree data");
ensure!(
is_merkle_tree_size_valid(leafs, branches),
"MerkleTree size is invalid given the arity"
);
Ok(MerkleTree {
data,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
#[inline]
pub fn gen_proof(&self, i: usize) -> Result<Proof<T, U>> {
ensure!(
i < self.leafs,
"{} is out of bounds (max: {})",
i,
self.leafs
);
let mut base = 0;
let mut j = i;
let mut width = self.leafs;
let branches = U::to_usize();
ensure!(width == next_pow2(width), "Must be a power of 2 tree");
ensure!(
branches == next_pow2(branches),
"branches must be a power of 2"
);
let shift = log2_pow2(branches);
let mut lemma: Vec<T> =
Vec::with_capacity(get_merkle_proof_lemma_len(self.height, branches));
let mut path: Vec<usize> = Vec::with_capacity(self.height - 1);
lemma.push(self.read_at(j)?);
while base + 1 < self.len() {
let hash_index = (j / branches) * branches;
for k in hash_index..hash_index + branches {
if k != j {
lemma.push(self.read_at(base + k)?)
}
}
path.push(j % branches);
base += width;
width >>= shift; j >>= shift; }
lemma.push(self.root());
ensure!(
lemma.len() == get_merkle_proof_lemma_len(self.height, branches),
"Invalid proof lemma length"
);
ensure!(path.len() == self.height - 1, "Invalid proof path length");
Proof::new(lemma, path)
}
#[allow(clippy::type_complexity)]
pub fn gen_proof_and_partial_tree(
&self,
i: usize,
levels: usize,
) -> Result<(Proof<T, U>, MerkleTree<T, A, VecStore<T>, U>)> {
ensure!(
i < self.leafs,
"{} is out of bounds (max: {})",
i,
self.leafs
);
ensure!(
self.leafs == next_pow2(self.leafs),
"The size of the data layer must be a power of 2"
);
let branches = U::to_usize();
let total_size = get_merkle_tree_len(self.leafs, branches);
let cache_size = get_merkle_tree_cache_size(self.leafs, branches, levels);
ensure!(
cache_size < total_size,
"Generate a partial proof with all data available?"
);
let cached_leafs = get_merkle_tree_leafs(cache_size, branches);
ensure!(
cached_leafs == next_pow2(cached_leafs),
"The size of the cached leafs must be a power of 2"
);
let cache_height = get_merkle_tree_height(cached_leafs, branches);
let partial_height = self.height - cache_height + 1;
let segment_width = self.leafs / cached_leafs;
let segment_start = (i / segment_width) * segment_width;
let segment_end = segment_start + segment_width;
debug!("leafs {}, branches {}, total size {}, total height {}, cache_size {}, cached levels above base {}, \
partial_height {}, cached_leafs {}, segment_width {}, segment range {}-{} for {}",
self.leafs, branches, total_size, self.height, cache_size, levels, partial_height,
cached_leafs, segment_width, segment_start, segment_end, i);
let mut data_copy = vec![0; segment_width * T::byte_len()];
self.data
.read_range_into(segment_start, segment_end, &mut data_copy)?;
let partial_store = VecStore::new_from_slice(segment_width, &data_copy)?;
ensure!(
Store::len(&partial_store) == segment_width,
"Inconsistent store length"
);
data_copy.resize(
get_merkle_tree_len(segment_width, branches) * T::byte_len(),
0,
);
let partial_tree: MerkleTree<T, A, VecStore<T>, U> =
Self::build_partial_tree(partial_store, segment_width, partial_height)?;
ensure!(
partial_height == partial_tree.height(),
"Inconsistent partial tree height"
);
let proof = self.gen_proof_with_partial_tree(i, levels, &partial_tree)?;
debug!(
"generated partial_tree of height {} and len {} with {} branches for proof at {}",
partial_tree.height,
partial_tree.len(),
branches,
i
);
Ok((proof, partial_tree))
}
pub fn gen_proof_with_partial_tree(
&self,
i: usize,
levels: usize,
partial_tree: &MerkleTree<T, A, VecStore<T>, U>,
) -> Result<Proof<T, U>> {
ensure!(
i < self.leafs,
"{} is out of bounds (max: {})",
i,
self.leafs
);
let mut width = self.leafs;
let branches = U::to_usize();
ensure!(width == next_pow2(width), "Must be a power of 2 tree");
ensure!(
branches == next_pow2(branches),
"branches must be a power of 2"
);
let data_width = width;
let total_size = get_merkle_tree_len(data_width, branches);
let cache_size = get_merkle_tree_cache_size(self.leafs, branches, levels);
let cache_index_start = total_size - cache_size;
let cached_leafs = get_merkle_tree_leafs(cache_size, branches);
ensure!(
cached_leafs == next_pow2(cached_leafs),
"Cached leafs size must be a power of 2"
);
let mut segment_width = width / cached_leafs;
let segment_start = (i / segment_width) * segment_width;
let shift = log2_pow2(branches);
let mut segment_shift = segment_start;
let mut j = i;
let mut base = 0;
let mut partial_base = 0;
let mut lemma: Vec<T> =
Vec::with_capacity(get_merkle_proof_lemma_len(self.height, branches));
let mut path: Vec<usize> = Vec::with_capacity(self.height - 1);
lemma.push(self.read_at(j)?);
while base + 1 < self.len() {
let hash_index = (j / branches) * branches;
for k in hash_index..hash_index + branches {
if k != j {
let read_index = base + k;
lemma.push(
if read_index < data_width || read_index >= cache_index_start {
self.read_at(base + k)?
} else {
let read_index = partial_base + k - segment_shift;
partial_tree.read_at(read_index)?
},
);
}
}
path.push(j % branches);
base += width;
width >>= shift;
partial_base += segment_width;
segment_width >>= shift;
segment_shift >>= shift;
j >>= shift; }
lemma.push(self.root());
ensure!(
lemma.len() == get_merkle_proof_lemma_len(self.height, branches),
"Invalid proof lemma length"
);
ensure!(path.len() == self.height - 1, "Invalid proof path length");
Proof::new(lemma, path)
}
#[inline]
pub fn root(&self) -> T {
self.root.clone()
}
#[inline]
pub fn len(&self) -> usize {
self.data.len()
}
#[inline]
pub fn compact(&mut self, config: StoreConfig, store_version: u32) -> Result<bool> {
let branches = U::to_usize();
self.data.compact(branches, config, store_version)
}
#[inline]
pub fn reinit(&mut self) -> Result<()> {
self.data.reinit()
}
#[inline]
pub fn delete(&self, config: StoreConfig) -> Result<()> {
K::delete(config)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[inline]
pub fn height(&self) -> usize {
self.height
}
#[inline]
pub fn leafs(&self) -> usize {
self.leafs
}
#[inline]
pub fn data(&self) -> &K {
&self.data
}
#[inline]
pub fn data_mut(&mut self) -> &mut K {
&mut self.data
}
#[inline]
pub fn read_at(&self, i: usize) -> Result<T> {
self.data.read_at(i)
}
pub fn read_range(&self, start: usize, end: usize) -> Result<Vec<T>> {
ensure!(start < end, "start must be less than end");
self.data.read_range(start..end)
}
pub fn read_range_into(&self, start: usize, end: usize, buf: &mut [u8]) -> Result<()> {
ensure!(start < end, "start must be less than end");
self.data.read_range_into(start, end, buf)
}
pub fn read_into(&self, pos: usize, buf: &mut [u8]) -> Result<()> {
self.data.read_into(pos, buf)
}
pub fn from_byte_slice_with_config(leafs: &[u8], config: StoreConfig) -> Result<Self> {
ensure!(
leafs.len() % T::byte_len() == 0,
"{} ist not a multiple of {}",
leafs.len(),
T::byte_len()
);
let leafs_count = leafs.len() / T::byte_len();
let branches = U::to_usize();
ensure!(leafs_count > 1, "not enough leaves");
ensure!(
next_pow2(leafs_count) == leafs_count,
"size MUST be a power of 2"
);
ensure!(
next_pow2(branches) == branches,
"branches MUST be a power of 2"
);
let size = get_merkle_tree_len(leafs_count, branches);
let height = get_merkle_tree_height(leafs_count, branches);
let mut data = K::new_from_slice_with_config(size, branches, leafs, config.clone())
.context("failed to create data store")?;
let root = K::build::<A, U>(&mut data, leafs_count, height, Some(config))?;
Ok(MerkleTree {
data,
leafs: leafs_count,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
pub fn from_byte_slice(leafs: &[u8]) -> Result<Self> {
ensure!(
leafs.len() % T::byte_len() == 0,
"{} is not a multiple of {}",
leafs.len(),
T::byte_len()
);
let leafs_count = leafs.len() / T::byte_len();
let branches = U::to_usize();
ensure!(leafs_count > 1, "not enough leaves");
ensure!(
next_pow2(leafs_count) == leafs_count,
"size MUST be a power of 2"
);
ensure!(
next_pow2(branches) == branches,
"branches MUST be a power of 2"
);
let size = get_merkle_tree_len(leafs_count, branches);
let height = get_merkle_tree_height(leafs_count, branches);
let mut data = K::new_from_slice(size, leafs).context("failed to create data store")?;
let root = K::build::<A, U>(&mut data, leafs_count, height, None)?;
Ok(MerkleTree {
data,
leafs: leafs_count,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
}
pub trait FromIndexedParallelIterator<T, U>: Sized
where
T: Send,
{
fn from_par_iter<I>(par_iter: I) -> Result<Self>
where
U: Unsigned,
I: IntoParallelIterator<Item = T>,
I::Iter: IndexedParallelIterator;
fn from_par_iter_with_config<I>(par_iter: I, config: StoreConfig) -> Result<Self>
where
I: IntoParallelIterator<Item = T>,
I::Iter: IndexedParallelIterator,
U: Unsigned;
}
impl<T: Element, A: Algorithm<T>, K: Store<T>, U: Unsigned> FromIndexedParallelIterator<T, U>
for MerkleTree<T, A, K, U>
{
fn from_par_iter<I>(into: I) -> Result<Self>
where
I: IntoParallelIterator<Item = T>,
I::Iter: IndexedParallelIterator,
{
let iter = into.into_par_iter();
let leafs = iter.opt_len().expect("must be sized");
let branches = U::to_usize();
ensure!(leafs > 1, "not enough leaves");
ensure!(next_pow2(leafs) == leafs, "size MUST be a power of 2");
ensure!(
next_pow2(branches) == branches,
"branches MUST be a power of 2"
);
let size = get_merkle_tree_len(leafs, branches);
let height = get_merkle_tree_height(leafs, branches);
let mut data = K::new(size).expect("failed to create data store");
populate_data_par::<T, A, K, U, _>(&mut data, iter)?;
let root = K::build::<A, U>(&mut data, leafs, height, None)?;
Ok(MerkleTree {
data,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
fn from_par_iter_with_config<I>(into: I, config: StoreConfig) -> Result<Self>
where
U: Unsigned,
I: IntoParallelIterator<Item = T>,
I::Iter: IndexedParallelIterator,
{
let iter = into.into_par_iter();
let leafs = iter.opt_len().expect("must be sized");
let branches = U::to_usize();
ensure!(leafs > 1, "not enough leaves");
ensure!(next_pow2(leafs) == leafs, "size MUST be a power of 2");
ensure!(
next_pow2(branches) == branches,
"branches MUST be a power of 2"
);
let size = get_merkle_tree_len(leafs, branches);
let height = get_merkle_tree_height(leafs, branches);
let mut data = K::new_with_config(size, branches, config.clone())
.context("failed to create data store")?;
if data.loaded_from_disk() {
let root = data.last().context("failed to read root")?;
return Ok(MerkleTree {
data,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
});
}
populate_data_par::<T, A, K, U, _>(&mut data, iter)?;
let root = K::build::<A, U>(&mut data, leafs, height, Some(config))?;
Ok(MerkleTree {
data,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
}
impl<T: Element, A: Algorithm<T>, K: Store<T>, U: Unsigned> MerkleTree<T, A, K, U> {
pub fn try_from_iter<I: IntoIterator<Item = Result<T>>>(into: I) -> Result<Self> {
let iter = into.into_iter();
let (_, n) = iter.size_hint();
let leafs = n.ok_or_else(|| anyhow!("could not get size hint from iterator"))?;
let branches = U::to_usize();
ensure!(leafs > 1, "not enough leaves");
ensure!(next_pow2(leafs) == leafs, "size MUST be a power of 2");
ensure!(
next_pow2(branches) == branches,
"branches MUST be a power of 2"
);
let size = get_merkle_tree_len(leafs, branches);
let height = get_merkle_tree_height(leafs, branches);
let mut data = K::new(size).context("failed to create data store")?;
populate_data::<T, A, K, U, I>(&mut data, iter).context("failed to populate data")?;
let root = K::build::<A, U>(&mut data, leafs, height, None)?;
Ok(MerkleTree {
data,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
pub fn try_from_iter_with_config<I: IntoIterator<Item = Result<T>>>(
into: I,
config: StoreConfig,
) -> Result<Self> {
let iter = into.into_iter();
let (_, n) = iter.size_hint();
let leafs = n.ok_or_else(|| anyhow!("could not get size hint from iterator"))?;
let branches = U::to_usize();
ensure!(leafs > 1, "not enough leaves");
ensure!(next_pow2(leafs) == leafs, "size MUST be a power of 2");
ensure!(
next_pow2(branches) == branches,
"branches MUST be a power of 2"
);
let size = get_merkle_tree_len(leafs, branches);
let height = get_merkle_tree_height(leafs, branches);
let mut data = K::new_with_config(size, branches, config.clone())
.context("failed to create data store")?;
if data.loaded_from_disk() {
let root = data.last().context("failed to read root")?;
return Ok(MerkleTree {
data,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
});
}
populate_data::<T, A, K, U, I>(&mut data, iter).expect("failed to populate data");
let root = K::build::<A, U>(&mut data, leafs, height, Some(config))?;
Ok(MerkleTree {
data,
leafs,
height,
root,
_u: PhantomData,
_a: PhantomData,
_t: PhantomData,
})
}
}
impl Element for [u8; 32] {
fn byte_len() -> usize {
32
}
fn from_slice(bytes: &[u8]) -> Self {
if bytes.len() != 32 {
panic!("invalid length {}, expected 32", bytes.len());
}
*array_ref!(bytes, 0, 32)
}
fn copy_to_slice(&self, bytes: &mut [u8]) {
bytes.copy_from_slice(self);
}
}
pub fn get_merkle_tree_len(leafs: usize, branches: usize) -> usize {
if branches == 2 {
assert!(leafs == next_pow2(leafs));
return 2 * leafs - 1;
}
let mut len = leafs;
let mut cur = leafs;
let shift = log2_pow2(branches);
while cur > 0 {
cur >>= shift; assert!(cur < leafs);
len += cur;
}
len
}
pub fn get_merkle_tree_cache_size(leafs: usize, branches: usize, levels: usize) -> usize {
let shift = log2_pow2(branches);
let len = get_merkle_tree_len(leafs, branches);
let mut height = get_merkle_tree_height(leafs, branches);
let stop_height = height - levels;
let mut cache_size = len;
let mut cur_leafs = leafs;
while height > stop_height {
cache_size -= cur_leafs;
cur_leafs >>= shift; height -= 1;
}
cache_size
}
pub fn is_merkle_tree_size_valid(leafs: usize, branches: usize) -> bool {
let mut cur = leafs;
let shift = log2_pow2(branches);
while cur != 1 {
cur >>= shift; assert!(cur < leafs);
if cur == 0 {
return false;
}
}
true
}
pub fn get_merkle_tree_height(leafs: usize, branches: usize) -> usize {
if branches == 2 {
(leafs * branches).trailing_zeros() as usize
} else {
(branches as f64 * leafs as f64).log(branches as f64) as usize
}
}
pub fn get_merkle_proof_lemma_len(height: usize, branches: usize) -> usize {
2 + ((branches - 1) * (height - 1))
}
pub fn get_merkle_tree_leafs(len: usize, branches: usize) -> usize {
if branches == 2 {
return (len >> 1) + 1;
}
let mut leafs = 1;
let mut cur = len;
let shift = log2_pow2(branches);
while cur != 1 {
leafs <<= shift; cur -= leafs;
assert!(cur < len);
}
leafs
}
pub fn next_pow2(n: usize) -> usize {
n.next_power_of_two()
}
pub fn log2_pow2(n: usize) -> usize {
n.trailing_zeros() as usize
}
pub fn populate_data<
T: Element,
A: Algorithm<T>,
K: Store<T>,
U: Unsigned,
I: IntoIterator<Item = Result<T>>,
>(
data: &mut K,
iter: <I as std::iter::IntoIterator>::IntoIter,
) -> Result<()> {
if !data.is_empty() {
return Ok(());
}
let mut buf = Vec::with_capacity(BUILD_DATA_BLOCK_SIZE * T::byte_len());
let mut a = A::default();
for item in iter {
let item = item?;
a.reset();
buf.extend(a.leaf(item).as_ref());
if buf.len() >= BUILD_DATA_BLOCK_SIZE * T::byte_len() {
let data_len = data.len();
data.copy_from_slice(&buf, data_len)?;
buf.clear();
}
}
let data_len = data.len();
data.copy_from_slice(&buf, data_len)?;
data.sync()?;
Ok(())
}
fn populate_data_par<T, A, K, U, I>(data: &mut K, iter: I) -> Result<()>
where
T: Element,
A: Algorithm<T>,
K: Store<T>,
U: Unsigned,
I: ParallelIterator<Item = T> + IndexedParallelIterator,
{
if !data.is_empty() {
return Ok(());
}
let store = Arc::new(RwLock::new(data));
iter.chunks(BUILD_DATA_BLOCK_SIZE)
.enumerate()
.try_for_each(|(index, chunk)| {
let mut a = A::default();
let mut buf = Vec::with_capacity(BUILD_DATA_BLOCK_SIZE * T::byte_len());
for item in chunk {
a.reset();
buf.extend(a.leaf(item).as_ref());
}
store
.write()
.unwrap()
.copy_from_slice(&buf[..], BUILD_DATA_BLOCK_SIZE * index)
})?;
store.write().unwrap().sync()?;
Ok(())
}