-
Notifications
You must be signed in to change notification settings - Fork 331
crypto: Use Newton–Raphson for modinv in modexp #1420
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
base: master
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1420 +/- ##
==========================================
- Coverage 81.64% 81.64% -0.01%
==========================================
Files 152 152
Lines 13550 13548 -2
Branches 3217 3217
==========================================
- Hits 11063 11061 -2
Misses 343 343
Partials 2144 2144
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
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.
Pull request overview
This PR optimizes the modular inverse computation in the modexp precompile by replacing a bit-by-bit algorithm with the Newton-Raphson method. The change significantly improves performance for modexp operations with even moduli, especially when the power-of-two factor is large.
Changes:
- Replaced the iterative bit-by-bit modular inversion algorithm with Newton-Raphson doubling method
- Reuses the existing
inv_mod()function from ModArith to compute an initial 64-bit inverse - Added documentation note about the return value potentially exceeding
kbits
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Use the Newton–Raphson method to compute the modular inverse of the
odd part of the modulus in the modexp for even modulus.
This reuses the inv_mod() procedure from ModArith to compute initial
64-bit value of the inversion.
Benchmarks of modified modexp cases with big `k` in the decomposition
to `mod_odd * 2^k`:
```
│ before │ after │
│ gas/s │ gas/s vs base │
modexp<expmod_execute>/mod_len:8/exp_bits:33-14 722.7M ± 0% 870.1M ± 0% +20.39% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:16/exp_bits:33-14 863.9M ± 0% 868.3M ± 0% +0.50% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:24/exp_bits:33-14 206.1M ± 0% 217.0M ± 0% +5.24% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/exp_bits:33-14 217.7M ± 0% 218.1M ± 0% +0.16% (p=0.034 n=11)
modexp<expmod_execute>/mod_len:40/exp_bits:11-14 136.5M ± 0% 181.0M ± 0% +32.65% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:48/exp_bits:8-14 211.5M ± 0% 237.4M ± 0% +12.24% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:56/exp_bits:6-14 210.2M ± 0% 296.2M ± 0% +40.89% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:64/exp_bits:5-14 33.74M ± 0% 324.07M ± 0% +860.53% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:72/exp_bits:4-14 76.66M ± 0% 116.36M ± 0% +51.79% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:80/exp_bits:4-14 91.70M ± 0% 139.26M ± 0% +51.87% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:88/exp_bits:4-14 70.52M ± 0% 167.91M ± 0% +138.11% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:96/exp_bits:4-14 171.1M ± 0% 192.2M ± 0% +12.30% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:112/exp_bits:4-14 106.2M ± 0% 239.8M ± 16% +125.91% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:136/exp_bits:3-14 53.91M ± 0% 86.57M ± 0% +60.58% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:192/exp_bits:2-14 83.53M ± 0% 107.25M ± 0% +28.39% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:200/exp_bits:2-14 2.302M ± 0% 95.886M ± 0% +4065.86% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:256/exp_bits:2-14 50.46M ± 0% 180.23M ± 1% +257.16% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:264/exp_bits:2-14 3.710M ± 0% 12.260M ± 1% +230.45% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:504/exp_bits:2-14 10.74M ± 0% 43.81M ± 1% +307.90% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:512/exp_bits:2-14 25.28M ± 0% 48.86M ± 1% +93.28% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:520/exp_bits:2-14 11.43M ± 0% 46.62M ± 0% +307.95% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:1016/exp_bits:2-14 43.47M ± 0% 175.31M ± 0% +303.26% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:1024/exp_bits:2-14 145.6M ± 81% 190.8M ± 12% +31.10% (p=0.000 n=11)
geomean 69.00M 150.5M +118.12%
```
Use the Newton–Raphson method to compute the modular inverse of the odd part of the modulus in the modexp for even modulus. This reuses the inv_mod() procedure from ModArith to compute initial 64-bit value of the inversion.
Benchmarks of modified modexp cases with big
kin the decomposition tomod_odd * 2^k: