arnaucube
arnaucube/plonky2-recursion-experimentPublic Self-hosted repository
Add InnerCircuit abstraction

Abstract signature gadget into InnerCircuit. So that PODs just need to
implement the InnerCircuit and then plug and recurse.
arnaucube git@arnaucube.com
Thu, 17 Oct 2024 19:12:53 +0200
commit

53ce944df52ccd3f4af58f7077272f5cf015caf3

parent

bea58b711e07ce3dc45dd7cfedb3ed92598c58b0

4 files changed, 280 insertions(+), 230 deletions(-)

jump to
A src/example_innercircuit.rs

@@ -0,0 +1,73 @@

+/// This file contains a simple example implementing the InnerCircuit trait, by a circuit that +/// checks a signature over the given msg. +use anyhow::Result; +use plonky2::iop::target::BoolTarget; +use plonky2::iop::witness::PartialWitness; +use plonky2::plonk::circuit_builder::CircuitBuilder; + +use sch::schnorr::*; +use sch::schnorr_prover::*; + +use super::tree_recursion::{selector_gate, InnerCircuit}; +use super::{C, D, F}; + +pub struct ExampleGadgetInput { + pub pk: SchnorrPublicKey, + pub sig: SchnorrSignature, +} + +pub struct ExampleGadgetTargets { + pub pk_targ: SchnorrPublicKeyTarget, + pub sig_targ: SchnorrSignatureTarget, +} + +/// The logic of this gadget verifies the given signature if `selector==0`. +/// +/// It implements the InnerCircuit trait, so it contains the methods to `add_targets` (ie. create +/// the targets, the logic of the circuit), and `set_targets` (ie. set the specific values to be +/// used for the previously created targets). +pub struct ExampleGadget {} + +impl InnerCircuit for ExampleGadget { + type Input = ExampleGadgetInput; + type Targets = ExampleGadgetTargets; + + fn add_targets( + mut builder: &mut CircuitBuilder<F, D>, + selector_booltarg: &BoolTarget, + msg_targ: &MessageTarget, + ) -> Result<Self::Targets> { + // signature verification: + let sb: SchnorrBuilder = SchnorrBuilder {}; + let pk_targ = SchnorrPublicKeyTarget::new_virtual(&mut builder); + let sig_targ = SchnorrSignatureTarget::new_virtual(&mut builder); + let sig_verif_targ = sb.verify_sig::<C>(&mut builder, &sig_targ, &msg_targ, &pk_targ); + + // if selector==0: verify the signature; else: don't check it. ie: + // if selector=0: check that sig_verif==1 + // if selector=1: check that one==1 + let one = builder.one(); + let expected = selector_gate( + builder, + sig_verif_targ.target, + one, + selector_booltarg.target, + ); + let one_2 = builder.one(); + builder.connect(expected, one_2); + + Ok(Self::Targets { pk_targ, sig_targ }) + } + + fn set_targets( + pw: &mut PartialWitness<F>, + targets: &Self::Targets, + pod: &Self::Input, + ) -> Result<()> { + // set signature related values: + targets.pk_targ.set_witness(pw, &pod.pk).unwrap(); + targets.sig_targ.set_witness(pw, &pod.sig).unwrap(); + + Ok(()) + } +}
M src/lib.rs → src/lib.rs

@@ -3,7 +3,7 @@ #![allow(non_snake_case)]

#![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] -pub mod sig_gadget; +pub mod example_innercircuit; pub mod tree_recursion; use plonky2::field::goldilocks_field::GoldilocksField;
D src/sig_gadget.rs

@@ -1,105 +0,0 @@

