Skip to content

Chapter 37: Layer-1 signature migration: Bitcoin and Ethereum

Bitcoin and Ethereum sign every Layer-1 transaction with ECDSA or Schnorr over secp256k1. Both reduce to ECDLP and break under Shor (Shor, 1994). The migration target is a post-quantum signature primitive that fits the per-block byte budget and the per-verification cost envelope. Ch 36 set the threat model and the surface taxonomy for the Strand running example. This chapter walks the operator from a candidate decision through to a deployed Bitcoin soft fork or a deployed Ethereum account abstraction. The Bitcoin path is two-layer at chain-tip 2026. BIP-360 Pay-to-Merkle-Root (P2MR, Draft v0.12.1) is a Taproot-adjacent script-only output that removes the always-exposed key path and reduces long-exposure quantum risk (Beast et al., 2024). A separate, not-yet-drafted soft fork would then introduce the post-quantum signature opcodes that verify ML-DSA or SLH-DSA at spend.

The Ethereum path is ERC-4337 account abstraction. The candidate set has four elements: classical-secp256k1, ML-DSA-65 (National Institute of Standards and Technology, 2024), SLH-DSA-128s (National Institute of Standards and Technology, 2024b), and an Ed25519+ML-DSA-65 composite per the Ch 27 framing.

For a chain-level operator the transaction surface is the first-wave migration target. Its X is bounded only by the lifetime of holdings whose keys are never rotated, so the Mosca window is dominated by X regardless of how cheap the migration path looks. The chapter measures the migration tax in two units: per-block transactions on Bitcoin under the 4-million weight-unit (WU) SegWit block limit, and per-block transactions on Ethereum under the chain-tip 2026 block gas limit.

The Ethereum anchor is 60 million gas, the execution-layer client-default recommendation in EIP-7935 (Informational, written for the Fusaka cycle) (Ethereum Improvement Proposal authors, 2025). The Fusaka meta-EIP lists it and dates the fork’s mainnet activation to 3 December 2025 (Beiko et al., 2024). EIP-7935 is advisory client-config guidance rather than a consensus-pinned constant. A miner or validator can configure a different target. The Pectra upgrade (May 2025) included EIP-7623 (calldata-floor pricing), EIP-7691 (blob-throughput target), and EIP-7702 (EOA account-code rule), among others. Pectra did not itself change the block gas limit (Beiko, 2024; Wahrstätter & Buterin, 2024). Both block-budget numbers favor the classical secp256k1 baseline today by an order of magnitude or more, and both move when the chain switches primitives.

A Strand transaction migrating to ML-DSA-65

Section titled “A Strand transaction migrating to ML-DSA-65”

The Strand chain from Ch 36 deploys secp256k1 ECDSA (and BIP-340 Schnorr after Taproot activation) on its transaction surface. Each transaction carries one 64-byte signature in the witness. Legacy P2WPKH spends also reveal a 33-byte compressed public key alongside it. The chapter uses a round-figure 380-weight-unit overhead per typical 1-in-1-out segwit transaction. BIP-141 weighs each non-witness byte at 4 units and each witness byte at 1 (Lombrozo et al., 2015). The stripped serialization of that shape (version, one input with its outpoint, empty-scriptSig length byte and sequence, one output with its value, script length byte and 34-byte script, locktime, and the two counts) is 94 bytes, or 376 weight units, before roughly 4 more units of witness framing. The exact overhead varies with transaction shape. The 380-weight-unit figure is the wallet-output anchor used in every per-block calculation below. The post-Taproot baseline is the P2TR key-path spend per BIP-341: the 32-byte tweaked Schnorr public key lives in the output script, and the witness reveals only the 64-byte Schnorr signature. Each transaction therefore costs roughly 444 weight units (380 of overhead plus 64 of witness), and the chain admits floor(4{,}000{,}000 / 444) = 9009 transactions per 4-million-WU block.

A Strand operator preparing for migration picks ML-DSA-65 as the candidate per the chapter’s planning decision. The chapter’s model for the future PQ-signature soft fork follows the P2WPKH-style commit-then-reveal pattern. The output script hash-commits to the post-quantum public key, and the witness reveals both the public key (1952 bytes for ML-DSA-65) and the signature (3309 bytes per FIPS 204 Table 2) at spend. One transaction now carries 5261 bytes of cryptographic material in the witness. With 380 weight units of overhead and a 5261-byte witness, each ML-DSA-65 spend costs 5641 weight units. The chain admits floor(4{,}000{,}000 / 5641) = 709 transactions per block, a 12.7-fold throughput drop against the post-Taproot baseline. Exact BIP-141 serialization of the same spend, with its two three-byte witness length prefixes, lands at 5646 weight units and 708 transactions. The one-constant model is within one transaction of the exact count for every candidate below.

The lifecycle stays the same shape: sign locally, broadcast to the mempool, wait for inclusion, observe finality. The numbers change. The mempool pressure rises because a single block clears fewer transactions. The per-fee-byte rate for the same priority level rises in turn. The wallet that signed the transaction holds an ML-DSA-65 keypair instead of a secp256k1 keypair. The address derives from the hash of the post-quantum public key under the P2WPKH-style framing the chapter assumes for the future PQ-signature output type. The legacy scheme hashed the secp256k1 public key instead. The verifier on every full node runs the FIPS 204 verification routine in place of secp256k1 ECDSA verification.

Ethereum follows a different deployment path. The Strand ERC-4337-style account abstraction lets a smart-contract wallet pick the signature scheme (Buterin et al., 2021). The wallet exposes a validateUserOp entry point that any post-quantum verifier can implement. The EntryPoint contract calls the wallet to authenticate each user operation. Account-level migration replaces a Layer-1 hard fork. The cost shifts onto the wallet operator and the user, who pay for the verifier’s gas envelope on every transaction.

