Repository navigation
evmone v0.25.0 - #7
Conversation
Re-vendor evmone/ from upstream tag v0.25.0 (was v0.23.0); intx stays v0.15.0. capi.cpp: the evmmax namespace is gone since 0.24, the bn254 helpers live in evmone::crypto.
domiwei
left a comment
There was a problem hiding this comment.
The code looks good. evmone/ matches upstream v0.25.0 byte for byte, apart from test/evm-benchmarks, and intx/ is exactly v0.15.0. ModExp and EcAdd matched math/big and gnark-crypto in differential tests: 150k+ ModExp cases on arm64, x86-64 and the generic and ia32 carry paths, with UBSan, and 220k+ EcAdd inputs. Both ran with 0 mismatches. The code compiles cleanly with gcc 10–14, clang and mingw, and erigon's TestPrecompiled* passes against this head. I found no correctness defects. Below are some points on the description, plus small optional follow-ups.
1. The description overstates what the bump brings
- "0.23 the windowed exponentiation" is already on main, because main carries v0.23.0 (
evmone/CHANGELOG.md:214). - "0.22-0.24 BN254 pairing and line-evaluation work that
ecaddshares viaecc.hpp": between v0.23.0 and v0.25.0,ecc.hpp,bn254.hppandbn254.cppchange only the namespace and one include.pairing/is not compiled by this module, sincebn254_link.cppincludes onlybn254.cpp. So EcAdd gets no behavior or speed change from this bump. - The description does not mention the change that does reach modexp: 0.24 reduces the exponent for the power-of-two part of the modulus (
modexp.cpp:536-569). This is the new code path worth pointing reviewers of the erigon pin PR to.
2. EcAdd is about 2.5x slower without -DNDEBUG
-
0.24 added
assert(x < mod); assert(y < mod);tomodadd/modsub(modarith.hpp:68-69,79-80).modinv_scaledcalls them in its loop, so every non-trivial addition runs them. -
The
#cgo CXXFLAGSinbn254.go/modexp.godo not defineNDEBUG. -
Measured on Apple clang, arm64,
EcAdd(G,G):Build ns/op main ~1240 this PR ~3050–3300 this PR, -DNDEBUGat parity with main -
With gcc 14 there was no difference, and ModExp did not regress.
-
Erigon is not affected: its Makefile sets
-DNDEBUGby default, and it calls onlyevmone.ModExp. Other consumers, or a plaingo build/go test, pay the cost. Adding#cgo CXXFLAGS: -DNDEBUGwould fix that; it is your call.
3. -I./evmone/include is now dead (bn254.go:10, modexp.go:10)
Its only user was <evmmax/evmmax.hpp>, which this PR deletes. ecc.hpp now includes "modarith.hpp". All three .cpp files and go build ./... work without it, so it can be removed.
4. CI does not run the new arithmetic
There are no _test.go files, so CI only compiles the new carry folding (modexp.cpp:357, mulmod.cpp:46) and the pow2 exponent reduction. This gap is older than this PR, but a small math/big differential test in the module would guard future bumps. A follow-up is fine.
5. Speedup claim not reproduced on arm64 (FYI)
The "half the 256-bit modexp time" claim did not show up on arm64 with clang or gcc 14. We had no real x86-64 hardware, so the GCC x86-64 claim is unverified, not disproved. The carry fold itself is arithmetically equivalent to the old two-step carry.
Simplification (optional, future)
Only 9 files from lib/evmone_precompiles plus intx.hpp are compiled. Vendoring only those files and the LICENSE files builds fine and would shrink each future bump from ~178 changed files to ~8.
domiwei
left a comment
There was a problem hiding this comment.
Approving. The points in my earlier comment are non-blocking: the description fix and the optional -DNDEBUG / dead -I cleanup can follow. Erigon builds with -DNDEBUG and calls only ModExp, so it is not affected by the EcAdd assert cost.
Re-vendor
evmone/from upstream tagv0.25.0(main carriesv0.23.0);intx/stays v0.15.0, which v0.25.0 still pins.test/evm-benchmarksis left out as before.One wrapper change: 0.24 removed the
evmmaxnamespace, socapi.cppnow takesAffinePoint,validateandadd_affinefromevmone::crypto.modexp_link.cppandbn254_link.cppneed nothing.What the bump brings to the two precompiles erigon takes from here: 0.24 folds the Montgomery multiplication carries into one addition in
modexp(upstream: half the 256-bit modexp time with GCC on x86-64), 0.23 the windowed exponentiation, 0.22-0.24 BN254 pairing and line-evaluation work thatecaddshares viaecc.hpp.Verified against erigon's precompile suite (
execution/vm:TestPrecompiled*, the modexp fuzz againstmath/big) through a localreplace. Numbers follow on the erigon PR that pins this.