Skip to content

Commit

Permalink
Implemented Batched Proof for multiple openings and Path Pruning (#130)
Browse files Browse the repository at this point in the history
* implemented multipath

* reverted index logic in verify

* fixed compile errors

* unittests passing

* changed signature of generate_multi_proof to sort indexes

* cargo fmt

* implemented unit test for multi_proof internals

* renamed multi_proof specific test

* cargo fmt

* commnts in unittest

* changed function signatures

* cargo fmt

* modified use of BtreeSet and HashMap from ark_std crate

Co-authored-by: Pratyush Mishra <pratyush795@gmail.com>

* modified multipath to derivative(PartialEq...)

Co-authored-by: Pratyush Mishra <pratyush795@gmail.com>

* keep leaves as iterator in multipath verify

Co-authored-by: Marcin <marcin.gorny.94@protonmail.com>

* auth_paths to peekable in multipath.verify

Co-authored-by: Marcin <marcin.gorny.94@protonmail.com>

* updated syntax for iterators in multipath.verify

Co-authored-by: Marcin <marcin.gorny.94@protonmail.com>

* updated syntax for iterators in multipath.verify

Co-authored-by: Marcin <marcin.gorny.94@protonmail.com>

* updated syntax for iterators in multipath.verify

Co-authored-by: Marcin <marcin.gorny.94@protonmail.com>

* shortend init for multipath

* fixed build issues and implementing benches

* implemented benches for proof and multiproof

* removed extra loop in decompress

* removed explicit decompress and merged decompression into multipath verification

* removed multi_path.compress and merged compression step in generate_multi_proof

* implemented prefix_decode_path

* removed redundant code with new helper functions

* added doc for get_leaf_sibling_hash and made it pub. Renamed compute_path to compute_auth_path

* cargo fmt

* changed multiproof.verify to use "insert_with" instead of "insert" (this solves a bug where hashes were computed no matter what). This makes the lut optimization effective

* cargo fmt

* Use iterators in prefix_encode_path

* Allow function-specific sample size in merkle tree benches

* removed redundant imports (nightly build tests)

* cargo fmt

* nightly build fix

---------

Co-authored-by: Pratyush Mishra <pratyush795@gmail.com>
Co-authored-by: Marcin <marcin.gorny.94@protonmail.com>
Co-authored-by: Cesar199999 <cesar.descalzo2@gmail.com>
  • Loading branch information
4 people authored Mar 25, 2024
1 parent b93e005 commit fc1c949
Show file tree
Hide file tree
Showing 32 changed files with 525 additions and 100 deletions.
154 changes: 152 additions & 2 deletions crypto-primitives/benches/merkle_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod bytes_mt_benches {
use ark_std::{test_rng, UniformRand};
use criterion::Criterion;
use std::borrow::Borrow;
use std::iter::zip;

use crate::NUM_LEAVES;

Expand Down Expand Up @@ -56,11 +57,160 @@ mod bytes_mt_benches {
});
}

pub fn merkle_tree_generate_proof(c: &mut Criterion) {
let mut rng = test_rng();
let leaves: Vec<_> = (0..NUM_LEAVES)
.map(|_| {
let rnd = BigInteger256::rand(&mut rng);
to_uncompressed_bytes!(rnd).unwrap()
})
.collect();
let leaf_crh_params = <LeafH as CRHScheme>::setup(&mut rng).unwrap();
let two_to_one_params = <CompressH as TwoToOneCRHScheme>::setup(&mut rng)
.unwrap()
.clone();

let tree = Sha256MerkleTree::new(
&leaf_crh_params.clone(),
&two_to_one_params.clone(),
&leaves,
)
.unwrap();
c.bench_function("Merkle Tree Generate Proof (Leaves as [u8])", move |b| {
b.iter(|| {
for (i, _) in leaves.iter().enumerate() {
tree.generate_proof(i).unwrap();
}
})
});
}

pub fn merkle_tree_verify_proof(c: &mut Criterion) {
let mut rng = test_rng();
let leaves: Vec<_> = (0..NUM_LEAVES)
.map(|_| {
let rnd = BigInteger256::rand(&mut rng);
to_uncompressed_bytes!(rnd).unwrap()
})
.collect();
let leaf_crh_params = <LeafH as CRHScheme>::setup(&mut rng).unwrap();
let two_to_one_params = <CompressH as TwoToOneCRHScheme>::setup(&mut rng)
.unwrap()
.clone();

let tree = Sha256MerkleTree::new(
&leaf_crh_params.clone(),
&two_to_one_params.clone(),
&leaves,
)
.unwrap();

let root = tree.root();

let proofs: Vec<_> = leaves
.iter()
.enumerate()
.map(|(i, _)| tree.generate_proof(i).unwrap())
.collect();

c.bench_function("Merkle Tree Verify Proof (Leaves as [u8])", move |b| {
b.iter(|| {
for (proof, leaf) in zip(proofs.clone(), leaves.clone()) {
proof
.verify(&leaf_crh_params, &two_to_one_params, &root, leaf.as_slice())
.unwrap();
}
})
});
}