-use anyhow::Result; -use plonky2::iop::target::{BoolTarget, Target}; -use plonky2::iop::witness::{PartialWitness, WitnessWrite}; -use plonky2::plonk::circuit_builder::CircuitBuilder; - -use sch::schnorr::*; -use sch::schnorr_prover::*; - -use super::{C, D, F}; - -/// if s==0: returns x -/// if s==1: returns y -/// Warning: this method assumes all input values are ensured to be \in {0,1} -fn selector_gate(builder: &mut CircuitBuilder<F, D>, x: Target, y: Target, s: Target) -> Target { - // z = x + s(y-x) - let y_x = builder.sub(y, x); - // z = x+s(y-x) <==> mul_add(s, yx, x)=s*(y-x)+x - builder.mul_add(s, y_x, x) -} - -/// ensures b \in {0,1} -fn binary_check(builder: &mut CircuitBuilder<F, D>, b: Target) { - let zero = builder.zero(); - let one = builder.one(); - // b * (b-1) == 0 - let b_1 = builder.sub(b, one); - let r = builder.mul(b, b_1); - builder.connect(r, zero); -} - -pub struct PODInput { - pub pk: SchnorrPublicKey, - pub sig: SchnorrSignature, -} - -/// The logic of this gadget verifies the given signature if `selector==0`. -/// We reuse this gadget for all the the signature verifications in the node of the recursion tree. -/// -/// Contains the methods to `add_targets` (ie. create the targets, the logic of the circuit), and -/// `set_targets` (ie. set the specific values to be used for the previously created targets). -pub struct PODGadgetTargets { - pub selector_targ: Target, - pub selector_booltarg: BoolTarget, - - pub pk_targ: SchnorrPublicKeyTarget, - pub sig_targ: SchnorrSignatureTarget, -} - -impl PODGadgetTargets { - pub fn add_targets( - mut builder: &mut CircuitBuilder<F, D>, - msg_targ: &MessageTarget, - ) -> Result<Self> { - let selector_targ = builder.add_virtual_target(); - // ensure that selector_booltarg is \in {0,1} - binary_check(builder, selector_targ); - let selector_booltarg = BoolTarget::new_unsafe(selector_targ); - - // signature verification: - let sb: SchnorrBuilder = SchnorrBuilder {}; - let pk_targ = SchnorrPublicKeyTarget::new_virtual(&mut builder); - let sig_targ = SchnorrSignatureTarget::new_virtual(&mut builder); - let sig_verif_targ = sb.verify_sig::<C>(&mut builder, &sig_targ, &msg_targ, &pk_targ); - - // - if selector=0 - // verify_sig==1 && proof_enabled=0 - // - if selector=1 - // verify_sig==NaN && proof_enabled=1 (don't check the sig) - // - // if selector=0: check that sig_verif==1 - // if selector=1: check that one==1 - let one = builder.one(); - let expected = selector_gate( - builder, - sig_verif_targ.target, - one, - selector_booltarg.target, - ); - let one_2 = builder.one(); - builder.connect(expected, one_2); - - Ok(Self { - selector_targ, - selector_booltarg, - pk_targ, - sig_targ, - }) - } - pub fn set_targets( - &mut self, - pw: &mut PartialWitness<F>, - // if `selector` set to 0 will verify the given signature, if set to 1 won't (and the - // recursion layer will verify the respective plonky2 proof) - selector: F, - pod: &PODInput, - ) -> Result<()> { - pw.set_target(self.selector_targ, selector)?; - - // set signature related values: - self.pk_targ.set_witness(pw, &pod.pk).unwrap(); - self.sig_targ.set_witness(pw, &pod.sig).unwrap(); - - Ok(()) - } -}
M src/tree_recursion.rs → src/tree_recursion.rs

@@ -1,97 +1,150 @@

