Skip to content

Commit 5c6efe8

Browse files
authored
Implement API for two-phase constraint system proofs (#232)
This provides the implementation for two-phase protocol redesign as described in #222. Challenges are available in a section of code within a closure provided to `cs.specify_randomized_constraints` call: ```rust cs.specify_randomized_constraints(move |cs| { let z = cs.challenge_scalar(b"shuffle challenge"); ... }) ``` Prover and Verifier now allow interspersing high-level variable commitments with the constraints in the first phase (which allows gadgets to introduce their own high-level variables during CS construction). Since the callbacks must return a known-to-the-framework error type (`R1CSError`) and some gadgets can be composed within the second phase (cf. tuple shuffle + scalar shuffle), this PR also introduces a catch-all error variant `R1CSError::GadgetError` which allows gadgets to signal inconsistency in their parameters.
1 parent f95940a commit 5c6efe8

File tree

12 files changed

+675
-377
lines changed

12 files changed

+675
-377
lines changed

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ language: rust
22
cache: cargo
33

44
rust:
5-
- nightly
5+
- nightly-2018-12-31
66

77
env:
88
- TEST_COMMAND=test EXTRA_FLAGS='' FEATURES=''
@@ -12,8 +12,9 @@ env:
1212
- TEST_COMMAND=bench EXTRA_FLAGS='"DONTRUNBENCHMARKS"' FEATURES=''
1313

1414
matrix:
15+
fast_finish: true
1516
include:
16-
- rust: nightly-2018-12-04
17+
- rust: nightly-2018-12-31
1718
before_script:
1819
- rustup component add rustfmt-preview
1920
script:

benches/r1cs.rs

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
extern crate bulletproofs;
2-
use bulletproofs::r1cs::{ConstraintSystem, Prover, R1CSError, R1CSProof, Variable, Verifier};
2+
use bulletproofs::r1cs::{
3+
ConstraintSystem, Prover, R1CSError, R1CSProof, RandomizedConstraintSystem, Variable, Verifier,
4+
};
35
use bulletproofs::{BulletproofGens, PedersenGens};
46

57
#[macro_use]
@@ -71,42 +73,51 @@ For K = 1:
7173
struct KShuffleGadget {}
7274

7375
impl KShuffleGadget {
74-
fn fill_cs<CS: ConstraintSystem>(cs: &mut CS, x: &[Variable], y: &[Variable]) {
76+
fn fill_cs<CS: ConstraintSystem>(
77+
cs: &mut CS,
78+
x: Vec<Variable>,
79+
y: Vec<Variable>,
80+
) -> Result<(), R1CSError> {
7581
let one = Scalar::one();
76-
let z = cs.challenge_scalar(b"k-scalar shuffle challenge");
7782

7883
assert_eq!(x.len(), y.len());
7984

8085
let k = x.len();
8186
if k == 1 {
8287
cs.constrain([(x[0], -one), (y[0], one)].iter().collect());
83-
return;
88+
return Ok(());
8489
}
8590

86-
// Make last x multiplier for i = k-1 and k-2
87-
let (_, _, last_mulx_out) = cs.multiply(x[k - 1] - z, x[k - 2] - z);
88-
89-
// Make multipliers for x from i == [0, k-3]
90-
let first_mulx_out = (0..k - 2).rev().fold(last_mulx_out, |prev_out, i| {
91-
let (_, _, o) = cs.multiply(prev_out.into(), x[i] - z);
92-
o
93-
});
94-
95-
// Make last y multiplier for i = k-1 and k-2
96-
let (_, _, last_muly_out) = cs.multiply(y[k - 1] - z, y[k - 2] - z);
97-
98-
// Make multipliers for y from i == [0, k-3]
99-
let first_muly_out = (0..k - 2).rev().fold(last_muly_out, |prev_out, i| {
100-
let (_, _, o) = cs.multiply(prev_out.into(), y[i] - z);
101-
o
102-
});
103-
104-
// Constrain last x mul output and last y mul output to be equal
105-
cs.constrain(
106-
[(first_muly_out, -one), (first_mulx_out, one)]
107-
.iter()
108-
.collect(),
109-
);
91+
cs.specify_randomized_constraints(move |cs| {
92+
let z = cs.challenge_scalar(b"shuffle challenge");
93+
94+
// Make last x multiplier for i = k-1 and k-2
95+
let (_, _, last_mulx_out) = cs.multiply(x[k - 1] - z, x[k - 2] - z);
96+
97+
// Make multipliers for x from i == [0, k-3]
98+
let first_mulx_out = (0..k - 2).rev().fold(last_mulx_out, |prev_out, i| {
99+
let (_, _, o) = cs.multiply(prev_out.into(), x[i] - z);
100+
o
101+
});
102+
103+
// Make last y multiplier for i = k-1 and k-2
104+
let (_, _, last_muly_out) = cs.multiply(y[k - 1] - z, y[k - 2] - z);
105+
106+
// Make multipliers for y from i == [0, k-3]
107+
let first_muly_out = (0..k - 2).rev().fold(last_muly_out, |prev_out, i| {
108+
let (_, _, o) = cs.multiply(prev_out.into(), y[i] - z);
109+
o
110+
});
111+
112+
// Constrain last x mul output and last y mul output to be equal
113+
cs.constrain(
114+
[(first_muly_out, -one), (first_mulx_out, one)]
115+
.iter()
116+
.collect(),
117+
);
118+
119+
Ok(())
120+
})
110121
}
111122

112123
pub fn prove<'a, 'b>(
@@ -144,11 +155,8 @@ impl KShuffleGadget {
144155
.map(|v| prover.commit(*v, Scalar::random(&mut blinding_rng)))
145156
.unzip();
146157

147-
let mut cs = prover.finalize_inputs();
148-
149-
Self::fill_cs(&mut cs, &input_vars, &output_vars);
150-
151-
let proof = cs.prove()?;
158+
Self::fill_cs(&mut prover, input_vars, output_vars)?;
159+
let proof = prover.prove()?;
152160

153161
Ok((proof, input_commitments, output_commitments))
154162
}
@@ -178,11 +186,8 @@ impl KShuffleGadget {
178186
.map(|commitment| verifier.commit(*commitment))
179187
.collect();
180188

181-
let mut cs = verifier.finalize_inputs();
182-
183-
Self::fill_cs(&mut cs, &input_vars, &output_vars);
184-
185-
cs.verify(proof)
189+
Self::fill_cs(&mut verifier, input_vars, output_vars)?;
190+
verifier.verify(proof)
186191
}
187192
}
188193

0 commit comments

Comments
 (0)