Skip to content

Quantum Tripwire demo#121

Open
Sjors wants to merge 6 commits into
masterfrom
quantum-tripwire-demo
Open

Quantum Tripwire demo#121
Sjors wants to merge 6 commits into
masterfrom
quantum-tripwire-demo

Conversation

@Sjors

@Sjors Sjors commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Experimental demo of the quantum tripwire: Anthony Towns' "aRsm" ECDL-break proof from the bitcoindev thread https://gnusha.org/pi/bitcoindev/aj9SkwXqdRbuVZxH@erisian.com.au/

A 128-byte proof a || R || s || m is valid for a NUMS point N if (R, s) is a valid BIP-340 signature of m under P = N + a·G. A valid signature proves knowledge of dlog(N), which is only possible by breaking the elliptic-curve discrete log problem on secp256k1 — i.e. it is self-incriminating evidence of a post-quantum, key-path theft of a NUMS-internal-key Taproot output. The owner (or anyone) can assemble the proof from the public tweak a and the attacker's on-chain signature.

This branch implements it as a series of commits:

  1. test — a functional test that simulates the theft end to end (using a fake NUMS point with a known discrete log, so the theft can actually be signed) and verifies the proof in Python.
  2. node — an in-memory store holding a single proof, verified against a configurable NUMS point (default the BIP-341 NUMS point; -test=fakenums on regtest selects the known-dlog point). Adds submitquantumproof / getquantumproof RPCs and an XOnlyPubKey::AddTweak helper to compute P = N + a·G.
  3. mining — the held proof is published as a single required coinbase OP_RETURN, via both the generate* RPCs and the Mining IPC getCoinbaseTx() required outputs (the proof doesn't fit in the 80-byte header).
  4. validation — the block carrying the proof instantly activates the tripwire from the next block; after activation the OP_RETURN is no longer added and further proofs are ignored. Activation is persisted to a small self-verifying file: the activation block hash, the full coinbase transaction, and its merkle inclusion path. At startup — after headers load from disk, before the network accepts new headers (to avoid a reorg race) — it is checked two ways: the coinbase's merkle path must reconstruct the header's merkle root, and the coinbase must carry a verifying proof; the block header is also confirmed still in the active chain. Only the header is read, so it works on pruned nodes, and the proof is recovered by scanning the coinbase rather than stored twice. Deactivation is keyed on the activation block, so reorging out a later proof-bearing block does not deactivate. Not a consensus rule change.
  5. rpc — surface the tripwire as a quantum deployment (type tripwire) in getdeploymentinfo, so clients can observe it like a soft fork.
  6. p2p — a new qproof message gossips proofs: the first valid one is stored and flooded to peers; malformed/invalid/duplicate proofs are ignored. submitquantumproof also relays to peers (even when one is already held).

Caveats: this is a demo to explore the mechanism, not for merge. The held proof itself is kept only in memory (just the activation point is persisted), and the store is a process-global singleton.

Co-authored with Claude (Opus 4.8).

Add a functional test and helper module for Anthony Towns' "aRsm" ECDL-break
proof (the quantum tripwire), from the bitcoindev thread
https://gnusha.org/pi/bitcoindev/aj9SkwXqdRbuVZxH@erisian.com.au/

A 128-byte proof a || R || s || m is valid for NUMS point N if (R, s) is a
valid BIP-340 signature of m under P = N + a*G; a valid signature proves
knowledge of dlog(N), which is only possible by breaking ECDL.

The test uses a fake NUMS point with a known discrete log so it can simulate a
quantum attacker: a victim creates a script-path-only Taproot output with N as
its internal key, a thief key-path spends it, and the proof is assembled from
the public tweak and the thief's on-chain signature and verified in Python.

Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
@Sjors Sjors force-pushed the quantum-tripwire-demo branch 2 times, most recently from 15516e8 to 3978cc0 Compare June 27, 2026 13:32
@Sjors

Sjors commented Jun 27, 2026

Copy link
Copy Markdown
Owner Author

cc @ajtowns

Sjors and others added 2 commits June 27, 2026 15:54
Add an in-memory store for the single "aRsm" ECDL-break proof the node holds,
verified against a configurable NUMS point N (default the BIP-341 NUMS point;
-test=fakenums selects a point with a known discrete log so a theft can be
simulated). Verification computes P = N + a*G via a new XOnlyPubKey::AddTweak
helper and checks the BIP-340 signature.

Expose submitquantumproof and getquantumproof RPCs, and extend the functional
test to submit a proof, reject a bogus one, and confirm only one is held.

Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
Add the single held quantum-tripwire proof as a required coinbase OP_RETURN
output (CoinbaseTx::required_outputs), so it is published via both the
generate* RPCs and the Mining IPC. The proof is ~128 bytes and cannot fit in
the block header, so the coinbase is the only place to carry it; a comment
links the coinbase-signalling discussion this mirrors.

getblocktemplate now surfaces the proof in a quantum_proof field. Extend the
functional test to confirm the proof appears in the mined coinbase.

Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
@Sjors Sjors force-pushed the quantum-tripwire-demo branch 2 times, most recently from 5c1dc40 to ef9fb7e Compare June 27, 2026 14:39
Sjors and others added 3 commits June 27, 2026 17:50
…tarts

The block carrying the proof instantly activates the tripwire from the next
block: the store becomes a CValidationInterface, records the activation point,
and the miner stops adding the coinbase OP_RETURN once active. getquantumproof
reports the activation height.

Activation is persisted so it survives a restart. On firing, a small file is
written with the activation block hash, the full coinbase transaction, and its
merkle inclusion path. At startup (after headers are loaded from disk, before
the network accepts new headers, to avoid a reorg race) the file is verified
two ways: the coinbase's merkle path must reconstruct the block header's merkle
root, and the coinbase must carry a proof that verifies -- a defense against
broken/malicious software writing a bogus file. Only the header is needed (not
the block body), so this works on pruned nodes, and the proof is recovered by
scanning the coinbase rather than stored twice. Deactivation is keyed on the
activation block alone, so reorging out a later proof-bearing block does not
deactivate.

Not a consensus rule change -- just a signal that a NUMS discrete log has been
published. Covered by the functional test: activation, restart persistence,
reorg (de)activation, and rejection of a bogus activation file.

Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
Surface the tripwire as a "quantum" deployment (type "tripwire") in
getdeploymentinfo, reported active for the block after the activation height.
This is not a real BIP9/buried deployment -- there is no consensus rule change
-- but it lets clients observe the tripwire the same way they observe soft
forks. Extend the functional test (and rpc_blockchain.py) accordingly.

Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
Add a QPROOF p2p message carrying a 128-byte aRsm ECDL-break proof. On receipt
the node verifies it, stores it if it is the first valid proof seen, and floods
it to its other peers; malformed, invalid, or superfluous proofs are ignored
and not relayed. A proof submitted locally via submitquantumproof is relayed to
all peers even when one is already held, so an operator can inject one.

Add a functional test that a fake proof is ignored while a valid proof relays,
is stored, and is published in the coinbase OP_RETURN, activating the tripwire.

Co-authored-by: Claude (Opus 4.8) <noreply@anthropic.com>
@Sjors Sjors force-pushed the quantum-tripwire-demo branch from ef9fb7e to cb0aee4 Compare June 27, 2026 16:09
@ajtowns

ajtowns commented Jun 29, 2026

Copy link
Copy Markdown

What sort of idiot would call it "aRsm" when "ASMR" was right there? Tsktsktsk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants