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

Faster final exponentiation for BLS12 #211

Merged
merged 12 commits into from
Mar 17, 2021
Merged

Conversation

Pratyush
Copy link
Member

@Pratyush Pratyush commented Feb 6, 2021

Description

Implements the faster final exponentiation from https://eprint.iacr.org/2020/875.pdf. In my local benchmarks, this speeds up final exponentiation by ~2%


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.

  • Targeted PR against correct branch (master)
  • Linked to Github issue with discussion and accepted design OR have an explanation in the PR that describes this work.
  • Wrote unit tests
  • Updated relevant documentation in the code
  • Added a relevant changelog entry to the Pending section in CHANGELOG.md
  • Re-reviewed Files changed in the Github PR explorer

@Pratyush
Copy link
Member Author

Pratyush commented Feb 6, 2021

cc @yelhousni this is adapted from your code

@Pratyush
Copy link
Member Author

This is ready for a final review + merge

Copy link

@mratsim mratsim left a comment

Choose a reason for hiding this comment

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

I would introduce out-of-place pow_by_x functions.

Also I don't see you using the x/2 trick which also exists in the 2016 paper, a cyclotomic is an interesting saving.

For reference this is my implementation: https://github.com/mratsim/constantine/blob/5806cc46387752d4d011ba663eca0766ff4561e4/constantine/pairing/pairing_bls12.nim#L116-L147

// t[1].Mul(&t[1], &t[2])
y1 *= y2;
// t[2].Expt(&t[1])
y2 = Self::exp_by_x(y1);
Copy link

Choose a reason for hiding this comment

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

I would be wary if copies of Fp12 elements, in my experience the compiler produce a bench of movaps, movups instructions, you might want an out-of-place pow_by_x

Copy link
Member Author

@Pratyush Pratyush Mar 8, 2021

Choose a reason for hiding this comment

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

To clarify, you mean that exp_by_x should take y1 by reference? Or do you mean that it should mutate y2 in place?

Copy link

@mratsim mratsim Mar 10, 2021

Choose a reason for hiding this comment

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

I mean mutate y2 in-place. Does Rust take large stack parameter by reference by default? If not it's needed as well but given that Option and Result work well in Rust I assume it does the right thing.

// t[2].Expt(&t[0])
y2 = Self::exp_by_x(y0);
// t[0].FrobeniusSquare(&t[1])
y0 = y1;
Copy link

Choose a reason for hiding this comment

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

Ditto for the copy here

Copy link
Member Author

Choose a reason for hiding this comment

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

Hm how do I avoid the copy of y1 here?

Copy link

@mratsim mratsim Mar 10, 2021

Choose a reason for hiding this comment

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

This is how I did it

  # (x+p)
  v1.pow_x(v0)                 # v1 = f^((x-1)².x)
  v0.frobenius_map(v0)         # v0 = f^((x-1)².p)
  v0 *= v1                     # v0 = f^((x-1)².(x+p))

  # + 3
  f *= v2                      # f = f³

  # (x²+p²−1)
  v2.pow_x(v0, invert = false)
  v1.pow_x(v2, invert = false) # v1 = f^((x-1)².(x+p).x²)
  v2.frobenius_map(v0, 2)      # v2 = f^((x-1)².(x+p).p²)
  v0.cyclotomic_inv()          # v0 = f^((x-1)².(x+p).-1)
  v0 *= v1                     # v0 = f^((x-1)².(x+p).(x²-1))
  v0 *= v2                     # v0 = f^((x-1)².(x+p).(x²+p²-1))

  # (x−1)².(x+p).(x²+p²−1) + 3
  f *= v0

ec/src/models/bls12/mod.rs Outdated Show resolved Hide resolved
ec/src/models/bls12/mod.rs Outdated Show resolved Hide resolved
ec/src/models/bls12/mod.rs Outdated Show resolved Hide resolved
ec/src/models/bls12/mod.rs Outdated Show resolved Hide resolved
Copy link
Member

@ValarDragon ValarDragon left a comment

Choose a reason for hiding this comment

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

This LGTM!

Should we leave todo's in the code / or generally usage of fp12 regarding the copies?

@Pratyush
Copy link
Member Author

Pushed some changes which optimize the copying behaviour; this improves the performance by another 2%, for an overall 4% improvement.

@Pratyush Pratyush changed the title New final exp for BLS12 Faster final exponentiation for BLS12 Mar 17, 2021
@Pratyush Pratyush merged commit 4e316d1 into master Mar 17, 2021
@Pratyush Pratyush deleted the faster-bls12-final-exp branch March 17, 2021 15:28
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.

3 participants