From 53ce944df52ccd3f4af58f7077272f5cf015caf3 Mon Sep 17 00:00:00 2001 From: arnaucube Date: Thu, 17 Oct 2024 19:12:53 +0200 Subject: [PATCH] Add InnerCircuit abstraction Abstract signature gadget into InnerCircuit. So that PODs just need to implement the InnerCircuit and then plug and recurse. --- src/example_innercircuit.rs | 73 ++++++++ src/lib.rs | 2 +- src/sig_gadget.rs | 105 ------------ src/tree_recursion.rs | 330 ++++++++++++++++++++++-------------- 4 files changed, 280 insertions(+), 230 deletions(-) create mode 100644 src/example_innercircuit.rs delete mode 100644 src/sig_gadget.rs diff --git a/src/example_innercircuit.rs b/src/example_innercircuit.rs new file mode 100644 index 0000000..d3f4234 --- /dev/null +++ b/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, + selector_booltarg: &BoolTarget, + msg_targ: &MessageTarget, + ) -> Result { + // 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::(&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, + 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(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index ec4fc61..56519b0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,7 @@ #![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; diff --git a/src/sig_gadget.rs b/src/sig_gadget.rs deleted file mode 100644 index 825b751..0000000 --- a/src/sig_gadget.rs +++ /dev/null @@ -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, 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, 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, - msg_targ: &MessageTarget, - ) -> Result { - 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::(&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, - // 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(()) - } -} diff --git a/src/tree_recursion.rs b/src/tree_recursion.rs index 2b2aeb6..7f77335 100644 --- a/src/tree_recursion.rs +++ b/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}; + +/// 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, + 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, 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, + selector_booltarg: &BoolTarget, + msg_targ: &MessageTarget, + ) -> Result; -/// 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 { + fn set_targets( + pw: &mut PartialWitness, + 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 { msg_targ: MessageTarget, - sigs_targ: Vec, + selectors_targ: Vec, + inner_circuit_targ: Vec, proofs_targ: Vec>, // the next two are common for all the given proofs. It is the data for this circuit itself // (cyclic circuit). @@ -99,7 +152,7 @@ pub struct RecursiveCircuit { verifier_data: VerifierCircuitData, } -impl RecursiveCircuit { +impl RecursiveCircuit { pub fn prepare_public_inputs( verifier_data: VerifierCircuitData, msg: Vec, @@ -130,11 +183,23 @@ impl RecursiveCircuit { // set msg as public input builder.register_public_inputs(&msg_targ.msg); - // build the signature verification logic - let mut sigs_targ: Vec = 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 = vec![]; + let mut selectors_bool_targ: Vec = vec![]; + let mut inner_circuit_targ: Vec = 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 @@ impl RecursiveCircuit { for i in 0..N { let proof_targ = builder.add_virtual_proof_with_pis(&common_data); builder.conditionally_verify_cyclic_proof_or_dummy::( - sigs_targ[i].selector_booltarg, + selectors_bool_targ[i], &proof_targ, &common_data, )?; @@ -155,7 +220,8 @@ impl RecursiveCircuit { Ok(Self { msg_targ, - sigs_targ, + selectors_targ, + inner_circuit_targ, proofs_targ, verifier_data_targ, verifier_data, @@ -166,18 +232,19 @@ impl RecursiveCircuit { &mut self, pw: &mut PartialWitness, msg: &Vec, - // 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, - pods_input: Vec, + inner_circuit_input: Vec, recursive_proofs: &Vec, ) -> 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 @@ impl RecursiveCircuit { // recursive proofs verification pw.set_verifier_data_target(&self.verifier_data_targ, &self.verifier_data.verifier_only)?; - let public_inputs = - RecursiveCircuit::::prepare_public_inputs(self.verifier_data.clone(), msg.clone()); + let public_inputs = RecursiveCircuit::::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 @@ impl RecursiveCircuit { } } -#[derive(Debug, Clone)] -pub struct Recursion {} - -pub fn common_data_for_recursion(msg_len: usize) -> Result> { +pub fn common_data_for_recursion( + msg_len: usize, +) -> Result> { // 1st let config = CircuitConfig::standard_recursion_config(); let builder = CircuitBuilder::::new(config); @@ -226,7 +294,6 @@ pub fn common_data_for_recursion(msg_len: usize) -> Result::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 @@ pub fn common_data_for_recursion(msg_len: usize) -> Result() -> Result { Ok(n_gates) } -impl Recursion { +#[derive(Debug, Clone)] +pub struct Recursion { + _i: PhantomData, +} + +impl Recursion { /// returns the full-recursive CircuitData pub fn circuit_data(msg_len: usize) -> Result> { - let mut data = common_data_for_recursion::(msg_len)?; + let mut data = common_data_for_recursion::(msg_len)?; // build the actual RecursiveCircuit circuit data let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::new(config); - let _ = RecursiveCircuit::::add_targets(&mut builder, data.verifier_data(), msg_len)?; + let _ = RecursiveCircuit::::add_targets(&mut builder, data.verifier_data(), msg_len)?; dbg!(builder.num_gates()); data = builder.build::(); @@ -294,22 +371,18 @@ impl Recursion { pub fn prove_step( verifier_data: VerifierCircuitData, - msg: &Vec, // 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, + // if selectors[i]==0: verify InnerCircuit. if selectors[i]==1: verify recursive_proof[i] selectors: Vec, - pods_input: Vec, + inner_circuits_input: Vec, recursive_proofs: &Vec, ) -> Result { 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 @@ impl Recursion { // assign the targets let start = Instant::now(); let mut circuit = - RecursiveCircuit::::add_targets(&mut builder, verifier_data.clone(), msg.len())?; + RecursiveCircuit::::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 @@ mod tests { 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 @@ mod tests { // 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 @@ mod tests { .collect(); // build the circuit_data & verifier_data for the recursive circuit - let circuit_data = Recursion::::circuit_data(MSG_LEN)?; + let circuit_data = Recursion::::circuit_data(MSG_LEN)?; let verifier_data = circuit_data.verifier_data(); let dummy_proof_pis = cyclic_base_proof( @@ -461,9 +541,9 @@ mod tests { // prepare the inputs for the `Recursion::prove_step` call let selectors = (0..N).into_iter().map(|_| proof_enabled.clone()).collect(); - let pods_input: Vec = (0..N) + let innercircuits_input: Vec = (0..N) .into_iter() - .map(|k| PODInput { + .map(|k| ExampleGadgetInput { pk: pk_vec[j + k], sig: sig_vec[j + k], }) @@ -476,11 +556,11 @@ mod tests { // do the recursive step let start = Instant::now(); - let new_proof = Recursion::::prove_step( + let new_proof = Recursion::::prove_step( verifier_data.clone(), &msg, selectors, - pods_input, + innercircuits_input, &proofs, )?; println!( @@ -491,7 +571,7 @@ mod tests { ); // verify the recursive proof - let public_inputs = RecursiveCircuit::::prepare_public_inputs( + let public_inputs = RecursiveCircuit::::prepare_public_inputs( verifier_data.clone(), msg.clone(), ); @@ -509,8 +589,10 @@ mod tests { let last_proof = proofs_at_level_i[0].clone(); // verify the last proof - let public_inputs = - RecursiveCircuit::::prepare_public_inputs(verifier_data.clone(), msg.clone()); + let public_inputs = RecursiveCircuit::::prepare_public_inputs( + verifier_data.clone(), + msg.clone(), + ); verifier_data.clone().verify(ProofWithPublicInputs { proof: last_proof.clone(), public_inputs: public_inputs.clone(),