pub fn merkle_tree_generate_multi_proof(c: &mut Criterion) {
let mut rng = test_rng();
let leaves: Vec<_> = (0..NUM_LEAVES)
.map(|_| {
let rnd = BigInteger256::rand(&mut rng);
to_uncompressed_bytes!(rnd).unwrap()
})
.collect();
let leaf_crh_params = <LeafH as CRHScheme>::setup(&mut rng).unwrap();
let two_to_one_params = <CompressH as TwoToOneCRHScheme>::setup(&mut rng)
.unwrap()
.clone();

let tree = Sha256MerkleTree::new(
&leaf_crh_params.clone(),
&two_to_one_params.clone(),
&leaves,
)
.unwrap();
c.bench_function(
"Merkle Tree Generate Multi Proof (Leaves as [u8])",
move |b| {
b.iter(|| {
tree.generate_multi_proof((0..leaves.len()).collect::<Vec<_>>())
.unwrap();
})
},
);
}

pub fn merkle_tree_verify_multi_proof(c: &mut Criterion) {
let mut rng = test_rng();
let leaves: Vec<_> = (0..NUM_LEAVES)
.map(|_| {
let rnd = BigInteger256::rand(&mut rng);
to_uncompressed_bytes!(rnd).unwrap()
})
.collect();
let leaf_crh_params = <LeafH as CRHScheme>::setup(&mut rng).unwrap();
let two_to_one_params = <CompressH as TwoToOneCRHScheme>::setup(&mut rng)
.unwrap()
.clone();

let tree = Sha256MerkleTree::new(
&leaf_crh_params.clone(),
&two_to_one_params.clone(),
&leaves,
)
.unwrap();

let root = tree.root();

let multi_proof = tree
.generate_multi_proof((0..leaves.len()).collect::<Vec<_>>())
.unwrap();

c.bench_function(
"Merkle Tree Verify Multi Proof (Leaves as [u8])",
move |b| {
b.iter(|| {
multi_proof.verify(&leaf_crh_params, &two_to_one_params, &root, leaves.clone())
})
},
);
}

criterion_group! {
name = mt_create;
config = Criterion::default().sample_size(10);
config = Criterion::default().sample_size(100);
targets = merkle_tree_create
}

criterion_group! {
name = mt_proof;
config = Criterion::default().sample_size(100);
targets = merkle_tree_generate_proof, merkle_tree_generate_multi_proof
}

criterion_group! {
name = mt_verify;
config = Criterion::default().sample_size(10);
targets = merkle_tree_verify_proof, merkle_tree_verify_multi_proof
}
}

