mirror of
https://github.com/arnaucube/fold-babyjubjubs.git
synced 2026-01-12 00:41:32 +01:00
add folding logic using Sonobe
This commit is contained in:
16
README.md
Normal file
16
README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# fold-babyjubjubs
|
||||
|
||||
Repo folding BabyJubJub EdDSA signatures using [arkeddsa](https://github.com/kilic/arkeddsa), showcasing usage of [Sonobe](https://github.com/privacy-scaling-explorations/sonobe) with [Arkworks](https://github.com/arkworks-rs).
|
||||
|
||||
The main idea is to prove $z_n = F(F(...~F(F(F(z_0)))))$, where $n$ is the number of BabyJubJub EdDSA signature verifications ($F$) that we compute. Proving this in a 'normal' R1CS circuit for a large $n$ would be too costly, but with folding we can manage to prove it in a reasonable time span.
|
||||
|
||||
For more info about Sonobe, check out [Sonobe's docs](https://privacy-scaling-explorations.github.io/sonobe-docs).
|
||||
|
||||
<p align="center">
|
||||
<img src="https://privacy-scaling-explorations.github.io/sonobe-docs/imgs/folding-main-idea-diagram.png" style="width:70%;" />
|
||||
</p>
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
- `cargo test --release -- --nocapture`
|
||||
93
src/fold_babyjubjubs.rs
Normal file
93
src/fold_babyjubjubs.rs
Normal file
@@ -0,0 +1,93 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use ark_bn254::{constraints::GVar, Fr, G1Projective as G1};
|
||||
use ark_grumpkin::{constraints::GVar as GVar2, Projective as G2};
|
||||
use std::time::Instant;
|
||||
|
||||
use arkeddsa::ed_on_bn254_twist::{constraints::EdwardsVar, EdwardsProjective};
|
||||
|
||||
use folding_schemes::{
|
||||
commitment::pedersen::Pedersen,
|
||||
folding::nova::{Nova, PreprocessorParam},
|
||||
frontend::FCircuit,
|
||||
transcript::poseidon::poseidon_canonical_config,
|
||||
FoldingScheme,
|
||||
};
|
||||
|
||||
use crate::fcircuit::{tests::gen_signatures, FoldSigsStepCircuit};
|
||||
|
||||
#[test]
|
||||
fn test_full_flow() {
|
||||
// 5 recursive steps, 10 signature verifications per step
|
||||
full_flow::<5, 10>();
|
||||
// 5 recursive steps, 50 signature verifications per step
|
||||
full_flow::<5, 50>();
|
||||
}
|
||||
|
||||
fn full_flow<const N_STEPS: usize, const SIGS_PER_STEP: usize>() {
|
||||
println!("\nrunning Nova folding scheme on FoldSigsStepCircuit, with N_STEPS={}, SIGS_PER_STEP={}. Total sigs = {}", N_STEPS, SIGS_PER_STEP, N_STEPS* SIGS_PER_STEP);
|
||||
|
||||
let mut rng = rand::rngs::OsRng;
|
||||
let poseidon_config = poseidon_canonical_config::<Fr>();
|
||||
|
||||
let pks_sigs =
|
||||
gen_signatures::<rand::rngs::OsRng, SIGS_PER_STEP>(&mut rng, &poseidon_config, N_STEPS);
|
||||
|
||||
// set the initial state
|
||||
let z_0: Vec<Fr> = vec![0_u8; 1]
|
||||
.iter()
|
||||
.map(|v| Fr::from(*v))
|
||||
.collect::<Vec<Fr>>();
|
||||
|
||||
type FC<const S: usize> = FoldSigsStepCircuit<Fr, EdwardsProjective, EdwardsVar, S>;
|
||||
let f_circuit = FC::<SIGS_PER_STEP>::new(poseidon_config.clone()).unwrap();
|
||||
|
||||
// define type aliases for the FoldingScheme (FS) and Decider (D), to avoid writting the
|
||||
// whole type each time
|
||||
pub type FS<const S: usize> =
|
||||
Nova<G1, GVar, G2, GVar2, FC<S>, Pedersen<G1>, Pedersen<G2>, false>;
|
||||
|
||||
// prepare the Nova prover & verifier params
|
||||
let nova_preprocess_params =
|
||||
PreprocessorParam::new(poseidon_config.clone(), f_circuit.clone());
|
||||
let start = Instant::now();
|
||||
let nova_params =
|
||||
FS::<SIGS_PER_STEP>::preprocess(&mut rng, &nova_preprocess_params).unwrap();
|
||||
println!("Nova params generated: {:?}", start.elapsed());
|
||||
|
||||
// initialize the folding scheme engine, in our case we use Nova
|
||||
let mut nova = FS::<SIGS_PER_STEP>::init(&nova_params, f_circuit, z_0.clone()).unwrap();
|
||||
|
||||
// run n steps of the folding iteration
|
||||
let start_full = Instant::now();
|
||||
for i in 0..N_STEPS {
|
||||
let start = Instant::now();
|
||||
nova.prove_step(rng, pks_sigs[i].clone(), None).unwrap();
|
||||
println!("Nova::prove_step {}: {:?}", nova.i, start.elapsed());
|
||||
}
|
||||
let t = start_full.elapsed();
|
||||
println!("Nova's all {} steps time: {:?}", N_STEPS, t);
|
||||
println!(
|
||||
"N_STEPS={}, SIGS_PER_STEP={}. Total sigs = {}",
|
||||
N_STEPS,
|
||||
SIGS_PER_STEP,
|
||||
N_STEPS * SIGS_PER_STEP
|
||||
);
|
||||
println!(
|
||||
"SIGS PER SECOND: {:?}",
|
||||
(N_STEPS * SIGS_PER_STEP) as f64 / t.as_secs_f64()
|
||||
);
|
||||
println!(
|
||||
"TIME FOR EACH SIG: {:?} ms",
|
||||
t / (N_STEPS * SIGS_PER_STEP) as u32
|
||||
);
|
||||
|
||||
// verify the last IVC proof
|
||||
let ivc_proof = nova.ivc_proof();
|
||||
FS::<SIGS_PER_STEP>::verify(
|
||||
nova_params.1.clone(), // Nova's verifier params
|
||||
ivc_proof,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
7
src/lib.rs
Normal file
7
src/lib.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
#![allow(non_snake_case)]
|
||||
#![allow(dead_code)]
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
|
||||
mod fcircuit;
|
||||
mod fold_babyjubjubs;
|
||||
Reference in New Issue
Block a user