ECDSA over secp256k1 produces a 64-byte canonical signature: a pair (r, s) of 32-byte big-endian integers. Bitcoin’s pre-Taproot DER encoding wraps the same (r, s) in 70 to 72 bytes, and the witness or scriptSig typically carries a one-byte sighash flag alongside it. The chapter’s “64 bytes” is the canonical cryptographic lower bound rather than the exact on-chain encoding. BIP-340 Schnorr-secp256k1 (Wuille et al., 2020) also produces a 64-byte signature, paired with a 32-byte public key. It is deployed via Taproot per BIP-341 (key path) (Wuille, Nick, & Towns, 2020) and BIP-342 (script path) (Wuille, Nick, & Towns, 2020b), active on Bitcoin since November 2021. The chapter’s bar chart and per-block calculations use the 64-byte canonical form for both ECDSA and Schnorr as the toy-model lower bound. The 64-byte form is the figure relevant to the post-Taproot transaction surface on Bitcoin and to every transaction on Ethereum.

ML-DSA-65 produces a 3,309-byte signature paired with a 1,952-byte public key per FIPS 204 Table 2. Verification (FIPS 204 Algorithm 8, ML-DSA.Verify_internal) is dominated by polynomial matrix-vector multiplication in the NTT domain, one SampleInBall computation, hint application via UseHint, an infinity-norm check on the response vector, and a hash-equality check against the commitment. Rejection sampling belongs to signing (FIPS 204 Algorithm 7), not verification. The verifier runs straight through with no abort-retry loop. Ch 12 walked ML-DSA verification from scratch, recomputing the commitment through UseHint. The cost accounting is simple: a verifier evaluates a fixed number of NTT-domain polynomial multiplications and a hash chain, with no curve operations.

SLH-DSA-128s produces a 7,856-byte signature paired with a 32-byte public key per FIPS 205 Table 2. The hash-tree traversal during verification touches a fixed number of FORS authentication paths and a fixed number of WOTS+ chain evaluations. Ch 17 walked the construction from scratch. The ‘s’ parameter set (‘s’ for small) trades signing speed for smaller signatures relative to the ‘f’ set. The Layer-1 transaction surface signs once per spend and verifies on every node. The smaller-signature tradeoff favors ‘s’ as the default for that surface.

The Ed25519+ML-DSA-65 composite carries a 3,373-byte signature (64 from Ed25519 plus 3,309 from ML-DSA-65) paired with a 1,984-byte public key (32 from Ed25519 plus 1,952 from ML-DSA-65). The composite is EUF-CMA secure if either component is, per the Ch 27 framing. Ed25519 is specified in RFC 8032 (Josefsson & Liusvaara, 2017). The composite buys defense in depth during the cutover window at a marginal byte cost dominated by the larger component.

Figure 37.1 below is the per-signature byte-budget bar chart across the candidate set. The chart anchors the throughput tradeoff in absolute bytes so the operator can see at a glance which candidate moves the per-block envelope most.

Per-signature byte budget across the candidate set A horizontal-bar chart with five rows. Top to bottom: ECDSA-secp256k1 at 64 bytes, Schnorr-secp256k1 at 64 bytes, ML-DSA-65 at 3,309 bytes, Ed25519+ML-DSA-65 composite at 3,373 bytes, SLH-DSA-128s at 7,856 bytes. Every bar is drawn at one scale, 460 pixels to 7,856 bytes, so the SLH-DSA-128s bar reaches the right edge and the two classical 64-byte bars are four pixels wide. Numeric labels appear at the right end of each bar. A four-entry legend keys the fills to primitive family: classical, PQ lattice, composite, hash-based. Per-signature byte budget 0 ~4 KB ~8 KB ECDSA-secp256k1 Schnorr-secp256k1 ML-DSA-65 Ed25519+ML-DSA-65 SLH-DSA-128s 64 B 64 B 3,309 B 3,373 B 7,856 B Classical (64 B) PQ lattice Composite Hash-based
Figure 37.1. Signature byte budget by candidate. ECDSA and Schnorr at 64 bytes set the byte baseline; ML-DSA-65 at 3,309 bytes is roughly 50x larger; SLH-DSA-128s at 7,856 bytes is roughly 120x larger. On Ethereum's contract-wallet model the throughput tax tracks the bar length above the baseline. On Bitcoin the revealed post-quantum public key adds to it (Block 1, below).

XMSS-MT and LMS are stateful hash-based schemes. State management does not survive the multi-device wallet pattern that Layer-1 transactions assume. An operator with a phone wallet, a desktop wallet, and a hardware wallet cannot reliably synchronize a one-time-key index across devices. A re-used index breaks either scheme. Ch 15 walked the state burden in detail. The conclusion carries through here. Stateful hash-based schemes are not a good default for general-purpose per-spend wallet signatures. Specialized contexts with single-signer state machines remain viable.

The migration is a four-part decision and deployment process: candidate choice, address-format design, deployment shape (branching on Bitcoin versus Ethereum), and cutover.

The Strand operator picks from the four-element candidate set per the chapter’s planning notes. ML-DSA-65 wins the per-block throughput axis. SLH-DSA-128s wins the conservative-assumption axis: its security depends on the hash function and not on a structured-lattice assumption. The composite wins the cutover-confidence axis at the cost of carrying both signatures forever for any address that opts in. The legacy classical-secp256k1 row stays in the table as the contract-wallet baseline against which the migration tax is measured.

The byte budget across the candidate set is the first inline block. The function below is a pedagogical slice of l1_migration.byte_budget.evaluate.

