WOTS+C
WOTS+C (Winternitz One-Time Signature, with the "+C" checksum-compression trick) was the second-generation primary signer. It replaced ephemeral ECDSA with a genuinely post-quantum, hash-based scheme: security reduces to preimage resistance of Keccak-256, and an observed signature gives a quantum adversary nothing to invert. The mempool window vulnerability is gone.
How it worked
The account stored H(pk_i) (the hash of the WOTS+C public key). Validation:
- Call the WOTS+C verifier to reconstruct
pk_ifrom the signature and theuserOpHash; assertH(pk_i)matches the stored value. - On match, return
SIG_VALIDATION_SUCCESS. - Rotate atomically: overwrite the stored value with
H(pk_{i+1}), supplied in the UserOp calldata.
WOTS+C signs the raw userOpHash (no Ethereum message prefix). Keys are derived deterministically from the user's seed via a BIP-44-like path, so one seed reproduces the whole key sequence.
Deployed parameters
| Parameter | Value |
|---|---|
Hash truncation n | 16 bytes |
Winternitz parameter w | 32 |
Chains l | 26 |
| Target checksum sum | 403 |
| Signature size | 468 bytes |
| Verifier gas | ~93k |
The "+C" compression brute-forces a counter so the message digest produces a fixed, known checksum, letting the checksum chains be dropped from the signature. The byte-level layout is in docs/signing-spec.md.
Why it was superseded
WOTS+C is a one-time signature. Signing two different messages with the same key leaks enough chain information for immediate classical forgery, so a single accidental reuse (a reverted transaction, a dropped UserOp, a replacement transaction) is catastrophic, not just degraded.
That fragility is the entire reason FORS+C became the primary scheme. FORS+C pays ~3× the signature bytes (2,448 B vs 468 B) but degrades gracefully under reuse, turning those same failure modes into a bounded, recoverable reuse budget instead of an immediate break.
| WOTS+C | FORS+C | |
|---|---|---|
| Type | one-time | few-time |
| Reuse failure | immediate classical forgery | graceful degradation |
| Signature size | 468 B | 2,448 B |
| Verifier gas | ~93k | ~34–38k |