Skip to content

Add endo scalar decomposition#24

Merged
davidnevadoc merged 5 commits into
mainfrom
endo
Jun 8, 2023
Merged

Add endo scalar decomposition#24
davidnevadoc merged 5 commits into
mainfrom
endo

Conversation

@kilic

@kilic kilic commented Feb 1, 2023

Copy link
Copy Markdown
Contributor

Adds scalar decomposition for endomorphism for pasta and bn curves. Now we should be able to rebase privacy-ethereum/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

@kilic kilic force-pushed the update/pasta_0.5.0 branch from a62397a to 32f2d39 Compare February 1, 2023 18:09
@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

CPerezz commented Feb 2, 2023

Copy link
Copy Markdown
Contributor

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

kilic commented Feb 3, 2023

Copy link
Copy Markdown
Contributor Author

Documents:

Implementations that helped:

Comment thread src/arithmetic.rs
Comment thread src/bn256/curve.rs
Comment thread src/pasta/mod.rs
Comment thread src/arithmetic.rs Outdated
Comment thread src/arithmetic.rs Outdated
Comment thread src/arithmetic.rs Outdated
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
Copy Markdown
Contributor

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
Copy Markdown
Contributor

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?

Comment thread src/arithmetic.rs Outdated
.iter()
.rev()
.zip(k2_wnaf.iter().rev())
.fold(C::identity(), |acc, (e1, e2)| {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread src/arithmetic.rs Outdated
k1_wnaf
.iter()
.rev()
.zip(k2_wnaf.iter().rev())

Copy link
Copy Markdown
Contributor

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
Copy Markdown
Collaborator

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 thread src/arithmetic.rs Outdated
Comment on lines +177 to +178
#[test]
fn test_wnaf_form() {

Copy link
Copy Markdown
Contributor

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
Copy Markdown
Contributor 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

Comment thread src/derive/curve.rs

@davidnevadoc davidnevadoc left a comment

Copy link
Copy Markdown
Collaborator

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.

Comment thread src/derive/curve.rs
};

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

Copy link
Copy Markdown
Collaborator

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
Copy Markdown
Contributor 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
Copy Markdown
Collaborator

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!

Comment thread src/bn256/curve.rs
]),
};

const ENDO_PARAMS: EndoParameters = EndoParameters {

Copy link
Copy Markdown
Collaborator

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
Copy Markdown
Contributor 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

Comment thread src/derive/curve.rs
macro_rules! endo {
($name:ident, $field:ident, $params:expr) => {
impl CurveEndo for $name {
fn decompose_scalar(k: &$field) -> (u128, bool, u128, bool) {

Copy link
Copy Markdown
Collaborator

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
Copy Markdown
Collaborator

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

@davidnevadoc davidnevadoc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! Thanks a lot 👍

Comment thread src/arithmetic.rs Outdated
k1_wnaf
.iter()
.rev()
.zip(k2_wnaf.iter().rev())

Copy link
Copy Markdown
Collaborator

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 thread src/arithmetic.rs Outdated
Comment thread src/derive/curve.rs
};

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

Copy link
Copy Markdown
Collaborator

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!

@davidnevadoc davidnevadoc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM! Thanks a lot 👍

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