# Block 1: pedagogical slice of l1_migration.byte_budget.evaluate (stdlib only).
BTC_BLOCK_WEIGHT_LIMIT = 4_000_000
BTC_TX_OVERHEAD_WU = 380
ETH_BLOCK_GAS_LIMIT = 60_000_000 # EIP-7935 / Fusaka, Dec 2025
ETH_TX_BASE_GAS = 21_000
ETH_GAS_PER_NONZERO_CALLDATA_BYTE = 16
# The 64-byte classical row is the deployed baseline on both chains, and
# the primitive differs by chain: BIP-340 Schnorr for a Taproot key-path
# spend on the Bitcoin side, ECDSA for the Ethereum contract wallet.
# Both are 64 bytes. On the Bitcoin side the tweaked public key lives in
# the output script, so the witness reveals only the signature; pk_bytes
# below is the 33-byte Ethereum compressed key, and BIP-340's own key is
# 32-byte x-only and never enters the Bitcoin figure.
# The PQ candidates are modeled as P2WPKH-style commit-then-reveal,
# so the spend witness reveals both the public key and the signature.
CANDIDATES = {
"classical-secp256k1": {"sig_bytes": 64, "pk_bytes": 33, "reveal_pk": False},
"ML-DSA-65": {"sig_bytes": 3309, "pk_bytes": 1952, "reveal_pk": True},
"SLH-DSA-128s": {"sig_bytes": 7856, "pk_bytes": 32, "reveal_pk": True},
"Ed25519+ML-DSA-65": {"sig_bytes": 64+3309, "pk_bytes": 32+1952, "reveal_pk": True},
}
def evaluate(primitive):
assert primitive in CANDIDATES, f"unknown primitive: {primitive!r}"
sig = CANDIDATES[primitive]["sig_bytes"]
pk = CANDIDATES[primitive]["pk_bytes"]
witness = sig + (pk if CANDIDATES[primitive]["reveal_pk"] else 0)
btc_tx = BTC_BLOCK_WEIGHT_LIMIT // (BTC_TX_OVERHEAD_WU + witness)
# Ethereum side assumes the wallet contract stores the public key
# in state (paid at deployment), so only the signature rides in
# calldata per user operation.
eth_per_tx_gas = ETH_TX_BASE_GAS + sig * ETH_GAS_PER_NONZERO_CALLDATA_BYTE
eth_tx = ETH_BLOCK_GAS_LIMIT // eth_per_tx_gas
return sig, pk, btc_tx, eth_tx
for primitive in CANDIDATES:
sig, pk, btc, eth = evaluate(primitive)
print(f"{primitive:<20} sig={sig:>5} pk={pk:>5} btc_tx={btc:>5} eth_tx={eth:>4}")
# ==> classical-secp256k1 sig= 64 pk= 33 btc_tx= 9009 eth_tx=2724
# ==> ML-DSA-65 sig= 3309 pk= 1952 btc_tx= 709 eth_tx= 811
# ==> SLH-DSA-128s sig= 7856 pk= 32 btc_tx= 483 eth_tx= 409
# ==> Ed25519+ML-DSA-65 sig= 3373 pk= 1984 btc_tx= 697 eth_tx= 800

Every Python block this chapter prints is also a standalone file in the companion repository, under chapter-code/ch37/, one file per block. Appendix C covers the clone and the environment they run on.

The Bitcoin column reports a 12.7-fold throughput drop for ML-DSA-65 against the post-Taproot baseline: the spend witness carries both the 1952-byte public key and the 3309-byte signature, so per-tx weight is 5641 against the 4-million-WU budget. Ethereum reports a 3.4-fold drop on the same comparison under the marginal-calldata model above. The difference is structural. Bitcoin’s 380-weight overhead is small relative to the witness for a PQ spend, so the public-key reveal dominates the per-block envelope. Ethereum’s 21000-gas base cost dwarfs the ECDSA signature calldata cost (1024 gas). The chapter’s Ethereum model assumes the public key lives in the smart-contract wallet’s state rather than in per-tx calldata, so adding signature bytes scales more linearly. The composite row trails the ML-DSA-65 row by 1.7 percent on Bitcoin and 1.4 percent on Ethereum. The Ed25519 component contributes 64 bytes and 1024 gas, dominated by the larger PQ component.

The Ethereum figures above are the execution-gas-dominant marginal model. They count the legacy 16-gas-per-nonzero-byte calldata cost that applies on the standard-path branch of the EIP-7623 max(). After Pectra, EIP-7623 charges a transaction 21000 plus the larger of two branches (Wahrstätter & Buterin, 2024). The standard branch charges STANDARD_TOKEN_COST * tokens plus execution_gas_used; the floor branch charges TOTAL_COST_FLOOR_PER_TOKEN * tokens and nothing else. STANDARD_TOKEN_COST is 4 and TOTAL_COST_FLOOR_PER_TOKEN is 10, and tokens counts each zero calldata byte once and each nonzero byte four times. The execution_gas_used term is what selects the branch, so a transaction that runs little EVM code relative to its payload falls to the floor.

For a calldata-dominant transaction where the floor branch wins the max, an all-nonzero signature payload effectively costs 40 gas per nonzero byte rather than the 16 the standard branch charges. ERC-4337 UserOperations whose verifier executes few EVM operations relative to the signature size fall in the floor regime; UserOperations whose PQ-verifier consumes millions of gas in EVM bytecode fall in the execution-gas-dominant marginal regime. The chapter’s package exposes both sensitivities. The data-floor figures are:

CandidateSig bytesMarginal (16 gas/byte)EIP-7623 floor (40 gas/byte)
classical-secp256k1 (contract wallet, sig in calldata)642,724 tx/block2,546 tx/block
ML-DSA-653,309811 tx/block391 tx/block
SLH-DSA-128s7,856409 tx/block178 tx/block
Ed25519+ML-DSA-653,373800 tx/block384 tx/block

Neither model includes the cost of verifying ML-DSA or SLH-DSA in EVM bytecode. A plain EOA transfer carries its secp256k1 signature in the transaction envelope, not in calldata, and pays the 21000-gas base alone, giving 2,857 transactions per 60-million-gas block. The ECDSA row above is a contract-wallet figure paying 5 to 12 percent more gas, so its throughput sits correspondingly below 2,857. The PQ rows have no EOA counterpart, since no PQ signature is in the envelope. An ERC-4337 smart-contract wallet that calls ECRECOVER from inside a verifier contract pays the precompile’s fixed 3000-gas cost on top of base. ML-DSA-65 and SLH-DSA-128s have no precompile at chain-tip 2026. Verification runs in EVM bytecode at a cost in the millions of gas per call. That cost also has to clear ERC-4337’s admission rule: a bundler following the specification drops a UserOperation whose verificationGasLimit is not lower than MAX_VERIFICATION_GAS, 500,000 gas (Buterin et al., 2021). A verifier costing millions of gas therefore needs either an implementation optimized below that line or an alternative mempool with relaxed validation rules, whose procedures the ERC leaves out of scope. The actual per-block PQ throughput on Ethereum is therefore well below the calldata-only ceiling reported here: omitting verification gives a cost floor, which is a throughput ceiling. That gap between calldata-only cost and actual EVM verification cost is the argument for a future ML-DSA and SLH-DSA verification precompile.

