mirror of
https://github.com/logos-storage/zk-benchmarks.git
synced 2026-01-05 07:13:08 +00:00
rust-crypto accelerated sha and poseidon2 over babybear(ark-ff) benchmarking
This commit is contained in:
parent
882a55557e
commit
d5193cce6e
@ -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.
|
||||
|
||||
@ -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<F: Elem> {
|
||||
// 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<F>,
|
||||
// pub(crate) _mat_internal: Vec<Vec<F>>,
|
||||
// pub(crate) round_constants: Vec<Vec<F>>,
|
||||
// }
|
||||
use ark_ff::PrimeField;
|
||||
|
||||
// pub fn mat_inverse<F: Elem>(mat: &[Vec<F>]) -> Vec<Vec<F>> {
|
||||
// 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<F: Elem> Poseidon2Params<F> {
|
||||
// #[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<F>],
|
||||
// round_constants: &[Vec<F>],
|
||||
// ) -> 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<F>],
|
||||
// mat_internal: &[Vec<F>],
|
||||
// rounds_f_beginning: usize,
|
||||
// rounds_p: usize,
|
||||
// ) -> Vec<Vec<F>> {
|
||||
// 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<F>], input: &[F]) -> Vec<F> {
|
||||
// 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<F: Elem> {
|
||||
// pub(crate) params: Arc<Poseidon2Params<F>>,
|
||||
// }
|
||||
|
||||
// impl<F: Elem> Poseidon2<F> {
|
||||
// pub fn new(params: &Arc<Poseidon2Params<F>>) -> Self {
|
||||
// Poseidon2 {
|
||||
// params: Arc::clone(params),
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub fn get_t(&self) -> usize {
|
||||
// self.params.t
|
||||
// }
|
||||
|
||||
// pub fn permutation(&self, input: &[F]) -> Vec<F> {
|
||||
// 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<F> {
|
||||
// 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<F> {
|
||||
// input
|
||||
// .iter()
|
||||
// .zip(rc.iter())
|
||||
// .map(|(a, b)| {
|
||||
// let mut r = *a;
|
||||
// r.add_assign(*b);
|
||||
// r
|
||||
// })
|
||||
// .collect()
|
||||
// }
|
||||
// }
|
||||
|
||||
// pub trait MerkleTreeHash<F: Elem> {
|
||||
// fn compress(&self, input: &[&F]) -> Vec<F>;
|
||||
// }
|
||||
|
||||
// #[derive(Clone, Debug)]
|
||||
// pub struct MerkleTree<F: Elem, P: MerkleTreeHash<F>> {
|
||||
// perm: P,
|
||||
// field: PhantomData<F>,
|
||||
// }
|
||||
|
||||
// impl<F: Elem, P: MerkleTreeHash<F>> MerkleTree<F, P> {
|
||||
// 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<F> = 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<F> = 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<F> {
|
||||
// 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<F> = 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<F> = 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<F: Elem> MerkleTreeHash<F> for Poseidon2<F> {
|
||||
// fn compress(&self, input: &[&F]) -> Vec<F> {
|
||||
// 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<FpBabyBear>, input: Vec<FpBabyBear>) -> Vec<FpBabyBear>{
|
||||
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<F: PrimeField> {
|
||||
fn compress(&self, input: &[&F]) -> Vec<F>;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct MerkleTree<F: PrimeField, P: MerkleTreeHash<F>> {
|
||||
perm: P,
|
||||
field: PhantomData<F>,
|
||||
}
|
||||
|
||||
impl<F: PrimeField, P: MerkleTreeHash<F>> MerkleTree<F, P> {
|
||||
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<F> {
|
||||
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<F> = 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<F> = 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<F: PrimeField> MerkleTreeHash<F> for Poseidon2<F> {
|
||||
fn compress(&self, input: &[&F]) -> Vec<F> {
|
||||
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<FpBabyBear> = 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<u8>> = Vec::new();
|
||||
for i in 0..8 {
|
||||
let mut temp: Vec<u8> = 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);
|
||||
|
||||
}
|
||||
|
||||
@ -7,6 +7,7 @@ pub fn main() {
|
||||
|
||||
let data: Vec<u8> = env::read();
|
||||
let hash = sha::Impl::hash_bytes(&data);
|
||||
eprintln!("total cycle count for hashing: {:?}",env::get_cycle_count());
|
||||
env::commit(&hash)
|
||||
}
|
||||
|
||||
|
||||
20
hash/risc0/bench/methods/guest/src/bin/sha256_accelerated.rs
Normal file
20
hash/risc0/bench/methods/guest/src/bin/sha256_accelerated.rs
Normal file
@ -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<u8> = 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)
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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<u8>> = 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<Scalar> = (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);
|
||||
}
|
||||
@ -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<u8>) {
|
||||
|
||||
// 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<u8>) {
|
||||
// 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);
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
_ => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user