EIP-8355: Precompiles for ML-DSA verification

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

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.

What are your thoughts on EIP-8288? It seems like another way of achieving ML-DSA signed accounts.

Instead of being verified onchain directly, an ML-DSA sig can be wrapped in a STARK proof and aggregated with others into a single proof. Since the signatures are large it would be much cheaper this way than using the precompile.

Are there any benefits / use cases that would only work with the precompile and not the 8288 approach?

This is not an Either/Or situation. This is an And situation.

One major thing 8288 does not provide is a non-hash signature. Ethereum needs to be in a position that is cryptographically agile, meaning we can swap out signature algorithms with minimal problems. Making 8288 as the only solution locks the environment in.

EIP-8355 provides the industry standard lattice signature, and when they come online the EVM should gain access to MPC-in-the-head, isogeny, multivariate, etc. family signatures. Currently the EVM cannot efficiently do any of these without precompiles. Industry standard crypto provides easy access to HSMs, Cloud KMS, and all sorts of other items downstream users will want to use.

So in summary <Road to El Dorado meme>Both, both is good..</>

My understanding of 8288 is that it does support arbirtary signatures wrapped in a STARK. The EIP defines two pathways, LeanSPHINCS (hash-based, what you’re referring to) and LeanSTARK, which supports different circuits. So you could wrap an ML-DSA signature in a STARK to use this pipeline.
From the EIP:

Users who want to use quantum-resistant signature schemes other than leanSPHINCS signatures will have to either use them in the clear, and accept the onchain gas costs of doing so, or wrap them client-side in a STARK, and then reuse the leanSTARK route.

How soon is 8288 shipping? I*? J*? I’m still not seeing the either/or requirement against an EIP that is yet to be proposed for a fork.

Thats one to two extra years without any standard post-quantum sigs.

Don’t forget we need to save time for a large set of end users to migrate to post EC addresses, which in itself will take at least 2 years.

Yeah I agree, we could do both. I just think it changes the framing of the EIP - the precompile isn’t the endgame solution, but provides a way for users who don’t mind paying higher gas costs to migrate earlier.

The critical thing 8288 solves is the data load from post quantum signatures. All the current algos have a large footprint and there are only a couple on standardization track that have a key and sig size that I would characterize as “not awful”, and they have their warts (SQISign has a huge compute burden and MAYO-2 has a large pubkey). so zk aggregation needs to be in the toolbox.

But the penalty for staying out of that toolbox should be on the order of tens of gas, not tens of millions of gas.

That’s a good point, the cost of staying out of the toolbox is pretty significant though, probably too expensive for most users.

I think the motivation or rationale could mention this though - in the long-term it provides an opt-out from using zk aggregation. For some applications that care about proving latency, regulator compliance, or using certain HSMs might chose the precompile over the default path