-/// N-arity tree of recursion with conditionals. -/// -/// p_root -/// ▲ -/// │ -/// ┌────────┐ -/// │ F │ -/// └────────┘ -/// ▲ ▲ ▲ ▲ -/// ┌─┘ │ │ └─┐ -/// ┌────┘ ┌─┘ └┐ └───┐ -/// │ │ ... │ │ -/// ┌────────┐┌┴┐┌─┐┌┴┐ ┌────────┐ -/// │ F ││.││.││.│ │ F │ -/// └────────┘└─┘└─┘└─┘ └────────┘ -/// ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ -/// ┌─┘ │ └┐ └─┐ ┌─┘┌┘ └┐ └┐ -/// │ │ │ │ │ │ │ │ -/// p_1 p_2 ... p_n p'_1 p'_2... p'_n -/// -/// -/// where each p_i is either -/// - signature verification -/// - recursive plonky2 proof (proof that verifies previous proof) -/// (generated by `RecursiveCircuit::prove_step` method) -/// in other words, each p_i is checking: -/// `(signature proof OR recursive proof)` -/// -/// Each node of the recursion tree, ie. each F, verifies the N incoming p_i's, that is -/// `(signature proof OR recursive proof) AND ... AND (signature proof OR recursive proof)` -/// and produces a new proof. -/// -/// For example, if N is set to N=2, then we work with a binary recursion tree: -/// p_root -/// ▲ -/// │ -/// ┌─┴─┐ -/// │ F │ -/// └───┘ -/// ▲ ▲ -/// ┌─┘ └─┐ -/// ┌───┘ └───┐ -/// │p_5 │p_6 -/// ┌─┴─┐ ┌─┴─┐ -/// │ F │ │ F │ -/// └───┘ └───┘ -/// ▲ ▲ ▲ ▲ -/// ┌─┘ └─┐ ┌─┘ └─┐ -/// │ │ │ │ -/// p_1 p_2 p_3 p_4 -/// -/// So that each node (F box) is verifying 2 p_i's, ie: -/// `(signature proof OR recursive proof) AND (signature proof OR recursive proof)` -/// -/// -/// With N=3, each node will be verifying 3 p_i's. -/// `(signature proof OR recursive proof) AND (signature proof OR recursive proof) AND (signature proof OR recursive proof)` -/// -/// -/// -/// Also, notice that if we set N=1, it is directly a linear chain of recursive proofs ('tree' of -/// arity 1): -/// ┌─┐ ┌─┐ ┌─┐ ┌─┐ -/// ─────►│F├────►│F├────►│F├────►│F├────► -/// p_1 └─┘ p_2 └─┘ p_3 └─┘ p_4 └─┘ p_5 -/// -/// where each p_i is proving: `(signature proof OR recursive proof)`. -/// -/// -/// To run the tests that checks this logic: -/// cargo test --release test_tree_recursion -- --nocapture +/* + N-arity tree of recursion with conditionals. + + p_root + ▲ + │ + ┌────────┐ + │ F │ + └────────┘ + ▲ ▲ ▲ ▲ + ┌─┘ │ │ └─┐ + ┌────┘ ┌─┘ └┐ └───┐ + │ │ ... │ │ + ┌────────┐┌┴┐┌─┐┌┴┐ ┌────────┐ + │ F ││.││.││.│ │ F │ + └────────┘└─┘└─┘└─┘ └────────┘ + ▲ ▲ ▲ ▲ ▲ ▲ ▲ ▲ + ┌─┘ │ └┐ └─┐ ┌─┘┌┘ └┐ └┐ + │ │ │ │ │ │ │ │ + p_1 p_2 ... p_n p'_1 p'_2... p'_n + + + where each p_i is either + - InnerCircuit verification + - recursive plonky2 proof (proof that verifies previous proof) + (generated by `RecursiveCircuit::prove_step` method) + in other words, each p_i is checking: + `(InnerCircuit OR recursive proof verify)` + + Each node of the recursion tree, ie. each F, verifies the N incoming p_i's, that is + `(InnerCircuit OR recursive proof verify) AND ... AND (InnerCircuit OR recursive proof verify)` + and produces a new proof. + + For example, if N is set to N=2, then we work with a binary recursion tree: + p_root + ▲ + │ + ┌─┴─┐ + │ F │ + └───┘ + ▲ ▲ + ┌─┘ └─┐ + ┌───┘ └───┐ + │p_5 │p_6 + ┌─┴─┐ ┌─┴─┐ + │ F │ │ F │ + └───┘ └───┘ + ▲ ▲ ▲ ▲ + ┌─┘ └─┐ ┌─┘ └─┐ + │ │ │ │ + p_1 p_2 p_3 p_4 + + p_i: `(InnerCircuit OR recursive-proof-verification)` + + + So that each node (F box) is verifying 2 p_i's, ie: + `(InnerCircuit OR recursive-proof-verification) AND (InnerCircuit OR recursive-proof-verification)` + + + With N=3, each node will be verifying 3 p_i's. + `(InnerCircuit OR recursive-proof-verification) AND (InnerCircuit OR recursive-proof-verification) AND (InnerCircuit OR recursive-proof-verification)` + + + + Also, notice that if we set N=1, it is directly a linear chain of recursive proofs ('tree' of + arity 1): + ┌─┐ ┌─┐ ┌─┐ ┌─┐ + ─────►│F├────►│F├────►│F├────►│F├────► + p_1 └─┘ p_2 └─┘ p_3 └─┘ p_4 └─┘ p_5 + + where each p_i is proving: `(InnerCircuit OR recursive-proof-verification)`. + + + To run the tests that checks this logic: + cargo test --release test_tree_recursion -- --nocapture +*/ use anyhow::{anyhow, Result}; use plonky2::field::types::Field; use plonky2::gates::noop::NoopGate; +use plonky2::iop::target::{BoolTarget, Target}; use plonky2::iop::witness::{PartialWitness, WitnessWrite}; use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_data::{ CircuitConfig, CircuitData, VerifierCircuitData, VerifierCircuitTarget, }; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; +use std::marker::PhantomData; use std::time::Instant; use sch::schnorr_prover::*; -use super::{ - sig_gadget::{PODGadgetTargets, PODInput}, - PlonkyProof, C, D, F, -}; +use super::{PlonkyProof, C, D, F}; -/// Contains the methods to `add_targets` (ie. create the targets, the logic of the circuit), and -/// `set_targets` (ie. set the specific values to be used for the previously created targets). -pub struct RecursiveCircuit<const N: usize> { +/// if s==0: returns x +/// if s==1: returns y +/// Warning: this method assumes all input values are ensured to be \in {0,1} +pub fn selector_gate( + builder: &mut CircuitBuilder<F, D>, + x: Target, + y: Target, + s: Target, +) -> Target { + // z = x + s(y-x) + let y_x = builder.sub(y, x); + // z = x+s(y-x) <==> mul_add(s, yx, x)=s*(y-x)+x + builder.mul_add(s, y_x, x) +} + +/// ensures b \in {0,1} +pub fn binary_check(builder: &mut CircuitBuilder<F, D>, b: Target) { + let zero = builder.zero(); + let one = builder.one(); + // b * (b-1) == 0 + let b_1 = builder.sub(b, one); + let r = builder.mul(b, b_1); + builder.connect(r, zero); +} + +/// InnerCircuit is the trait that is used to define the logic of the circuit that is used at each +/// node of the recursive tree. +pub trait InnerCircuit { + type Input; + type Targets; + + fn add_targets( + builder: &mut CircuitBuilder<F, D>, + selector_booltarg: &BoolTarget, + msg_targ: &MessageTarget, + ) -> Result<Self::Targets>; + + fn set_targets( + pw: &mut PartialWitness<F>, + targets: &Self::Targets, + input: &Self::Input, + ) -> Result<()>; +} + +/// RecursiveCircuit defines the circuit used on each node of the recursion tree, which is doing +/// `(InnerCircuit OR recursive-proof-verification)` N times, and generating a new proof that can +/// be verified by the same circuit itself. +/// +/// It contains the methods to `add_targets` (ie. create the targets, the logic of the circuit), +/// and `set_targets` (ie. set the specific values to be used for the previously created targets). +pub struct RecursiveCircuit<I: InnerCircuit, const N: usize> { msg_targ: MessageTarget, - sigs_targ: Vec<PODGadgetTargets>, + selectors_targ: Vec<Target>, + inner_circuit_targ: Vec<I::Targets>, proofs_targ: Vec<ProofWithPublicInputsTarget<D>>, // the next two are common for all the given proofs. It is the data for this circuit itself // (cyclic circuit).

