//! Shared setup for the proof generation and verification benchmarks. use commonware_cryptography::{Sha256, sha256}; use commonware_math::algebra::Random as _; use commonware_storage::merkle::{ self, Bagging::ForwardFold, Family, Location, LocationRangeExt as _, mem::Mem, }; use commonware_utils::test_rng; use futures::executor::block_on; use rand::{RngExt as _, seq::IndexedRandom}; use std::ops::Range; pub type StandardHasher = merkle::hasher::Standard; /// Number of leaves or ranges sampled from each tree. pub const SAMPLE_SIZE: usize = 100; #[cfg(not(full_bench))] pub const N_LEAVES: [usize; 2] = [10_000, 100_000]; #[cfg(full_bench)] pub const N_LEAVES: [usize; 5] = [10_000, 100_000, 1_000_000, 5_000_000, 10_000_000]; /// A proven leaf and its location. pub type SingleSample = (Location, sha256::Digest); /// A proven range of leaves and their elements. pub type RangeSample = (Range>, Vec); /// Builds an in-memory tree of `n` random elements and returns it with its root /// and the elements in location order. fn build(n: usize) -> (Mem, sha256::Digest, Vec) { let hasher = StandardHasher::::new(ForwardFold); let mut mem = Mem::::new(); let mut elements = Vec::with_capacity(n); let mut sampler = test_rng(); block_on(async { let batch = { let mut batch = mem.new_batch(); for _ in 0..n { let element = sha256::Digest::random(&mut sampler); batch = batch.add(&hasher, &element); elements.push(element); } batch.merkleize(&mem, &hasher) }; mem.apply_batch(&batch).unwrap(); }); let root = mem.root(&hasher, 0).unwrap(); (mem, root, elements) } /// Builds a tree of `n` elements and samples `SAMPLE_SIZE` distinct leaves to prove. pub fn single_samples( n: usize, ) -> (Mem, sha256::Digest, Vec>) { let (mem, root, elements) = build::(n); let mut sampler = test_rng(); let samples = elements .iter() .enumerate() .collect::>() .sample(&mut sampler, SAMPLE_SIZE) .map(|&(loc, element)| (Location::::new(loc as u64), *element)) .collect(); (mem, root, samples) } /// Like `single_samples`, with the leaves sorted by location. pub fn multi_samples( n: usize, ) -> (Mem, sha256::Digest, Vec>) { let (mem, root, mut samples) = single_samples::(n); samples.sort_unstable_by_key(|(loc, _)| *loc); (mem, root, samples) } /// Builds a tree of `n` elements and samples `SAMPLE_SIZE` ranges of `range` /// leaves with distinct starts to prove. pub fn range_samples( n: usize, range: u64, ) -> (Mem, sha256::Digest, Vec>) { let (mem, root, elements) = build::(n); let mut sampler = test_rng(); let max_start = n as u64 - range; let mut samples: Vec> = Vec::with_capacity(SAMPLE_SIZE); while samples.len() < SAMPLE_SIZE { let start_index = sampler.random_range(0..max_start); let leaf_range = Location::::new(start_index)..Location::::new(start_index + range); if samples .iter() .any(|(range, _)| range.start == leaf_range.start) { continue; } let expected = elements[leaf_range.to_usize_range()].to_vec(); samples.push((leaf_range, expected)); } (mem, root, samples) }