Skip to content

crypto: Use Almost Montgomery Multiplication in modexp#1427

Merged
chfast merged 1 commit into
masterfrom
crypto/modexp_amm
Feb 2, 2026
Merged

crypto: Use Almost Montgomery Multiplication in modexp#1427
chfast merged 1 commit into
masterfrom
crypto/modexp_amm

Conversation

@chfast

@chfast chfast commented Jan 27, 2026

Copy link
Copy Markdown
Member

Use the relaxed version of the Montgomery multiplication called Almost Montgomery Multiplication from
"Efficient Software Implementations of Modular Exponentiation" (https://eprint.iacr.org/2011/239.pdf).

                                                     │ old              │          new                       │
                                                     │      gas/s       │    gas/s     vs base               │
modexp<expmod_execute>/mod_len:8/exp_bits:33-14             902.5M ± 0%   941.3M ± 0%  +4.29% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:16/exp_bits:33-14            896.6M ± 1%   931.5M ± 0%  +3.88% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:24/exp_bits:33-14            233.0M ± 1%   241.2M ± 0%  +3.53% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/exp_bits:33-14            233.9M ± 1%   242.0M ± 0%  +3.43% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/exp_bits:256-14           245.3M ± 1%   254.7M ± 0%  +3.83% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/exp_bits:8192-14          488.2M ± 0%   505.2M ± 0%  +3.48% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:40/exp_bits:11-14            204.1M ± 0%   212.3M ± 1%  +3.99% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:48/exp_bits:8-14             277.2M ± 0%   288.6M ± 0%  +4.14% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:48/exp_bits:256-14           338.4M ± 0%   351.9M ± 0%  +4.01% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:56/exp_bits:6-14             359.1M ± 0%   371.5M ± 0%  +3.46% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:64/exp_bits:5-14             434.1M ± 0%   446.5M ± 0%  +2.87% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:72/exp_bits:4-14             160.5M ± 1%   161.3M ± 0%  +0.48% (p=0.001 n=11)
modexp<expmod_execute>/mod_len:112/exp_bits:4-14            368.1M ± 0%   369.0M ± 0%  +0.24% (p=0.002 n=11)
modexp<expmod_execute>/mod_len:136/exp_bits:3-14            132.1M ± 0%   133.2M ± 1%  +0.79% (p=0.001 n=11)
modexp<expmod_execute>/mod_len:192/exp_bits:2-14            186.7M ± 1%   186.7M ± 2%       ~ (p=0.199 n=11)
modexp<expmod_execute>/mod_len:504/exp_bits:2-14            82.04M ± 0%   81.86M ± 1%  -0.21% (p=0.010 n=11)
modexp<expmod_execute>/mod_len:512/exp_bits:2-14            84.51M ± 1%   84.42M ± 0%       ~ (p=0.270 n=11)
modexp<expmod_execute>/mod_len:512/exp_bits:8192-14         348.0M ± 0%   348.4M ± 0%  +0.12% (p=0.034 n=11)
modexp<expmod_execute>/mod_len:520/exp_bits:2-14            87.13M ± 0%   87.00M ± 0%       ~ (p=0.300 n=11)
modexp<expmod_execute>/mod_len:1016/exp_bits:2-14           310.5M ± 1%   309.7M ± 0%       ~ (p=0.171 n=11)
modexp<expmod_execute>/mod_len:1024/exp_bits:2-14           315.2M ± 0%   314.7M ± 0%       ~ (p=0.151 n=11)
modexp<expmod_execute>/mod_len:1024/exp_bits:256-14         704.2M ± 0%   705.1M ± 0%       ~ (p=0.217 n=11)
modexp<expmod_execute>/mod_len:1024/exp_bits:2048-14        1.327G ± 0%   1.325G ± 0%       ~ (p=0.519 n=11)
geomean                                                     290.3M        295.5M       +1.79%

@chfast chfast requested review from Copilot and rodiazet and removed request for Copilot January 27, 2026 11:37
@codecov

codecov Bot commented Jan 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.03%. Comparing base (20e81a4) to head (4f0666d).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1427      +/-   ##
==========================================
+ Coverage   81.70%   83.03%   +1.32%     
==========================================
  Files         152      152              
  Lines       13602    13802     +200     
  Branches     3222     3223       +1     
==========================================
+ Hits        11114    11460     +346     
+ Misses        343      197     -146     
  Partials     2145     2145              
Flag Coverage Δ
eest-develop 91.09% <77.77%> (-0.04%) ⬇️
eest-develop-gmp 28.69% <3.43%> (-0.41%) ⬇️
eest-legacy 15.83% <0.00%> (+0.52%) ⬆️
eest-legacy-silkpre 24.85% <3.43%> (+0.42%) ⬆️
evmone-unittests 76.65% <100.00%> (+0.38%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
core 97.61% <100.00%> (+3.22%) ⬆️
tooling 83.63% <ø> (ø)
tests 74.31% <100.00%> (+0.66%) ⬆️
Files with missing lines Coverage Δ
lib/evmone_precompiles/modexp.cpp 99.00% <100.00%> (+0.05%) ⬆️
test/unittests/precompiles_expmod_test.cpp 98.17% <100.00%> (+1.88%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@chfast chfast force-pushed the crypto/modexp_amm branch from dcf71b3 to 4a4320a Compare January 28, 2026 14:57
Copilot AI review requested due to automatic review settings January 28, 2026 14:57

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Updates the expmod precompile’s modular exponentiation to use Almost Montgomery Multiplication (AMM) for improved performance, and extends unit coverage with additional vectors targeting AMM edge cases.

Changes:

  • Replace classic Montgomery multiplication with AMM in the odd-modulus exponentiation path.
  • Add a final conditional reduction step after converting out of Montgomery form to ensure canonical output.
  • Add extensive unit test vectors intended to exercise AMM-related corner cases.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
lib/evmone_precompiles/modexp.cpp Switches modexp’s multiplication primitive to AMM and adjusts the final reduction step.
test/unittests/precompiles_expmod_test.cpp Adds new expmod test vectors covering AMM-specific scenarios and boundary conditions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/evmone_precompiles/modexp.cpp Outdated
Comment thread test/unittests/precompiles_expmod_test.cpp Outdated
Comment thread lib/evmone_precompiles/modexp.cpp
@chfast chfast force-pushed the crypto/modexp_amm branch 2 times, most recently from 1de9128 to 37db421 Compare January 29, 2026 10:20
@chfast chfast requested a review from Copilot January 29, 2026 10:20

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/evmone_precompiles/modexp.cpp Outdated
Comment thread lib/evmone_precompiles/modexp.cpp Outdated
Comment thread lib/evmone_precompiles/modexp.cpp Outdated
@chfast chfast force-pushed the crypto/modexp_amm branch 6 times, most recently from be90520 to 2cfa624 Compare February 2, 2026 16:38
@chfast

chfast commented Feb 2, 2026

Copy link
Copy Markdown
Member Author

Newer benchmark set:

                                                                 │ old              │          new                       │
                                                                 │      gas/s       │    gas/s     vs base               │
modexp<expmod_execute>/mod_len:8/mod_tz:8/exp_bits:33-14                921.9M ± 0%   931.5M ± 1%  +1.04% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:16/mod_tz:8/exp_bits:33-14               919.6M ± 0%   929.7M ± 1%  +1.10% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:24/mod_tz:8/exp_bits:33-14               232.7M ± 1%   242.5M ± 1%  +4.23% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:0/exp_bits:33-14               254.3M ± 1%   264.7M ± 0%  +4.11% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:1/exp_bits:33-14               234.6M ± 1%   243.5M ± 0%  +3.79% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:8/exp_bits:33-14               233.3M ± 1%   242.6M ± 0%  +3.99% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:127/exp_bits:33-14             232.6M ± 0%   241.6M ± 1%  +3.86% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:254/exp_bits:33-14             233.1M ± 1%   241.5M ± 0%  +3.60% (p=0.001 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:0/exp_bits:256-14              266.4M ± 0%   276.8M ± 0%  +3.93% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:8/exp_bits:256-14              246.0M ± 0%   255.1M ± 0%  +3.70% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:127/exp_bits:256-14            245.4M ± 0%   254.5M ± 0%  +3.71% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:254/exp_bits:256-14            245.6M ± 0%   254.7M ± 0%  +3.72% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/mod_tz:8/exp_bits:8192-14             487.6M ± 0%   505.2M ± 0%  +3.61% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:40/mod_tz:8/exp_bits:11-14               206.8M ± 0%   212.4M ± 0%  +2.67% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:48/mod_tz:8/exp_bits:8-14                281.2M ± 1%   288.2M ± 2%  +2.50% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:48/mod_tz:8/exp_bits:256-14              341.5M ± 0%   351.0M ± 1%  +2.79% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:56/mod_tz:8/exp_bits:6-14                361.7M ± 0%   370.7M ± 0%  +2.50% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:64/mod_tz:8/exp_bits:5-14                435.3M ± 0%   445.2M ± 0%  +2.27% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:72/mod_tz:8/exp_bits:4-14                163.9M ± 0%   164.0M ± 0%       ~ (p=0.606 n=11)
modexp<expmod_execute>/mod_len:112/mod_tz:8/exp_bits:4-14               376.1M ± 0%   376.3M ± 1%       ~ (p=0.133 n=11)
modexp<expmod_execute>/mod_len:136/mod_tz:8/exp_bits:3-14               132.4M ± 0%   132.8M ± 1%       ~ (p=0.606 n=11)
modexp<expmod_execute>/mod_len:192/mod_tz:8/exp_bits:2-14               186.4M ± 0%   185.8M ± 1%       ~ (p=0.133 n=11)
modexp<expmod_execute>/mod_len:504/mod_tz:0/exp_bits:2-14               135.9M ± 0%   135.9M ± 1%       ~ (p=0.478 n=11)
modexp<expmod_execute>/mod_len:504/mod_tz:8/exp_bits:2-14               81.93M ± 0%   81.57M ± 1%       ~ (p=0.076 n=11)
modexp<expmod_execute>/mod_len:504/mod_tz:1000/exp_bits:2-14            54.27M ± 0%   54.24M ± 0%       ~ (p=0.438 n=11)
modexp<expmod_execute>/mod_len:504/mod_tz:4000/exp_bits:2-14            47.77M ± 1%   47.80M ± 1%       ~ (p=0.438 n=11)
modexp<expmod_execute>/mod_len:504/mod_tz:0/exp_bits:255-14             234.6M ± 0%   235.9M ± 0%  +0.55% (p=0.001 n=11)
modexp<expmod_execute>/mod_len:504/mod_tz:8/exp_bits:255-14             170.2M ± 1%   170.8M ± 0%  +0.38% (p=0.001 n=11)
modexp<expmod_execute>/mod_len:504/mod_tz:1000/exp_bits:255-14          169.3M ± 1%   170.3M ± 0%  +0.59% (p=0.001 n=11)
modexp<expmod_execute>/mod_len:504/mod_tz:4000/exp_bits:255-14          169.0M ± 0%   169.6M ± 1%  +0.37% (p=0.007 n=11)
modexp<expmod_execute>/mod_len:512/mod_tz:8/exp_bits:2-14               84.42M ± 0%   84.57M ± 0%  +0.18% (p=0.004 n=11)
modexp<expmod_execute>/mod_len:512/mod_tz:8/exp_bits:8192-14            347.3M ± 0%   348.3M ± 1%       ~ (p=0.056 n=11)
modexp<expmod_execute>/mod_len:520/mod_tz:8/exp_bits:2-14               86.91M ± 1%   87.22M ± 0%  +0.36% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:1016/mod_tz:8/exp_bits:2-14              309.7M ± 1%   310.3M ± 1%       ~ (p=0.056 n=11)
modexp<expmod_execute>/mod_len:1024/mod_tz:8/exp_bits:2-14              314.4M ± 0%   315.5M ± 1%       ~ (p=0.076 n=11)
modexp<expmod_execute>/mod_len:1024/mod_tz:8/exp_bits:256-14            701.6M ± 1%   704.6M ± 0%  +0.43% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:1024/mod_tz:8/exp_bits:2048-14           1.322G ± 0%   1.329G ± 0%  +0.47% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:1024/mod_tz:4096/exp_bits:2048-14        1.323G ± 0%   1.327G ± 2%  +0.26% (p=0.019 n=11)
modexp<expmod_execute>/mod_len:1024/mod_tz:8190/exp_bits:2048-14        1.324G ± 0%   1.326G ± 0%  +0.18% (p=0.023 n=11)
geomean                                                                 261.1M        265.2M       +1.56%

Use the relaxed version of the Montgomery multiplication called
Almost Montgomery Multiplication from
"Efficient Software Implementations of Modular Exponentiation"
(https://eprint.iacr.org/2011/239.pdf).

```
                                                     │ old              │          new                       │
                                                     │      gas/s       │    gas/s     vs base               │
modexp<expmod_execute>/mod_len:8/exp_bits:33-14             902.5M ± 0%   941.3M ± 0%  +4.29% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:16/exp_bits:33-14            896.6M ± 1%   931.5M ± 0%  +3.88% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:24/exp_bits:33-14            233.0M ± 1%   241.2M ± 0%  +3.53% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/exp_bits:33-14            233.9M ± 1%   242.0M ± 0%  +3.43% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/exp_bits:256-14           245.3M ± 1%   254.7M ± 0%  +3.83% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:32/exp_bits:8192-14          488.2M ± 0%   505.2M ± 0%  +3.48% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:40/exp_bits:11-14            204.1M ± 0%   212.3M ± 1%  +3.99% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:48/exp_bits:8-14             277.2M ± 0%   288.6M ± 0%  +4.14% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:48/exp_bits:256-14           338.4M ± 0%   351.9M ± 0%  +4.01% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:56/exp_bits:6-14             359.1M ± 0%   371.5M ± 0%  +3.46% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:64/exp_bits:5-14             434.1M ± 0%   446.5M ± 0%  +2.87% (p=0.000 n=11)
modexp<expmod_execute>/mod_len:72/exp_bits:4-14             160.5M ± 1%   161.3M ± 0%  +0.48% (p=0.001 n=11)
modexp<expmod_execute>/mod_len:112/exp_bits:4-14            368.1M ± 0%   369.0M ± 0%  +0.24% (p=0.002 n=11)
modexp<expmod_execute>/mod_len:136/exp_bits:3-14            132.1M ± 0%   133.2M ± 1%  +0.79% (p=0.001 n=11)
modexp<expmod_execute>/mod_len:192/exp_bits:2-14            186.7M ± 1%   186.7M ± 2%       ~ (p=0.199 n=11)
modexp<expmod_execute>/mod_len:504/exp_bits:2-14            82.04M ± 0%   81.86M ± 1%  -0.21% (p=0.010 n=11)
modexp<expmod_execute>/mod_len:512/exp_bits:2-14            84.51M ± 1%   84.42M ± 0%       ~ (p=0.270 n=11)
modexp<expmod_execute>/mod_len:512/exp_bits:8192-14         348.0M ± 0%   348.4M ± 0%  +0.12% (p=0.034 n=11)
modexp<expmod_execute>/mod_len:520/exp_bits:2-14            87.13M ± 0%   87.00M ± 0%       ~ (p=0.300 n=11)
modexp<expmod_execute>/mod_len:1016/exp_bits:2-14           310.5M ± 1%   309.7M ± 0%       ~ (p=0.171 n=11)
modexp<expmod_execute>/mod_len:1024/exp_bits:2-14           315.2M ± 0%   314.7M ± 0%       ~ (p=0.151 n=11)
modexp<expmod_execute>/mod_len:1024/exp_bits:256-14         704.2M ± 0%   705.1M ± 0%       ~ (p=0.217 n=11)
modexp<expmod_execute>/mod_len:1024/exp_bits:2048-14        1.327G ± 0%   1.325G ± 0%       ~ (p=0.519 n=11)
geomean                                                     290.3M        295.5M       +1.79%
```
@chfast chfast force-pushed the crypto/modexp_amm branch from 2cfa624 to 4f0666d Compare February 2, 2026 16:52
@chfast chfast merged commit e3f720e into master Feb 2, 2026
23 checks passed
@chfast chfast deleted the crypto/modexp_amm branch February 2, 2026 19:02
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.

2 participants