use ark_bn254::{Fr, G1Projective};
use ark_crypto_primitives::sponge::poseidon::{
PoseidonConfig, PoseidonSponge, constraints::PoseidonSpongeVar,
};
use ark_grumpkin::Projective;
use ark_r1cs_std::fields::fp::FpVar;
use ark_relations::gr1cs::SynthesisError;
use ark_std::{error::Error, rand::thread_rng};
use sonobe_ivc::{IVC, IVCStatefulProver, compilers::cyclefold::adapters::nova::NovaNovaIVC};
use sonobe_primitives::{
circuits::FCircuit,
commitments::pedersen::Pedersen,
transcripts::{TranscriptGadget, poseidon::poseidon_paper_config},
};
struct HashChainCircuit {
config: PoseidonConfig<Fr>,
}
impl FCircuit for HashChainCircuit {
type Field = Fr;
type State = [Fr; 1];
type StateVar = [FpVar<Fr>; 1];
type ExternalInputs = ();
type ExternalOutputs = ();
fn same_state_shape(_a: &Self::State, _b: &Self::State) -> bool {
true
}
fn dummy_state(&self) -> Self::State {
[Fr::from(0)]
}
fn dummy_external_inputs(&self) -> Self::ExternalInputs {}
fn generate_step_constraints(
&self,
_i: FpVar<Self::Field>,
state: Self::StateVar,
_external_inputs: Self::ExternalInputs,
) -> Result<(Self::StateVar, Self::ExternalOutputs), SynthesisError> {
let [z] = state;
let mut sponge = PoseidonSpongeVar::new(self.config.clone());
sponge.add(&z)?;
Ok(([sponge.get_field_element()?], ()))
}
}
type I = NovaNovaIVC<Pedersen<G1Projective, true>, Pedersen<Projective, true>, PoseidonSponge<Fr>>;
fn main() -> Result<(), Box<dyn Error>> {
let mut rng = thread_rng();
let config = poseidon_paper_config::<Fr, 128>(5, 4);
let step_circuit = HashChainCircuit {
config: config.clone(),
};
let initial_state = [Fr::from(1)];
let n_steps = 5;
let pp = I::preprocess((65536, 2048, config.clone()), &mut rng)?;
let (pk, vk) = I::generate_keys(pp, &step_circuit)?;
let mut prover = IVCStatefulProver::<_, I>::new(&pk, &step_circuit, initial_state)?;
for _ in 0..n_steps {
prover.prove_step((), &mut rng)?;
}
I::verify::<HashChainCircuit>(
&vk,
prover.i,
&prover.initial_state,
&prover.current_state,
&prover.current_proof,
)?;
println!(
"verified a chain of {} hashes that updates {:?} to {:?}",
prover.i, prover.initial_state, prover.current_state
);
Ok(())
}