pub use polydigest::*;
pub use polydigest::{LogError as Error, LogResult as Result};
pub mod error {
pub use polydigest::{LogError as Error, LogResult as Result};
}
pub const LOG_ARITY: u64 = 2;
#[must_use]
pub fn config() -> TreeConfig {
TreeConfig { arity: LOG_ARITY }
}
pub async fn new<S: Storage>(
storage: S,
hasher: Box<dyn Hasher>,
) -> Result<NaryMerkleLog<S>, S::Error> {
NaryMerkleLog::new(storage, hasher, config()).await
}
pub async fn from_storage<S: Storage>(
storage: S,
hashers: Vec<(u64, Box<dyn Hasher>)>,
) -> Result<NaryMerkleLog<S>, S::Error> {
NaryMerkleLog::from_storage_with_config(storage, hashers, config()).await
}
#[cfg(test)]
mod tests {
use polydigest::MemoryStorage;
use sha2::{Digest, Sha256};
use super::*;
#[derive(Debug)]
struct Sha256Hasher;
impl Hasher for Sha256Hasher {
fn leaf(&self, data: &[u8]) -> Vec<u8> {
Sha256::digest(data).to_vec()
}
fn node(&self, children: &[&[u8]]) -> Vec<u8> {
let mut h = Sha256::new();
for child in children {
h.update(child);
}
h.finalize().to_vec()
}
fn empty(&self) -> Vec<u8> {
Sha256::digest(b"").to_vec()
}
fn hash(&self, data: &[u8]) -> Vec<u8> {
Sha256::digest(data).to_vec()
}
fn clone_box(&self) -> Box<dyn Hasher> {
Box::new(Sha256Hasher)
}
}
#[test]
fn preset_is_binary() {
assert_eq!(config().arity, 2);
}
#[test]
fn new_builds_binary_log() {
smol::block_on(async {
let mut log = new(MemoryStorage::new(), Box::new(Sha256Hasher))
.await
.unwrap();
assert_eq!(log.config().arity, 2);
log.append_leaf(b"a").await.unwrap();
log.append_leaf(b"b").await.unwrap();
assert_eq!(log.size(), 2);
let root = log.root();
let expected = Sha256Hasher.node(&[
Sha256Hasher.leaf(b"a").as_slice(),
Sha256Hasher.leaf(b"b").as_slice(),
]);
assert_eq!(root, expected);
});
}
}