Skip to content
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

Add endo scalar decomposition #24

Merged
merged 5 commits into from
Jun 8, 2023
Merged

Add endo scalar decomposition #24

merged 5 commits into from
Jun 8, 2023

Conversation

kilic
Copy link
Collaborator

@kilic kilic commented Feb 1, 2023

Adds scalar decomposition for endomorphism for pasta and bn curves. Now we should be able to rebase privacy-scaling-explorations/halo2#40. Also in tests there is a naive glv multiplication applilcation. I think it should not be replaced with the present multiplication function since that one also applies constant time multiplication. Closes #17

@CPerezz CPerezz force-pushed the update/pasta_0.5.0 branch 2 times, most recently from 694b451 to 89021ff Compare February 1, 2023 19:14
Base automatically changed from update/pasta_0.5.0 to main February 1, 2023 19:36
@CPerezz
Copy link
Member

CPerezz commented Feb 2, 2023

Where can we check the endomorfism docs from which you derived the impl? Is the endomorfism formalized somewhere?

@CPerezz CPerezz self-requested a review February 2, 2023 18:04
@kilic
Copy link
Collaborator Author

kilic commented Feb 3, 2023

Documents:

Implementations that helped:

src/arithmetic.rs Show resolved Hide resolved
src/bn256/curve.rs Outdated Show resolved Hide resolved
src/pasta/mod.rs Outdated Show resolved Hide resolved
src/arithmetic.rs Outdated Show resolved Hide resolved
src/arithmetic.rs Outdated Show resolved Hide resolved
Comment on lines 137 to 143
$acc += if $e.is_positive() {
$table[idx]
} else if $e.is_negative() {
-$table[idx]
} else {
C::identity()
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd try a match statement here. It maybe brings tiny bit more performance than if-else chains

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we bench the diff? Or not worth?

.iter()
.rev()
.zip(k2_wnaf.iter().rev())
.fold(C::identity(), |acc, (e1, e2)| {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

k1_wnaf
.iter()
.rev()
.zip(k2_wnaf.iter().rev())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we reverse k2 here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are both reversed to apply the sliding window mul algorithm starting from the less significant bit.

Comment on lines 177 to 178
#[test]
fn test_wnaf_form() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe move this test inside of wnaf mod?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added glv multiplication as an example application of endo decomposition and whole thing is in test mod. And I think it can be removed. We can change ecc mul with another PR. However it seems like single multiplication hasn't been a bottlenck for us that much so I think it is better to keep the original and simple one unless such change is strictly necessary

src/derive/curve.rs Show resolved Hide resolved
Copy link
Contributor

@davidnevadoc davidnevadoc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall LGTM! Great work :)
I have made some suggestions to add some comments and references to make the code more understandable.

};

let is_neg = |e: &$field| {
let e = to_limbs(e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am unsure of the criteria of this function. Could you give some further explanation please? :)
Do we get is_neg(e) when e[3] >0?
Aren't the 3 first assignments of borrow always 0?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This trick actually reveals whether a element is ~128 bit or ~F::NUM_BITS. if latter we see that element is negative and subtract it from modulus and get the actual ~128 bit element. It was originally like below

let (_, borrow) = sbb(0xffffffffffffffff, e[0], 0);
let (_, borrow) = sbb(0xffffffffffffffff, e[1], borrow);
let (_, borrow) = sbb(0x00, e[2], borrow);
let (_, borrow) = sbb(0x00, e[3], borrow);

However in some fields we hit scalars decomposed into 129 bits so I just also made third control limb sparse�

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks for the explanation!

@@ -109,6 +115,20 @@ const G2_GENERATOR_Y: Fq2 = Fq2 {
]),
};

const ENDO_PARAMS: EndoParameters = EndoParameters {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these derived directly or taken form some implementation/ article? I think it would be good to add some reference in any case.
I also think it would be good to add a reference to some resource that explains what these are. Maybe something like:

//  https://www.iacr.org/archive/crypto2001/21390189.pdf
//  Vectors v1, v2 described in Section 4.

Without some indication I know future me will forget what these are x)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is resolved with de71b18

macro_rules! endo {
($name:ident, $field:ident, $params:expr) => {
impl CurveEndo for $name {
fn decompose_scalar(k: &$field) -> (u128, bool, u128, bool) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! However there are some non-obvious optimizations that make the algorithm quite hard to follow.
I gave some explanation of what I believe is going on in this note
I think some comments should be added so that working in this code is easier in the future.

@davidnevadoc
Copy link
Contributor

Can we fix the changes and merge the PR @kilic ?

Copy link
Contributor

@davidnevadoc davidnevadoc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks a lot 👍

k1_wnaf
.iter()
.rev()
.zip(k2_wnaf.iter().rev())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are both reversed to apply the sliding window mul algorithm starting from the less significant bit.

src/arithmetic.rs Outdated Show resolved Hide resolved
};

let is_neg = |e: &$field| {
let e = to_limbs(e);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, thanks for the explanation!

Copy link
Contributor

@davidnevadoc davidnevadoc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Thanks a lot 👍

@davidnevadoc davidnevadoc merged commit 21def8d into main Jun 8, 2023
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement scalar encoding with endomorphism for pasta curves
3 participants