arnaucube
arnaucube/miden-cryptoPublic Self-hosted repository
miden-crypto/src/main.rs
src/main.rsRaw
  1use std::time::Instant;
  2
  3use clap::Parser;
  4use miden_crypto::{
  5    hash::rpo::{Rpo256, RpoDigest},
  6    merkle::{MerkleError, Smt},
  7    Felt, Word, ONE,
  8};
  9use rand_utils::rand_value;
 10
 11#[derive(Parser, Debug)]
 12#[clap(name = "Benchmark", about = "SMT benchmark", version, rename_all = "kebab-case")]
 13pub struct BenchmarkCmd {
 14    /// Size of the tree
 15    #[clap(short = 's', long = "size")]
 16    size: u64,
 17}
 18
 19fn main() {
 20    benchmark_smt();
 21}
 22
 23/// Run a benchmark for [`Smt`].
 24pub fn benchmark_smt() {
 25    let args = BenchmarkCmd::parse();
 26    let tree_size = args.size;
 27
 28    // prepare the `leaves` vector for tree creation
 29    let mut entries = Vec::new();
 30    for i in 0..tree_size {
 31        let key = rand_value::<RpoDigest>();
 32        let value = [ONE, ONE, ONE, Felt::new(i)];
 33        entries.push((key, value));
 34    }
 35
 36    let mut tree = construction(entries, tree_size).unwrap();
 37    insertion(&mut tree, tree_size).unwrap();
 38    proof_generation(&mut tree, tree_size).unwrap();
 39}
 40
 41/// Runs the construction benchmark for [`Smt`], returning the constructed tree.
 42pub fn construction(entries: Vec<(RpoDigest, Word)>, size: u64) -> Result<Smt, MerkleError> {
 43    println!("Running a construction benchmark:");
 44    let now = Instant::now();
 45    let tree = Smt::with_entries(entries)?;
 46    let elapsed = now.elapsed();
 47    println!(
 48        "Constructed a SMT with {} key-value pairs in {:.3} seconds",
 49        size,
 50        elapsed.as_secs_f32(),
 51    );
 52
 53    println!("Number of leaf nodes: {}\n", tree.leaves().count());
 54
 55    Ok(tree)
 56}
 57
 58/// Runs the insertion benchmark for the [`Smt`].
 59pub fn insertion(tree: &mut Smt, size: u64) -> Result<(), MerkleError> {
 60    println!("Running an insertion benchmark:");
 61
 62    let mut insertion_times = Vec::new();
 63
 64    for i in 0..20 {
 65        let test_key = Rpo256::hash(&rand_value::<u64>().to_be_bytes());
 66        let test_value = [ONE, ONE, ONE, Felt::new(size + i)];
 67
 68        let now = Instant::now();
 69        tree.insert(test_key, test_value);
 70        let elapsed = now.elapsed();
 71        insertion_times.push(elapsed.as_secs_f32());
 72    }
 73
 74    println!(
 75        "An average insertion time measured by 20 inserts into a SMT with {} key-value pairs is {:.3} milliseconds\n",
 76        size,
 77        // calculate the average by dividing by 20 and convert to milliseconds by multiplying by
 78        // 1000. As a result, we can only multiply by 50
 79        insertion_times.iter().sum::<f32>() * 50f32,
 80    );
 81
 82    Ok(())
 83}
 84
 85/// Runs the proof generation benchmark for the [`Smt`].
 86pub fn proof_generation(tree: &mut Smt, size: u64) -> Result<(), MerkleError> {
 87    println!("Running a proof generation benchmark:");
 88
 89    let mut insertion_times = Vec::new();
 90
 91    for i in 0..20 {
 92        let test_key = Rpo256::hash(&rand_value::<u64>().to_be_bytes());
 93        let test_value = [ONE, ONE, ONE, Felt::new(size + i)];
 94        tree.insert(test_key, test_value);
 95
 96        let now = Instant::now();
 97        let _proof = tree.open(&test_key);
 98        let elapsed = now.elapsed();
 99        insertion_times.push(elapsed.as_secs_f32());
100    }
101
102    println!(
103        "An average proving time measured by 20 value proofs in a SMT with {} key-value pairs in {:.3} microseconds",
104        size,
105        // calculate the average by dividing by 20 and convert to microseconds by multiplying by
106        // 1000000. As a result, we can only multiply by 50000
107        insertion_times.iter().sum::<f32>() * 50000f32,
108    );
109
110    Ok(())
111}