use cmt::{Cmt, Config, Hasher, ProofStep};
pub use cmt::{Config as CmtConfig, Error as CmtError, Result as CmtResult};
use spine::Seal;
use crate::Sealed;
use crate::root::combined_root;
const OPEN_EPOCH: (u64, u64) = (0, u64::MAX);
#[derive(Debug)]
pub struct EpochTree {
inner: Cmt,
}
impl EpochTree {
pub fn new(config: Config) -> cmt::Result<Self> {
Ok(Self {
inner: Cmt::new(config)?,
})
}
pub fn register_algorithm(&mut self, alg_id: u64, hasher: Box<dyn Hasher>) -> cmt::Result<()> {
self.inner.register_algorithm(alg_id, hasher)
}
pub fn add_algorithm_at(
&mut self,
alg_id: u64,
index: u64,
hasher: Box<dyn Hasher>,
) -> cmt::Result<usize> {
self.inner.add_algorithm_at(alg_id, index, hasher)
}
pub fn set(&mut self, index: u64, payload: Vec<u8>, metadata: Vec<u8>) -> cmt::Result<()> {
self.inner.set(index, payload, metadata)
}
#[must_use]
pub fn get(&self, index: u64) -> Option<&[u8]> {
self.inner.get(index)
}
#[must_use]
pub fn metadata(&self, index: u64) -> Option<&[u8]> {
self.inner.metadata(index)
}
#[must_use]
pub fn len(&self) -> u64 {
self.inner.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
#[must_use]
pub fn arity(&self) -> u64 {
self.inner.arity()
}
#[must_use]
pub fn root(&self, alg_id: u64) -> Option<Vec<u8>> {
self.inner.root(alg_id)
}
#[must_use]
pub fn combined_root(&self, alg_id: u64) -> Option<Vec<u8>> {
let hasher = self.inner.hasher(alg_id)?;
self.inner.root(alg_id)?;
let member_roots = self.inner.member_roots();
let alg_epochs: Vec<(u64, Vec<(u64, u64)>)> = member_roots
.iter()
.map(|&(id, _)| (id, vec![OPEN_EPOCH]))
.collect();
Some(combined_root(
hasher,
&member_roots,
&alg_epochs,
self.len(),
self.arity(),
))
}
#[must_use]
pub fn inclusion_proof(&self, alg_id: u64, index: u64) -> Option<(Vec<u8>, Vec<ProofStep>)> {
self.inner.inclusion_proof(alg_id, index)
}
#[must_use]
pub fn leaf_proof(&self, alg_id: u64, index: u64) -> Option<spine::LeafProof> {
self.inner.leaf_proof(alg_id, index)
}
#[must_use]
pub fn non_membership_proof(
&self,
alg_id: u64,
index: u64,
) -> Option<(Vec<u8>, Vec<ProofStep>)> {
self.inner.non_membership_proof(alg_id, index)
}
pub fn seal(self) -> cmt::Result<Sealed> {
let seal: Seal = self.inner.seal()?;
let alg_epochs: Vec<(u64, Vec<(u64, u64)>)> = seal
.frontiers()
.iter()
.map(|(id, _)| (*id, vec![OPEN_EPOCH]))
.collect();
Sealed::new(
seal.tree_size(),
seal.arity(),
seal.frontiers().to_vec(),
alg_epochs,
)
.map_err(|_| cmt::Error::MalformedSeal)
}
}