Skip to content

WOTS+C Alternative

Post-quantum signing scheme with key rotation

The current NiceTry design achieves quantum resistance through key rotation: each ECDSA key is used exactly once and discarded post-execution. This page describes an alternative where the signature scheme itself is quantum-safe, using WOTS+C (Winternitz One-Time Signature Plus, Compressed) in place of ECDSA. Both designs could be integrated into the same wallet as parallel options, allowing users to choose their preferred tradeoff between security and cost.

Why WOTS+C

ECDSA security rests on the hardness of the elliptic curve discrete logarithm problem, which a sufficiently capable quantum computer can break via Shor's algorithm. WOTS+C is a hash-based one-time signature scheme whose security reduces to the collision resistance and second-preimage resistance of the underlying hash function — properties unaffected by known quantum algorithms.

The one-time constraint is not a limitation here: NiceTry already rotates the signing key after every transaction, so a scheme that is secure for exactly one use is a natural fit.

How It Works

The validator holds a WOTS+C public key as the current signer. The corresponding private key is derived deterministically from a root seed using a BIP44-like path to generate successive keys, used purely as a KDF. This produces a fresh key at each rotation index without requiring the private seed to be stored on-chain.

Derive

Off-chain, derive the WOTS+C key pair at index n from the root seed using a BIP44-like derivation path.

Register

The smart account stores the WOTS+C public key hash on-chain as the active signer for index n.

Sign

User signs the UserOperation hash with the WOTS+C private key at index n. The signature payload is 292 bytes at NIST security level 1.

Validate

The on-chain validator reconstructs the public key from the signature and checks it against the stored hash.

Rotate

Post-execution, the validator records the public key hash for index n+1, derived from a commitment published in the current transaction. The key at index n is marked spent and will not be accepted again.

Signature Size

WOTS+C signatures are larger than ECDSA. At NIST security level 1 (n=16 bytes, w=256):

ParameterValue
Security parameter n16 bytes (NIST level 1, 128-bit)
Winternitz parameter w256
Number of chains l16 (= n / log2(w) = 128 / 8)
WOTS+C signature size292 bytes (= l × n + 32 byte randomness + 4 byte counter)
Verification cost (EVM)To be estimated
ECDSA comparison65 bytes / ~3k gas

The w=256 value is the most compact choice: larger w yields fewer, longer chains and therefore shorter signatures, at the cost of slower signing. It has no effect on security.

Hybrid Mode: WOTS+C + Backup Signer

A pure WOTS+C design has one operational risk: if a transaction is submitted but fails before the rotation step executes, the WOTS+C key at index n has been revealed in the mempool but the on-chain state has not advanced to n+1. Re-signing with the same key violates the one-time constraint.

To handle this, the validator can register one or more backup signers alongside the primary WOTS+C key. Backup signers are only authorised to perform a rotation — they cannot execute arbitrary calldata.

Primary signer:   WOTS+C key at index n          (normal path)
Backup signer(s): pool of pre-committed keys     (rotation-only, emergency path)

Once a backup signer triggers a rotation, it is consumed and replaced together with the new primary key.

Pool of Pre-committed WOTS+C Keys

The simplest fully post-quantum backup is to register a small pool of additional WOTS+C keys at setup time — for example, four keys derived from the root seed at successive indices — and commit their public key hashes on-chain. If the primary key is exposed without rotating, any one of the pool keys can be used to perform the rotation.

Each pool key is consumed on use, but can be replaced itself at the moment of signing.

This option requires no stateless scheme and no ECDSA, making it fully hash-based end to end.

ECDSA as Backup

another practical way to safegueard this king od wallet against key exposure is ECDSA backup: it is cheap to verify on-chain and already well-supported by existing infrastructure.

The backup ECDSA key should be submitted through a private mempool (e.g. Flashbots Protect) when used. This prevents the key from being exposed publicly before inclusion, preserving secrecy against a quantum adversary who might be monitoring public mempool traffic.

SPHINCS+ as Backup

SPHINCS+ is a stateless hash-based scheme: unlike WOTS+C, it does not require the signer to track a key index. This makes it a lower-risk backup because a lost or desynchronised state cannot cause key reuse. The tradeoff is larger signatures (~8–50 KB depending on parameter set), making it expensive as a primary signer but acceptable for an infrequent emergency rotation.

