mirror of
https://github.com/arnaucube/plonky2-recursion-experiment.git
synced 2026-01-21 05:11:36 +01:00
group signature verification inputs (prepare for POD abstraction). Use proper & names
This commit is contained in:
@@ -28,23 +28,29 @@ fn binary_check(builder: &mut CircuitBuilder<F, D>, b: Target) {
|
|||||||
builder.connect(r, zero);
|
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`.
|
/// 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.
|
/// 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
|
/// Contains the methods to `add_targets` (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).
|
/// `set_targets` (ie. set the specific values to be used for the previously created targets).
|
||||||
pub struct SignatureGadgetTargets {
|
pub struct PODGadgetTargets {
|
||||||
pub selector_targ: Target,
|
pub selector_targ: Target,
|
||||||
pub selector_booltarg: BoolTarget,
|
pub selector_booltarg: BoolTarget,
|
||||||
|
|
||||||
pub pk_targ: SchnorrPublicKeyTarget,
|
pub pk_targ: SchnorrPublicKeyTarget,
|
||||||
pub sig_targ: SchnorrSignatureTarget,
|
pub sig_targ: SchnorrSignatureTarget,
|
||||||
}
|
}
|
||||||
impl SignatureGadgetTargets {
|
|
||||||
pub fn build(
|
impl PODGadgetTargets {
|
||||||
|
pub fn add_targets(
|
||||||
mut builder: &mut CircuitBuilder<F, D>,
|
mut builder: &mut CircuitBuilder<F, D>,
|
||||||
msg_targ: &MessageTarget,
|
msg_targ: &MessageTarget,
|
||||||
) -> Result<SignatureGadgetTargets> {
|
) -> Result<Self> {
|
||||||
let selector_targ = builder.add_virtual_target();
|
let selector_targ = builder.add_virtual_target();
|
||||||
// ensure that selector_booltarg is \in {0,1}
|
// ensure that selector_booltarg is \in {0,1}
|
||||||
binary_check(builder, selector_targ);
|
binary_check(builder, selector_targ);
|
||||||
@@ -80,18 +86,19 @@ impl SignatureGadgetTargets {
|
|||||||
sig_targ,
|
sig_targ,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn fill_targets(
|
pub fn set_targets(
|
||||||
&mut self,
|
&mut self,
|
||||||
pw: &mut PartialWitness<F>,
|
pw: &mut PartialWitness<F>,
|
||||||
selector: F, // 1=proof, 0=sig
|
// if `selector` set to 0 will verify the given signature, if set to 1 won't (and the
|
||||||
pk: &SchnorrPublicKey,
|
// recursion layer will verify the respective plonky2 proof)
|
||||||
sig: &SchnorrSignature,
|
selector: F,
|
||||||
|
pod: &PODInput,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
pw.set_target(self.selector_targ, selector)?;
|
pw.set_target(self.selector_targ, selector)?;
|
||||||
|
|
||||||
// set signature related values:
|
// set signature related values:
|
||||||
self.pk_targ.set_witness(pw, &pk).unwrap();
|
self.pk_targ.set_witness(pw, &pod.pk).unwrap();
|
||||||
self.sig_targ.set_witness(pw, &sig).unwrap();
|
self.sig_targ.set_witness(pw, &pod.sig).unwrap();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
/// `(signature proof OR recursive proof) AND ... AND (signature proof OR recursive proof)`
|
/// `(signature proof OR recursive proof) AND ... AND (signature proof OR recursive proof)`
|
||||||
/// and produces a new proof.
|
/// and produces a new proof.
|
||||||
///
|
///
|
||||||
///
|
|
||||||
/// For example, if N is set to N=2, then we work with a binary recursion tree:
|
/// For example, if N is set to N=2, then we work with a binary recursion tree:
|
||||||
/// p_root
|
/// p_root
|
||||||
/// ▲
|
/// ▲
|
||||||
@@ -81,16 +80,18 @@ use plonky2::plonk::circuit_data::{
|
|||||||
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
use plonky2::plonk::proof::{ProofWithPublicInputs, ProofWithPublicInputsTarget};
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use sch::schnorr::*;
|
|
||||||
use sch::schnorr_prover::*;
|
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
|
/// Contains the methods to `add_targets` (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).
|
/// `set_targets` (ie. set the specific values to be used for the previously created targets).
|
||||||
pub struct RecursiveCircuit<const N: usize> {
|
pub struct RecursiveCircuit<const N: usize> {
|
||||||
msg_targ: MessageTarget,
|
msg_targ: MessageTarget,
|
||||||
sigs_targ: Vec<SignatureGadgetTargets>,
|
sigs_targ: Vec<PODGadgetTargets>,
|
||||||
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).
|
||||||
@@ -120,7 +121,7 @@ impl<const N: usize> RecursiveCircuit<N> {
|
|||||||
|
|
||||||
// notice that this method does not fill the targets, which is done in the method
|
// notice that this method does not fill the targets, which is done in the method
|
||||||
// `fill_recursive_circuit_targets`
|
// `fill_recursive_circuit_targets`
|
||||||
pub fn build(
|
pub fn add_targets(
|
||||||
builder: &mut CircuitBuilder<F, D>,
|
builder: &mut CircuitBuilder<F, D>,
|
||||||
verifier_data: VerifierCircuitData<F, C, D>,
|
verifier_data: VerifierCircuitData<F, C, D>,
|
||||||
msg_len: usize,
|
msg_len: usize,
|
||||||
@@ -130,9 +131,9 @@ impl<const N: usize> RecursiveCircuit<N> {
|
|||||||
builder.register_public_inputs(&msg_targ.msg);
|
builder.register_public_inputs(&msg_targ.msg);
|
||||||
|
|
||||||
// build the signature verification logic
|
// build the signature verification logic
|
||||||
let mut sigs_targ: Vec<SignatureGadgetTargets> = vec![];
|
let mut sigs_targ: Vec<PODGadgetTargets> = vec![];
|
||||||
for _ in 0..N {
|
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);
|
sigs_targ.push(sig_targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,13 +162,14 @@ impl<const N: usize> RecursiveCircuit<N> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_targets(
|
pub fn set_targets(
|
||||||
&mut self,
|
&mut self,
|
||||||
pw: &mut PartialWitness<F>,
|
pw: &mut PartialWitness<F>,
|
||||||
msg: &Vec<F>,
|
msg: &Vec<F>,
|
||||||
selectors: Vec<F>, // 1=proof, 0=sig
|
// if selectors[i]==0: verify pods[i] signature. if selectors[i]==1: verify
|
||||||
pks: &Vec<SchnorrPublicKey>,
|
// recursive_proof[i]
|
||||||
sigs: &Vec<SchnorrSignature>,
|
selectors: Vec<F>,
|
||||||
|
pods_input: Vec<PODInput>,
|
||||||
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 sig gadgets)
|
||||||
@@ -175,7 +177,7 @@ impl<const N: usize> RecursiveCircuit<N> {
|
|||||||
|
|
||||||
// set the signature related values
|
// set the signature related values
|
||||||
for i in 0..N {
|
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:
|
// set proof related values:
|
||||||
@@ -236,8 +238,8 @@ pub fn common_data_for_recursion<const N: usize>(msg_len: usize) -> Result<Circu
|
|||||||
vec![],
|
vec![],
|
||||||
);
|
);
|
||||||
|
|
||||||
let _ = SignatureGadgetTargets::build(&mut builder, &msg_targ).unwrap();
|
let _ = PODGadgetTargets::add_targets(&mut builder, &msg_targ).unwrap();
|
||||||
let _ = SignatureGadgetTargets::build(&mut builder, &msg_targ).unwrap();
|
let _ = PODGadgetTargets::add_targets(&mut builder, &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();
|
||||||
@@ -283,7 +285,7 @@ impl<const N: usize> Recursion<N> {
|
|||||||
// 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>::build(&mut builder, data.verifier_data(), msg_len)?;
|
let _ = RecursiveCircuit::<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>();
|
||||||
|
|
||||||
@@ -292,18 +294,22 @@ impl<const N: usize> Recursion<N> {
|
|||||||
|
|
||||||
pub fn prove_step(
|
pub fn prove_step(
|
||||||
verifier_data: VerifierCircuitData<F, C, D>,
|
verifier_data: VerifierCircuitData<F, C, D>,
|
||||||
msg: &Vec<F>,
|
msg: &Vec<F>, // will be an array of "pod roots (hashes)'
|
||||||
selectors: Vec<F>, // 1=proof, 0=sig
|
// if selectors[i]==0: verify pods[i] signature. if selectors[i]==1: verify
|
||||||
pks: &Vec<SchnorrPublicKey>,
|
// recursive_proof[i]
|
||||||
sigs: &Vec<SchnorrSignature>,
|
selectors: Vec<F>,
|
||||||
|
pods_input: Vec<PODInput>,
|
||||||
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!(" (selectors[{}]==1), verify {}-th proof", i, i);
|
println!(" (pods_input[{}].selector==1), verify {}-th proof", i, i);
|
||||||
} else {
|
} else {
|
||||||
println!(" (selectors[{}]==0), verify {}-th signature", i, i);
|
println!(
|
||||||
|
" (pods_input[{}].selector==0), verify {}-th signature",
|
||||||
|
i, i
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,14 +319,14 @@ impl<const N: usize> Recursion<N> {
|
|||||||
// assign the targets
|
// assign the targets
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let mut circuit =
|
let mut circuit =
|
||||||
RecursiveCircuit::<N>::build(&mut builder, verifier_data.clone(), msg.len())?;
|
RecursiveCircuit::<N>::add_targets(&mut builder, verifier_data.clone(), msg.len())?;
|
||||||
println!("RecursiveCircuit::build(): {:?}", 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.fill_targets(&mut pw, msg, selectors, pks, sigs, recursive_proofs)?;
|
circuit.set_targets(&mut pw, msg, selectors, pods_input, recursive_proofs)?;
|
||||||
println!("circuit.fill_targets(): {:?}", start.elapsed());
|
println!("circuit.set_targets(): {:?}", start.elapsed());
|
||||||
|
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
let data = builder.build::<C>();
|
let data = builder.build::<C>();
|
||||||
@@ -361,6 +367,7 @@ mod tests {
|
|||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use sch::schnorr::*;
|
||||||
|
|
||||||
// this sets the plonky2 internal logs level
|
// this sets the plonky2 internal logs level
|
||||||
fn set_log() {
|
fn set_log() {
|
||||||
@@ -377,7 +384,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(())
|
||||||
}
|
}
|
||||||
@@ -387,7 +394,7 @@ mod tests {
|
|||||||
println!("\n--------------------------------------------------");
|
println!("\n--------------------------------------------------");
|
||||||
println!("\n--------------------------------------------------");
|
println!("\n--------------------------------------------------");
|
||||||
println!(
|
println!(
|
||||||
"\nrunning test:\n test_tree_recursion_opt with N={} (arity)",
|
"\nrunning test:\n===test_tree_recursion_opt with N={} (arity)",
|
||||||
N
|
N
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -432,7 +439,7 @@ mod tests {
|
|||||||
|
|
||||||
// loop over the recursion levels
|
// loop over the recursion levels
|
||||||
for i in 0..l {
|
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![];
|
let mut next_level_proofs: Vec<PlonkyProof> = vec![];
|
||||||
|
|
||||||
// loop over the nodes of each recursion tree level
|
// loop over the nodes of each recursion tree level
|
||||||
@@ -453,16 +460,13 @@ mod tests {
|
|||||||
let proof_enabled = if i == 0 { F::ZERO } else { F::ONE };
|
let proof_enabled = if i == 0 { F::ZERO } else { F::ONE };
|
||||||
|
|
||||||
// prepare the inputs for the `Recursion::prove_step` call
|
// prepare the inputs for the `Recursion::prove_step` call
|
||||||
let proofs_selectors = (0..N).into_iter().map(|_| proof_enabled.clone()).collect();
|
let selectors = (0..N).into_iter().map(|_| proof_enabled.clone()).collect();
|
||||||
let pks = (0..N)
|
let pods_input: Vec<PODInput> = (0..N)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.map(|k| PODInput {
|
||||||
.map(|(k, _)| pk_vec[j + k].clone())
|
pk: pk_vec[j + k],
|
||||||
.collect();
|
sig: sig_vec[j + k],
|
||||||
let sigs = (0..N)
|
})
|
||||||
.into_iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(k, _)| sig_vec[j + k].clone())
|
|
||||||
.collect();
|
.collect();
|
||||||
let proofs = (0..N)
|
let proofs = (0..N)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -475,9 +479,8 @@ mod tests {
|
|||||||
let new_proof = Recursion::<N>::prove_step(
|
let new_proof = Recursion::<N>::prove_step(
|
||||||
verifier_data.clone(),
|
verifier_data.clone(),
|
||||||
&msg,
|
&msg,
|
||||||
proofs_selectors,
|
selectors,
|
||||||
&pks,
|
pods_input,
|
||||||
&sigs,
|
|
||||||
&proofs,
|
&proofs,
|
||||||
)?;
|
)?;
|
||||||
println!(
|
println!(
|
||||||
|
|||||||
Reference in New Issue
Block a user