Skip to content

Commit 2d9f552

Browse files
committed
fix for newer pairing and ff
1 parent b6160fc commit 2d9f552

File tree

5 files changed

+207
-164
lines changed

5 files changed

+207
-164
lines changed

Cargo.toml

+4-6
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ homepage = "https://github.com/matter-labs/bellman"
66
license = "MIT/Apache-2.0"
77
name = "bellman_ce"
88
repository = "https://github.com/matter-labs/bellman"
9-
version = "0.3.0"
9+
version = "0.3.1"
1010
edition = "2018"
1111

1212
[lib]
@@ -18,8 +18,8 @@ bit-vec = "0.4.4"
1818
futures = "0.1"
1919
cfg-if = "0.1.7"
2020

21-
#pairing_ce = { path = "../pairing" }
22-
pairing_ce = { version = "0.17.0" }
21+
pairing = {package = "pairing_ce", path = "../pairing" }
22+
#pairing = {package = "pairing_ce", version = "0.17.0" }
2323
byteorder = "1"
2424

2525
futures-cpupool = {version = "0.1", optional = true}
@@ -32,9 +32,7 @@ tiny-keccak = {version = "1.4.2", optional = true}
3232
blake2-rfc = {version = "0.2.18", optional = true}
3333

3434
[features]
35-
#default = ["multicore"]
36-
default = ["multicore", "sonic"]
37-
#default = ["multicore", "gm17", "sonic"]
35+
default = ["multicore"]
3836
#default = ["wasm"]
3937
multicore = ["futures-cpupool", "num_cpus", "crossbeam"]
4038
sonic = ["tiny-keccak", "blake2-rfc"]

src/groth16/prover.rs

+61-152
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,48 @@ fn eval<E: Engine>(
8686
acc
8787
}
8888

