Skip to content

Conversation

@chfast
Copy link
Member

@chfast chfast commented Jan 8, 2026

  • Replace Straus-Shamir MSM with windowed NAF (sliding window) method.
  • Set conservative initial windows size w=4.
  • Add NAF helper class, wNAF recoding, and shared MSM utility.
  • Cover NAF encoding/decoding with new crypto_wnaf unit tests.

Benchmark results

                                                    │   o/ec.txt   │           o/ec-wnaf-4.txt            │
                                                    │    sec/op    │    sec/op     vs base                │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14    126.3µ ±  0%   111.0µ ±  0%  -12.13% (p=0.001 n=11)
precompile<PrecompileId::ecmul,_evmmax_cpp>-14        53.91µ ±  0%   46.83µ ±  0%  -13.13% (p=0.000 n=11)
precompile<PrecompileId::p256verify,_evmone_cpp>-14   124.4µ ± 90%   107.2µ ± 90%  -13.83% (p=0.028 n=11)
geomean                                               94.61µ         82.28µ        -13.03%

                                                    │  o/ec.txt   │           o/ec-wnaf-4.txt            │
                                                    │   gas/op    │   gas/op     vs base                 │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14    30.00k ± 0%   30.00k ± 0%       ~ (p=1.000 n=11) ¹
precompile<PrecompileId::ecmul,_evmmax_cpp>-14        60.00k ± 0%   60.00k ± 0%       ~ (p=1.000 n=11) ¹
precompile<PrecompileId::p256verify,_evmone_cpp>-14   69.00k ± 0%   69.00k ± 0%       ~ (p=1.000 n=11) ¹
geomean                                               49.89k        49.89k       +0.00%
¹ all samples are equal

                                                    │  o/ec.txt   │           o/ec-wnaf-4.txt           │
                                                    │    gas/s    │    gas/s     vs base                │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14    23.75M ± 0%   27.04M ± 0%  +13.86% (p=0.000 n=11)
precompile<PrecompileId::ecmul,_evmmax_cpp>-14        111.3M ± 0%   128.1M ± 1%  +15.09% (p=0.000 n=11)
precompile<PrecompileId::p256verify,_evmone_cpp>-14   55.39M ± 0%   64.30M ± 0%  +16.09% (p=0.000 n=11)
geomean                                               52.71M        60.62M       +15.01%

                                                    │   o/ec.txt   │           o/ec-wnaf-4.txt           │
                                                    │  cycles/op   │  cycles/op   vs base                │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14    503.5k ±  1%   441.4k ± 0%  -12.33% (p=0.000 n=11)
precompile<PrecompileId::ecmul,_evmmax_cpp>-14        214.9k ±  0%   186.5k ± 0%  -13.22% (p=0.000 n=11)
precompile<PrecompileId::p256verify,_evmone_cpp>-14   495.8k ± 90%   427.4k ± 0%  -13.79% (p=0.010 n=11)
geomean                                               377.1k         327.7k       -13.11%

                                                    │    o/ec.txt     │             o/ec-wnaf-4.txt             │
                                                    │ instructions/op │ instructions/op  vs base                │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14        1.537M ± 0%       1.382M ± 0%  -10.12% (p=0.000 n=11)
precompile<PrecompileId::ecmul,_evmmax_cpp>-14            737.5k ± 0%       663.6k ± 0%  -10.03% (p=0.000 n=11)
precompile<PrecompileId::p256verify,_evmone_cpp>-14       1.552M ± 0%       1.386M ± 0%  -10.74% (p=0.000 n=11)
geomean                                                   1.207M            1.083M       -10.29%

@chfast chfast requested review from Copilot and rodiazet and removed request for Copilot January 8, 2026 16:37
@chfast
Copy link
Member Author

chfast commented Jan 8, 2026

Using w=5 window size gives mixed results, probably depends on the scalar size.

                                                    │ o/ec-wnaf-4.txt │          o/ec-wnaf-5.txt           │
                                                    │      gas/s      │    gas/s     vs base               │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14        27.04M ± 0%   27.89M ± 2%  +3.14% (p=0.000 n=11)
precompile<PrecompileId::ecmul,_evmmax_cpp>-14            128.1M ± 1%   125.6M ± 1%  -1.99% (p=0.000 n=11)
precompile<PrecompileId::p256verify,_evmone_cpp>-14       64.30M ± 0%   66.38M ± 0%  +3.23% (p=0.000 n=11)
geomean                                                   60.62M        61.49M       +1.43%

@codecov
Copy link

codecov bot commented Jan 8, 2026

Codecov Report

❌ Patch coverage is 68.57143% with 33 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.57%. Comparing base (67adeb2) to head (afbdec8).

Files with missing lines Patch % Lines
test/unittests/crypto_wnaf.cpp 48.38% 0 Missing and 32 partials ⚠️
lib/evmone_precompiles/ecc.hpp 97.67% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1419      +/-   ##
==========================================
- Coverage   81.64%   81.57%   -0.08%     
==========================================
  Files         152      153       +1     
  Lines       13550    13671     +121     
  Branches     3217     3264      +47     
