diff --git a/hash/risc0/bench/bench.cfg b/hash/risc0/bench/bench.cfg index d5adade..5e47ea2 100644 --- a/hash/risc0/bench/bench.cfg +++ b/hash/risc0/bench/bench.cfg @@ -6,7 +6,7 @@ params: , INPUT_SIZE: [ 256, 512, 1024, 2048 ] , WHICH: [ LINEAR ] ] -tags: CPU, SHA256, KECCAK, BLAKE2B, BLAKE3 +tags: CPU, SHA256, KECCAK, BLAKE2B, BLAKE3, POSEIDON2, BN128, BABYBEAR comments: - The benchmarks includes for sha256, keccak, blake2b, blake3. + The benchmarks includes for sha256, keccak, blake2b, blake3 & poseidon2(merkle hashing). the hashing is done inside the guest and receipt is received which is verified. diff --git a/hash/risc0/bench/methods/guest/src/bin/poseidon2_babybear.rs b/hash/risc0/bench/methods/guest/src/bin/poseidon2_babybear.rs index 141814f..a00e7ad 100644 --- a/hash/risc0/bench/methods/guest/src/bin/poseidon2_babybear.rs +++ b/hash/risc0/bench/methods/guest/src/bin/poseidon2_babybear.rs @@ -1,587 +1,97 @@ #![no_main] #![allow(non_snake_case)] -use ark_ff::Field; -use risc0_zkvm::{guest::env/* , sha::Digest*/}; -// use sha3::{Digest as _, Keccak256}; +use risc0_zkvm::guest::env; use zkhash::poseidon2::poseidon2; use zkhash::poseidon2::poseidon2::Poseidon2; use zkhash::poseidon2::poseidon2_instance_babybear::{/*POSEIDON2_BABYBEAR_16_PARAMS , */POSEIDON2_BABYBEAR_24_PARAMS}; use zkhash::fields::babybear::FpBabyBear; use ark_serialize::{CanonicalSerialize, CanonicalDeserialize}; -// use zkhash::merkle_tree::merkle_tree_fp::MerkleTreeHash; -use risc0_core::field::Elem; - -use std::sync::Arc; use std::marker::PhantomData; -use risc0_core::field::baby_bear::BabyBear; -use lazy_static::lazy_static; -// #[derive(Clone, Debug)] -// pub struct Poseidon2Params { -// pub(crate) t: usize, // statesize -// pub(crate) d: usize, // sbox degree -// pub(crate) rounds_f_beginning: usize, -// pub(crate) rounds_p: usize, -// #[allow(dead_code)] -// pub(crate) rounds_f_end: usize, -// pub(crate) rounds: usize, -// pub(crate) mat_internal_diag_m_1: Vec, -// pub(crate) _mat_internal: Vec>, -// pub(crate) round_constants: Vec>, -// } +use ark_ff::PrimeField; -// pub fn mat_inverse(mat: &[Vec]) -> Vec> { -// let n = mat.len(); -// assert!(mat[0].len() == n); - -// let mut m = mat.to_owned(); -// let mut inv = vec![vec![F::ZERO; n]; n]; -// for (i, invi) in inv.iter_mut().enumerate() { -// invi[i] = F::ONE; -// } - -// // upper triangle -// for row in 0..n { -// for j in 0..row { -// // subtract from these rows -// let el = m[row][j]; -// for col in 0..n { -// // do subtraction for each col -// if col < j { -// m[row][col] = F::ZERO; -// } else { -// let mut tmp = m[j][col]; -// tmp.mul_assign(el); -// m[row][col].sub_assign(tmp); -// } -// if col > row { -// inv[row][col] = F::ZERO; -// } else { -// let mut tmp = inv[j][col]; -// tmp.mul_assign(el); -// inv[row][col].sub_assign(tmp); -// } -// } -// } -// // make 1 in diag -// let el_inv = m[row][row].inv(); -// for col in 0..n { -// match col.cmp(&row) { -// std::cmp::Ordering::Less => inv[row][col].mul_assign(el_inv), -// std::cmp::Ordering::Equal => { -// m[row][col] = F::ONE; -// inv[row][col].mul_assign(el_inv) -// } -// std::cmp::Ordering::Greater => m[row][col].mul_assign(el_inv), -// } -// } -// } - -// // upper triangle -// for row in (0..n).rev() { -// for j in (row + 1..n).rev() { -// // subtract from these rows -// let el = m[row][j]; -// for col in 0..n { -// // do subtraction for each col - -// #[cfg(debug_assertions)] -// { -// if col >= j { -// m[row][col] = F::ZERO; -// } -// } -// let mut tmp = inv[j][col]; -// tmp.mul_assign(el); -// inv[row][col].sub_assign(tmp); -// } -// } -// } - -// #[cfg(debug_assertions)] -// { -// for (row, mrow) in m.iter().enumerate() { -// for (col, v) in mrow.iter().enumerate() { -// if row == col { -// debug_assert!(*v == F::ONE); -// } else { -// debug_assert!(*v == F::ZERO); -// } -// } -// } -// } - -// inv -// } - -// impl Poseidon2Params { -// #[allow(clippy::too_many_arguments)] - -// pub const INIT_SHAKE: &'static str = "Poseidon2"; - -// pub fn new( -// t: usize, -// d: usize, -// rounds_f: usize, -// rounds_p: usize, -// mat_internal_diag_m_1: &[F], -// mat_internal: &[Vec], -// round_constants: &[Vec], -// ) -> Self { -// assert!(d == 3 || d == 5 || d == 7 || d == 11); -// assert_eq!(rounds_f % 2, 0); -// let r = rounds_f / 2; -// let rounds = rounds_f + rounds_p; - -// Poseidon2Params { -// t, -// d, -// rounds_f_beginning: r, -// rounds_p, -// rounds_f_end: r, -// rounds, -// mat_internal_diag_m_1: mat_internal_diag_m_1.to_owned(), -// _mat_internal: mat_internal.to_owned(), -// round_constants: round_constants.to_owned(), -// } -// } - - -// // Unused -// pub fn equivalent_round_constants( -// round_constants: &[Vec], -// mat_internal: &[Vec], -// rounds_f_beginning: usize, -// rounds_p: usize, -// ) -> Vec> { -// let mut opt = vec![Vec::new(); rounds_p + 1]; -// let mat_internal_inv = mat_inverse(mat_internal); - -// let p_end = rounds_f_beginning + rounds_p - 1; -// let mut tmp = round_constants[p_end].clone(); -// for i in (0..rounds_p - 1).rev() { -// let inv_cip = Self::mat_vec_mul(&mat_internal_inv, &tmp); -// opt[i + 1] = vec![inv_cip[0]]; -// tmp = round_constants[rounds_f_beginning + i].clone(); -// for i in 1..inv_cip.len() { -// tmp[i].add_assign(inv_cip[i]); -// } -// } -// opt[0] = tmp; -// opt[rounds_p] = vec![F::ZERO; opt[0].len()]; // opt[0].len() = t - -// opt -// } - -// pub fn mat_vec_mul(mat: &[Vec], input: &[F]) -> Vec { -// let t = mat.len(); -// debug_assert!(t == input.len()); -// let mut out = vec![F::ZERO; t]; -// for row in 0..t { -// for (col, inp) in input.iter().enumerate() { -// let mut tmp = mat[row][col]; -// tmp.mul_assign(*inp); -// out[row].add_assign(tmp); -// } -// } -// out -// } - -// } - -// #[derive(Clone, Debug)] -// pub struct Poseidon2 { -// pub(crate) params: Arc>, -// } - -// impl Poseidon2 { -// pub fn new(params: &Arc>) -> Self { -// Poseidon2 { -// params: Arc::clone(params), -// } -// } - -// pub fn get_t(&self) -> usize { -// self.params.t -// } - -// pub fn permutation(&self, input: &[F]) -> Vec { -// let t = self.params.t; -// assert_eq!(input.len(), t); - -// let mut current_state = input.to_owned(); - -// // Linear layer at beginning -// self.matmul_external(&mut current_state); - -// for r in 0..self.params.rounds_f_beginning { -// current_state = self.add_rc(¤t_state, &self.params.round_constants[r]); -// current_state = self.sbox(¤t_state); -// self.matmul_external(&mut current_state); -// } - -// let p_end = self.params.rounds_f_beginning + self.params.rounds_p; -// for r in self.params.rounds_f_beginning..p_end { -// current_state[0].add_assign(self.params.round_constants[r][0]); -// current_state[0] = self.sbox_p(¤t_state[0]); -// self.matmul_internal(&mut current_state, &self.params.mat_internal_diag_m_1); -// } - -// for r in p_end..self.params.rounds { -// current_state = self.add_rc(¤t_state, &self.params.round_constants[r]); -// current_state = self.sbox(¤t_state); -// self.matmul_external(&mut current_state); -// } -// current_state -// } - -// fn sbox(&self, input: &[F]) -> Vec { -// input.iter().map(|el| self.sbox_p(el)).collect() -// } - -// fn sbox_p(&self, input: &F) -> F { -// let mut input2 = *input; -// input2.mul_assign(input2); - -// match self.params.d { -// 3 => { -// let mut out = input2; -// out.mul_assign(*input); -// out -// } -// 5 => { -// let mut out = input2; -// out.mul_assign(out); -// out.mul_assign(*input); -// out -// } -// 7 => { -// let mut out = input2; -// out.mul_assign(out); -// out.mul_assign(input2); -// out.mul_assign(*input); -// out -// } -// _ => { -// panic!() -// } -// } -// } - -// fn matmul_m4(&self, input: &mut[F]) { -// let t = self.params.t; -// let t4 = t / 4; -// for i in 0..t4 { -// let start_index = i * 4; -// let mut t_0 = input[start_index]; -// t_0.add_assign(input[start_index + 1]); -// let mut t_1 = input[start_index + 2]; -// t_1.add_assign(input[start_index + 3]); -// let mut t_2 = input[start_index + 1]; -// t_2.add_assign(t_2); -// t_2.add_assign(t_1); -// let mut t_3 = input[start_index + 3]; -// t_3.add_assign(t_3); -// t_3.add_assign(t_0); -// let mut t_4 = t_1; -// t_4.add_assign(t_4); -// t_4.add_assign(t_4); -// t_4.add_assign(t_3); -// let mut t_5 = t_0; -// t_5.add_assign(t_5); -// t_5.add_assign(t_5); -// t_5.add_assign(t_2); -// let mut t_6 = t_3; -// t_6.add_assign(t_5); -// let mut t_7 = t_2; -// t_7.add_assign(t_4); -// input[start_index] = t_6; -// input[start_index + 1] = t_5; -// input[start_index + 2] = t_7; -// input[start_index + 3] = t_4; -// } -// } - -// fn matmul_external(&self, input: &mut[F]) { -// let t = self.params.t; -// match t { -// 2 => { -// // Matrix circ(2, 1) -// let mut sum = input[0]; -// sum.add_assign(input[1]); -// input[0].add_assign(sum); -// input[1].add_assign(sum); -// } -// 3 => { -// // Matrix circ(2, 1, 1) -// let mut sum = input[0]; -// sum.add_assign(input[1]); -// sum.add_assign(input[2]); -// input[0].add_assign(sum); -// input[1].add_assign(sum); -// input[2].add_assign(sum); -// } -// 4 => { -// // Applying cheap 4x4 MDS matrix to each 4-element part of the state -// self.matmul_m4(input); -// } -// 8 | 12 | 16 | 20 | 24 => { -// // Applying cheap 4x4 MDS matrix to each 4-element part of the state -// self.matmul_m4(input); - -// // Applying second cheap matrix for t > 4 -// let t4 = t / 4; -// let mut stored = [F::ZERO; 4]; -// for l in 0..4 { -// stored[l] = input[l]; -// for j in 1..t4 { -// stored[l].add_assign(input[4 * j + l]); -// } -// } -// for i in 0..input.len() { -// input[i].add_assign(stored[i % 4]); -// } -// } -// _ => { -// panic!() -// } -// } -// } - -// fn matmul_internal(&self, input: &mut[F], mat_internal_diag_m_1: &[F]) { -// let t = self.params.t; - -// match t { -// 2 => { -// // [2, 1] -// // [1, 3] -// let mut sum = input[0]; -// sum.add_assign(input[1]); -// input[0].add_assign(sum); -// input[1].add_assign(input[1]); -// input[1].add_assign(sum); -// } -// 3 => { -// // [2, 1, 1] -// // [1, 2, 1] -// // [1, 1, 3] -// let mut sum = input[0]; -// sum.add_assign(input[1]); -// sum.add_assign(input[2]); -// input[0].add_assign(sum); -// input[1].add_assign(sum); -// input[2].add_assign(input[2]); -// input[2].add_assign(sum); -// } -// 4 | 8 | 12 | 16 | 20 | 24 => { -// // Compute input sum -// let mut sum = input[0]; -// input -// .iter() -// .skip(1) -// .take(t-1) -// .for_each(|el| sum.add_assign(*el)); -// // Add sum + diag entry * element to each element -// for i in 0..input.len() { -// input[i].mul_assign(mat_internal_diag_m_1[i]); -// input[i].add_assign(sum); -// } -// } -// _ => { -// panic!() -// } -// } -// } - -// fn add_rc(&self, input: &[F], rc: &[F]) -> Vec { -// input -// .iter() -// .zip(rc.iter()) -// .map(|(a, b)| { -// let mut r = *a; -// r.add_assign(*b); -// r -// }) -// .collect() -// } -// } - -// pub trait MerkleTreeHash { -// fn compress(&self, input: &[&F]) -> Vec; -// } - -// #[derive(Clone, Debug)] -// pub struct MerkleTree> { -// perm: P, -// field: PhantomData, -// } - -// impl> MerkleTree { -// pub fn new(perm: P) -> Self { -// MerkleTree { -// perm, -// field: PhantomData, -// } -// } - -// fn round_up_pow_n(input: usize, n: usize) -> usize { -// debug_assert!(n >= 1); -// let mut res = 1; -// // try powers, starting from n -// loop { -// res *= n; -// if res >= input { -// break; -// } -// } -// res -// } - -// // pub fn accumulate(&mut self, set: &[F]) -> F { -// // let set_size = set.len(); -// // let mut bound = Self::round_up_pow_n(set_size, 2); -// // loop { -// // if bound >= 2 { -// // break; -// // } -// // bound *= 2; -// // } -// // let mut nodes: Vec = Vec::with_capacity(bound); -// // for s in set { -// // nodes.push(s.to_owned()); -// // } -// // // pad -// // for _ in nodes.len()..bound { -// // nodes.push(nodes[set_size - 1].to_owned()); -// // } - -// // while nodes.len() > 1 { -// // let new_len = nodes.len() / 2; -// // let mut new_nodes: Vec = Vec::with_capacity(new_len); -// // for i in (0..nodes.len()).step_by(2) { -// // let inp = [&nodes[i], &nodes[i + 1]]; -// // let dig = self.perm.compress(&inp); -// // new_nodes.push(dig); -// // } -// // nodes = new_nodes; -// // } -// // nodes[0].to_owned() -// // } - -// pub fn accumulate(&mut self, set: &[F]) -> Vec { -// let set_size = set.len(); -// let mut bound = Self::round_up_pow_n(set_size, 2); -// loop { -// if bound >= 16 { -// break; -// } -// bound *= 2; -// } - -// let mut nodes: Vec = Vec::with_capacity(bound); - -// // Populate nodes with set elements -// for s in set { -// nodes.push(s.to_owned()); -// } - -// // Pad nodes to reach the required size -// while nodes.len() < bound { -// nodes.push(nodes[set_size - 1].to_owned()); -// } - -// // Compress pairs of 8 elements until a single set of 8 elements is left -// while nodes.len() > 8 { -// let new_len = nodes.len() / 2; -// let mut new_nodes: Vec = Vec::with_capacity(new_len); - -// // Compress pairs of 8 elements at a time -// for i in (0..nodes.len()).step_by(16) { -// let inp: Vec<_> = nodes[i..i + 16].iter().collect(); -// let dig = self.perm.compress(&inp); -// new_nodes.push(dig[0]); -// new_nodes.push(dig[1]); -// new_nodes.push(dig[2]); -// new_nodes.push(dig[3]); -// new_nodes.push(dig[4]); -// new_nodes.push(dig[5]); -// new_nodes.push(dig[6]); -// new_nodes.push(dig[7]); -// } - -// nodes = new_nodes; -// } - -// nodes -// } - -// } - -// impl MerkleTreeHash for Poseidon2 { -// fn compress(&self, input: &[&F]) -> Vec { -// let res = self.permutation(&[ -// input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), -// input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), input[0].to_owned(), -// F::ZERO, F::ZERO, F::ZERO, F::ZERO, F::ZERO, F::ZERO, F::ZERO, F::ZERO]); - -// vec![res[0], res[1], res[2], res[3], res[4], res[5], res[6], res[7] ] -// } -// } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// for POSEIDON2_BABYBEAR_24_PARAMS only -pub fn compress(perm: Poseidon2, input: Vec) -> Vec{ - let p = perm.permutation( - &[ - *input.get(0).unwrap(), *input.get(1).unwrap(), *input.get(2).unwrap(), *input.get(3).unwrap(), *input.get(4).unwrap(), *input.get(5).unwrap(), *input.get(6).unwrap(), *input.get(7).unwrap(), - *input.get(8).unwrap(), *input.get(9).unwrap(), *input.get(10).unwrap(), *input.get(11).unwrap(), *input.get(12).unwrap(), *input.get(13).unwrap(), *input.get(14).unwrap(), *input.get(15).unwrap(), - FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0) - ] - ); - vec![p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7] ] +pub trait MerkleTreeHash { + fn compress(&self, input: &[&F]) -> Vec; } +#[derive(Clone, Debug)] +pub struct MerkleTree> { + perm: P, + field: PhantomData, +} +impl> MerkleTree { + pub fn new(perm: P) -> Self { + MerkleTree { + perm, + field: PhantomData, + } + } + + fn round_up_pow_n(input: usize, n: usize) -> usize { + debug_assert!(n >= 1); + let mut res = 1; + // try powers, starting from n + loop { + res *= n; + if res >= input { + break; + } + } + res + } + + pub fn accumulate(&mut self, set: &[F]) -> Vec { + assert!(set.len()%8 == 0); + let set_size = set.len() / 8; + let mut bound = Self::round_up_pow_n(set_size, 2); + loop { + if bound >= 2 { + break; + } + bound *= 2; + } + let mut nodes: Vec = Vec::with_capacity(bound * 8); + for s in set { + nodes.push(s.to_owned()); + } + // pad + for _ in nodes.len()..bound { + nodes.push(nodes[set_size * 8 - 1].to_owned()); + } + + while nodes.len() > 8 { + let new_len = nodes.len() / 2; + let mut new_nodes: Vec = Vec::with_capacity(new_len); + for i in (0..nodes.len()).step_by(16) { + let inp = [ + &nodes[i], &nodes[i + 1], &nodes[i + 2], &nodes[i + 3], &nodes[i + 4], &nodes[i + 5], &nodes[i + 6], &nodes[i + 7], + &nodes[i + 8], &nodes[i + 9], &nodes[i + 10], &nodes[i + 11], &nodes[i + 12], &nodes[i + 13], &nodes[i + 14], &nodes[i + 15] + ]; + let dig = self.perm.compress(&inp); + + for j in 0..8 { + new_nodes.push(dig[j]); + } + + } + nodes = new_nodes; + } + vec![nodes[0].to_owned(), nodes[1].to_owned(), nodes[2].to_owned(), nodes[3].to_owned(), nodes[4].to_owned(), nodes[5].to_owned(), nodes[6].to_owned(), nodes[7].to_owned()] + } +} + +impl MerkleTreeHash for Poseidon2 { + fn compress(&self, input: &[&F]) -> Vec { + let p = self.permutation(&[ + input[0].to_owned(), input[1].to_owned(),input[2].to_owned(), input[3].to_owned(),input[4].to_owned(), input[5].to_owned(),input[6].to_owned(), input[7].to_owned(), + input[8].to_owned(), input[9].to_owned(),input[10].to_owned(), input[11].to_owned(),input[12].to_owned(), input[13].to_owned(),input[14].to_owned(), input[15].to_owned(), + F::zero(), F::zero(), F::zero(), F::zero(), F::zero(), F::zero(), F::zero(), F::zero() + ]); + + vec![p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]] + } +} risc0_zkvm::guest::entry!(main); @@ -597,42 +107,18 @@ pub fn main() { } let cycles2 = env::get_cycle_count(); + let permutation = poseidon2::Poseidon2::new(&POSEIDON2_BABYBEAR_24_PARAMS); - // let perm: Vec = permutation.permutation(&hash_data); - let input1: [FpBabyBear;24] = [ - *hash_data.get(0).unwrap(), *hash_data.get(1).unwrap(), *hash_data.get(2).unwrap(), *hash_data.get(3).unwrap(), *hash_data.get(4).unwrap(), *hash_data.get(5).unwrap(), *hash_data.get(6).unwrap(), *hash_data.get(7).unwrap(), - *hash_data.get(8).unwrap(), *hash_data.get(9).unwrap(), *hash_data.get(10).unwrap(), *hash_data.get(11).unwrap(), *hash_data.get(12).unwrap(), *hash_data.get(13).unwrap(), *hash_data.get(14).unwrap(), *hash_data.get(15).unwrap(), - FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0) - ]; - - let input2: [FpBabyBear;24] = [ - *hash_data.get(16).unwrap(), *hash_data.get(17).unwrap(), *hash_data.get(18).unwrap(), *hash_data.get(19).unwrap(), *hash_data.get(20).unwrap(), *hash_data.get(21).unwrap(), *hash_data.get(22).unwrap(), *hash_data.get(23).unwrap(), - *hash_data.get(24).unwrap(), *hash_data.get(25).unwrap(), *hash_data.get(26).unwrap(), *hash_data.get(27).unwrap(), *hash_data.get(28).unwrap(), *hash_data.get(29).unwrap(), *hash_data.get(30).unwrap(), *hash_data.get(31).unwrap(), - FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0) - ]; - - let output1 = compress(permutation.clone(), input1.into()); - let output2 = compress(permutation.clone(), input2.into()); - - let input3 = vec![ - output1[0], output1[1], output1[2], output1[3], output1[4], output1[5], output1[6], output1[7], - output2[0], output2[1], output2[2], output2[3], output2[4], output2[5], output2[6], output2[7], - FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0), FpBabyBear::from(0) - ]; - let output_final = compress(permutation.clone(), input3); - - - // // let mut merkle_tree = MerkleTree::new(permutation.clone()); - // let cycles4 = env::get_cycle_count(); - // // let hash_final = merkle_tree.accumulate(&hash_data); - // let cycles5 = env::get_cycle_count(); + let mut merkle_tree = MerkleTree::new(permutation.clone()); + let cycles3 = env::get_cycle_count(); + let hash_final = merkle_tree.accumulate(&hash_data); let cycles4 = env::get_cycle_count(); let mut perm_seralised: Vec> = Vec::new(); for i in 0..8 { let mut temp: Vec = Vec::new(); - output_final.get(i).unwrap().serialize_uncompressed(&mut temp).unwrap(); + hash_final.get(i).unwrap().serialize_uncompressed(&mut temp).unwrap(); perm_seralised.push(temp); } let cycles6 = env::get_cycle_count(); @@ -640,7 +126,9 @@ pub fn main() { env::commit(&perm_seralised); eprintln!("number of cycles for input builder: {:?}", cycles2 - cycles1); - eprintln!("number of cycles for hash permutation builder: {:?}", cycles4 - cycles2); + eprintln!("number of cycles for hash permutation builder: {:?}", cycles3 - cycles2); + eprintln!("number of cycles for hash accumulation: {:?}", cycles4 - cycles3); + eprintln!("number of cycles for permutation seralisation: {:?}", cycles6 - cycles4); } diff --git a/hash/risc0/bench/methods/guest/src/bin/sha256.rs b/hash/risc0/bench/methods/guest/src/bin/sha256.rs index f133700..d67a766 100644 --- a/hash/risc0/bench/methods/guest/src/bin/sha256.rs +++ b/hash/risc0/bench/methods/guest/src/bin/sha256.rs @@ -7,6 +7,7 @@ pub fn main() { let data: Vec = env::read(); let hash = sha::Impl::hash_bytes(&data); + eprintln!("total cycle count for hashing: {:?}",env::get_cycle_count()); env::commit(&hash) } diff --git a/hash/risc0/bench/methods/guest/src/bin/sha256_accelerated.rs b/hash/risc0/bench/methods/guest/src/bin/sha256_accelerated.rs new file mode 100644 index 0000000..91d7e9c --- /dev/null +++ b/hash/risc0/bench/methods/guest/src/bin/sha256_accelerated.rs @@ -0,0 +1,20 @@ + +// accelerated sha2 crate +#![no_main] + +use risc0_zkvm::guest::env; +use sha2::{Sha256, Digest}; +// use base16ct::lower::encode_str; +risc0_zkvm::guest::entry!(main); + +pub fn main() { + + let data: Vec = env::read(); + let result = Sha256::digest(data); + let c1 = env::get_cycle_count(); + eprintln!("total cycle count for hashing: {:?}",c1); + let result_bytes: [u8;32] = result.into(); + let c2 = env::get_cycle_count(); + eprintln!("cycle count to convert into bytes array: {:?}",c2-c1); + env::commit(&result_bytes) +} diff --git a/hash/risc0/bench/run.sh b/hash/risc0/bench/run.sh index e51695a..3a91834 100755 --- a/hash/risc0/bench/run.sh +++ b/hash/risc0/bench/run.sh @@ -28,7 +28,7 @@ echo "Input Size (KB) = $ZKBENCH_INPUT_SIZE_KB" # Run the benchmarks using cargo run # Check if the environment variable is set to "poseidon2_bn128" -if [ "$ZKBENCH_HASH_TYPE" == "poseidon2_bn128" ]; then +if [[ "$ZKBENCH_HASH_TYPE" == "poseidon2_bn128" || "$ZKBENCH_HASH_TYPE" == "poseidon2_babybear" ]]; then # echo "Running Poseidon2 benchmark over bn128 field" CARGO_BUILD_JOBS=$ZKBENCH_NTHREADS cargo run $ZKBENCH_HASH_TYPE $ZKBENCH_TREE_DEPTH else diff --git a/hash/risc0/bench/src/benches/poseidon2_babybear.rs b/hash/risc0/bench/src/benches/poseidon2_babybear.rs index 382f34b..d2ede50 100644 --- a/hash/risc0/bench/src/benches/poseidon2_babybear.rs +++ b/hash/risc0/bench/src/benches/poseidon2_babybear.rs @@ -1,24 +1,28 @@ #![allow(non_snake_case)] use methods::{ - POSEIDON2_BABYBEAR_ELF, POSEIDON2_BABYBEAR_ID + POSEIDON2_BABYBEAR_ELF, + POSEIDON2_BABYBEAR_ID }; -use risc0_zkvm::{default_prover, ExecutorEnv}; -use zkhash::{fields::{babybear::FpBabyBear, utils::random_scalar} , poseidon2::poseidon2_instance_babybear::POSEIDON2_BABYBEAR_24_PARAMS}; -use zkhash::poseidon2::poseidon2::Poseidon2; -// use std::convert::TryFrom; +use risc0_zkvm::{ + default_prover, + ExecutorEnv +}; +use zkhash::fields::{ + babybear::FpBabyBear, + utils::random_scalar + }; use std::time::Instant; -// use zkhash::merkle_tree::merkle_tree_fp::MerkleTree; -// use std::convert::TryInto; -// use hex::encode_to_slice; -use ark_serialize::{CanonicalSerialize, CanonicalDeserialize}; +use ark_serialize::{ + CanonicalSerialize, + CanonicalDeserialize +}; -pub fn poseidon2_babybear_bench() { +pub fn poseidon2_babybear_bench(mt_depth: usize) { type Scalar = FpBabyBear; - let permutation = Poseidon2::new(&POSEIDON2_BABYBEAR_24_PARAMS); - // let t = permutation.get_t(); - let t = 32; + + let t = (1 << mt_depth) * 8; let mut input_scalar: Vec> = Vec::new(); for _ in 0..t { @@ -58,50 +62,4 @@ pub fn poseidon2_babybear_bench() { // eprintln!("Hash: {:?}", hash_final); - - - - // let input2:[Scalar;16] = [Scalar::from(1), Scalar::from(2), Scalar::from(3), Scalar::from(4),Scalar::from(5), Scalar::from(6), Scalar::from(7), Scalar::from(8),Scalar::from(9), Scalar::from(10), Scalar::from(11), Scalar::from(12), Scalar::from(13), Scalar::from(14), Scalar::from(15), Scalar::from(16)]; - // let hash = merkle_tree.accumulate(&input2); - - // let hash_string = hash.0.to_string(); - // // eprintln!("merkle hash: {:?}",hex::encode(hash_string)); - // eprintln!("merkle hash: {:?}", hash_string); - - // let x = hash.0.0; - // eprintln!("from: {:x}{:x}{:x}{:x}", x[0],x[1], x[2], x[3]); - // eprintln!("scalar: {:?}", Scalar::from(4)); - - // let a = Scalar::from(4); - // let mut uncompressed_bytes = Vec::new(); - // a.serialize_uncompressed(&mut uncompressed_bytes).unwrap(); - // eprintln!("compress: {:?}", uncompressed_bytes); - - // let a_uncompressed = Scalar::deserialize_uncompressed(&*uncompressed_bytes).unwrap(); - // eprintln!("uncompress: {:?}", a_uncompressed); - - // let t = poseidon2.get_t(); - // let input1: Vec = (0..t).map(|_| random_scalar()).collect(); - // let perm = poseidon2.permutation(&input1); - // eprintln!("output: {:?}", perm); - - // let env = ExecutorEnv::builder().write(&input).unwrap().build().unwrap(); - - // Obtain the default prover. - // let prover = default_prover(); - - // let start_time = Instant::now(); - // // Produce a receipt by proving the specified ELF binary. - // let receipt = prover.prove_elf(env, POSEIDON2_BN128_ELF).unwrap(); - // let elapsed_time = start_time.elapsed(); - - // // For example: - // let _output: sha::Digest = receipt.journal.decode().unwrap(); - - // // verify your receipt - // receipt.verify(POSEIDON2_BN128_ID).unwrap(); - - - // eprintln!("Total time: {:?}", elapsed_time); - // eprintln!("Hash: {:?}", _output); } \ No newline at end of file diff --git a/hash/risc0/bench/src/benches/sha256.rs b/hash/risc0/bench/src/benches/sha256.rs index 553623f..46a0489 100644 --- a/hash/risc0/bench/src/benches/sha256.rs +++ b/hash/risc0/bench/src/benches/sha256.rs @@ -1,5 +1,5 @@ use methods::{ - SHA256_ELF, SHA256_ID + SHA256_ELF, SHA256_ID, SHA256_ACCELERATED_ELF, SHA256_ACCELERATED_ID }; use risc0_zkvm::{default_prover, ExecutorEnv}; use risc0_zkvm::{ sha}; @@ -14,7 +14,7 @@ pub fn sha_bench(input: Vec) { // Obtain the default prover. let prover = default_prover(); - + eprintln!("------risc0_zkvm sha hashing------"); let start_time = Instant::now(); // Produce a receipt by proving the specified ELF binary. let receipt = prover.prove_elf(env, SHA256_ELF).unwrap(); @@ -26,7 +26,25 @@ pub fn sha_bench(input: Vec) { // verify your receipt receipt.verify(SHA256_ID).unwrap(); - + eprintln!("Total time: {:?}", elapsed_time); + eprintln!("Hash: {:?}", _output); + + let env = ExecutorEnv::builder().write(&input).unwrap().build().unwrap(); + eprintln!("------RustCrypto sha hashing------"); + // Obtain the default prover. + let prover = default_prover(); + + let start_time = Instant::now(); + // Produce a receipt by proving the specified ELF binary. + let receipt = prover.prove_elf(env, SHA256_ACCELERATED_ELF).unwrap(); + let elapsed_time = start_time.elapsed(); + + // For example: + let _output: [u8;32] = receipt.journal.decode().unwrap(); + + // verify your receipt + receipt.verify(SHA256_ACCELERATED_ID).unwrap(); + eprintln!("Total time: {:?}", elapsed_time); eprintln!("Hash: {:?}", _output); } \ No newline at end of file diff --git a/hash/risc0/bench/src/main.rs b/hash/risc0/bench/src/main.rs index 140db08..25bfce0 100644 --- a/hash/risc0/bench/src/main.rs +++ b/hash/risc0/bench/src/main.rs @@ -58,8 +58,9 @@ fn main() { "poseidon2_babybear" => { println!("Poseidon2 Benchmarking on the BabyBear field: "); - eprintln!("number of inputs {:?}", 32); - poseidon2_babybear_bench(); + eprintln!("Tree Depth: {:?}", size_kb); + eprintln!("number of inputs {:?}", (1 << size_kb) * 8); + poseidon2_babybear_bench(size_kb); } _ => {