criterion_main!(crate::bytes_mt_benches::mt_create,);
criterion_main!(
bytes_mt_benches::mt_create,
bytes_mt_benches::mt_proof,
bytes_mt_benches::mt_verify
);
1 change: 0 additions & 1 deletion crypto-primitives/src/commitment/blake2s/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use ark_relations::r1cs::{Namespace, SynthesisError};
use crate::{
commitment::{blake2s, CommitmentGadget},
prf::blake2s::constraints::{evaluate_blake2s, OutputVar},
Vec,
};
use ark_ff::{Field, PrimeField};
use ark_r1cs_std::prelude::*;
Expand Down
1 change: 0 additions & 1 deletion crypto-primitives/src/commitment/pedersen/constraints.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::{
commitment::pedersen::{Commitment, Parameters, Randomness},
crh::pedersen::Window,
Vec,
};
use ark_ec::CurveGroup;
use ark_ff::{
Expand Down
2 changes: 1 addition & 1 deletion crypto-primitives/src/commitment/pedersen/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{crh::CRHScheme, Error, Vec};
use crate::{crh::CRHScheme, Error};
use ark_ec::CurveGroup;
use ark_ff::{BitIteratorLE, Field, PrimeField, ToConstraintField};
use ark_serialize::CanonicalSerialize;
Expand Down
16 changes: 5 additions & 11 deletions crypto-primitives/src/crh/bowe_hopwood/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,16 @@ use ark_ec::twisted_edwards::{Projective as TEProjective, TECurveConfig};
use ark_ec::CurveConfig;
use core::{borrow::Borrow, iter, marker::PhantomData};

use crate::{
crh::{
bowe_hopwood::{Parameters, CHUNK_SIZE},
pedersen::{self, Window},
CRHSchemeGadget, TwoToOneCRHSchemeGadget,
},
Vec,
use crate::crh::{
bowe_hopwood::{Parameters, CHUNK_SIZE},
pedersen::{self, Window},
CRHSchemeGadget, TwoToOneCRHSchemeGadget,
};
use ark_ff::Field;
use ark_r1cs_std::{
alloc::AllocVar, groups::curves::twisted_edwards::AffineVar, prelude::*, uint8::UInt8,
};
use ark_r1cs_std::{groups::curves::twisted_edwards::AffineVar, prelude::*};
use ark_relations::r1cs::{Namespace, SynthesisError};

use crate::crh::bowe_hopwood::{TwoToOneCRH, CRH};
use ark_r1cs_std::boolean::Boolean;

type ConstraintF<P> = <<P as CurveConfig>::BaseField as Field>::BasePrimeField;

Expand Down
2 changes: 1 addition & 1 deletion crypto-primitives/src/crh/bowe_hopwood/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//! specific Twisted Edwards (TE) curves. See [Section 5.4.17 of the Zcash protocol specification](https://raw.githubusercontent.com/zcash/zips/master/protocol/protocol.pdf#concretepedersenhash) for a formal description of this hash function, specialized for the Jubjub curve.
//! The implementation in this repository is generic across choice of TE curves.

use crate::{Error, Vec};
use crate::Error;
use ark_std::rand::Rng;
use ark_std::{
fmt::{Debug, Formatter, Result as FmtResult},
Expand Down
4 changes: 1 addition & 3 deletions crypto-primitives/src/crh/injective_map/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ use ark_ec::{
};
use ark_ff::fields::{Field, PrimeField};
use ark_r1cs_std::{
fields::fp::FpVar,
groups::{curves::twisted_edwards::AffineVar as TEVar, CurveVar},
prelude::*,
fields::fp::FpVar, groups::curves::twisted_edwards::AffineVar as TEVar, prelude::*,
};
use ark_relations::r1cs::SynthesisError;

Expand Down
1 change: 0 additions & 1 deletion crypto-primitives/src/crh/injective_map/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ use ark_ec::{
};
use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
use ark_std::borrow::Borrow;
use ark_std::vec::Vec;
#[cfg(feature = "r1cs")]
pub mod constraints;

Expand Down
9 changes: 3 additions & 6 deletions crypto-primitives/src/crh/pedersen/constraints.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
use crate::{
crh::{
pedersen::{Parameters, Window},
CRHSchemeGadget as CRHGadgetTrait,
},
Vec,
use crate::crh::{
pedersen::{Parameters, Window},
CRHSchemeGadget as CRHGadgetTrait,
};
use ark_ec::CurveGroup;
use ark_ff::Field;
Expand Down
2 changes: 1 addition & 1 deletion crypto-primitives/src/crh/pedersen/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Error, Vec};
use crate::Error;
use ark_std::rand::Rng;
use ark_std::{
fmt::{Debug, Formatter, Result as FmtResult},
Expand Down
2 changes: 1 addition & 1 deletion crypto-primitives/src/crh/poseidon/constraints.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::crh::poseidon::{TwoToOneCRH, CRH};
use crate::crh::CRHScheme;
use crate::crh::{
CRHSchemeGadget as CRHGadgetTrait, TwoToOneCRHSchemeGadget as TwoToOneCRHGadgetTrait,
};
use crate::sponge::constraints::CryptographicSpongeVar;
use crate::sponge::poseidon::constraints::PoseidonSpongeVar;
use crate::sponge::poseidon::PoseidonConfig;
use crate::{crh::CRHScheme, Vec};

use crate::sponge::Absorb;
use ark_ff::PrimeField;
Expand Down
12 changes: 2 additions & 10 deletions crypto-primitives/src/crh/sha256/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ use ark_r1cs_std::{
R1CSVar,
};
use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError};
use ark_std::{vec, vec::Vec};

const STATE_LEN: usize = 8;

Expand Down Expand Up @@ -383,17 +382,10 @@ where
#[cfg(test)]
mod test {
use super::*;
use crate::crh::{
sha256::{digest::Digest, Sha256},
CRHScheme, CRHSchemeGadget, TwoToOneCRHScheme, TwoToOneCRHSchemeGadget,
};
use crate::crh::{sha256::digest::Digest, CRHScheme, TwoToOneCRHScheme};

use ark_bls12_377::Fr;
use ark_r1cs_std::R1CSVar;
use ark_relations::{
ns,
r1cs::{ConstraintSystem, Namespace},
};
use ark_relations::{ns, r1cs::ConstraintSystem};
use ark_std::rand::RngCore;

const TEST_LENGTHS: &[usize] = &[
Expand Down
2 changes: 1 addition & 1 deletion crypto-primitives/src/crh/sha256/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::crh::{CRHScheme, TwoToOneCRHScheme};
use crate::{Error, Vec};
use crate::Error;

use ark_std::rand::Rng;

Expand Down
2 changes: 1 addition & 1 deletion crypto-primitives/src/encryption/elgamal/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use ark_ff::{
Zero,
};
use ark_serialize::CanonicalSerialize;
use ark_std::{borrow::Borrow, marker::PhantomData, vec::Vec};
use ark_std::{borrow::Borrow, marker::PhantomData};

pub type ConstraintF<C> = <<C as CurveGroup>::BaseField as Field>::BasePrimeField;

Expand Down
1 change: 0 additions & 1 deletion crypto-primitives/src/merkle_tree/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use ark_r1cs_std::prelude::*;
use ark_relations::r1cs::{Namespace, SynthesisError};
use ark_std::borrow::Borrow;
use ark_std::fmt::Debug;
use ark_std::vec::Vec;

pub trait DigestVarConverter<From, To: ?Sized> {
type TargetType: Borrow<To>;
Expand Down
Loading

0 comments on commit fc1c949

Please sign in to comment.