Skip to content

crypto: Reduce the exponent for the power-of-two modulus part - #1662

Merged
chfast merged 1 commit into
masterfrom
crypto/modexp-pow2-exp
Sep 11, 2026
Merged

chfast merged 1 commit into
masterfrom
crypto/modexp-pow2-exp

Conversation

@chfast

@chfast chfast commented Aug 16, 2026

Copy link
Copy Markdown
Member

modexp_pow2 iterated over every exponent bit although base^exp % 2ᵏ is periodic in exp. For an odd base the multiplicative order divides λ(2ᵏ) = 2ᵏ⁻², so only that many low bits of the exponent matter. For an even base the result is 0 once exp >= k, which the bit widths of exp and k are enough to decide. Either way the loop is now bounded by k instead of the exponent width: for a modulus with 8 trailing zero bits and an 8192-bit exponent it processes 6 exponent bits instead of 8192.

Gives up to ~30% fewer cycles for even moduli with wide exponents.

@codspeed

codspeed Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will improve performance by 6.66%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 14 improved benchmarks
✅ 115 untouched benchmarks

Performance Changes

Benchmark BASE HEAD Efficiency
modexp<expmod_execute_evmone>[mod_len:32/mod_tz:254/exp_bits:256] 133.3 µs 115.4 µs +15.53%
modexp<expmod_execute_evmone>[mod_len:32/mod_tz:8/exp_bits:8192] 3.2 ms 2.8 ms +14.53%
modexp<expmod_execute_evmone>[mod_len:32/mod_tz:8/exp_bits:256] 117.2 µs 105.3 µs +11.34%
modexp<expmod_execute_evmone>[mod_len:32/mod_tz:127/exp_bits:256] 168.9 µs 151.7 µs +11.32%
modexp<expmod_execute_evmone>[mod_len:32/mod_tz:1/exp_bits:33] 29.3 µs 27.1 µs +8.12%
modexp<expmod_execute_evmone>[mod_len:32/mod_tz:254/exp_bits:33] 31.4 µs 29.2 µs +7.71%
modexp<expmod_execute_evmone>[mod_len:8/mod_tz:8/exp_bits:33] 19.1 µs 17.9 µs +6.42%
modexp<expmod_execute_evmone>[mod_len:16/mod_tz:8/exp_bits:33] 25.9 µs 24.8 µs +4.64%
modexp<expmod_execute_evmone>[mod_len:32/mod_tz:8/exp_bits:33] 29.7 µs 28.7 µs +3.57%
modexp<expmod_execute_evmone>[mod_len:24/mod_tz:8/exp_bits:33] 33.8 µs 32.7 µs +3.52%
modexp<expmod_execute_evmone>[mod_len:48/mod_tz:8/exp_bits:256] 430.3 µs 418.2 µs +2.9%
modexp<expmod_execute_evmone>[mod_len:504/mod_tz:4000/exp_bits:255] 15.9 ms 15.5 ms +2.51%
modexp<expmod_execute_evmone>[mod_len:1024/mod_tz:8190/exp_bits:2048] 519.4 ms 512.9 ms +1.26%
modexp<expmod_execute_evmone>[mod_len:504/mod_tz:4000/exp_bits:2] 140.5 µs 138.8 µs +1.23%

Tip

Curious why performance improved? Comment @codspeedbot explain why performance improved on this PR, or directly use the CodSpeed MCP with your agent.


Comparing crypto/modexp-pow2-exp (29d92b1) with master (f52b1c1)

Open in CodSpeed

@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.02%. Comparing base (f52b1c1) to head (29d92b1).
⚠️ Report is 1 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1662   +/-   ##
=======================================
  Coverage   98.02%   98.02%           
=======================================
  Files         179      179           
  Lines       16317    16347   +30     
  Branches     3760     3765    +5     
=======================================
+ Hits        15994    16024   +30     
  Misses        243      243           
  Partials       80       80           
Flag Coverage Δ
eest-develop 82.78% <100.00%> (+0.03%) ⬆️
eest-develop-gmp 26.23% <0.00%> (-0.05%) ⬇️
eest-legacy 17.22% <0.00%> (-0.04%) ⬇️
eest-libsecp256k1 28.49% <48.38%> (+0.03%) ⬆️
eest-stable 82.75% <100.00%> (+0.03%) ⬆️
evmone-unittests 94.31% <100.00%> (+0.01%) ⬆️

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

Components Coverage Δ
core 96.20% <100.00%> (+0.01%) ⬆️
tooling 94.06% <ø> (ø)
tests 99.81% <100.00%> (+<0.01%) ⬆️
Files with missing lines Coverage Δ
lib/evmone_precompiles/modexp.cpp 99.69% <100.00%> (+0.01%) ⬆️
test/unittests/precompiles_expmod_test.cpp 100.00% <100.00%> (ø)
🚀 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-pow2-exp branch 4 times, most recently from 9a67d2d to 6a870d6 Compare August 19, 2026 14:19
@chfast chfast mentioned this pull request Aug 19, 2026
25 tasks
@chfast
chfast force-pushed the crypto/modexp-pow2-exp branch from 6a870d6 to e5fcfa3 Compare September 7, 2026 13:51
@chfast
chfast requested a balanced review from Copilot September 11, 2026 12:39

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.

🟢 Approval recommended

The reduction logic is mathematically sound and covered by focused boundary tests.

Pull request overview

Optimizes modular exponentiation for power-of-two modulus factors by safely reducing exponent processing.

Changes:

  • Bounds exponentiation work using modulus trailing-zero bits.
  • Adds edge-case regression tests.
  • Documents missing even-base benchmark coverage.
File summaries
File Description
lib/evmone_precompiles/modexp.cpp Implements exponent reduction and early exits.
test/unittests/precompiles_expmod_test.cpp Adds reduction and boundary tests.
test/precompiles_bench/precompiles_bench.cpp Notes benchmark coverage limitation.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@chfast
chfast force-pushed the crypto/modexp-pow2-exp branch from e5fcfa3 to aee0362 Compare September 11, 2026 13:55
modexp_pow2 iterated over every exponent bit although base^exp % 2^k is
periodic in exp. For an odd base the multiplicative order divides
λ(2ᵏ) = 2ᵏ⁻², so only that many low bits of the exponent matter. For an
even base the result is 0 once exp >= k, which the bit widths of exp and
k are enough to decide. Either way the loop is now bounded by k instead
of the exponent width: for a modulus with 8 trailing zero bits and an
8192-bit exponent it processes 6 exponent bits instead of 8192.

Gives up to ~30% fewer cycles for even moduli with wide exponents.
@chfast
chfast force-pushed the crypto/modexp-pow2-exp branch from aee0362 to 29d92b1 Compare September 11, 2026 14:02
@chfast
chfast merged commit bf8303f into master Sep 11, 2026
25 checks passed
@chfast
chfast deleted the crypto/modexp-pow2-exp branch September 11, 2026 14:27
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