@@ -99,7 +152,7 @@ verifier_data_targ: VerifierCircuitTarget,

verifier_data: VerifierCircuitData<F, C, D>, } -impl<const N: usize> RecursiveCircuit<N> { +impl<I: InnerCircuit, const N: usize> RecursiveCircuit<I, N> { pub fn prepare_public_inputs( verifier_data: VerifierCircuitData<F, C, D>, msg: Vec<F>,

@@ -130,11 +183,23 @@ let msg_targ = MessageTarget::new_with_size(builder, msg_len);

// set msg as public input builder.register_public_inputs(&msg_targ.msg); - // build the signature verification logic - let mut sigs_targ: Vec<PODGadgetTargets> = vec![]; + // build the InnerCircuit logic. Also set the selectors, used both by the InnerCircuit and + // by the recursive proofs verifications. + let mut selectors_targ: Vec<Target> = vec![]; + let mut selectors_bool_targ: Vec<BoolTarget> = vec![]; + let mut inner_circuit_targ: Vec<I::Targets> = vec![]; for _ in 0..N { - let sig_targets = PODGadgetTargets::add_targets(builder, &msg_targ)?; - sigs_targ.push(sig_targets); + // selectors: + let selector_F_targ = builder.add_virtual_target(); + // ensure that selector_booltarg is \in {0,1} + binary_check(builder, selector_F_targ); + let selector_bool_targ = BoolTarget::new_unsafe(selector_F_targ); + selectors_targ.push(selector_F_targ); + selectors_bool_targ.push(selector_bool_targ); + + // inner circuits: + let inner_circuit_targets = I::add_targets(builder, &selector_bool_targ, &msg_targ)?; + inner_circuit_targ.push(inner_circuit_targets); } // proof verification:

@@ -146,7 +211,7 @@ let mut proofs_targ: Vec<ProofWithPublicInputsTarget<D>> = vec![];

for i in 0..N { let proof_targ = builder.add_virtual_proof_with_pis(&common_data); builder.conditionally_verify_cyclic_proof_or_dummy::<C>( - sigs_targ[i].selector_booltarg, + selectors_bool_targ[i], &proof_targ, &common_data, )?;

@@ -155,7 +220,8 @@ }

Ok(Self { msg_targ, - sigs_targ, + selectors_targ, + inner_circuit_targ, proofs_targ, verifier_data_targ, verifier_data,

@@ -166,18 +232,19 @@ pub fn set_targets(

&mut self, pw: &mut PartialWitness<F>, msg: &Vec<F>, - // if selectors[i]==0: verify pods[i] signature. if selectors[i]==1: verify - // recursive_proof[i] + // if selectors[i]==0: verify InnerCircuit. if selectors[i]==1: verify recursive_proof[i] selectors: Vec<F>, - pods_input: Vec<PODInput>, + inner_circuit_input: Vec<I::Input>, recursive_proofs: &Vec<PlonkyProof>, ) -> Result<()> { - // set the msg value (used by all N sig gadgets) + // set the msg value (used by all N InnerCircuit gadgets) self.msg_targ.set_witness(pw, &msg).unwrap(); - // set the signature related values + // set the InnerCircuit related values for i in 0..N { - self.sigs_targ[i].set_targets(pw, selectors[i], &pods_input[i])?; + pw.set_target(self.selectors_targ[i], selectors[i])?; + + I::set_targets(pw, &self.inner_circuit_targ[i], &inner_circuit_input[i])?; } // set proof related values:

@@ -185,8 +252,10 @@

// recursive proofs verification pw.set_verifier_data_target(&self.verifier_data_targ, &self.verifier_data.verifier_only)?; - let public_inputs = - RecursiveCircuit::<N>::prepare_public_inputs(self.verifier_data.clone(), msg.clone()); + let public_inputs = RecursiveCircuit::<I, N>::prepare_public_inputs( + self.verifier_data.clone(), + msg.clone(), + ); for i in 0..N { pw.set_proof_with_pis_target( &self.proofs_targ[i],

@@ -201,10 +270,9 @@ Ok(())

} } -#[derive(Debug, Clone)] -pub struct Recursion<const N: usize> {} - -pub fn common_data_for_recursion<const N: usize>(msg_len: usize) -> Result<CircuitData<F, C, D>> { +pub fn common_data_for_recursion<I: InnerCircuit, const N: usize>( + msg_len: usize, +) -> Result<CircuitData<F, C, D>> { // 1st let config = CircuitConfig::standard_recursion_config(); let builder = CircuitBuilder::<F, D>::new(config);

@@ -226,7 +294,6 @@ // 3rd

let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::<F, D>::new(config.clone()); let msg_targ = MessageTarget::new_with_size(&mut builder, msg_len); - // sigs verify builder.register_public_inputs(&msg_targ.msg); builder.add_gate(

@@ -238,8 +305,13 @@ plonky2::gates::constant::ConstantGate::new(config.num_constants),

vec![], ); - let _ = PODGadgetTargets::add_targets(&mut builder, &msg_targ).unwrap(); - let _ = PODGadgetTargets::add_targets(&mut builder, &msg_targ).unwrap(); + // InnerCircuits targets + for _ in 0..N { + let selector_F_targ = builder.add_virtual_target(); + binary_check(&mut builder, selector_F_targ); + let b = BoolTarget::new_unsafe(selector_F_targ); + let _ = I::add_targets(&mut builder, &b, &msg_targ).unwrap(); + } // proofs verify let verifier_data = builder.add_verifier_data_public_inputs();

@@ -277,15 +349,20 @@ }

Ok(n_gates) } -impl<const N: usize> Recursion<N> { +#[derive(Debug, Clone)] +pub struct Recursion<I: InnerCircuit, const N: usize> { + _i: PhantomData<I>, +} + +impl<I: InnerCircuit, const N: usize> Recursion<I, N> { /// returns the full-recursive CircuitData pub fn circuit_data(msg_len: usize) -> Result<CircuitData<F, C, D>> { - let mut data = common_data_for_recursion::<N>(msg_len)?; + let mut data = common_data_for_recursion::<I, N>(msg_len)?; // build the actual RecursiveCircuit circuit data let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::new(config); - let _ = RecursiveCircuit::<N>::add_targets(&mut builder, data.verifier_data(), msg_len)?; + let _ = RecursiveCircuit::<I, N>::add_targets(&mut builder, data.verifier_data(), msg_len)?; dbg!(builder.num_gates()); data = builder.build::<C>();

@@ -294,22 +371,18 @@ }

pub fn prove_step( verifier_data: VerifierCircuitData<F, C, D>, - msg: &Vec<F>, // will be an array of "pod roots (hashes)' - // if selectors[i]==0: verify pods[i] signature. if selectors[i]==1: verify - // recursive_proof[i] + msg: &Vec<F>, + // if selectors[i]==0: verify InnerCircuit. if selectors[i]==1: verify recursive_proof[i] selectors: Vec<F>, - pods_input: Vec<PODInput>, + inner_circuits_input: Vec<I::Input>, recursive_proofs: &Vec<PlonkyProof>, ) -> Result<PlonkyProof> { println!("prove_step:"); for i in 0..N { if selectors[i].is_nonzero() { - println!(" (pods_input[{}].selector==1), verify {}-th proof", i, i); + println!(" (selectors[{}]==1), verify {}-th proof", i, i); } else { - println!( - " (pods_input[{}].selector==0), verify {}-th signature", - i, i - ); + println!(" (selectors[{}]==0), verify {}-th inner circuit", i, i); } }

@@ -319,13 +392,19 @@

// assign the targets let start = Instant::now(); let mut circuit = - RecursiveCircuit::<N>::add_targets(&mut builder, verifier_data.clone(), msg.len())?; + RecursiveCircuit::<I, N>::add_targets(&mut builder, verifier_data.clone(), msg.len())?; println!("RecursiveCircuit::add_targets(): {:?}", start.elapsed()); // fill the targets let mut pw = PartialWitness::new(); let start = Instant::now(); - circuit.set_targets(&mut pw, msg, selectors, pods_input, recursive_proofs)?; + circuit.set_targets( + &mut pw, + msg, + selectors, + inner_circuits_input, + recursive_proofs, + )?; println!("circuit.set_targets(): {:?}", start.elapsed()); let start = Instant::now();

@@ -367,6 +446,7 @@ use rand;

use std::time::Instant; use super::*; + use crate::example_innercircuit::{ExampleGadget, ExampleGadgetInput}; use sch::schnorr::*; // this sets the plonky2 internal logs level

@@ -384,7 +464,7 @@ fn test_tree_recursion() -> Result<()> {

// For testing: change the following `N` value to try different arities of the recursion tree: test_tree_recursion_opt::<2>()?; // N=2 - // test_tree_recursion_opt::<3>()?; // N=3 + test_tree_recursion_opt::<3>()?; // N=3 Ok(()) }

@@ -422,7 +502,7 @@ .map(|&sk| schnorr.sign(&msg, &sk, &mut rng))

.collect(); // build the circuit_data & verifier_data for the recursive circuit - let circuit_data = Recursion::<N>::circuit_data(MSG_LEN)?; + let circuit_data = Recursion::<ExampleGadget, N>::circuit_data(MSG_LEN)?; let verifier_data = circuit_data.verifier_data(); let dummy_proof_pis = cyclic_base_proof(

@@ -461,9 +541,9 @@ let proof_enabled = if i == 0 { F::ZERO } else { F::ONE };

// prepare the inputs for the `Recursion::prove_step` call let selectors = (0..N).into_iter().map(|_| proof_enabled.clone()).collect(); - let pods_input: Vec<PODInput> = (0..N) + let innercircuits_input: Vec<ExampleGadgetInput> = (0..N) .into_iter() - .map(|k| PODInput { + .map(|k| ExampleGadgetInput { pk: pk_vec[j + k], sig: sig_vec[j + k], })

@@ -476,11 +556,11 @@ .collect();

// do the recursive step let start = Instant::now(); - let new_proof = Recursion::<N>::prove_step( + let new_proof = Recursion::<ExampleGadget, N>::prove_step( verifier_data.clone(), &msg, selectors, - pods_input, + innercircuits_input, &proofs, )?; println!(

@@ -491,7 +571,7 @@ start.elapsed()

); // verify the recursive proof - let public_inputs = RecursiveCircuit::<N>::prepare_public_inputs( + let public_inputs = RecursiveCircuit::<ExampleGadget, N>::prepare_public_inputs( verifier_data.clone(), msg.clone(), );

@@ -509,8 +589,10 @@ assert_eq!(proofs_at_level_i.len(), 1);

let last_proof = proofs_at_level_i[0].clone(); // verify the last proof - let public_inputs = - RecursiveCircuit::<N>::prepare_public_inputs(verifier_data.clone(), msg.clone()); + let public_inputs = RecursiveCircuit::<ExampleGadget, N>::prepare_public_inputs( + verifier_data.clone(), + msg.clone(), + ); verifier_data.clone().verify(ProofWithPublicInputs { proof: last_proof.clone(), public_inputs: public_inputs.clone(),