Skip to content

crypto: Compute modexp base_mont using var-length division#1457

Open
chfast wants to merge 1 commit intomasterfrom
crypto/modexp_dyn2
Open

crypto: Compute modexp base_mont using var-length division#1457
chfast wants to merge 1 commit intomasterfrom
crypto/modexp_dyn2

Conversation

@chfast
Copy link
Member

@chfast chfast commented Feb 18, 2026

Replace fixed-width intx::udivrem with span-based mod_rem() for computing
the Montgomery form of the base in modexp_odd. The mod_rem function reuses
intx's internal division primitives (udivrem_by1, udivrem_by2, udivrem_knuth)
operating on dynamic word spans.

The modexp_odd_fixed_size template is split into modexp_odd_mont (which takes
a pre-computed base_mont) and the base_mont computation via mod_rem.
This removes the need for doubled-width intx types (uint<N*2>) for the
base conversion step.

@codecov
Copy link

codecov bot commented Feb 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.82%. Comparing base (86b3c01) to head (5f1551b).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1457      +/-   ##
==========================================
+ Coverage   96.80%   96.82%   +0.01%     
==========================================
  Files         152      152              
  Lines       13934    14005      +71     
  Branches     3238     3245       +7     
==========================================
+ Hits        13489    13560      +71     
  Misses        306      306              
  Partials      139      139              
Flag Coverage Δ
eest-develop 92.67% <100.00%> (+0.07%) ⬆️
eest-develop-gmp 27.91% <0.00%> (-0.15%) ⬇️
eest-legacy 15.16% <0.00%> (-0.08%) ⬇️
eest-libsecp256k1 29.23% <71.05%> (+0.20%) ⬆️
evmone-unittests 91.55% <96.05%> (+0.02%) ⬆️

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

Components Coverage Δ
core 95.91% <100.00%> (+0.04%) ⬆️
tooling 85.03% <ø> (ø)
tests 99.78% <100.00%> (+<0.01%) ⬆️
Files with missing lines Coverage Δ
lib/evmone_precompiles/modexp.cpp 100.00% <100.00%> (ø)
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.

Copy link

Copilot AI left a 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 refactors the odd-modulus modular exponentiation path to compute the Montgomery-form base using a new span-based remainder routine, avoiding the previous fixed doubled-width intx::uint<N*2> conversion.

Changes:

  • Added a new dynamic-word mod() helper to compute remainder using intx::internal division primitives.
  • Split the previous odd-modexp template into modexp_odd_mont() (expects Montgomery base) and a new Montgomery-base conversion step using mod().
  • Extended expmod unit tests with vectors intended to cover dispatch-width cases where n != N.

Reviewed changes

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

File Description
lib/evmone_precompiles/modexp.cpp Introduces span-based remainder routine and rewires modexp_odd() to compute base_mont without doubled-width intx integers.
test/unittests/precompiles_expmod_test.cpp Adds test vectors to exercise odd-modulus dispatch-width coverage cases.

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

@chfast chfast force-pushed the crypto/modexp_dyn2 branch from e605a78 to 0f5a8b0 Compare February 18, 2026 17:11
@chfast
Copy link
Member Author

chfast commented Feb 18, 2026

                                                                        │ /proc/self/fd/11 │         /proc/self/fd/16          │
                                                                        │      gas/s       │    gas/s     vs base              │
