Discussion topic for EIP-8355 (PR #12048)
Three precompiles that verify FIPS 204 ML-DSA signatures at NIST security levels II, III, and V (parameter sets ML-DSA-44, 65, and 87).
This overlaps with EIP-8051, and I want to be upfront that it isn’t a competing design so much as four specific disagreements with it. If those are resolved in EIP-8051, I would rather this be folded into it than shipped alongside or in lieu of.
Each precompile takes a single concatenated input with no length prefixes:
pubkey ++ signature ++ message
The public key and signature are fixed-length for a given parameter set, so the message is exactly the trailing bytes: len(message) = len(input) - PK_LEN - SIG_LEN. The precompile returns a 32-byte word, 1 for a valid signature and 0 otherwise. Cryptographic failure is a return value, never a revert, so callers branch with ISZERO.
Delta 1: levels III and V, not just II. EIP-8051 specifies ML-DSA-44 only. An account authenticator is long-lived and holds funds for years, and ML-DSA-65 and ML-DSA-87 are the tiers NIST recommends when you want margin above 128-bit classical security. Cheap to add now, awkward to retrofit later.
Delta 2: variable-length message, placed last. EIP-8051 fixes the message at a 32-byte pre-hash at the front of the input. My objection is that this puts the precompile outside FIPS 204 rather than inside it. A 32-byte input can only be a digest, so every caller is forced into pre-hashing — but FIPS 204 §5.4 makes pre-hashing a distinct construction, HashML-DSA, which binds the digest to the identifier of the hash that produced it. A bare 32-byte message carries no such binding, and a 32-byte-only precompile cannot verify a real HashML-DSA signature either, since the encoded OID pushes the message representative past 32 bytes. What’s left is neither pure ML-DSA nor HashML-DSA. Callers should stay free to pass a digest, and most will, but the precompile shouldn’t force it on callers who have a message they can sign directly.
Delta 3: Compressed public keys: EIP-8051 takes a pre-expanded 20512-byte key so its precompile can skip ExpandA; this draft takes the standard 1312/1952/2592-byte key and expands inside, pricing the work into gas. The reason is that the intended caller stores the key in account code, where every byte is persistent state — 2592 bytes is tolerable there and 20512 is not. Both tradeoffs are defensible and could coexist as siblings.
Delta 4: FIPS 204 verification only: This does not propose any alterations from the FIPs standard. No Ethereum specific hash functions and no decomposition of the components of the precompile.
Worth Noting: Empty context string: ctx is fixed to the FIPS 204 default, matching what X.509 and TLS do with ML-DSA. A caller wanting domain separation prefixes it onto the message. Also, not every cryptographic library exposes the context parameter so a context-carrying precompile would be unimplementable on top of some clients’ natural dependency.
Update Log
- 2026-07-30: initial draft PR #12048
External Reviews
None as of 2026-07-30.
Outstanding Issues
- 2026-07-30: Precompile addresses are unassigned; the proposal needs a contiguous three-address block allocated during standardization.
- 2026-07-30: Gas costs are placeholders (6500/9000/13500 base, 6 per message word) and need benchmarking against a reference implementation. Measurements from anyone who has implemented compressed-key ML-DSA verification in a client codebase would be welcome.