arnaucube
arnaucube/plonky2-recursion-experimentPublic Self-hosted repository
group signature verification inputs (prepare for POD abstraction). Use proper  &  names
arnaucube git@arnaucube.com
Thu, 17 Oct 2024 11:21:51 +0200
commit

bea58b711e07ce3dc45dd7cfedb3ed92598c58b0

parent

d08f082ca4bba91f7f4c56820d864d93f16d041f

2 files changed, 64 insertions(+), 54 deletions(-)

jump to
M src/sig_gadget.rs → src/sig_gadget.rs

@@ -28,23 +28,29 @@ 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 `build` (ie. create the targets, the logic of the circuit), and -/// `fill_targets` (ie. set the specific values to be used for the previously created targets). -pub struct SignatureGadgetTargets { +/// 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 SignatureGadgetTargets { - pub fn build( + +impl PODGadgetTargets { + pub fn add_targets( mut builder: &mut CircuitBuilder<F, D>, msg_targ: &MessageTarget, - ) -> Result<SignatureGadgetTargets> { + ) -> Result<Self> { let selector_targ = builder.add_virtual_target(); // ensure that selector_booltarg is \in {0,1} binary_check(builder, selector_targ);

@@ -80,18 +86,19 @@ pk_targ,

sig_targ, }) } - pub fn fill_targets( + pub fn set_targets( &mut self, pw: &mut PartialWitness<F>, - selector: F, // 1=proof, 0=sig - pk: &SchnorrPublicKey, - sig: &SchnorrSignature, + // 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, &pk).unwrap(); - self.sig_targ.set_witness(pw, &sig).unwrap(); + 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

@@ -30,7 +30,6 @@ /// 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 /// ▲

@@ -81,16 +80,18 @@ };

use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget}; use std::time::Instant; -use sch::schnorr::*; use sch::schnorr_prover::*; -use super::{sig_gadget::SignatureGadgetTargets, PlonkyProof, C, D, F}; +use super::{ + sig_gadget::{PODGadgetTargets, PODInput}, + PlonkyProof, C, D, F, +}; -/// Contains the methods to `build` (ie. create the targets, the logic of the circuit), and -/// `fill_targets` (ie. set the specific values to be used for the previously created 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> { msg_targ: MessageTarget, - sigs_targ: Vec<SignatureGadgetTargets>, + sigs_targ: Vec<PODGadgetTargets>, 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).

@@ -120,7 +121,7 @@ }

// notice that this method does not fill the targets, which is done in the method // `fill_recursive_circuit_targets` - pub fn build( + pub fn add_targets( builder: &mut CircuitBuilder<F, D>, verifier_data: VerifierCircuitData<F, C, D>, msg_len: usize,

@@ -130,9 +131,9 @@ // set msg as public input

builder.register_public_inputs(&msg_targ.msg); // build the signature verification logic - let mut sigs_targ: Vec<SignatureGadgetTargets> = vec![]; + let mut sigs_targ: Vec<PODGadgetTargets> = vec![]; for _ in 0..N { - let sig_targets = SignatureGadgetTargets::build(builder, &msg_targ)?; + let sig_targets = PODGadgetTargets::add_targets(builder, &msg_targ)?; sigs_targ.push(sig_targets); }