BIP-360 introduces Pay-to-Merkle-Root (P2MR) as a SegWit version 2 output type alongside Taproot (Beast et al., 2024). The proposed output script is OP_2 OP_PUSHBYTES_32 <hash>, committing to a Merkle root of a script tree rather than to a key-path public key. P2MR is Taproot-adjacent with the always-exposed key path removed. The spending witness reveals the script and the script-leaf data needed to verify the spend against the committed root. The BIP is Draft v0.12.1 at chain-tip 2026. Its changelog records a proposal renamed twice, from Pay-to-Quantum-Resistant-Hash (P2QRH) through Pay-to-Tapscript-Hash (P2TSH) to its current title:

VersionDateChange
v0.8.02025-07-07P2TR-style output, key-path spend removed
v0.10.02025-09-17Renamed P2QRH to P2TSH
v0.11.02026-02-10Renamed P2TSH to P2MR
v0.12.02026-06-18Depth-zero script trees made anyone-can-spend
v0.12.12026-07-24Python example implementation, test-vector fixes

The BIP explicitly states that P2MR by itself does not introduce post-quantum signature schemes. ML-DSA and SLH-DSA are named as candidates for future work and require a separate proposal.

The chapter’s running example therefore treats the Bitcoin path as two-layer. The first layer is P2MR, which reduces long-exposure key-path risk by replacing the Taproot tweaked-key commitment with a script-tree commitment. The second layer is a hypothetical future PQ-signature soft fork. It would define the post-quantum verification opcodes (or a leaf-version-tagged Merkle-root semantics) under which an ML-DSA or SLH-DSA spend can validate. The chapter’s byte-budget arithmetic in Block 1 above models the second layer’s output type as a P2WPKH-style commit-then-reveal pattern. The output script hash-commits to the post-quantum public key, and the witness reveals both the public key and the signature on spend. This is the same shape as P2WPKH against P2PK, and the chapter’s assumed analogue for whatever future BIP introduces ML-DSA spends. The exact wire format is the future-BIP author’s choice. A dedicated-opcode variant of commit-then-reveal changes the budget by only a few witness-overhead bytes. The leaf-version-tagged Merkle-root variant also reveals a leaf script and a control block at spend. The current draft fixes the control block at 1+32m1 + 32m bytes for a tree of depth mm, so 33 bytes at depth 1 (Beast et al., 2024). The leaf script’s own opcode and push framing are the future BIP’s to fix, and this chapter’s model puts them at a few bytes. That moves the ML-DSA-65 throughput factor from 12.7 to about 12.8.

Figure 37.2 below compares three Bitcoin output shapes side by side: the legacy P2TR key-path baseline, the BIP-360 P2MR script-root commitment (long-exposure mitigation only), and the chapter’s assumed future PQ-signature output type (P2WPKH-style commit-then-reveal layered on top of P2MR). The figure illustrates the two-layer activation envelope: P2MR removes the always-exposed key path, and a separate future soft fork would change the witness shape to carry the post-quantum public key and signature on spend.

P2TR, P2MR, and future PQ-signature output shape comparison Three columns side by side. Left column titled Legacy P2TR shows the output script line and the witness line: ScriptPubKey is OP_1 followed by 32-byte tweaked public key (34 bytes total), witness is one 64-byte Schnorr signature. Middle column titled BIP-360 P2MR shows: ScriptPubKey is OP_2 followed by 32-byte script-tree Merkle root (34 bytes total), witness is the script-tree reveal (size depends on the chosen script; no key-path public key exposed at rest). Right column titled Future PQ-signature soft fork shows: ScriptPubKey is a SegWit-version opcode plus 32-byte hash of the post-quantum public key (34 bytes total), witness is one 1952-byte ML-DSA-65 public key plus one 3309-byte ML-DSA-65 signature. The right column's witness is drawn as two stacked boxes, one per item revealed on spend, where the other two columns carry a single box. Box height and fill mark row position rather than byte count or primitive family, so the byte magnitudes are the labels and Figure 37.1, not the geometry here. Dashed arrows run left to right between the columns, labelled BIP-360 and future BIP. Legacy P2TR BIP-360 P2MR Future PQ-sig soft fork (deployed) (Draft v0.12.1) (not yet proposed) ScriptPubKey Witness OP_1 + 32-byte tweaked pk 34 bytes BIP-340 Schnorr signature 64 bytes Witness total: 64 bytes OP_2 + 32-byte script-tree root 34 bytes Script-tree reveal (no exposed key path) script-dependent Long-exposure mitigation only SegWit op + 32-byte hash(pk) 34 bytes ML-DSA-65 pk 1952 bytes (revealed at spend) ML-DSA-65 signature 3309 bytes Witness total: 5261 bytes BIP-360 future BIP P2MR mitigates long-exposure key-path risk; a separate future soft fork is needed for ML-DSA spends.
Figure 37.2. Three Bitcoin output shapes side by side. P2TR (deployed) holds the tweaked public key in scriptPubKey and reveals a 64-byte Schnorr signature in the witness. BIP-360 P2MR (Draft v0.12.1) holds a 32-byte script-tree root in scriptPubKey and removes the key-path public key from the at-rest exposure surface. A future PQ-signature soft fork, modeled here as P2WPKH-style commit-then-reveal, would hold a 32-byte hash of the post-quantum public key in scriptPubKey. The witness on spend would reveal both the 1952-byte ML-DSA-65 public key and the 3309-byte signature (5261 bytes total).

