Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-'static second phase #323

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/r1cs/constraint_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ pub trait ConstraintSystem {
/// while gadgets that need randomization should use trait bound `CS: RandomizedConstraintSystem`.
/// Gadgets generally _should not_ use this trait as a bound on the CS argument: it should be used
/// by the higher-order protocol that composes gadgets together.
pub trait RandomizableConstraintSystem: ConstraintSystem {
pub trait RandomizableConstraintSystem<'constraints>: ConstraintSystem {
/// Represents a concrete type for the CS in a randomization phase.
type RandomizedCS: RandomizedConstraintSystem;
type RandomizedCS: RandomizedConstraintSystem + 'constraints;

/// Specify additional variables and constraints randomized using a challenge scalar
/// bound to the assignments of the non-randomized variables.
Expand All @@ -104,9 +104,12 @@ pub trait RandomizableConstraintSystem: ConstraintSystem {
/// // ...
/// })
/// ```
fn specify_randomized_constraints<F>(&mut self, callback: F) -> Result<(), R1CSError>
fn specify_randomized_constraints<'a: 'constraints, F>(
&mut self,
callback: F,
) -> Result<(), R1CSError>
where
F: 'static + Fn(&mut Self::RandomizedCS) -> Result<(), R1CSError>;
F: 'a + FnOnce(&mut Self::RandomizedCS) -> Result<(), R1CSError>;
}

/// Represents a constraint system in the second phase:
Expand Down
32 changes: 20 additions & 12 deletions src/r1cs/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::transcript::TranscriptProtocol;
/// When all constraints are added, the proving code calls `prove`
/// which consumes the `Prover` instance, samples random challenges
/// that instantiate the randomized constraints, and creates a complete proof.
pub struct Prover<'g, T: BorrowMut<Transcript>> {
pub struct Prover<'g, 'c, T: BorrowMut<Transcript>> {
transcript: T,
pc_gens: &'g PedersenGens,
/// The constraints accumulated so far.
Expand All @@ -37,7 +37,8 @@ pub struct Prover<'g, T: BorrowMut<Transcript>> {

/// This list holds closures that will be called in the second phase of the protocol,
/// when non-randomized variables are committed.
deferred_constraints: Vec<Box<dyn Fn(&mut RandomizingProver<'g, T>) -> Result<(), R1CSError>>>,
deferred_constraints:
Vec<Box<dyn 'c + FnOnce(&mut RandomizingProver<'g, 'c, T>) -> Result<(), R1CSError>>>,

/// Index of a pending multiplier that's not fully assigned yet.
pending_multiplier: Option<usize>,
Expand Down Expand Up @@ -65,8 +66,8 @@ struct Secrets {
/// monomorphize the closures for the proving and verifying code.
/// However, this type cannot be instantiated by the user and therefore can only be used within
/// the callback provided to `specify_randomized_constraints`.
pub struct RandomizingProver<'g, T: BorrowMut<Transcript>> {
prover: Prover<'g, T>,
pub struct RandomizingProver<'g, 'c, T: BorrowMut<Transcript>> {
prover: Prover<'g, 'c, T>,
}

/// Overwrite secrets with null bytes when they go out of scope.
Expand All @@ -93,7 +94,7 @@ impl Drop for Secrets {
}
}

impl<'g, T: BorrowMut<Transcript>> ConstraintSystem for Prover<'g, T> {
impl<'g, 'c, T: BorrowMut<Transcript>> ConstraintSystem for Prover<'g, 'c, T> {
fn transcript(&mut self) -> &mut Transcript {
self.transcript.borrow_mut()
}
Expand Down Expand Up @@ -177,19 +178,26 @@ impl<'g, T: BorrowMut<Transcript>> ConstraintSystem for Prover<'g, T> {
}
}

impl<'g, T: BorrowMut<Transcript>> RandomizableConstraintSystem for Prover<'g, T> {
type RandomizedCS = RandomizingProver<'g, T>;
impl<'g, 'constraints, T: BorrowMut<Transcript> + 'constraints>
RandomizableConstraintSystem<'constraints> for Prover<'g, 'constraints, T>
where
'g: 'constraints,
{
type RandomizedCS = RandomizingProver<'g, 'constraints, T>;

fn specify_randomized_constraints<F>(&mut self, callback: F) -> Result<(), R1CSError>
fn specify_randomized_constraints<'a: 'constraints, F>(
&mut self,
callback: F,
) -> Result<(), R1CSError>
where
F: 'static + Fn(&mut Self::RandomizedCS) -> Result<(), R1CSError>,
F: 'a + FnOnce(&mut Self::RandomizedCS) -> Result<(), R1CSError>,
{
self.deferred_constraints.push(Box::new(callback));
Ok(())
}
}

impl<'g, T: BorrowMut<Transcript>> ConstraintSystem for RandomizingProver<'g, T> {
impl<'g, 'c, T: BorrowMut<Transcript>> ConstraintSystem for RandomizingProver<'g, 'c, T> {
fn transcript(&mut self) -> &mut Transcript {
self.prover.transcript.borrow_mut()
}
Expand Down Expand Up @@ -222,13 +230,13 @@ impl<'g, T: BorrowMut<Transcript>> ConstraintSystem for RandomizingProver<'g, T>
}
}

impl<'g, T: BorrowMut<Transcript>> RandomizedConstraintSystem for RandomizingProver<'g, T> {
impl<'g, 'c, T: BorrowMut<Transcript>> RandomizedConstraintSystem for RandomizingProver<'g, 'c, T> {
fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar {
self.prover.transcript.borrow_mut().challenge_scalar(label)
}
}

impl<'g, T: BorrowMut<Transcript>> Prover<'g, T> {
impl<'g, 'c, T: BorrowMut<Transcript>> Prover<'g, 'c, T> {
/// Construct an empty constraint system with specified external
/// input variables.
///
Expand Down
30 changes: 18 additions & 12 deletions src/r1cs/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::transcript::TranscriptProtocol;
/// When all constraints are added, the verifying code calls `verify`
/// which consumes the `Verifier` instance, samples random challenges
/// that instantiate the randomized constraints, and verifies the proof.
pub struct Verifier<T: BorrowMut<Transcript>> {
pub struct Verifier<'c, T: BorrowMut<Transcript>> {
transcript: T,
constraints: Vec<LinearCombination>,

Expand All @@ -43,7 +43,8 @@ pub struct Verifier<T: BorrowMut<Transcript>> {
/// when non-randomized variables are committed.
/// After that, the option will flip to None and additional calls to `randomize_constraints`
/// will invoke closures immediately.
deferred_constraints: Vec<Box<dyn Fn(&mut RandomizingVerifier<T>) -> Result<(), R1CSError>>>,
deferred_constraints:
Vec<Box<dyn 'c + FnOnce(&mut RandomizingVerifier<'c, T>) -> Result<(), R1CSError>>>,

/// Index of a pending multiplier that's not fully assigned yet.
pending_multiplier: Option<usize>,
Expand All @@ -56,11 +57,11 @@ pub struct Verifier<T: BorrowMut<Transcript>> {
/// monomorphize the closures for the proving and verifying code.
/// However, this type cannot be instantiated by the user and therefore can only be used within
/// the callback provided to `specify_randomized_constraints`.
pub struct RandomizingVerifier<T: BorrowMut<Transcript>> {
verifier: Verifier<T>,
pub struct RandomizingVerifier<'c, T: BorrowMut<Transcript>> {
verifier: Verifier<'c, T>,
}

impl<T: BorrowMut<Transcript>> ConstraintSystem for Verifier<T> {
impl<'c, T: BorrowMut<Transcript>> ConstraintSystem for Verifier<'c, T> {
fn transcript(&mut self) -> &mut Transcript {
self.transcript.borrow_mut()
}
Expand Down Expand Up @@ -129,19 +130,24 @@ impl<T: BorrowMut<Transcript>> ConstraintSystem for Verifier<T> {
}
}

impl<T: BorrowMut<Transcript>> RandomizableConstraintSystem for Verifier<T> {
type RandomizedCS = RandomizingVerifier<T>;
impl<'constraints, T: BorrowMut<Transcript> + 'constraints>
RandomizableConstraintSystem<'constraints> for Verifier<'constraints, T>
{
type RandomizedCS = RandomizingVerifier<'constraints, T>;

fn specify_randomized_constraints<F>(&mut self, callback: F) -> Result<(), R1CSError>
fn specify_randomized_constraints<'a: 'constraints, F>(
&mut self,
callback: F,
) -> Result<(), R1CSError>
where
F: 'static + Fn(&mut Self::RandomizedCS) -> Result<(), R1CSError>,
F: 'a + FnOnce(&mut Self::RandomizedCS) -> Result<(), R1CSError>,
{
self.deferred_constraints.push(Box::new(callback));
Ok(())
}
}

impl<T: BorrowMut<Transcript>> ConstraintSystem for RandomizingVerifier<T> {
impl<'c, T: BorrowMut<Transcript>> ConstraintSystem for RandomizingVerifier<'c, T> {
fn transcript(&mut self) -> &mut Transcript {
self.verifier.transcript.borrow_mut()
}
Expand Down Expand Up @@ -174,7 +180,7 @@ impl<T: BorrowMut<Transcript>> ConstraintSystem for RandomizingVerifier<T> {
}
}

impl<T: BorrowMut<Transcript>> RandomizedConstraintSystem for RandomizingVerifier<T> {
impl<'c, T: BorrowMut<Transcript>> RandomizedConstraintSystem for RandomizingVerifier<'c, T> {
fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar {
self.verifier
.transcript
Expand All @@ -183,7 +189,7 @@ impl<T: BorrowMut<Transcript>> RandomizedConstraintSystem for RandomizingVerifie
}
}

impl<T: BorrowMut<Transcript>> Verifier<T> {
impl<'c, T: BorrowMut<Transcript>> Verifier<'c, T> {
/// Construct an empty constraint system with specified external
/// input variables.
///
Expand Down
37 changes: 36 additions & 1 deletion tests/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use rand::thread_rng;
struct ShuffleProof(R1CSProof);

impl ShuffleProof {
fn gadget<CS: RandomizableConstraintSystem>(
fn gadget<'c, CS: RandomizableConstraintSystem<'c>>(
cs: &mut CS,
x: Vec<Variable>,
y: Vec<Variable>,
Expand Down Expand Up @@ -452,3 +452,38 @@ fn range_proof_helper(v_val: u64, n: usize) -> Result<(), R1CSError> {
// Verifier verifies proof
verifier.verify(&proof, &pc_gens, &bp_gens)
}

#[test]
fn non_static_lifetimes() {
// Common
let pc_gens = PedersenGens::default();
let bp_gens = BulletproofGens::new(128, 1);

let a = 1;
let a: &u32 = &a;

let proof = {
let mut prover_transcript = Transcript::new(b"NonStaticRandomClosuresTest");
let mut prover = Prover::new(&pc_gens, &mut prover_transcript);

prover
.specify_randomized_constraints(|rcs| {
rcs.constrain((Scalar::from(a.clone()) - Scalar::one()).into());
Ok(())
})
.unwrap();

let proof = prover.prove(&bp_gens).unwrap();
proof
};

let mut verifier_transcript = Transcript::new(b"NonStaticRandomClosuresTest");
let mut verifier = Verifier::new(&mut verifier_transcript);
verifier
.specify_randomized_constraints(|rcs| {
rcs.constrain((Scalar::from(a.clone()) - Scalar::one()).into());
Ok(())
})
.unwrap();
verifier.verify(&proof, &pc_gens, &bp_gens).unwrap();
}