-
Notifications
You must be signed in to change notification settings - Fork 136
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
Improvements over plonk #671
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -341,33 +341,38 @@ where | |
fn round_2( | ||
&self, | ||
witness: &Witness<F>, | ||
common_preprocessed_input: &CommonPreprocessedInput<F>, | ||
cpi: &CommonPreprocessedInput<F>, | ||
beta: FieldElement<F>, | ||
gamma: FieldElement<F>, | ||
) -> Round2Result<F, CS::Commitment> { | ||
let cpi = common_preprocessed_input; | ||
let mut coefficients: Vec<FieldElement<F>> = vec![FieldElement::one()]; | ||
let mut z_evaluations: Vec<FieldElement<F>> = vec![FieldElement::one()]; | ||
let (s1, s2, s3) = (&cpi.s1_lagrange, &cpi.s2_lagrange, &cpi.s3_lagrange); | ||
|
||
let k2 = &cpi.k1 * &cpi.k1; | ||
|
||
let lp = |w: &FieldElement<F>, eta: &FieldElement<F>| w + &beta * eta + γ | ||
|
||
let z_nums: Vec<_> = (0..&cpi.n - 1) | ||
.map(|i| { | ||
lp(&witness.a[i], &cpi.domain[i]) | ||
* lp(&witness.b[i], &(&cpi.domain[i] * &cpi.k1)) | ||
* lp(&witness.c[i], &(&cpi.domain[i] * &k2)) | ||
}) | ||
.collect(); | ||
let mut z_denoms: Vec<_> = (0..&cpi.n - 1) | ||
.map(|i| { | ||
lp(&witness.a[i], &s1[i]) * lp(&witness.b[i], &s2[i]) * lp(&witness.c[i], &s3[i]) | ||
}) | ||
.collect(); | ||
FieldElement::inplace_batch_inverse(&mut z_denoms).unwrap(); | ||
|
||
for i in 0..&cpi.n - 1 { | ||
let (a_i, b_i, c_i) = (&witness.a[i], &witness.b[i], &witness.c[i]); | ||
let num = lp(a_i, &cpi.domain[i]) | ||
* lp(b_i, &(&cpi.domain[i] * &cpi.k1)) | ||
* lp(c_i, &(&cpi.domain[i] * &k2)); | ||
let den = lp(a_i, &s1[i]) * lp(b_i, &s2[i]) * lp(c_i, &s3[i]); | ||
let new_factor = num / den; | ||
let new_term = coefficients.last().unwrap() * &new_factor; | ||
coefficients.push(new_term); | ||
z_evaluations.push(z_evaluations.last().unwrap() * (&z_nums[i] * &z_denoms[i])); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this can be done better using a scan iterator. That avoids pushing every evaluation into the vector, which is not super efficient |
||
} | ||
|
||
let p_z = Polynomial::interpolate_fft(&coefficients) | ||
let p_z = Polynomial::interpolate_fft(&z_evaluations) | ||
.expect("xs and ys have equal length and xs are unique"); | ||
let z_h = Polynomial::new_monomial(FieldElement::one(), common_preprocessed_input.n) | ||
- FieldElement::one(); | ||
let z_h = Polynomial::new_monomial(FieldElement::one(), cpi.n) - FieldElement::one(); | ||
let p_z = self.blind_polynomial(&p_z, &z_h, 3); | ||
let z_1 = self.commitment_scheme.commit(&p_z); | ||
Round2Result { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,51 +34,55 @@ pub fn test_srs(n: usize) -> StructuredReferenceString<G1Point, G2Point> { | |
let g1 = <BLS12381Curve as IsEllipticCurve>::generator(); | ||
let g2 = <BLS12381TwistCurve as IsEllipticCurve>::generator(); | ||
|
||
let powers_main_group: Vec<G1Point> = (0..n + 3) | ||
.map(|exp| g1.operate_with_self(s.pow(exp as u64).representative())) | ||
.collect(); | ||
let powers_main_group: Vec<G1Point> = | ||
core::iter::successors(Some(FieldElement::from(1)), |acc| Some(acc * &s)) | ||
.take(n + 3) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no need for two maps; we can just fuse them into a single one with g1.operate_with_self(power.representative()). |
||
.map(|power| power.representative()) | ||
.map(|power| g1.operate_with_self(power)) | ||
.collect(); | ||
let powers_secondary_group = [g2.clone(), g2.operate_with_self(s.representative())]; | ||
|
||
StructuredReferenceString::new(&powers_main_group, &powers_secondary_group) | ||
} | ||
|
||
/// Generates a domain to interpolate: 1, omega, omega², ..., omega^size | ||
pub fn generate_domain<F: IsField>(omega: &FieldElement<F>, size: usize) -> Vec<FieldElement<F>> { | ||
(1..size).fold(vec![FieldElement::one()], |mut acc, _| { | ||
acc.push(acc.last().unwrap() * omega); | ||
acc | ||
}) | ||
core::iter::successors(Some(FieldElement::one()), |prev| Some(prev * omega)) | ||
.take(size) | ||
.collect() | ||
} | ||
|
||
/// Generates the permutation coefficients for the copy constraints. | ||
/// polynomials S1, S2, S3. | ||
pub fn generate_permutation_coefficients<F: IsField>( | ||
omega: &FieldElement<F>, | ||
n: usize, | ||
domain: &[FieldElement<F>], | ||
permutation: &[usize], | ||
order_r_minus_1_root_unity: &FieldElement<F>, | ||
) -> Vec<FieldElement<F>> { | ||
let identity = identity_permutation(omega, n, order_r_minus_1_root_unity); | ||
let permuted: Vec<FieldElement<F>> = (0..n * 3) | ||
.map(|i| identity[permutation[i]].clone()) | ||
.collect(); | ||
permuted | ||
let identity = identity_permutation(domain, order_r_minus_1_root_unity); | ||
permutation | ||
.iter() | ||
.map(|perm| identity[*perm].clone()) | ||
.collect() | ||
} | ||
|
||
/// The identity permutation, auxiliary function to generate the copy constraints. | ||
fn identity_permutation<F: IsField>( | ||
w: &FieldElement<F>, | ||
n: usize, | ||
domain: &[FieldElement<F>], | ||
order_r_minus_1_root_unity: &FieldElement<F>, | ||
) -> Vec<FieldElement<F>> { | ||
let u = order_r_minus_1_root_unity; | ||
let mut result: Vec<FieldElement<F>> = vec![]; | ||
for index_column in 0..=2 { | ||
for index_row in 0..n { | ||
result.push(w.pow(index_row) * u.pow(index_column as u64)); | ||
} | ||
} | ||
result | ||
let u_powers = [&FieldElement::one(), &u, &(u * u)]; | ||
|
||
(0..=2) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is no need to start from zero if it is just multiplying with one |
||
.map(|col| { | ||
domain | ||
.iter() | ||
.map(|elem| elem * u_powers[col]) | ||
.collect::<Vec<_>>() | ||
}) | ||
.collect::<Vec<_>>() | ||
.concat() | ||
} | ||
|
||
/// A mock of a random number generator, to have deterministic tests. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this could be more efficient just by just iterating over cpi.domain zipped with witness.a, witness.b, witness.c