-
Notifications
You must be signed in to change notification settings - Fork 245
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
Refactor MSM: Use VariableBaseMSM
trait
#425
Conversation
@@ -170,7 +172,7 @@ impl<P: Parameters> Add<Self> for GroupAffine<P> { | |||
impl<'a, P: Parameters> AddAssign<&'a Self> for GroupAffine<P> { | |||
fn add_assign(&mut self, other: &'a Self) { | |||
let mut s_proj = GroupProjective::from(*self); | |||
s_proj.add_assign_mixed(other); | |||
ProjectiveCurve::add_assign_mixed(&mut s_proj, other); |
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.
Did this break? i.e. does s_proj.add_assign_mixed(other)
no longer work?
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 needed for disambiguation, since we have two traits that define that method
Ah I see that we need to put the I have a couple of ideas to fix this, but the cleanest way would be to do the refactor from #294 =/ |
EDITED: @mmagician thanks a lot for the pull request! I have a few edits that are available in https://github.com/mmaker/arkworks-algebra/tree/fix/425 and I think will overall improve the quality of this new API. I'd also much rather keep fancy unicode out of the documentation and add latex support for properly explaining things. I'll add this in a separate pull reuqest. |
The default, user-friendly way is to multiply group elements by elements in the scalar field. In an attempt to add some ergonomics, I'm using the same template but for scalars and adding a big fat warning that no checks is performed on the size. The function that acts immediately on the bigints can also be called explicitly if the caller knows that the same scalar vectors will be used multiple times. Note that copying that vector only buys a few ms per MSM of 2^20 elements or more. The extra function `msm_bigint` also allows to perform optimizations on `msm` before the call to `msm_bigint`: instead of normalizing into `BigInt`s with `u64` we can move to `i32` and use half the number of buckets in Pippenger, exploiting group addition, using the representation in buckets as [-w/2 + 1, w/2] instead of [0, w-1]. Use the frontend API `VariableBaseMSM::msm` in tests when possible. Change (again) defaults for VariableBaseMSM not to panic. After asking around, looks like most people assume that there is no bound check (e.g. when committing to a vector or a polynomial). I'm therefore reverting the change on the bound check
@mmaker Thanks a lot, I agree that your edits make the API better! Do you want to make a PR to my branch with these changes? @Pratyush Sure, duplicated method names aren't ideal, but I think that using fully qualified syntax isn't so bad? While the user has to be more explicit, the code stays easy to read. Ultimately, I agree though that having a |
@mmagician done! |
@mmagician thanks! maybe this pull request is not anymore a "Draft"? |
I was actually thinking of doing the same for FixedMSM, hence I left it as a draft to get feedback before tackling it. |
@mmagician understood -- any chance they could be separated into two different pull requests? I feel like that is another battle and I'm interested in getting this more ergonomic trait available in |
|
||
type Scalar = <Self as ProjectiveCurve>::ScalarField; | ||
|
||
fn double_in_place(&mut self) -> &mut Self { |
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.
May be let's rename this to _double_in_place
and put it behind a #[doc(hidden)]
, so that we can avoid having to disambiguate everywhere.
ProjectiveCurve::double_in_place(self) | ||
} | ||
|
||
fn add_assign_mixed(&mut self, other: &Self::MSMBase) { |
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 for this.
ec/src/msm/fixed_base.rs
Outdated
C: ProjectiveCurve, | ||
I: IntoIterator, | ||
I::Item: Borrow<C::ScalarField>, |
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.
Does this more generic bound but us much? the IntoIterator
I can understand (but we will want to fix it to be conditionally IntoParallelIterator
, or call par_bridge()
on it.)
However, the Borrow
one doesn't seem as useful, IMO
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.
mmmmh, I was trying to emulate @oleganza in curve25519-dalek: https://github.com/dalek-cryptography/curve25519-dalek/blob/main/src/backend/serial/scalar_mul/pippenger.rs.
Looking at https://github.com/search?q=optional_multiscalar_mul&type=code there's a bunch of repos that use .iter().chain()
or iter::once
(which can avoid copying the scalars if we support Borrow<C::ScalarField>
). I'm however happy to move this into a separate pull request, this can be a different discussion.
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.
@mmagician, @Pratyush: with a % git checkout master -- ec/src/msm/fixed_base.rs
we are all good with the new VariableBaseMSM
API, only the Changelog might need minor edits.
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.
The impl in curve25519-dalek is not parallelized, which is why they're fine with Iterator
. In our case, since we have parallelization, and because iterators are lazy, if you do iter().chain()
, the chain()
call will be evalauted many times. For more complex iterators this can be an issue.
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 response is not related to Borrow, is it?
To reply about iterators: we still have to copy them in order to make them bigints
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.
@mmaker So is the suggestion to provide an Iterator-based API for MSMs with Scalars, while providing the standard slice-based API for MSMs with bigints?
Prefix `add_assign_mixed` and `double_in_place` with underscore and hide from documentation.
Prefix `add_assign_mixed` and `double_in_place` with underscore and hide from documentation.
Co-Authored-By: Michele Orrù <[email protected]>
@mmaker I've cherry-picked your previous commit and also checked out the fixed-base file from master. Thanks for that! |
.collect::<Vec<_>>(); | ||
let g = (0..SAMPLES) | ||
.map(|_| G::Projective::rand(&mut rng)) | ||
.collect::<Vec<_>>(); | ||
let g = <G::Projective as ProjectiveCurve>::batch_normalization_into_affine(&g); | ||
|
||
let naive = naive_var_base_msm(g.as_slice(), v.as_slice()); | ||
let fast = VariableBase::msm(g.as_slice(), v.as_slice()); | ||
let fast = <G::Projective as VariableBaseMSM>::msm(g.as_slice(), v.as_slice()); |
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 fast = <G::Projective as VariableBaseMSM>::msm(g.as_slice(), v.as_slice()); | |
let fast = VariableBaseMSM::msm(g.as_slice(), v.as_slice()); |
Should still work, right?
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.
No, error[E0282]: type annotations needed
. We can be explicit about the type of fast
, though:
let fast: G::Projective = VariableBaseMSM::msm(g.as_slice(), v.as_slice());
@@ -48,7 +54,7 @@ pub fn test_chunked_pippenger<G: AffineCurve>() { | |||
.collect::<Vec<_>>(); | |||
let g = <G::Projective as ProjectiveCurve>::batch_normalization_into_affine(&g); | |||
|
|||
let arkworks = VariableBase::msm(g.as_slice(), v.as_slice()); | |||
let arkworks = <G::Projective as VariableBaseMSM>::msm_bigint(g.as_slice(), v.as_slice()); |
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 arkworks = <G::Projective as VariableBaseMSM>::msm_bigint(g.as_slice(), v.as_slice()); | |
let arkworks = VariableBaseMSM::msm_bigint(g.as_slice(), v.as_slice()); |
@@ -76,7 +86,7 @@ pub fn test_hashmap_pippenger<G: AffineCurve>() { | |||
.collect::<Vec<_>>(); | |||
let g = <G::Projective as ProjectiveCurve>::batch_normalization_into_affine(&g); | |||
|
|||
let arkworks = VariableBase::msm(g.as_slice(), v.as_slice()); | |||
let arkworks = <G::Projective as VariableBaseMSM>::msm_bigint(g.as_slice(), v.as_slice()); |
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 arkworks = <G::Projective as VariableBaseMSM>::msm_bigint(g.as_slice(), v.as_slice()); | |
let arkworks = VariableBaseMSM::msm_bigint(g.as_slice(), v.as_slice()); |
On Thu 23 Jun 2022 at 10:11, Pratyush Mishra ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In ec/src/msm/fixed_base.rs
<#425 (comment)>:
> + C: ProjectiveCurve,
+ I: IntoIterator,
+ I::Item: Borrow<C::ScalarField>,
@mmaker <https://github.com/mmaker> So is the suggestion to provide an
Iterator-based API for MSMs with Scalars, while providing the standard
slice-based API for MSMs with bigints?
In a glorious future yes
… —
Reply to this email directly, view it on GitHub
<#425 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACD7BIPU635MOIGQ4U2WATVQSLDBANCNFSM5XYNYCBQ>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
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.
The documentation has now wrong links:
--> ec/src/msm/variable_base/mod.rs:39:24
|
39 | /// Multiply the [`ScalarField::BigInt`] elements in `scalars` with the
| ^^^^^^^^^^^^^^^^^^^ no item named `ScalarField` in scope
|
= note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default
warning: unresolved link to `VariableBase::msm`
--> ec/src/msm/variable_base/mod.rs:60:22
|
60 | /// Reference: [`VariableBase::msm`]
| ^^^^^^^^^^^^^^^^^ no item named `VariableBase` in scope
@mmagician I fixed those in mmaker@42e733a or mmagician@42e733a.
@mmagician can you remove |
{Fixed,Variable}BaseMSM
traitsVariableBaseMSM
trait
Description
I believe this PR should address the comments from #423 and offer more flexible interface.
closes: #411
Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
WroteAdapted unit testsPending
section inCHANGELOG.md
Files changed
in the GitHub PR explorer