The byte-budget model also assumes the future PQ-signature soft fork lifts or bypasses Tapscript’s 520-byte maximum stack-element size. BIP-342 explicitly retains the limit from pre-Taproot Bitcoin Script: “the existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes” (Wuille, Nick, & Towns, 2020b). ML-DSA-65 public keys at 1,952 bytes and signatures at 3,309 bytes exceed that limit by factors of roughly 3.7x and 6.4x; SLH-DSA-128s signatures at 7,856 bytes by 15x. BIP-342 reserves the OP_SUCCESSx opcode range (OP_SUCCESS80, OP_SUCCESS98, and several others) as a soft-fork upgrade hook. Encountering one of these opcodes succeeds validation under current rules, so a future soft fork can define new opcode semantics, including a new OP_CHECKMLDSA (or equivalent) that admits larger stack elements. The chapter’s “P2WPKH-style commit-then-reveal” model assumes this future soft fork pairs the new opcode with a stack-element rule that accepts ML-DSA / SLH-DSA payloads.

The derivation path follows BIP-32. The future PQ-signature output type would commit to a per-spend public-key hash rather than a per-address public key. Wallets should treat PQ-signature outputs as single-use by policy: public-key reuse recreates long-exposure key-recovery risk once the key is revealed on first spend. That is a wallet-hygiene rule, not a BIP-360 consensus property. Ch 38 walks the wallet-side derivation in detail. The output script and the witness shape are what the future PQ-signature soft fork would change relative to the P2MR baseline.

The Ethereum side has no equivalent hard-fork primitive change. ERC-4337 admits any signature scheme via the smart-contract wallet’s validateUserOp entry point. The EntryPoint contract calls the wallet’s verifier on every user operation. The wallet writer ships an ML-DSA-65 verifier (or any other) as the implementation. The address derivation lives entirely in the wallet contract’s deployment code rather than in a chain-level address scheme.

Deploy the soft fork or the account abstraction

Section titled “Deploy the soft fork or the account abstraction”

Bitcoin’s soft-fork path activates BIP-360 alongside Taproot. The chain admits both legacy ECDSA outputs and new P2MR outputs in the same blocks. Node operators upgrade asynchronously, and the soft fork enforces the new validation rules at a coordinated block height. The BIP itself takes no position on the quantum-computing timeline. Co-author Heilman has publicly estimated a roughly seven-year activation-through-completion horizon: two and a half years of specification and review, half a year to activate, and five more before 90 percent of holders have moved (Bitcoin May Take 7 Years to Upgrade to Post-Quantum: BIP-360 Co-Author, 2026). That is a personal forecast conditioned on everyone agreeing on the roadmap, offered with the caveat that no one actually knows, and it is not a parameter of BIP-360.

The activation horizon sits inside the Mosca window for the transaction surface. The Strand running example has X = 50, Y = 5, and Z = 9. The breach window is 46 years per Ch 36 Exercise 4. The activation horizon is the work to begin once the operator commits to the candidate. The work continues for the half-decade after activation as wallets and exchanges migrate user balances.

Ethereum’s account-abstraction path is a wallet-deployment problem. EntryPoint contracts have been deployed on Ethereum mainnet since 2023, and the v0.6 release of 24 April 2023 records the deployed contract’s address (eth-infinitism, 2023). The ERC itself is Final (Buterin et al., 2021). The ERCs repository’s history moves it there on 2 June 2026 (Weiss, 2026). EntryPoint deployments exist on Ethereum mainnet and on the major L2s (Arbitrum, Optimism, Base, Polygon). Deployment is per-chain ecosystem adoption rather than a protocol mandate. The post-quantum migration on Ethereum is therefore not a chain upgrade but a wallet rollout. Each smart-contract wallet that wants ML-DSA-65 ships the verifier in its validateUserOp implementation, and that verifier must fit the standard bundler’s validation-gas admission rule, MAX_VERIFICATION_GAS at 500,000 gas (Buterin et al., 2021), or run through an alternative mempool with its own rules. The cost of post-quantum verification falls on the wallet operator and the user, paid per transaction in gas. A precompile for ML-DSA verification would amortize the cost across every wallet, but no such precompile is standardized at chain-tip 2026. Pending an EIP, the cost lives in the wallet’s EVM bytecode.

The deployment shape therefore differs in the failure mode. A Bitcoin PQ-signature soft fork that activates without a sufficient operator-side migration ramp leaves the network with a primitive change that few users can spend against. The throughput tax is paid by every full node regardless of how few transactions land. An Ethereum account-abstraction rollout with a small migration ramp leaves the chain with most transactions still on ECDSA-secp256k1, paying the legacy precompile cost. The throughput tax is paid only by the wallets that opted in.

The composite signature is the cutover-window candidate. Each transaction carries both an Ed25519 signature and an ML-DSA-65 signature for the same message under a properly specified AND-composition. The required engineering conditions are: unambiguous encoding of the component signatures, domain separation between the two component hash inputs, independent key generation for each component, and verifier semantics that require both signatures to verify against their shared message. Under those conditions the EUF-CMA bound on the composite is the bound on the stronger component alone, per the Ch 27 framing. During the cutover, an operator running Ed25519+ML-DSA-65 retains the classical guarantee against a non-quantum adversary even if a cryptanalytic break or proof flaw later surfaces against MLWE / MSIS.

The composite carries a 64-byte overhead over ML-DSA-65 alone. The verification work adds one Ed25519 verification to one ML-DSA-65 verification. On measured x86-64 an Ed25519 verification and a Dilithium3 verification (the round-3 name, since SUPERCOP publishes no FIPS 204 ML-DSA-65 row) cost about the same, so the composite roughly doubles verification work (Bernstein & Lange, 2026). ML-DSA-65 verification is in turn well below SLH-DSA-128s verification, which pays for hash-tree traversal and WOTS+ / FORS chain evaluation. Appendix D Exercise 2 works the byte and verification-time arithmetic under stated illustrative timings. Specific timings depend on the CPU, the implementation, the parameter set, and constant-time hardening.

The deprecation schedule for legacy ECDSA spends parallels the cutover for the Strand running example. As post-quantum addresses accumulate balance, Strand’s chain governance schedules a sunset for new ECDSA outputs. Existing ECDSA outputs remain spendable until empty. The chain accepts no new ECDSA outputs after the sunset block. The sunset is the last point at which the operator can roll back: after it, the chain’s first-wave migration is committed. This sunset is a Strand-specific governance policy. BIP-360 P2MR does not itself impose such a sunset; it only proposes a new output form. Bitcoin’s eventual migration path would require its own separate sunset proposal.