Alternative Primary: Few-Time Signatures

Instead of a strict one-time scheme, the primary signer could use a few-time signature (FTS) scheme — one designed to remain secure when the same key is used a small, bounded number of times.

This would relax the operational constraint: a failed transaction that exposes the primary key in the mempool without rotating would not immediately compromise security, since the key could safely sign once more to complete the rotation.

FORS (Forest of Random Subsets) is a concrete FTS scheme, used as the message-signing layer inside SPHINCS+. As a standalone signer, FORS would allow a bounded number of signatures per key before security degrades, which is precisely the property needed here.

Validator Logic

The on-chain RotatingWOTSValidator enforces the following rules:

  1. Primary path: accept a UserOperation if the WOTS+C signature is valid against the stored public key hash at the current index, then rotate.
  2. Backup path: accept a UserOperation with empty calldata and a valid backup signature, then rotate primary and backup keys simultaneously. Reject if calldata is non-empty.
  3. Replay protection: store a bitmap of spent primary key indices. A key whose index appears in the bitmap is rejected unconditionally, even if the signature is valid.
function validateUserOp(
    PackedUserOperation calldata userOp,
    bytes32 userOpHash,
    uint256 missingAccountFunds
) external returns (uint256 validationData) {
    (bytes memory sig, uint8 path) = abi.decode(userOp.signature, (bytes, uint8));
 
    if (path == PATH_PRIMARY) {
        require(!_spent[_index], "key spent");
        require(_verifyWOTSC(userOpHash, sig, _primaryKeyHash), "invalid sig");
        // rotation happens in execution phase via frame or callback
        return SIG_VALIDATION_SUCCESS;
    }
 
    if (path == PATH_BACKUP) {
        require(userOp.callData.length == 0, "backup: no calldata allowed");
        require(_verifyBackup(userOpHash, sig), "invalid backup sig");
        return SIG_VALIDATION_SUCCESS;
    }
 
    return SIG_VALIDATION_FAILED;
}

Relation to SHRINCS

The hybrid design described above is structurally similar to SHRINCS (a scheme proposed for Bitcoin by Kudinov and Nick), which also combines a stateful WOTS+C path with a stateless SPHINCS+ fallback. The key difference is how multiple WOTS+C keys are managed.

SHRINCS places the WOTS+C keys as leaves of an unbalanced XMSS Merkle tree: the first key is at depth 1, the second at depth 2, and so on. Each signature includes the WOTS+C signature plus a Merkle authentication path to the tree root, whose length grows as q × n bytes (where q is the number of signatures issued so far). For q=1, the total SHRINCS signature is 308 bytes (292 bytes WOTS+C + 16 bytes authentication path).

The NiceTry design does not use a Merkle tree. Each rotation index maps directly to a fresh WOTS+C key pair derived from the root seed via a BIP44-like path. There is no authentication path overhead, and no shared public key root — the on-chain state is simply the hash of the current public key. This is simpler and has a fixed 292-byte signature regardless of how many rotations have occurred, but it means the signer public key changes with every rotation (which is by design: NiceTry stores the key hash in contract storage, not in a fixed on-chain commitment).

PropertyNiceTry (this design)SHRINCS
Key managementBIP44-like derived, no treeUnbalanced XMSS Merkle tree
First signature size292 bytes308 bytes (292 + 16 auth path)
Nth signature size292 bytes (fixed)292 + q×16 bytes (grows with q)
Public key commitmentPer-rotation hash in storageSingle Merkle root
Backup schemeECDSA or SPHINCS+ (explicit)SPHINCS+ (stateless fallback)

Comparison with the ECDSA Design

PropertyEphemeral ECDSAWOTS+C primary
Quantum resistanceRotation-dependentUnconditional
Signature size65 bytes292 bytes
On-chain verification gas~3kTo be estimated
Failed-tx recoveryRe-sign with same key (classically safe, not quantum-safe)Backup signer required

The ECDSA design is simpler and cheaper. The WOTS+C design provides a stronger guarantee: even if a quantum adversary breaks ECDSA before the rotation executes, the primary signer is not compromised.