modexp<expmod_execute_evmone>/mod_len:8/mod_tz:8/exp_bits:33-14                410.7M ± 2%   408.4M ± 0%       ~ (p=0.161 n=9)
modexp<expmod_execute_evmone>/mod_len:16/mod_tz:8/exp_bits:33-14               406.9M ± 0%   403.1M ± 0%  -0.94% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:24/mod_tz:8/exp_bits:33-14               201.8M ± 0%   198.7M ± 0%  -1.56% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:0/exp_bits:33-14               227.0M ± 0%   225.2M ± 0%  -0.79% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:1/exp_bits:33-14               201.9M ± 1%   198.4M ± 0%  -1.76% (p=0.001 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:8/exp_bits:33-14               201.1M ± 0%   197.5M ± 0%  -1.82% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:127/exp_bits:33-14             187.3M ± 0%   183.6M ± 0%  -1.98% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:254/exp_bits:33-14             168.6M ± 0%   168.0M ± 1%  -0.34% (p=0.040 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:0/exp_bits:256-14              241.3M ± 0%   239.6M ± 0%  -0.69% (p=0.002 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:8/exp_bits:256-14              214.2M ± 1%   214.9M ± 0%       ~ (p=0.297 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:127/exp_bits:256-14            200.4M ± 1%   200.3M ± 0%       ~ (p=0.730 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:254/exp_bits:256-14            181.5M ± 1%   181.1M ± 0%       ~ (p=0.136 n=9)
modexp<expmod_execute_evmone>/mod_len:32/mod_tz:8/exp_bits:8192-14             426.9M ± 0%   427.1M ± 0%       ~ (p=0.605 n=9)
modexp<expmod_execute_evmone>/mod_len:40/mod_tz:8/exp_bits:11-14               222.6M ± 1%   223.9M ± 0%  +0.62% (p=0.011 n=9)
modexp<expmod_execute_evmone>/mod_len:48/mod_tz:8/exp_bits:8-14                302.9M ± 0%   300.7M ± 0%  -0.73% (p=0.001 n=9)
modexp<expmod_execute_evmone>/mod_len:48/mod_tz:8/exp_bits:256-14              371.2M ± 1%   375.3M ± 1%  +1.10% (p=0.002 n=9)
modexp<expmod_execute_evmone>/mod_len:56/mod_tz:8/exp_bits:6-14                386.2M ± 1%   380.0M ± 1%  -1.61% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:64/mod_tz:8/exp_bits:5-14                461.5M ± 1%   450.5M ± 0%  -2.38% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:72/mod_tz:8/exp_bits:4-14                191.8M ± 0%   189.0M ± 1%  -1.46% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:112/mod_tz:8/exp_bits:4-14               435.0M ± 0%   431.0M ± 0%  -0.94% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:136/mod_tz:8/exp_bits:3-14               173.5M ± 2%   173.9M ± 1%       ~ (p=0.136 n=9)
modexp<expmod_execute_evmone>/mod_len:192/mod_tz:8/exp_bits:2-14               249.4M ± 1%   249.4M ± 1%       ~ (p=0.436 n=9)
modexp<expmod_execute_evmone>/mod_len:504/mod_tz:0/exp_bits:2-14               129.8M ± 1%   128.7M ± 1%  -0.83% (p=0.019 n=9)
modexp<expmod_execute_evmone>/mod_len:504/mod_tz:8/exp_bits:2-14               125.4M ± 1%   128.1M ± 1%  +2.11% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:504/mod_tz:1000/exp_bits:2-14            126.0M ± 2%   124.4M ± 1%       ~ (p=0.077 n=9)
modexp<expmod_execute_evmone>/mod_len:504/mod_tz:4000/exp_bits:2-14            124.9M ± 1%   126.2M ± 1%       ~ (p=0.077 n=9)
modexp<expmod_execute_evmone>/mod_len:504/mod_tz:0/exp_bits:255-14             223.9M ± 2%   218.6M ± 1%  -2.35% (p=0.001 n=9)
modexp<expmod_execute_evmone>/mod_len:504/mod_tz:8/exp_bits:255-14             224.1M ± 0%   218.2M ± 1%  -2.67% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:504/mod_tz:1000/exp_bits:255-14          223.1M ± 0%   216.9M ± 0%  -2.81% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:504/mod_tz:4000/exp_bits:255-14          210.0M ± 1%   205.1M ± 0%  -2.30% (p=0.004 n=9)
modexp<expmod_execute_evmone>/mod_len:512/mod_tz:8/exp_bits:2-14               131.8M ± 1%   131.0M ± 1%       ~ (p=0.796 n=9)
modexp<expmod_execute_evmone>/mod_len:512/mod_tz:8/exp_bits:8192-14            452.3M ± 0%   449.2M ± 1%  -0.68% (p=0.011 n=9)
modexp<expmod_execute_evmone>/mod_len:520/mod_tz:8/exp_bits:2-14               135.5M ± 0%   135.7M ± 1%       ~ (p=0.796 n=9)
modexp<expmod_execute_evmone>/mod_len:1016/mod_tz:8/exp_bits:2-14              458.5M ± 1%   463.9M ± 1%  +1.18% (p=0.014 n=9)
modexp<expmod_execute_evmone>/mod_len:1024/mod_tz:8/exp_bits:2-14              465.0M ± 0%   468.5M ± 1%  +0.74% (p=0.011 n=9)
modexp<expmod_execute_evmone>/mod_len:1024/mod_tz:8/exp_bits:256-14            918.4M ± 1%   897.5M ± 1%  -2.27% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:1024/mod_tz:8/exp_bits:2048-14           1.721G ± 1%   1.701G ± 1%  -1.15% (p=0.000 n=9)
modexp<expmod_execute_evmone>/mod_len:1024/mod_tz:4096/exp_bits:2048-14        1.619G ± 1%   1.606G ± 1%  -0.85% (p=0.006 n=9)
modexp<expmod_execute_evmone>/mod_len:1024/mod_tz:8190/exp_bits:2048-14        1.383G ± 1%   1.366G ± 1%  -1.21% (p=0.000 n=9)
geomean                                                                        283.8M        281.7M       -0.76%

Copy link

Copilot AI left a comment

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 no new comments.


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

Replace fixed-width intx::udivrem with span-based mod_rem() for computing
the Montgomery form of the base in modexp_odd. The mod_rem function reuses
intx's internal division primitives (udivrem_by1, udivrem_by2, udivrem_knuth)
operating on dynamic word spans.

The modexp_odd_fixed_size template is split into modexp_odd_mont (which takes
a pre-computed base_mont) and the base_mont computation via mod_rem.
This removes the need for doubled-width intx types (uint<N*2>) for the
base conversion step.
@chfast chfast force-pushed the crypto/modexp_dyn2 branch from da801fe to 5f1551b Compare February 18, 2026 21:34
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.

1 participant

Comments