The throughput-rank function is the second inline block. The function below is a pedagogical slice of l1_migration.throughput_compare.rank.

# Block 2: pedagogical slice of l1_migration.throughput_compare.rank (stdlib only).
BTC_BLOCK_WEIGHT_LIMIT = 4_000_000
BTC_TX_OVERHEAD_WU = 380
ETH_BLOCK_GAS_LIMIT = 60_000_000
ETH_TX_BASE_GAS = 21_000
ETH_GAS_PER_NONZERO_CALLDATA_BYTE = 16
# The classical row is BIP-340 Schnorr on the Bitcoin side (Taproot
# key path, no key in the witness) and ECDSA on the Ethereum side.
CANDIDATES = {
"classical-secp256k1": {"sig": 64, "pk": 33, "reveal_pk": False},
"ML-DSA-65": {"sig": 3309, "pk": 1952, "reveal_pk": True},
"SLH-DSA-128s": {"sig": 7856, "pk": 32, "reveal_pk": True},
"Ed25519+ML-DSA-65": {"sig": 64+3309, "pk": 32+1952, "reveal_pk": True},
}
def btc_tx_per_block(primitive):
c = CANDIDATES[primitive]
witness = c["sig"] + (c["pk"] if c["reveal_pk"] else 0)
return BTC_BLOCK_WEIGHT_LIMIT // (BTC_TX_OVERHEAD_WU + witness)
def eth_tx_per_block(primitive):
# Calldata-only lower bound; pk is assumed in wallet contract state.
per_tx = ETH_TX_BASE_GAS + CANDIDATES[primitive]["sig"] * ETH_GAS_PER_NONZERO_CALLDATA_BYTE
return ETH_BLOCK_GAS_LIMIT // per_tx
def rank(budget):
assert budget in ("btc", "eth"), f"unknown budget: {budget!r}"
fn = btc_tx_per_block if budget == "btc" else eth_tx_per_block
scored = [(p, fn(p)) for p in CANDIDATES]
return sorted(scored, key=lambda pair: (-pair[1], pair[0]))
for budget in ("btc", "eth"):
print(f"-- {budget} --")
for primitive, count in rank(budget):
print(f"{primitive:<20} {count:>6}")
# ==> -- btc --
# ==> classical-secp256k1 9009
# ==> ML-DSA-65 709
# ==> Ed25519+ML-DSA-65 697
# ==> SLH-DSA-128s 483
# ==> -- eth --
# ==> classical-secp256k1 2724
# ==> ML-DSA-65 811
# ==> Ed25519+ML-DSA-65 800
# ==> SLH-DSA-128s 409

The ordering is the same on both budgets. The classical secp256k1 baseline dominates per-block throughput, which on the Bitcoin side is a BIP-340 Schnorr key-path spend and on the Ethereum side an ECDSA contract wallet. ML-DSA-65 leads the post-quantum candidates by 1.5x on Bitcoin and by 2x on Ethereum. The composite trails ML-DSA-65 alone by 1.7 percent on Bitcoin and 1.4 percent on Ethereum, driven by the Ed25519 component’s 64-byte signature and 32-byte public-key contributions. SLH-DSA-128s sits at the floor on both. The deciding tradeoff for the operator is therefore not throughput rank (which is the same on both budgets) but the conservative-assumption preference. That preference moves SLH-DSA-128s up the table for any operator who weighs the hash-only security argument over the per-block cost.

Cryptanalysis: three transaction-surface attacks

Section titled “Cryptanalysis: three transaction-surface attacks”

The transaction surface inherits three attack categories specific to the public-ledger setting beyond the generic Shor break covered in Ch 04 and Ch 36.

The first is mempool front-running. A transaction broadcast to the mempool sits open between the broadcast event and the inclusion event, typically minutes on Bitcoin and one to a few 12-second slots on Ethereum. Bitcoin’s mean block interval is ten minutes, and a transaction whose fee rate is below the clearing rate waits for more than one block. A fast-clock CRQC running Shor against a public key readable in that window would recover the private scalar before the legitimate transaction is mined, then sign a replacement transaction redirecting the value to the attacker.

What differs by output type is not the length of the mempool wait but the moment the public key first becomes readable.

Output typePublic key readable fromExposure runs
Ethereum transactionsender-address recovery, in flightbroadcast to inclusion
Bitcoin P2PKH, P2WPKHthe witness or scriptSig, at spendbroadcast to inclusion
Bitcoin P2TR key paththe scriptPubKey, from fundingfunding to spend
BIP-360 P2MRthe revealed script leaf, at spendbroadcast to inclusion
Future PQ output (modeled)the witness, at spendbroadcast to inclusion

Ethereum transactions carry no explicit public-key field. The secp256k1 public key is recoverable from the signature and the message hash during the execution client’s sender-address recovery, so an in-flight transaction hands an attacker the same material a Bitcoin P2WPKH spend discloses directly. Taproot key-path spends are the limiting case: the tweaked public key sits in the scriptPubKey from the moment the UTXO is funded, so the threat horizon is the whole life of the UTXO rather than the mempool wait.

BIP-360 P2MR removes that long exposure by committing to a script-tree root rather than to an exposed Taproot key, and a future P2WPKH-style post-quantum output type behaves like P2WPKH: hash-committed at output, revealed at spend. Neither shape closes the on-spend window, because any signature revealed during a spend is readable while the transaction waits. Full mitigation therefore requires the post-quantum signature itself, not the output shape.

Under the fast-clock CRQC assumptions analyzed by Babbush et al. (Babbush et al., 2026), the on-spend exposure window for secp256k1 becomes plausible at block-timescale or below. This is a scenario analysis, not a current operational capability. The mitigation is the primitive swap: ML-DSA-65, SLH-DSA-128s, or the composite removes the ECDLP target from the mempool exposure path. The Aggarwal et al. analysis covered the same threat for Bitcoin under earlier resource estimates and made the per-output-type distinction above (Aggarwal et al., 2018).

