-
Notifications
You must be signed in to change notification settings - Fork 543
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
Batch Verification API #59
Conversation
The CI is pinned to 1.44.0 and build failing, on 1.49.0 (latest stable toolchain) it's passing. |
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.
Untested ACK :-)
src/groth16/verifier/batch.rs
Outdated
|
||
ml_terms.push(((proof.a * z).into(), (-proof.b).into())); | ||
|
||
acc_Gammas[0] += &z; // a_0 is implicitly set to 1 (??) |
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.
That's correct.
acc_Gammas[0] += &z; // a_0 is implicitly set to 1 (??) | |
acc_Gammas[0] += &z; // a_0 is implicitly set to 1 |
src/groth16/verifier/batch.rs
Outdated
// | ||
// Y^acc_Y in multiplicative notation is [acc_Y]Y (scalar mul) in | ||
// additive notation, which is the code convention here. | ||
let Y = E::pairing(&vk.alpha_g1, &vk.beta_g2) * acc_Y; |
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.
This pairing could be precomputed.
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.
Also, calling the result Y
could be a little confusing.
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.
@daira is right that it can be precomputed, but it's probably not more efficient in practice to do that. We do it in the groth16 verifier because we're just checking one proof and acc_Y = 1
more or less. In your case the multiplication by acc_Y
is expensive -- it involves exponentiating by acc_Y
because the result of the pairing is an element of a multiplicative subgroup of a large extension field. Instead, in practice it's probably just fine to do
ml_terms.push((E::G1Affine::from(vk.alpha_g1 * acc_Y), E::G2Prepared::from(vk.beta_g2)));
so you multiply the G1 element by acc_Y
(because [z] e(A, B) = e([z] A, B)
forall z, A, B) and then just add it to your multi-miller loop.
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.
Please remove the last two commits.
.github/workflows/ci.yml
Outdated
toolchain: 1.44.0 | ||
toolchain: stable |
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.
This conflicts with #62, where the MSRV is set to 1.47.0.
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.
Resolved to 1.47.0
.github/workflows/ci.yml
Outdated
toolchain: 1.44.0 | ||
toolchain: stable |
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.
Ditto.
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.
Resolved to 1.47.0
src/lib.rs
Outdated
#![deny(intra_doc_link_resolution_failure)] | ||
#![deny(broken_intra_doc_links)] |
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.
We cannot change this until the MSRV is at least 1.48.0 (see zcash/librustzcash#279).
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.
Reverted
I believe that specific CI failure is related to #57 (the upstream |
let Psi = vk | ||
.ic | ||
.iter() | ||
.zip(acc_Gammas.iter()) | ||
.map(|(&Psi_i, acc_Gamma_i)| Psi_i * acc_Gamma_i) | ||
.sum(); |
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.
Constant factor improvement, but this can be done as a multiexp instead.
src/groth16/verifier/batch.rs
Outdated
// additive notation, which is the code convention here. | ||
let Y = E::pairing(&vk.alpha_g1, &vk.beta_g2) * acc_Y; | ||
|
||
let mut terms = vec![]; |
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.
let ml_terms = ml_terms.iter().map(|(a, b)| (a, b)).collect::<Vec<_>>();
src/groth16/verifier/batch.rs
Outdated
// | ||
// Y^acc_Y in multiplicative notation is [acc_Y]Y (scalar mul) in | ||
// additive notation, which is the code convention here. | ||
let Y = E::pairing(&vk.alpha_g1, &vk.beta_g2) * acc_Y; |
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.
@daira is right that it can be precomputed, but it's probably not more efficient in practice to do that. We do it in the groth16 verifier because we're just checking one proof and acc_Y = 1
more or less. In your case the multiplication by acc_Y
is expensive -- it involves exponentiating by acc_Y
because the result of the pairing is an element of a multiplicative subgroup of a large extension field. Instead, in practice it's probably just fine to do
ml_terms.push((E::G1Affine::from(vk.alpha_g1 * acc_Y), E::G2Prepared::from(vk.beta_g2)));
so you multiply the G1 element by acc_Y
(because [z] e(A, B) = e([z] A, B)
forall z, A, B) and then just add it to your multi-miller loop.
src/groth16/verifier/batch.rs
Outdated
let mut terms = vec![]; | ||
ml_terms.iter().for_each(|(a, b)| terms.push((a, b))); | ||
|
||
if E::multi_miller_loop(terms.as_slice()).final_exponentiation() + Y == E::Gt::identity() { |
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.
If you fold the change in like I mentioned then this becomes
if E::multi_miller_loop(&terms).final_exponentiation().is_identity().into() {
I think.
Co-authored-by: str4d <[email protected]>
Co-authored-by: str4d <[email protected]>
Co-authored-by: str4d <[email protected]>
The clippy 'failure' if you do as it recommends it will not compile because:
|
…y generate a zero
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.
Untested ACK.
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.
utACK b9737fc
@ebfull one more look por favor? 🙏 |
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.
Good job! :)
Yay, thank you! |
No description provided.