==========================================
+ Hits        11063    11152      +89     
- Misses        343      344       +1     
- Partials     2144     2175      +31     
Flag Coverage Δ
eest-develop 91.20% <97.67%> (+0.09%) ⬆️
eest-develop-gmp 28.99% <29.52%> (-0.10%) ⬇️
eest-legacy 15.23% <0.00%> (-0.14%) ⬇️
eest-legacy-silkpre 24.37% <29.52%> (-0.05%) ⬇️
evmone-unittests 76.12% <63.80%> (-0.06%) ⬇️

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

Components Coverage Δ
core 94.46% <97.67%> (+0.07%) ⬆️
tooling 83.63% <ø> (ø)
tests 73.32% <48.38%> (-0.21%) ⬇️
Files with missing lines Coverage Δ
lib/evmone_precompiles/ecc.hpp 96.37% <97.67%> (+0.98%) ⬆️
test/unittests/crypto_wnaf.cpp 48.38% <48.38%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI review requested due to automatic review settings January 8, 2026 16:43
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 replaces the Straus-Shamir multi-scalar multiplication (MSM) algorithm with a windowed Non-Adjacent Form (wNAF) method for elliptic curve cryptography operations, achieving ~13% performance improvement. The change introduces a NAF helper class for encoding scalars, implements wNAF recoding with a conservative window size of 4, and adds comprehensive unit tests for the NAF encoding/decoding functionality.

Key changes:

  • Implemented wNAF-based MSM algorithm with precomputed lookup tables for odd multiples
  • Added NAF class for storing and manipulating NAF representations
  • Created unit tests covering various window sizes, edge cases, and fuzzing for uint256 values

Reviewed changes

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

File Description
test/unittests/crypto_wnaf.cpp New unit tests for NAF encoding/decoding with comprehensive test cases including edge cases and fuzzing
test/unittests/CMakeLists.txt Added crypto_wnaf.cpp to the test sources
lib/evmone_precompiles/ecc.hpp Replaced Straus-Shamir MSM with wNAF-based implementation, added NAF class and helper functions

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

- Replace Straus-Shamir MSM with windowed NAF (sliding window) method.
- Set conservative initial windows size w=4.
- Add NAF helper class, wNAF recoding, and shared MSM utility.
- Cover NAF encoding/decoding with new crypto_wnaf unit tests.

### Benchmark results

```
                                                    │   o/ec.txt   │           o/ec-wnaf-4.txt            │
                                                    │    sec/op    │    sec/op     vs base                │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14    126.3µ ±  0%   111.0µ ±  0%  -12.13% (p=0.001 n=11)
precompile<PrecompileId::ecmul,_evmmax_cpp>-14        53.91µ ±  0%   46.83µ ±  0%  -13.13% (p=0.000 n=11)
precompile<PrecompileId::p256verify,_evmone_cpp>-14   124.4µ ± 90%   107.2µ ± 90%  -13.83% (p=0.028 n=11)
geomean                                               94.61µ         82.28µ        -13.03%

                                                    │  o/ec.txt   │           o/ec-wnaf-4.txt            │
                                                    │   gas/op    │   gas/op     vs base                 │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14    30.00k ± 0%   30.00k ± 0%       ~ (p=1.000 n=11) ¹
precompile<PrecompileId::ecmul,_evmmax_cpp>-14        60.00k ± 0%   60.00k ± 0%       ~ (p=1.000 n=11) ¹
precompile<PrecompileId::p256verify,_evmone_cpp>-14   69.00k ± 0%   69.00k ± 0%       ~ (p=1.000 n=11) ¹
geomean                                               49.89k        49.89k       +0.00%
¹ all samples are equal

                                                    │  o/ec.txt   │           o/ec-wnaf-4.txt           │
                                                    │    gas/s    │    gas/s     vs base                │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14    23.75M ± 0%   27.04M ± 0%  +13.86% (p=0.000 n=11)
precompile<PrecompileId::ecmul,_evmmax_cpp>-14        111.3M ± 0%   128.1M ± 1%  +15.09% (p=0.000 n=11)
precompile<PrecompileId::p256verify,_evmone_cpp>-14   55.39M ± 0%   64.30M ± 0%  +16.09% (p=0.000 n=11)
geomean                                               52.71M        60.62M       +15.01%

                                                    │   o/ec.txt   │           o/ec-wnaf-4.txt           │
                                                    │  cycles/op   │  cycles/op   vs base                │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14    503.5k ±  1%   441.4k ± 0%  -12.33% (p=0.000 n=11)
precompile<PrecompileId::ecmul,_evmmax_cpp>-14        214.9k ±  0%   186.5k ± 0%  -13.22% (p=0.000 n=11)
precompile<PrecompileId::p256verify,_evmone_cpp>-14   495.8k ± 90%   427.4k ± 0%  -13.79% (p=0.010 n=11)
geomean                                               377.1k         327.7k       -13.11%

                                                    │    o/ec.txt     │             o/ec-wnaf-4.txt             │
                                                    │ instructions/op │ instructions/op  vs base                │
precompile<PrecompileId::ecrecover,_evmmax_cpp>-14        1.537M ± 0%       1.382M ± 0%  -10.12% (p=0.000 n=11)
precompile<PrecompileId::ecmul,_evmmax_cpp>-14            737.5k ± 0%       663.6k ± 0%  -10.03% (p=0.000 n=11)
precompile<PrecompileId::p256verify,_evmone_cpp>-14       1.552M ± 0%       1.386M ± 0%  -10.74% (p=0.000 n=11)
geomean                                                   1.207M            1.083M       -10.29%
```
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