89+
pub(crate) fn field_elements_into_representations<E: Engine>(
90+
worker: &Worker,
91+
scalars: Vec<E::Fr>
92+
) -> Result<Vec<<E::Fr as PrimeField>::Repr>, SynthesisError>
93+
{
94+
let mut representations = vec![<E::Fr as PrimeField>::Repr::default(); scalars.len()];
95+
worker.scope(scalars.len(), |scope, chunk| {
96+
for (scalar, repr) in scalars.chunks(chunk)
97+
.zip(representations.chunks_mut(chunk)) {
98+
scope.spawn(move |_| {
99+
for (scalar, repr) in scalar.iter()
100+
.zip(repr.iter_mut()) {
101+
*repr = scalar.into_repr();
102+
}
103+
});
104+
}
105+
});
106+
107+
Ok(representations)
108+
}
109+
110+
pub(crate) fn scalars_into_representations<E: Engine>(
111+
worker: &Worker,
112+
scalars: Vec<Scalar<E>>
113+
) -> Result<Vec<<E::Fr as PrimeField>::Repr>, SynthesisError>
114+
{
115+
let mut representations = vec![<E::Fr as PrimeField>::Repr::default(); scalars.len()];
116+
worker.scope(scalars.len(), |scope, chunk| {
117+
for (scalar, repr) in scalars.chunks(chunk)
118+
.zip(representations.chunks_mut(chunk)) {
119+
scope.spawn(move |_| {
120+
for (scalar, repr) in scalar.iter()
121+
.zip(repr.iter_mut()) {
122+
*repr = scalar.0.into_repr();
123+
}
124+
});
125+
}
126+
});
127+
128+
Ok(representations)
129+
}
130+
89131
// This is a proving assignment with densities precalculated
90132
pub struct PreparedProver<E: Engine>{
91133
assignment: ProvingAssignment<E>,
@@ -145,7 +187,7 @@ pub fn prepare_prover<E, C>(
145187

146188
impl<E:Engine> PreparedProver<E> {
147189
pub fn create_random_proof<R, P: ParameterSource<E>>(
148-
& self,
190+
self,
149191
params: P,
150192
rng: &mut R
151193
) -> Result<Proof<E>, SynthesisError>
@@ -158,16 +200,16 @@ impl<E:Engine> PreparedProver<E> {
158200
}
159201

160202
pub fn create_proof<P: ParameterSource<E>>(
161-
& self,
203+
self,
162204
mut params: P,
163205
r: E::Fr,
164206
s: E::Fr
165207
) -> Result<Proof<E>, SynthesisError>
166208
{
167-
let prover = self.assignment.clone();
209+
let prover = self.assignment;
168210
let worker = Worker::new();
169211

170-
let vk = params.get_vk(self.assignment.input_assignment.len())?;
212+
let vk = params.get_vk(prover.input_assignment.len())?;
171213

172214
let stopwatch = Stopwatch::new();
173215

@@ -202,7 +244,8 @@ impl<E:Engine> PreparedProver<E> {
202244
a.truncate(a_len);
203245
// TODO: parallelize if it's even helpful
204246
// TODO: in large settings it may worth to parallelize
205-
let a = Arc::new(a.into_iter().map(|s| s.0.into_repr()).collect::<Vec<_>>());
247+
let a = Arc::new(scalars_into_representations::<E>(&worker, a)?);
248+
// let a = Arc::new(a.into_iter().map(|s| s.0.into_repr()).collect::<Vec<_>>());
206249

207250
multiexp(&worker, params.get_h(a.len())?, FullDensity, a)
208251
};
@@ -213,13 +256,19 @@ impl<E:Engine> PreparedProver<E> {
213256

214257
// TODO: Check that difference in operations for different chunks is small
215258

259+
let input_len = prover.input_assignment.len();
260+
let aux_len = prover.aux_assignment.len();
261+
262+
let input_assignment = Arc::new(field_elements_into_representations::<E>(&worker, prover.input_assignment)?);
263+
let aux_assignment = Arc::new(field_elements_into_representations::<E>(&worker, prover.aux_assignment)?);
264+
216265
// TODO: parallelize if it's even helpful
217266
// TODO: in large settings it may worth to parallelize
218-
let input_assignment = Arc::new(prover.input_assignment.into_iter().map(|s| s.into_repr()).collect::<Vec<_>>());
219-
let aux_assignment = Arc::new(prover.aux_assignment.into_iter().map(|s| s.into_repr()).collect::<Vec<_>>());
267+
// let input_assignment = Arc::new(prover.input_assignment.into_iter().map(|s| s.into_repr()).collect::<Vec<_>>());
268+
// let aux_assignment = Arc::new(prover.aux_assignment.into_iter().map(|s| s.into_repr()).collect::<Vec<_>>());
220269

221-
let input_len = input_assignment.len();
222-
let aux_len = aux_assignment.len();
270+
// let input_len = input_assignment.len();
271+
// let aux_len = aux_assignment.len();
223272
elog_verbose!("H query is dense in G1,\nOther queries are {} elements in G1 and {} elements in G2",
224273
2*(input_len + aux_len) + aux_len, input_len + aux_len);
225274

@@ -402,153 +451,13 @@ pub fn create_random_proof<E, C, R, P: ParameterSource<E>>(
402451

403452
pub fn create_proof<E, C, P: ParameterSource<E>>(
404453
circuit: C,
405-
mut params: P,
454+
params: P,
406455
r: E::Fr,
407456
s: E::Fr
408457
) -> Result<Proof<E>, SynthesisError>
409458
where E: Engine, C: Circuit<E>
410459
{
411-
let mut prover = ProvingAssignment {
412-
a_aux_density: DensityTracker::new(),
413-
b_input_density: DensityTracker::new(),
414-
b_aux_density: DensityTracker::new(),
415-
a: vec![],
416-
b: vec![],
417-
c: vec![],
418-
input_assignment: vec![],
419-
aux_assignment: vec![]
420-
};
421-
422-
prover.alloc_input(|| "", || Ok(E::Fr::one()))?;
460+
let prover = prepare_prover(circuit)?;
423461

424-
circuit.synthesize(&mut prover)?;
425-
426-
for i in 0..prover.input_assignment.len() {
427-
prover.enforce(|| "",
428-
|lc| lc + Variable(Index::Input(i)),
429-
|lc| lc,
430-
|lc| lc,
431-
);
432-
}
433-
434-
let worker = Worker::new();
435-
436-
let vk = params.get_vk(prover.input_assignment.len())?;
437-
438-
let stopwatch = Stopwatch::new();
439-
440-
let h = {
441-
let mut a = EvaluationDomain::from_coeffs(prover.a)?;
442-
let mut b = EvaluationDomain::from_coeffs(prover.b)?;
443-
let mut c = EvaluationDomain::from_coeffs(prover.c)?;
444-
elog_verbose!("H query domain size is {}", a.as_ref().len());
445-
// here a coset is a domain where denominator (z) does not vanish
446-
// inverse FFT is an interpolation
447-
a.ifft(&worker);
448-
// evaluate in coset
449-
a.coset_fft(&worker);
450-
// same is for B and C
451-
b.ifft(&worker);
452-
b.coset_fft(&worker);
453-
c.ifft(&worker);
454-
c.coset_fft(&worker);
455-
456-
// do A*B-C in coset
457-
a.mul_assign(&worker, &b);
458-
drop(b);
459-
a.sub_assign(&worker, &c);
460-
drop(c);
461-
// z does not vanish in coset, so we divide by non-zero
462-
a.divide_by_z_on_coset(&worker);
463-
// interpolate back in coset
464-
a.icoset_fft(&worker);
465-
let mut a = a.into_coeffs();
466-
let a_len = a.len() - 1;
467-
a.truncate(a_len);
468-
// TODO: parallelize if it's even helpful
469-
// TODO: in large settings it may worth to parallelize
470-
let a = Arc::new(a.into_iter().map(|s| s.0.into_repr()).collect::<Vec<_>>());
471-
472-
multiexp(&worker, params.get_h(a.len())?, FullDensity, a)
473-
};
474-
475-
elog_verbose!("{} seconds for prover for H evaluation (mostly FFT)", stopwatch.elapsed());
476-
477-
let stopwatch = Stopwatch::new();
478-
479-
// TODO: Check that difference in operations for different chunks is small
480-
481-
// TODO: parallelize if it's even helpful
482-
// TODO: in large settings it may worth to parallelize
483-
let input_assignment = Arc::new(prover.input_assignment.into_iter().map(|s| s.into_repr()).collect::<Vec<_>>());
484-
let aux_assignment = Arc::new(prover.aux_assignment.into_iter().map(|s| s.into_repr()).collect::<Vec<_>>());
485-
486-
// Run a dedicated process for dense vector
487-
let l = multiexp(&worker, params.get_l(aux_assignment.len())?, FullDensity, aux_assignment.clone());
488-
489-
let a_aux_density_total = prover.a_aux_density.get_total_density();
490-
491-
let (a_inputs_source, a_aux_source) = params.get_a(input_assignment.len(), a_aux_density_total)?;
492-
493-
let a_inputs = multiexp(&worker, a_inputs_source, FullDensity, input_assignment.clone());
494-
let a_aux = multiexp(&worker, a_aux_source, Arc::new(prover.a_aux_density), aux_assignment.clone());
495-
496-
let b_input_density = Arc::new(prover.b_input_density);
497-
let b_input_density_total = b_input_density.get_total_density();
498-
let b_aux_density = Arc::new(prover.b_aux_density);
499-
let b_aux_density_total = b_aux_density.get_total_density();
500-
501-
let (b_g1_inputs_source, b_g1_aux_source) = params.get_b_g1(b_input_density_total, b_aux_density_total)?;
502-
503-
let b_g1_inputs = multiexp(&worker, b_g1_inputs_source, b_input_density.clone(), input_assignment.clone());
504-
let b_g1_aux = multiexp(&worker, b_g1_aux_source, b_aux_density.clone(), aux_assignment.clone());
505-
506-
let (b_g2_inputs_source, b_g2_aux_source) = params.get_b_g2(b_input_density_total, b_aux_density_total)?;
507-
508-
let b_g2_inputs = multiexp(&worker, b_g2_inputs_source, b_input_density, input_assignment);
509-
let b_g2_aux = multiexp(&worker, b_g2_aux_source, b_aux_density, aux_assignment);
510-
511-
if vk.delta_g1.is_zero() || vk.delta_g2.is_zero() {
512-
// If this element is zero, someone is trying to perform a
513-
// subversion-CRS attack.
514-
return Err(SynthesisError::UnexpectedIdentity);
515-
}
516-
517-
let mut g_a = vk.delta_g1.mul(r);
518-
g_a.add_assign_mixed(&vk.alpha_g1);
519-
let mut g_b = vk.delta_g2.mul(s);
520-
g_b.add_assign_mixed(&vk.beta_g2);
521-
let mut g_c;
522-
{
523-
let mut rs = r;
524-
rs.mul_assign(&s);
525-
526-
g_c = vk.delta_g1.mul(rs);
527-
g_c.add_assign(&vk.alpha_g1.mul(s));
528-
g_c.add_assign(&vk.beta_g1.mul(r));
529-
}
530-
let mut a_answer = a_inputs.wait()?;
531-
a_answer.add_assign(&a_aux.wait()?);
532-
g_a.add_assign(&a_answer);
533-
a_answer.mul_assign(s);
534-
g_c.add_assign(&a_answer);
535-
536-
let mut b1_answer = b_g1_inputs.wait()?;
537-
b1_answer.add_assign(&b_g1_aux.wait()?);
538-
let mut b2_answer = b_g2_inputs.wait()?;
539-
b2_answer.add_assign(&b_g2_aux.wait()?);
540-
541-
g_b.add_assign(&b2_answer);
542-
b1_answer.mul_assign(r);
543-
g_c.add_assign(&b1_answer);
544-
g_c.add_assign(&h.wait()?);
545-
g_c.add_assign(&l.wait()?);
546-
547-
elog_verbose!("{} seconds for prover for point multiplication", stopwatch.elapsed());
548-
549-
Ok(Proof {
550-
a: g_a.into_affine(),
551-
b: g_b.into_affine(),
552-
c: g_c.into_affine()
553-
})
462+
prover.create_proof(params, r, s)
554463
}

src/lib.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#[macro_use]
44

55
extern crate cfg_if;
6-
extern crate pairing_ce as pairing_import;
6+
pub extern crate pairing;
77
extern crate rand;
88
extern crate bit_vec;
99
extern crate byteorder;
@@ -43,10 +43,6 @@ cfg_if! {
4343
}
4444
}
4545

46-
pub mod pairing {
47-
pub use pairing_import::*;
48-
}
49-
5046
mod cs;
5147
pub use self::cs::*;
5248

0 commit comments

Comments
 (0)