The second is historical forgery. Every signature ever recorded on a public ledger remains observable forever. A CRQC that arrives in 2035 can attack any signature recorded before 2035 whose public key is still active or controls funds. The mitigation is key rotation before ZZ: addresses that hold value on ZZ-day must rotate to a post-quantum primitive before ZZ, and addresses that already rotated and emptied are not at risk regardless of the signature’s archival status. The Strand running example sets X equal to 50 (the chain’s archival horizon) for the transaction surface, dominating the migration window. Ch 36 Exercise 4 ranks this surface as the most urgent by a wide margin. Ch 38 covers the wallet-side rotation playbook in detail.

The third is composite-signature interaction. The Ch 27 framing gives the EUF-CMA bound on a composite as the bound on the stronger component alone. The practical cryptanalytic concern is not the bound but the failure mode during cutover. A composite verifier that requires both components to verify rejects a transaction if either Ed25519 verification or ML-DSA-65 verification fails. A bug in the lattice verifier on a single full-node implementation produces a chain split: nodes that accept the transaction continue mining, nodes that reject it do not, and the chain forks. The mitigation is staged rollout: deploy the composite verifier on a testnet first, require multi-implementation agreement on the validation rules before mainnet activation, and carry in the activation itself a network-wide fallback rule stating whether, and on what signal, acceptance reverts to classical-only. A node that falls back on its own splits the chain exactly as the bug does, and every transaction accepted classical-only during the fallback has given up the post-quantum leg.

The four candidates trade off on four axes. The chapter package’s byte_budget.evaluate populates the per-tx columns. The rest of the row is operational rather than computed.

CandidatePer-sig bytesPer-verify cost classPer-pk bytesDeployment shape
classical-secp256k164EC scalar mul (fast in native code)33Deployed baseline
ML-DSA-653,309Lattice NTT (fast in native code)1,952Future PQ-signature soft fork over P2MR, or account-abstraction contract
SLH-DSA-128s7,856Hash-tree traversal (slow vs lattice)32Future PQ-signature soft fork over P2MR, or account-abstraction contract
Ed25519+ML-DSA-653,373Sum of components1,984Composite cutover

The conservative-assumption preference moves SLH-DSA-128s up the table. SLH-DSA’s security argument depends on the pseudorandomness of the underlying PRF and on preimage resistance and related properties of the underlying hash function, SHA-2 or SHAKE, with the hypothesis set named in Chapter 18. It does not depend on the structured-lattice assumption that ML-DSA inherits from MLWE and MSIS. An operator who weighs the prospect of a structural attack on the lattice problems will accept the 1.5x Bitcoin throughput penalty (2x on Ethereum) against ML-DSA-65 in exchange for the hash-only security argument. The cost is 7,856 bytes per signature against 3,309, and a verification cost that is substantially slower than ML-DSA-65 verification in optimized native implementations because of the hash-tree traversal and the WOTS+ / FORS chain evaluation.

The throughput preference moves ML-DSA-65 to the top. ML-DSA wins per-block throughput by 1.5 to 2 times against SLH-DSA on either budget, and the lattice verification is fast in absolute terms. The cost is the structured-lattice security argument and a 61-times-larger public key (1,952 bytes vs 32 for SLH-DSA-128s), which matters at the wallet derivation level (Ch 38) and, on Bitcoin, at the per-block throughput level too, because the commit-then-reveal witness carries the public key: the chapter’s 5,641 WU for ML-DSA-65 is 380 + 3,309 + 1,952. Only on the Ethereum smart-account model, where the key is already stored, is the public key free at the margin.

The composite preference applies during the cutover window only. Ed25519+ML-DSA-65 carries 64 bytes more than ML-DSA-65 alone (a 2 percent overhead) and roughly a second verification’s worth of work (one Ed25519 verification on top of one ML-DSA-65 verification). The composite is the right cutover candidate for an operator who wants both hedges at once and is willing to pay the marginal byte and verification overhead during the cutover. Under the AND rule the ML-DSA-65 leg carries the protection against an early CRQC, which breaks the Ed25519 leg outright, and the Ed25519 leg keeps the classical guarantee standing if the younger lattice scheme turns out to have a defect while classical signatures are still secure.

The deployment-shape axis splits Bitcoin and Ethereum. Bitcoin’s path is two-layer (P2MR plus a future PQ-signature soft fork) and costs the operator a multi-year activation horizon and a network-wide validation upgrade per layer. Ethereum’s account-abstraction path costs the operator a wallet deployment and per-transaction gas, paid by the wallets that opted in. Ch 29 covered the X.509 OID precedent for new signature-algorithm identifiers, and that precedent applies to the Bitcoin side at the address-format registry level. The Ethereum side is the Ch 26 modular-cryptographic-architecture case instead: the verifier is a swappable component behind the wallet contract’s validateUserOp interface, and the unit that versions is the deployed contract rather than a registered identifier.

  1. Bitcoin block weight under ML-DSA-65. Strand’s transaction surface is migrating to ML-DSA-65 via a future P2WPKH-style PQ-signature soft fork layered on top of BIP-360 P2MR. Use the chapter’s running-example values: 380 weight units of per-tx overhead, 1952 bytes of ML-DSA-65 public key plus 3309 bytes of signature revealed in the witness on spend. Compute the per-block transaction throughput under the 4 MB weight unit limit. Compare to the Taproot key-path baseline of about 9 thousand transactions per block, whose 64-byte witness signature is BIP-340 Schnorr rather than ECDSA. Report the throughput tax as a multiplicative factor.

  2. Compare two composite designs. Compute the byte overhead and verification work for two composite signatures: Ed25519+ML-DSA-65 (the chapter’s reference) and Ed25519+SLH-DSA-128s (the hash-only alternative). For each, report the composite signature size, the overhead vs the larger component alone, and the multiplicative ratio of composite size over the larger component. Use the FIPS 204 and FIPS 205 sizes from the chapter package.

  3. Open-ended: surface taxonomy on a fictional rollup. A fictional Layer-2 rollup anchored on Strand uses BLS over BLS12-381 for its operator-key signature on every state-update batch and Ed25519 for its end-user transaction signatures inside the rollup. Apply the Ch 36 surface taxonomy to each. State which is first-wave under the Ch 37 candidate set, which migration path applies (soft fork or account abstraction), and what a sensible cutover composite looks like. Justify each decision in one sentence.

  4. BIP-360 activation parameters for Strand. Strand has a stated CRQC scenario at Z=9Z = 9 (NCSC 2035 working assumption) and a transaction-surface migration target of ML-DSA-65 via the chapter’s two-layer Bitcoin path (BIP-360 P2MR plus a future PQ-signature soft fork). Sketch the activation parameters for the second layer: the activation block height, the operator-side migration ramp duration, and the Strand-specific legacy-ECDSA sunset block. Justify the activation window against Heilman’s roughly-seven-year planning estimate and against the chapter’s Mosca window for the transaction surface.

  5. Open-ended: map to the Ch 30 four-phase program. Map the Bitcoin and Ethereum migration paths to the Ch 30 four-phase program (discovery, first-wave, broad-rollout, end-of-migration). For each phase, name the dominant work-stream owner (operator, wallet vendor, exchange, governance multisig). Justify each mapping in one sentence.

