Browse Source

Add InnerCircuit abstraction

Abstract signature gadget into InnerCircuit. So that PODs just need to
implement the InnerCircuit and then plug and recurse.
main
arnaucube 10 months ago
parent
commit
53ce944df5
4 changed files with 280 additions and 230 deletions
  1. +73
    -0
      src/example_innercircuit.rs
  2. +1
    -1
      src/lib.rs
  3. +0
    -105
      src/sig_gadget.rs
  4. +206
    -124
      src/tree_recursion.rs

+ 73
- 0
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(())
}
}

+ 1
- 1
src/lib.rs

@ -3,7 +3,7 @@
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
pub mod sig_gadget;
pub mod example_innercircuit;
pub mod tree_recursion; pub mod tree_recursion;
use plonky2::field::goldilocks_field::GoldilocksField; use plonky2::field::goldilocks_field::GoldilocksField;

+ 0
- 105
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(())
}
}

+ 206
- 124
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):
FFFF
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 anyhow::{anyhow, Result};
use plonky2::field::types::Field; use plonky2::field::types::Field;
use plonky2::gates::noop::NoopGate; use plonky2::gates::noop::NoopGate;
use plonky2::iop::target::{BoolTarget, Target};
use plonky2::iop::witness::{PartialWitness, WitnessWrite}; use plonky2::iop::witness::{PartialWitness, WitnessWrite};
use plonky2::plonk::circuit_builder::CircuitBuilder; use plonky2::plonk::circuit_builder::CircuitBuilder;
use plonky2::plonk::circuit_data::{ use plonky2::plonk::circuit_data::{
CircuitConfig, CircuitData, VerifierCircuitData, VerifierCircuitTarget, CircuitConfig, CircuitData, VerifierCircuitData, VerifierCircuitTarget,
}; };
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
use std::marker::PhantomData;
use std::time::Instant; use std::time::Instant;
use sch::schnorr_prover::*; use sch::schnorr_prover::*;
use super::{
sig_gadget::{PODGadgetTargets, PODInput},
PlonkyProof, C, D, F,
};
use super::{PlonkyProof, 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}
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>;
/// 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> {
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, msg_targ: MessageTarget,
sigs_targ: Vec<PODGadgetTargets>,
selectors_targ: Vec<Target>,
inner_circuit_targ: Vec<I::Targets>,
proofs_targ: Vec<ProofWithPublicInputsTarget<D>>, proofs_targ: Vec<ProofWithPublicInputsTarget<D>>,
// the next two are common for all the given proofs. It is the data for this circuit itself // the next two are common for all the given proofs. It is the data for this circuit itself
// (cyclic circuit). // (cyclic circuit).
@ -99,7 +152,7 @@ pub struct RecursiveCircuit {
verifier_data: VerifierCircuitData<F, C, D>, 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( pub fn prepare_public_inputs(
verifier_data: VerifierCircuitData<F, C, D>, verifier_data: VerifierCircuitData<F, C, D>,
msg: Vec<F>, msg: Vec<F>,
@ -130,11 +183,23 @@ impl RecursiveCircuit {
// set msg as public input // set msg as public input
builder.register_public_inputs(&msg_targ.msg); 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 { 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: // proof verification:
@ -146,7 +211,7 @@ impl RecursiveCircuit {
for i in 0..N { for i in 0..N {
let proof_targ = builder.add_virtual_proof_with_pis(&common_data); let proof_targ = builder.add_virtual_proof_with_pis(&common_data);
builder.conditionally_verify_cyclic_proof_or_dummy::<C>( builder.conditionally_verify_cyclic_proof_or_dummy::<C>(
sigs_targ[i].selector_booltarg,
selectors_bool_targ[i],
&proof_targ, &proof_targ,
&common_data, &common_data,
)?; )?;
@ -155,7 +220,8 @@ impl RecursiveCircuit {
Ok(Self { Ok(Self {
msg_targ, msg_targ,
sigs_targ,
selectors_targ,
inner_circuit_targ,
proofs_targ, proofs_targ,
verifier_data_targ, verifier_data_targ,
verifier_data, verifier_data,
@ -166,18 +232,19 @@ impl RecursiveCircuit {
&mut self, &mut self,
pw: &mut PartialWitness<F>, pw: &mut PartialWitness<F>,
msg: &Vec<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>, selectors: Vec<F>,
pods_input: Vec<PODInput>,
inner_circuit_input: Vec<I::Input>,
recursive_proofs: &Vec<PlonkyProof>, recursive_proofs: &Vec<PlonkyProof>,
) -> Result<()> { ) -> 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(); self.msg_targ.set_witness(pw, &msg).unwrap();
// set the signature related values
// set the InnerCircuit related values
for i in 0..N { 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: // set proof related values:
@ -185,8 +252,10 @@ impl RecursiveCircuit {
// recursive proofs verification // recursive proofs verification
pw.set_verifier_data_target(&self.verifier_data_targ, &self.verifier_data.verifier_only)?; 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 { for i in 0..N {
pw.set_proof_with_pis_target( pw.set_proof_with_pis_target(
&self.proofs_targ[i], &self.proofs_targ[i],
@ -201,10 +270,9 @@ impl RecursiveCircuit {
} }
} }
#[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 // 1st
let config = CircuitConfig::standard_recursion_config(); let config = CircuitConfig::standard_recursion_config();
let builder = CircuitBuilder::<F, D>::new(config); let builder = CircuitBuilder::<F, D>::new(config);
@ -226,7 +294,6 @@ pub fn common_data_for_recursion(msg_len: usize) -> Result
let config = CircuitConfig::standard_recursion_config(); let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::<F, D>::new(config.clone()); let mut builder = CircuitBuilder::<F, D>::new(config.clone());
let msg_targ = MessageTarget::new_with_size(&mut builder, msg_len); let msg_targ = MessageTarget::new_with_size(&mut builder, msg_len);
// sigs verify
builder.register_public_inputs(&msg_targ.msg); builder.register_public_inputs(&msg_targ.msg);
builder.add_gate( builder.add_gate(
@ -238,8 +305,13 @@ pub fn common_data_for_recursion(msg_len: usize) -> Result
vec![], 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 // proofs verify
let verifier_data = builder.add_verifier_data_public_inputs(); let verifier_data = builder.add_verifier_data_public_inputs();
@ -277,15 +349,20 @@ fn compute_num_gates() -> Result {
Ok(n_gates) 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 /// returns the full-recursive CircuitData
pub fn circuit_data(msg_len: usize) -> Result<CircuitData<F, C, D>> { 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 // build the actual RecursiveCircuit circuit data
let config = CircuitConfig::standard_recursion_config(); let config = CircuitConfig::standard_recursion_config();
let mut builder = CircuitBuilder::new(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()); dbg!(builder.num_gates());
data = builder.build::<C>(); data = builder.build::<C>();
@ -294,22 +371,18 @@ impl Recursion {
pub fn prove_step( pub fn prove_step(
verifier_data: VerifierCircuitData<F, C, D>, 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>, selectors: Vec<F>,
pods_input: Vec<PODInput>,
inner_circuits_input: Vec<I::Input>,
recursive_proofs: &Vec<PlonkyProof>, recursive_proofs: &Vec<PlonkyProof>,
) -> Result<PlonkyProof> { ) -> Result<PlonkyProof> {
println!("prove_step:"); println!("prove_step:");
for i in 0..N { for i in 0..N {
if selectors[i].is_nonzero() { if selectors[i].is_nonzero() {
println!(" (pods_input[{}].selector==1), verify {}-th proof", i, i);
println!(" (selectors[{}]==1), verify {}-th proof", i, i);
} else { } else {
println!(
" (pods_input[{}].selector==0), verify {}-th signature",
i, i
);
println!(" (selectors[{}]==0), verify {}-th inner circuit", i, i);
} }
} }
@ -319,13 +392,19 @@ impl Recursion {
// assign the targets // assign the targets
let start = Instant::now(); let start = Instant::now();
let mut circuit = 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()); println!("RecursiveCircuit::add_targets(): {:?}", start.elapsed());
// fill the targets // fill the targets
let mut pw = PartialWitness::new(); let mut pw = PartialWitness::new();
let start = Instant::now(); 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()); println!("circuit.set_targets(): {:?}", start.elapsed());
let start = Instant::now(); let start = Instant::now();
@ -367,6 +446,7 @@ mod tests {
use std::time::Instant; use std::time::Instant;
use super::*; use super::*;
use crate::example_innercircuit::{ExampleGadget, ExampleGadgetInput};
use sch::schnorr::*; use sch::schnorr::*;
// this sets the plonky2 internal logs level // this sets the plonky2 internal logs level
@ -384,7 +464,7 @@ mod tests {
// For testing: change the following `N` value to try different arities of the recursion tree: // 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::<2>()?; // N=2
// test_tree_recursion_opt::<3>()?; // N=3
test_tree_recursion_opt::<3>()?; // N=3
Ok(()) Ok(())
} }
@ -422,7 +502,7 @@ mod tests {
.collect(); .collect();
// build the circuit_data & verifier_data for the recursive circuit // 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 verifier_data = circuit_data.verifier_data();
let dummy_proof_pis = cyclic_base_proof( let dummy_proof_pis = cyclic_base_proof(
@ -461,9 +541,9 @@ mod tests {
// prepare the inputs for the `Recursion::prove_step` call // prepare the inputs for the `Recursion::prove_step` call
let selectors = (0..N).into_iter().map(|_| proof_enabled.clone()).collect(); 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() .into_iter()
.map(|k| PODInput {
.map(|k| ExampleGadgetInput {
pk: pk_vec[j + k], pk: pk_vec[j + k],
sig: sig_vec[j + k], sig: sig_vec[j + k],
}) })
@ -476,11 +556,11 @@ mod tests {
// do the recursive step // do the recursive step
let start = Instant::now(); let start = Instant::now();
let new_proof = Recursion::<N>::prove_step(
let new_proof = Recursion::<ExampleGadget, N>::prove_step(
verifier_data.clone(), verifier_data.clone(),
&msg, &msg,
selectors, selectors,
pods_input,
innercircuits_input,
&proofs, &proofs,
)?; )?;
println!( println!(
@ -491,7 +571,7 @@ mod tests {
); );
// verify the recursive proof // verify the recursive proof
let public_inputs = RecursiveCircuit::<N>::prepare_public_inputs(
let public_inputs = RecursiveCircuit::<ExampleGadget, N>::prepare_public_inputs(
verifier_data.clone(), verifier_data.clone(),
msg.clone(), msg.clone(),
); );
@ -509,8 +589,10 @@ mod tests {
let last_proof = proofs_at_level_i[0].clone(); let last_proof = proofs_at_level_i[0].clone();
// verify the last proof // 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 { verifier_data.clone().verify(ProofWithPublicInputs {
proof: last_proof.clone(), proof: last_proof.clone(),
public_inputs: public_inputs.clone(), public_inputs: public_inputs.clone(),

Loading…
Cancel
Save