Files
zeekayandHanzo Dev 4230d3b3b1 The C++ EVM answers the precompile corpus
The subject is cevm's own seam, cevm::state::is_precompile and
call_precompile, which is what the C++ node's EVM host calls
(lib/evm/state/evmc_host.hpp) and therefore what a C++ validator would
put in a state root. The GPU dispatcher beside it registers a narrower
set behind a sixteen-bit address and documents itself as matching that
seam's accounting, so asking it would be asking the same table through a
smaller window. Nothing here reimplements a precompile: one translation
unit of cevm is compiled where it sits, its algorithm bodies come from
the same Conan packages cevm names, and this directory adds a program
that reads the corpus and prints what the seam said.

Gas is converted at the edge, and this is the edge that needed care.
call_precompile deducts the analyze cost up front, hands back what is
left, and zeroes even that on any non-success, so the charge on a refused
call survives nowhere in the result. On OK the charge is the limit minus
what came back; on FAILED it is read from the analyze function that
computed it. The price table that makes that possible is a second copy of
cevm's dispatch table, so it is checked against the seam in two ways
rather than trusted: every address the seam serves must have a price and
every price must name an address the seam serves, or the program refuses
to run; and on every call that succeeds the two numbers must agree, or it
stops there. Twelve refusals carry a non-zero charge and Go agrees with
all twelve, 375 for the G1ADD refusals, 12 for the malformed blake2f
block flag, 12000 for three G1MSM refusals and 50000 for the empty KZG
call.

Go and C++ agree on all 119 vectors at 0x01 through 0x0b and 0x0100's
gas-short boundary, which covers modexp under the Osaka repricing, the
three bn254 operations, KZG and BLS12-381 G1ADD. They disagree in three
places. The Lux bls12381 modules sit on the pre-final EIP-2537 layout —
G1Add, G1Mul, G1MSM, G2Add, G2Mul, G2MSM, Pairing packed from 0x0b — so
from 0x0c up every address runs a different operation at a different
price than the one Prague put there, which is 91 vectors and every
disagreement at those six addresses. The Lux p256verify module charges
3450 where cevm charges the stock 6900, which also moves the paying
boundary: the vector offering exactly 3450 succeeds in Go and runs out of
gas here. And cevm prices a blake2f input of the wrong length at
GasCostMax, so the call is refused for want of gas before it is read,
where geth prices it at zero and refuses it on reading; both consume
everything the caller offered, so the two report the same call under
different names.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-05 13:32:44 -07:00

13 lines
408 B
Plaintext

# cevm's precompile bodies come from the lux-crypto package and its blst, and
# its fixed-width integers from intx. Same packages, same versions as cevm's own
# conanfile.py — this file names only the part of that graph a precompile call
# reaches, so the evaluator does not build the GPU backends to ask what SHA-256
# costs.
[requires]
lux-crypto/1.4.5
intx/0.15.0
[generators]
CMakeDeps
CMakeToolchain