use ark_bn254::{Fr, G1Projective};
use ark_crypto_primitives::sponge::poseidon::PoseidonSponge;
use ark_ff::UniformRand;
use ark_r1cs_std::{
alloc::AllocVar,
eq::EqGadget,
fields::{FieldVar, fp::FpVar},
};
use ark_relations::gr1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError};
use ark_std::{error::Error, rand::thread_rng};
use sonobe_fs::{
DeciderKey, FoldingInstance, FoldingSchemeDecider, FoldingSchemeKeyGenerator,
FoldingSchemePreprocessor, FoldingSchemeProver, FoldingSchemeVerifier,
nova::{
Nova,
instances::{IncomingInstance, RunningInstance},
witnesses::{IncomingWitness, RunningWitness},
},
};
use sonobe_primitives::{
arithmetizations::r1cs::R1CS,
circuits::{ArithExtractor, AssignmentsExtractor},
commitments::pedersen::Pedersen,
relations::WitnessInstanceSampler,
transcripts::{Transcript, poseidon::poseidon_paper_config},
};
struct SolutionCircuit {
x: Fr,
}
impl ConstraintSynthesizer<Fr> for SolutionCircuit {
fn generate_constraints(self, cs: ConstraintSystemRef<Fr>) -> Result<(), SynthesisError> {
let x = FpVar::new_input(cs, || Ok(self.x))?;
let x2 = &x * &x;
let x3 = &x2 * &x;
let x4 = &x3 * &x;
let x5 = &x4 * &x;
let p = x5 - x4 * Fr::from(15) + x3 * Fr::from(85) - x2 * Fr::from(225) + x * Fr::from(274)
- Fr::from(120);
p.enforce_equal(&FpVar::zero())
}
}
type FS = Nova<Pedersen<G1Projective, true>>;
fn main() -> Result<(), Box<dyn Error>> {
let mut rng = thread_rng();
let config = poseidon_paper_config::<Fr, 128>(5, 4);
let roots = [1, 2, 3, 4, 5, 3, 1, 5, 5, 2].map(Fr::from);
let mut claims = vec![];
let pp = FS::preprocess(1024, &mut rng)?;
let dk = FS::generate_keys(pp, {
let cs = ArithExtractor::new();
cs.execute_synthesizer(SolutionCircuit {
x: Fr::rand(&mut rng),
})?;
cs.arith::<R1CS<_>>()?
})?;
let (pk, vk) = (dk.to_pk(), dk.to_vk());
#[allow(non_snake_case)]
let (mut W, mut U): (RunningWitness<_>, RunningInstance<_>) = dk.sample((), &mut rng)?;
let mut transcript_p = PoseidonSponge::new(config.clone());
let mut transcript_v = PoseidonSponge::new(config);
for x in roots {
let (w, u): (IncomingWitness<_>, IncomingInstance<_>) = dk.sample(
{
let cs = AssignmentsExtractor::new();
cs.execute_synthesizer(SolutionCircuit { x })?;
cs.assignments()?
},
&mut rng,
)?;
let (folded_w, folded_u, proof) =
FS::prove(pk, &mut transcript_p, &[&W], &[&U], &[&w], &[&u], &mut rng)?;
assert_eq!(
folded_u,
FS::verify(vk, &mut transcript_v, &[&U], &[&u], &proof)?
);
claims.push(u.public_inputs()[0]);
W = folded_w;
U = folded_u;
}
FS::decide_running(&dk, &W, &U)?;
println!("Verified claims {claims:?}");
Ok(())
}