Skip to content

Commit 8728213

Browse files
committed
R1CS: Allow non-static lifetimes for second-phase closures.
This adds a general lifetime for the second-phase constraints on RandomizeableConstraintSystem, which should cover the lifetime of each closure given to specify_randomized_constraints(). The latter can receive shorter lifetimes.
1 parent ec19cb3 commit 8728213

File tree

4 files changed

+79
-29
lines changed

4 files changed

+79
-29
lines changed

src/r1cs/constraint_system.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ pub trait ConstraintSystem {
8181
/// while gadgets that need randomization should use trait bound `CS: RandomizedConstraintSystem`.
8282
/// Gadgets generally _should not_ use this trait as a bound on the CS argument: it should be used
8383
/// by the higher-order protocol that composes gadgets together.
84-
pub trait RandomizableConstraintSystem: ConstraintSystem {
84+
pub trait RandomizableConstraintSystem<'constraints>: ConstraintSystem {
8585
/// Represents a concrete type for the CS in a randomization phase.
86-
type RandomizedCS: RandomizedConstraintSystem;
86+
type RandomizedCS: RandomizedConstraintSystem + 'constraints;
8787

8888
/// Specify additional variables and constraints randomized using a challenge scalar
8989
/// bound to the assignments of the non-randomized variables.
@@ -104,9 +104,12 @@ pub trait RandomizableConstraintSystem: ConstraintSystem {
104104
/// // ...
105105
/// })
106106
/// ```
107-
fn specify_randomized_constraints<F>(&mut self, callback: F) -> Result<(), R1CSError>
107+
fn specify_randomized_constraints<'a: 'constraints, F>(
108+
&mut self,
109+
callback: F,
110+
) -> Result<(), R1CSError>
108111
where
109-
F: 'static + FnOnce(&mut Self::RandomizedCS) -> Result<(), R1CSError>;
112+
F: 'a + FnOnce(&mut Self::RandomizedCS) -> Result<(), R1CSError>;
110113
}
111114

112115
/// Represents a constraint system in the second phase:

src/r1cs/prover.rs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use crate::transcript::TranscriptProtocol;
2727
/// When all constraints are added, the proving code calls `prove`
2828
/// which consumes the `Prover` instance, samples random challenges
2929
/// that instantiate the randomized constraints, and creates a complete proof.
30-
pub struct Prover<'g, T: BorrowMut<Transcript>> {
30+
pub struct Prover<'g, 'c, T: BorrowMut<Transcript>> {
3131
transcript: T,
3232
pc_gens: &'g PedersenGens,
3333
/// The constraints accumulated so far.
@@ -38,7 +38,7 @@ pub struct Prover<'g, T: BorrowMut<Transcript>> {
3838
/// This list holds closures that will be called in the second phase of the protocol,
3939
/// when non-randomized variables are committed.
4040
deferred_constraints:
41-
Vec<Box<dyn FnOnce(&mut RandomizingProver<'g, T>) -> Result<(), R1CSError>>>,
41+
Vec<Box<dyn 'c + FnOnce(&mut RandomizingProver<'g, 'c, T>) -> Result<(), R1CSError>>>,
4242

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

7373
/// Overwrite secrets with null bytes when they go out of scope.
@@ -94,7 +94,7 @@ impl Drop for Secrets {
9494
}
9595
}
9696

97-
impl<'g, T: BorrowMut<Transcript>> ConstraintSystem for Prover<'g, T> {
97+
impl<'g, 'c, T: BorrowMut<Transcript>> ConstraintSystem for Prover<'g, 'c, T> {
9898
fn transcript(&mut self) -> &mut Transcript {
9999
self.transcript.borrow_mut()
100100
}
@@ -178,19 +178,26 @@ impl<'g, T: BorrowMut<Transcript>> ConstraintSystem for Prover<'g, T> {
178178
}
179179
}
180180

181-
impl<'g, T: BorrowMut<Transcript>> RandomizableConstraintSystem for Prover<'g, T> {
182-
type RandomizedCS = RandomizingProver<'g, T>;
181+
impl<'g, 'constraints, T: BorrowMut<Transcript> + 'constraints>
182+
RandomizableConstraintSystem<'constraints> for Prover<'g, 'constraints, T>
183+
where
184+
'g: 'constraints,
185+
{
186+
type RandomizedCS = RandomizingProver<'g, 'constraints, T>;
183187

184-
fn specify_randomized_constraints<F>(&mut self, callback: F) -> Result<(), R1CSError>
188+
fn specify_randomized_constraints<'a: 'constraints, F>(
189+
&mut self,
190+
callback: F,
191+
) -> Result<(), R1CSError>
185192
where
186-
F: 'static + FnOnce(&mut Self::RandomizedCS) -> Result<(), R1CSError>,
193+
F: 'a + FnOnce(&mut Self::RandomizedCS) -> Result<(), R1CSError>,
187194
{
188195
self.deferred_constraints.push(Box::new(callback));
189196
Ok(())
190197
}
191198
}
192199

193-
impl<'g, T: BorrowMut<Transcript>> ConstraintSystem for RandomizingProver<'g, T> {
200+
impl<'g, 'c, T: BorrowMut<Transcript>> ConstraintSystem for RandomizingProver<'g, 'c, T> {
194201
fn transcript(&mut self) -> &mut Transcript {
195202
self.prover.transcript.borrow_mut()
196203
}
@@ -223,13 +230,13 @@ impl<'g, T: BorrowMut<Transcript>> ConstraintSystem for RandomizingProver<'g, T>
223230
}
224231
}
225232

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

232-
impl<'g, T: BorrowMut<Transcript>> Prover<'g, T> {
239+
impl<'g, 'c, T: BorrowMut<Transcript>> Prover<'g, 'c, T> {
233240
/// Construct an empty constraint system with specified external
234241
/// input variables.
235242
///

src/r1cs/verifier.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::transcript::TranscriptProtocol;
2525
/// When all constraints are added, the verifying code calls `verify`
2626
/// which consumes the `Verifier` instance, samples random challenges
2727
/// that instantiate the randomized constraints, and verifies the proof.
28-
pub struct Verifier<T: BorrowMut<Transcript>> {
28+
pub struct Verifier<'c, T: BorrowMut<Transcript>> {
2929
transcript: T,
3030
constraints: Vec<LinearCombination>,
3131

@@ -44,7 +44,7 @@ pub struct Verifier<T: BorrowMut<Transcript>> {
4444
/// After that, the option will flip to None and additional calls to `randomize_constraints`
4545
/// will invoke closures immediately.
4646
deferred_constraints:
47-
Vec<Box<dyn FnOnce(&mut RandomizingVerifier<T>) -> Result<(), R1CSError>>>,
47+
Vec<Box<dyn 'c + FnOnce(&mut RandomizingVerifier<'c, T>) -> Result<(), R1CSError>>>,
4848

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

64-
impl<T: BorrowMut<Transcript>> ConstraintSystem for Verifier<T> {
64+
impl<'c, T: BorrowMut<Transcript>> ConstraintSystem for Verifier<'c, T> {
6565
fn transcript(&mut self) -> &mut Transcript {
6666
self.transcript.borrow_mut()
6767
}
@@ -130,19 +130,24 @@ impl<T: BorrowMut<Transcript>> ConstraintSystem for Verifier<T> {
130130
}
131131
}
132132

133-
impl<T: BorrowMut<Transcript>> RandomizableConstraintSystem for Verifier<T> {
134-
type RandomizedCS = RandomizingVerifier<T>;
133+
impl<'constraints, T: BorrowMut<Transcript> + 'constraints>
134+
RandomizableConstraintSystem<'constraints> for Verifier<'constraints, T>
135+
{
136+
type RandomizedCS = RandomizingVerifier<'constraints, T>;
135137

136-
fn specify_randomized_constraints<F>(&mut self, callback: F) -> Result<(), R1CSError>
138+
fn specify_randomized_constraints<'a: 'constraints, F>(
139+
&mut self,
140+
callback: F,
141+
) -> Result<(), R1CSError>
137142
where
138-
F: 'static + FnOnce(&mut Self::RandomizedCS) -> Result<(), R1CSError>,
143+
F: 'a + FnOnce(&mut Self::RandomizedCS) -> Result<(), R1CSError>,
139144
{
140145
self.deferred_constraints.push(Box::new(callback));
141146
Ok(())
142147
}
143148
}
144149

145-
impl<T: BorrowMut<Transcript>> ConstraintSystem for RandomizingVerifier<T> {
150+
impl<'c, T: BorrowMut<Transcript>> ConstraintSystem for RandomizingVerifier<'c, T> {
146151
fn transcript(&mut self) -> &mut Transcript {
147152
self.verifier.transcript.borrow_mut()
148153
}
@@ -175,7 +180,7 @@ impl<T: BorrowMut<Transcript>> ConstraintSystem for RandomizingVerifier<T> {
175180
}
176181
}
177182

178-
impl<T: BorrowMut<Transcript>> RandomizedConstraintSystem for RandomizingVerifier<T> {
183+
impl<'c, T: BorrowMut<Transcript>> RandomizedConstraintSystem for RandomizingVerifier<'c, T> {
179184
fn challenge_scalar(&mut self, label: &'static [u8]) -> Scalar {
180185
self.verifier
181186
.transcript
@@ -184,7 +189,7 @@ impl<T: BorrowMut<Transcript>> RandomizedConstraintSystem for RandomizingVerifie
184189
}
185190
}
186191

187-
impl<T: BorrowMut<Transcript>> Verifier<T> {
192+
impl<'c, T: BorrowMut<Transcript>> Verifier<'c, T> {
188193
/// Construct an empty constraint system with specified external
189194
/// input variables.
190195
///

tests/r1cs.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rand::thread_rng;
1919
struct ShuffleProof(R1CSProof);
2020

2121
impl ShuffleProof {
22-
fn gadget<CS: RandomizableConstraintSystem>(
22+
fn gadget<'c, CS: RandomizableConstraintSystem<'c>>(
2323
cs: &mut CS,
2424
x: Vec<Variable>,
2525
y: Vec<Variable>,
@@ -452,3 +452,38 @@ fn range_proof_helper(v_val: u64, n: usize) -> Result<(), R1CSError> {
452452
// Verifier verifies proof
453453
verifier.verify(&proof, &pc_gens, &bp_gens)
454454
}
455+
456+
#[test]
457+
fn non_static_lifetimes() {
458+
// Common
459+
let pc_gens = PedersenGens::default();
460+
let bp_gens = BulletproofGens::new(128, 1);
461+
462+
let a = 1;
463+
let a: &u32 = &a;
464+
465+
let proof = {
466+
let mut prover_transcript = Transcript::new(b"NonStaticRandomClosuresTest");
467+
let mut prover = Prover::new(&pc_gens, &mut prover_transcript);
468+
469+
prover
470+
.specify_randomized_constraints(|rcs| {
471+
rcs.constrain((Scalar::from(a.clone()) - Scalar::one()).into());
472+
Ok(())
473+
})
474+
.unwrap();
475+
476+
let proof = prover.prove(&bp_gens).unwrap();
477+
proof
478+
};
479+
480+
let mut verifier_transcript = Transcript::new(b"NonStaticRandomClosuresTest");
481+
let mut verifier = Verifier::new(&mut verifier_transcript);
482+
verifier
483+
.specify_randomized_constraints(|rcs| {
484+
rcs.constrain((Scalar::from(a.clone()) - Scalar::one()).into());
485+
Ok(())
486+
})
487+
.unwrap();
488+
verifier.verify(&proof, &pc_gens, &bp_gens).unwrap();
489+
}

0 commit comments

Comments
 (0)