-
Notifications
You must be signed in to change notification settings - Fork 20.3k
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
Implement binary EEA inversion for faster BNADD precompile #21515
base: master
Are you sure you want to change the base?
Conversation
Oooh, this sounds nice. Would it make sense to upstream it to Cloudflare's original library? https://github.com/cloudflare/bn256 Edit: I've opened an upstream issue referencing this cloudflare/bn256#23. |
This is not constant time. |
I’m not sure if Cloudflare needs it constant time, but since element is not zero and inverse always exists then such inversion will finish in log(p) steps (for Eth purposes to be bounded computation). N.B. Original EIP for this functionality does not give constant time guarantees anyway |
EEA is not the recommeded way to perform inversion, because its execution is not performed in constant time with respect to the value of its input. Regarding performance, point operations can be performed in projective coordinates, and at the very end make just one conversion. |
As was mentioned above there is no need to constant time for the precompile. And addition is indeed performed in projective coordinates, but Ethereum ABI requires outputs to be in affine coordinates, so fast inversion is important for single addition performance. |
This change seems to be specific to the application, and it's likely not to be included in cloudflare/bn256. |
Had to do some duplication of code (to avoid global config variables), but now there are two flavors of 'constant time' and 'variable time' available functions. Fp6/Fp12 inversions do not benefit from variable time speedup much, but I've continued with the same approach everywhere. Miller loop and final exponentiations are left with constant time cause speedup there is also negligible. |
Before and after:
It does a real difference in many cases (not all) - particularly these five:
However, the particular cases where it does make a difference, are the cases which are currently the slowest: namely, these five:
Which are an order of magnitude worse than others:
As stated previously, constant time is not something we're bothered by. As long as this is mathematically correct, and doesn't suffer from a different set of worst-cases that we're as of yet unaware of, I'm all for merging this. |
Constant time must be the default. |
We geth-maintainers aren't cryptographers, and it's difficult for us to validate the proposed changes, other than that we can definitely agree that for us, constant time at the cost of speed, is not desireable. However, I'd highly appreciate any input from @bwesterb or @armfazh regarding:
I don't expect you to spend a lot of time auditing our code, but if you have already looked at it, perhaps you already have formed opinions about these questions. |
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.
few comments
I created some fuzzers for this change here: |
@armfazh I think all your concerns has been addressed - none of the variable-time functions are on default paths. Do you think this can/will be merged upstream? |
could anyone of you prepare a PR against upstream, so we can do a final review and merge it then, |
I started prepping an upstream PR, but for some reason the test fails. @shamatar do you have any idea why? I just copy-pasted the changes... https://github.com/holiman/bn256/tree/binary_eea_inversion
|
I'll have a look at the morning, sure. |
I've identified a problem: modulus size in the original repo is 256 bits, so the trick with |
@shamatar friendly ping, was this ever looked at? |
Hey @axic! I didn't, but the solution is quite simple, so since you have reminded me I should make a direct PR to the Cloudflare's repo, but for Ethereum the BN curve is different than in the original CF repo, so the trick with |
Single field inversion takes almost all the time of execution in case of point addition. Switching from inversion by exponentiation into
p-2
power to binary EEA inversion reduces execution time in 3 times