@@ -161,13 +162,14 @@ verifier_data,

}) } - pub fn fill_targets( + pub fn set_targets( &mut self, pw: &mut PartialWitness<F>, msg: &Vec<F>, - selectors: Vec<F>, // 1=proof, 0=sig - pks: &Vec<SchnorrPublicKey>, - sigs: &Vec<SchnorrSignature>, + // if selectors[i]==0: verify pods[i] signature. if selectors[i]==1: verify + // recursive_proof[i] + selectors: Vec<F>, + pods_input: Vec<PODInput>, recursive_proofs: &Vec<PlonkyProof>, ) -> Result<()> { // set the msg value (used by all N sig gadgets)

@@ -175,7 +177,7 @@ self.msg_targ.set_witness(pw, &msg).unwrap();

// set the signature related values for i in 0..N { - self.sigs_targ[i].fill_targets(pw, selectors[i], &pks[i], &sigs[i])?; + self.sigs_targ[i].set_targets(pw, selectors[i], &pods_input[i])?; } // set proof related values:

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

vec![], ); - let _ = SignatureGadgetTargets::build(&mut builder, &msg_targ).unwrap(); - let _ = SignatureGadgetTargets::build(&mut builder, &msg_targ).unwrap(); + let _ = PODGadgetTargets::add_targets(&mut builder, &msg_targ).unwrap(); + let _ = PODGadgetTargets::add_targets(&mut builder, &msg_targ).unwrap(); // proofs verify let verifier_data = builder.add_verifier_data_public_inputs();

@@ -283,7 +285,7 @@

// build the actual RecursiveCircuit circuit data let config = CircuitConfig::standard_recursion_config(); let mut builder = CircuitBuilder::new(config); - let _ = RecursiveCircuit::<N>::build(&mut builder, data.verifier_data(), msg_len)?; + let _ = RecursiveCircuit::<N>::add_targets(&mut builder, data.verifier_data(), msg_len)?; dbg!(builder.num_gates()); data = builder.build::<C>();

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

pub fn prove_step( verifier_data: VerifierCircuitData<F, C, D>, - msg: &Vec<F>, - selectors: Vec<F>, // 1=proof, 0=sig - pks: &Vec<SchnorrPublicKey>, - sigs: &Vec<SchnorrSignature>, + 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] + selectors: Vec<F>, + pods_input: Vec<PODInput>, recursive_proofs: &Vec<PlonkyProof>, ) -> Result<PlonkyProof> { println!("prove_step:"); for i in 0..N { if selectors[i].is_nonzero() { - println!(" (selectors[{}]==1), verify {}-th proof", i, i); + println!(" (pods_input[{}].selector==1), verify {}-th proof", i, i); } else { - println!(" (selectors[{}]==0), verify {}-th signature", i, i); + println!( + " (pods_input[{}].selector==0), verify {}-th signature", + i, i + ); } }

@@ -313,14 +319,14 @@

// assign the targets let start = Instant::now(); let mut circuit = - RecursiveCircuit::<N>::build(&mut builder, verifier_data.clone(), msg.len())?; - println!("RecursiveCircuit::build(): {:?}", start.elapsed()); + RecursiveCircuit::<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.fill_targets(&mut pw, msg, selectors, pks, sigs, recursive_proofs)?; - println!("circuit.fill_targets(): {:?}", start.elapsed()); + circuit.set_targets(&mut pw, msg, selectors, pods_input, recursive_proofs)?; + println!("circuit.set_targets(): {:?}", start.elapsed()); let start = Instant::now(); let data = builder.build::<C>();

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

use std::time::Instant; use super::*; + use sch::schnorr::*; // this sets the plonky2 internal logs level fn set_log() {

@@ -377,7 +384,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(()) }

@@ -387,7 +394,7 @@ set_log();

println!("\n--------------------------------------------------"); println!("\n--------------------------------------------------"); println!( - "\nrunning test:\n test_tree_recursion_opt with N={} (arity)", + "\nrunning test:\n===test_tree_recursion_opt with N={} (arity)", N );

@@ -432,7 +439,7 @@ (0..k).into_iter().map(|_| dummy_proof.clone()).collect();

// loop over the recursion levels for i in 0..l { - println!("\n=== recursion level i={}", i); + println!("\n--- recursion level i={}", i); let mut next_level_proofs: Vec<PlonkyProof> = vec![]; // loop over the nodes of each recursion tree level

@@ -453,16 +460,13 @@ // verify.

let proof_enabled = if i == 0 { F::ZERO } else { F::ONE }; // prepare the inputs for the `Recursion::prove_step` call - let proofs_selectors = (0..N).into_iter().map(|_| proof_enabled.clone()).collect(); - let pks = (0..N) + let selectors = (0..N).into_iter().map(|_| proof_enabled.clone()).collect(); + let pods_input: Vec<PODInput> = (0..N) .into_iter() - .enumerate() - .map(|(k, _)| pk_vec[j + k].clone()) - .collect(); - let sigs = (0..N) - .into_iter() - .enumerate() - .map(|(k, _)| sig_vec[j + k].clone()) + .map(|k| PODInput { + pk: pk_vec[j + k], + sig: sig_vec[j + k], + }) .collect(); let proofs = (0..N) .into_iter()

@@ -475,9 +479,8 @@ let start = Instant::now();

let new_proof = Recursion::<N>::prove_step( verifier_data.clone(), &msg, - proofs_selectors, - &pks, - &sigs, + selectors, + pods_input, &proofs, )?; println!(