The chapter package at solutions/ch37-l1-signature-migration and the test suite at tests/ch37 ground the byte-budget and throughput-rank computations the exercises reuse. Solutions to Exercises 1, 2, and 4 are in Appendix D, Chapter 37; Exercises 3 and 5 are open-ended and have editorial-note treatments rather than worked answers.

A separate track, for rebuilding rather than reading: the package exercises/ch37-l1-signature-migration has every function the chapter teaches replaced by a stub. Run PQC_IMPL=exercises pytest tests/ch37 to grade your version against the suite that proves the reference one.

Aggarwal, D., Brennen, G. K., Lee, T., Santha, M., & Tomamichel, M. (2018). Quantum Attacks on Bitcoin, and How to Protect Against Them. Ledger, 3, 68–90. https://doi.org/10.5195/ledger.2018.127
Babbush, R., Zalcman, A., Gidney, C., Broughton, M., Khattar, T., Neven, H., Bergamaschi, T., Drake, J., & Boneh, D. (2026). Securing Elliptic Curve Cryptocurrencies against Quantum Vulnerabilities: Resource Estimates and Mitigations. PRX Quantum, 7(3), 031001. https://doi.org/10.1103/j3xf-bw18
Beast, H., Heilman, E., & Foxen Duke, I. (2024). BIP-360: Pay-to-Merkle-Root (P2MR). Bitcoin Improvement Proposal (Draft). https://github.com/bitcoin/bips/blob/master/bip-0360.mediawiki
Beiko, T. (2024). EIP-7600: Hardfork Meta - Pectra. Ethereum Improvement Proposal / Meta. https://eips.ethereum.org/EIPS/eip-7600
Beiko, T., Stokes, A., & Dietrichs, A. (2024). EIP-7607: Hardfork Meta - Fusaka. Ethereum Improvement Proposal (Meta). https://eips.ethereum.org/EIPS/eip-7607
Bernstein, D. J., & Lange, T. (2026). eBACS: ECRYPT Benchmarking of Cryptographic Systems, SUPERCOP results for amd64-hertz (AMD Ryzen 7 7700, Zen 4). eBACS amd64-hertz results, sign, kem and dh pages; supercop-20260831, read 14 September 2026. https://bench.cr.yp.to/results-sign/amd64-hertz.html
Bitcoin may take 7 years to upgrade to post-quantum: BIP-360 co-author. (2026). Cointelegraph Magazine. https://cointelegraph.com/magazine/bitcoin-7-years-upgrade-post-quantum-bip-360-co-author/ (archived 2026-02-21)
Buterin, V., Weiss, Y., Tirosh, D., Nacson, S., Forshtat, A., Gazso, K., & Hess, T. (2021). ERC-4337: Account Abstraction Using Alt Mempool. Ethereum Request for Comments / EIP. https://eips.ethereum.org/EIPS/eip-4337
Ethereum Improvement Proposal authors. (2025). EIP-7935: Set default gas limit to 60M. Ethereum Improvement Proposal. https://eips.ethereum.org/EIPS/eip-7935
eth-infinitism. (2023). Account-Abstraction release v0.6.0. GitHub release, 24 April 2023. https://github.com/eth-infinitism/account-abstraction/releases/tag/v0.6.0
Josefsson, S., & Liusvaara, I. (2017). Edwards-Curve Digital Signature Algorithm (EdDSA). IETF RFC 8032. https://doi.org/10.17487/RFC8032
Lombrozo, E., Lau, J., & Wuille, P. (2015). BIP-141: Segregated Witness (Consensus layer). Bitcoin Improvement Proposal. https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki
National Institute of Standards and Technology. (2024a). FIPS 204: Module-Lattice-Based Digital Signature Standard. Federal Information Processing Standards Publication. https://doi.org/10.6028/NIST.FIPS.204
National Institute of Standards and Technology. (2024b). FIPS 205: Stateless Hash-Based Digital Signature Standard. Federal Information Processing Standards Publication. https://doi.org/10.6028/NIST.FIPS.205
Shor, P. W. (1994). Algorithms for quantum computation: discrete logarithms and factoring. Proceedings of the 35th Annual Symposium on Foundations of Computer Science (FOCS), 124–134. https://doi.org/10.1109/SFCS.1994.365700
Wahrstätter, T., & Buterin, V. (2024). EIP-7623: Increase calldata cost. Ethereum Improvement Proposal (Standards Track, Core). https://eips.ethereum.org/EIPS/eip-7623
Weiss, Y. (2026). Update ERC-4337: Move to Final. ethereum/ERCs repository, commit c8d8c2107f63, 2 June 2026. https://github.com/ethereum/ERCs/commit/c8d8c2107f63c996fe8b60af20081d4d911e1f9d
Wuille, P., Nick, J., & Ruffing, T. (2020). BIP-340: Schnorr Signatures for secp256k1. Bitcoin Improvement Proposal. https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
Wuille, P., Nick, J., & Towns, A. (2020a). BIP-341: Taproot: SegWit version 1 spending rules. Bitcoin Improvement Proposal. https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki
Wuille, P., Nick, J., & Towns, A. (2020b). BIP-342: Validation of Taproot Scripts (Tapscript). Bitcoin Improvement Proposal. https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki

Last updated: