Brings the whole project into git (previously only the on-ramp feature and a few parallel files were tracked). Includes: wallet core (src/), CashScript contracts/, the Capacitor shell (shells/), scripts/, tests, and the docs corpus (wiki/, snapshots/, Parameters/, Archive/, KnowledgeBase text). Excluded via .gitignore: node_modules/, dist/, .env (secrets), testnet WIF key files (.chipnet-*.json, devWallets.ts), KnowledgeBase/RAW media (~9.6 GB), transcripts/ (session logs), and machine-local config (.claude/*.local, *.lock). Secret-scanned before commit — no credentials in the tree. Note: src/swapMath.ts, src/swapBuilder.ts, contracts/OpenMintToken.cash are legacy (OP_RETURN era) but still imported; committed as-is, flagged for a separate removal once de-referenced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
155 lines
14 KiB
Python
155 lines
14 KiB
Python
#!/usr/bin/env python3
|
|
"""Build the SHORT corpus-styled HTML for the zero-conf / double-spend-FUD note,
|
|
reusing the Block Size Wars <head> (= Vol.13 stylesheet) so it matches the corpus.
|
|
Key ideas only — a companion note, not the full DRAFT (RAW/...DRAFT.md keeps the
|
|
long version). Re-runnable; refuses to clobber a hand-expanded destination.
|
|
"""
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
SRC = ROOT / "KnowledgeBase/03_historical_and_political_economic/blocksize-war_FOR-sophisticated-readers-and-historical-analysts.html"
|
|
# SUPERSEDED (2026-06-09): this standalone note is now folded into the Block Size
|
|
# Wars document as the "0-conf · The double-spend FUD" section. The standalone
|
|
# build is retired to Archive/ to avoid two drifting copies; the canonical source
|
|
# of the long-form argument is RAW/zero-conf-and-the-double-spend-fud_DRAFT.md.
|
|
DST = ROOT.parent / "Archive/zero-conf-double-spend-fud_FOR-sophisticated-readers-and-security-analysts.html" # D:/Dev/Archive (outside the repo)
|
|
|
|
if DST.exists():
|
|
raise SystemExit(f"REFUSING TO OVERWRITE existing {DST.name} — delete deliberately to regenerate.")
|
|
|
|
lines = SRC.read_text(encoding="utf-8").split("\n")
|
|
head = "\n".join(lines[0:842]).replace( # up to and incl. </head>
|
|
"<title>DEVIANT · The Block Size Wars</title>",
|
|
"<title>DEVIANT · Zero-Conf and the Double-Spend FUD</title>",
|
|
)
|
|
|
|
body = r"""<body>
|
|
<div class="frame">
|
|
|
|
<header class="master">
|
|
<div class="deviant-brand">Deviant</div>
|
|
<div class="vol-label">Companion note · the block-size conflict</div>
|
|
<span class="vol-tag">0-conf</span>
|
|
<h1>Zero-Conf and the <span class="accent">Double-Spend FUD.</span></h1>
|
|
<div class="subtitle">The attack, the defense Satoshi already wrote, and the narrative that erased the difference.</div>
|
|
<div class="descriptive">How a real, conditional, already-mitigated 2012 result was stripped of its conditions and its remedy, then recited as a timeless verdict against the one chain that implemented the remedy.</div>
|
|
<div class="meta">
|
|
<span><strong>For:</strong> Sophisticated readers and security analysts</span>
|
|
<span><strong>Date:</strong> June 2026</span>
|
|
<span><strong>Status:</strong> Companion note (full version: RAW/zero-conf-and-the-double-spend-fud_DRAFT.md)</span>
|
|
</div>
|
|
</header>
|
|
|
|
<p class="lede">The claim "Bitcoin 0-confirmation is unsafe" is true of a <em>naive</em> merchant, false of a <em>defended</em> one, and the difference was described by Satoshi in 2010. The peer-reviewed paper everyone cites is honest within its scope and even proposes the defense. What fails verification is not the measurement — it is the generalization built on top of it. The suspicion was warranted; its correct object is the narrative, not the science.</p>
|
|
|
|
<div class="callout">
|
|
<div class="callout-label">The comparison the title hides — same attack, different node</div>
|
|
<p>The 2012 paper is titled for the <em>attack</em>, but its data is a <em>comparison</em>: double-spend success is a function of the merchant's connectivity and defense, not of "0-conf" as such. Restoring that framing:</p>
|
|
<table style="width:100%; max-width:740px; border-collapse:collapse; font-size:13px; line-height:1.45; margin:10px 0 6px; font-family:'JetBrains Mono', ui-monospace, monospace;">
|
|
<thead>
|
|
<tr style="text-align:left; border-bottom:2px solid rgba(0,0,0,.45);">
|
|
<th style="padding:7px 9px; font-weight:700;">Node posture</th>
|
|
<th style="padding:7px 9px; font-weight:700;">Attacker effort to win</th>
|
|
<th style="padding:7px 9px; font-weight:700;">Outcome</th>
|
|
<th style="padding:7px 9px; font-weight:700;">Source</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr style="border-bottom:1px solid rgba(0,0,0,.12);">
|
|
<td style="padding:7px 9px;">Naive · low connectivity (≈8 peers) · no listening</td>
|
|
<td style="padding:7px 9px;">1 relay</td>
|
|
<td style="padding:7px 9px;"><strong>Succeeds</strong> (≈100%)</td>
|
|
<td style="padding:7px 9px;">KAC §4.4</td>
|
|
</tr>
|
|
<tr style="border-bottom:1px solid rgba(0,0,0,.12);">
|
|
<td style="padding:7px 9px;">Well-connected (≈125 peers) · no listening</td>
|
|
<td style="padding:7px 9px;">1 relay → coin-flip; needs ≥2 relays</td>
|
|
<td style="padding:7px 9px;">Harder; only with a relay fleet</td>
|
|
<td style="padding:7px 9px;">KAC §4.4</td>
|
|
</tr>
|
|
<tr style="border-bottom:1px solid rgba(0,0,0,.12);">
|
|
<td style="padding:7px 9px;">Well-connected <strong>payment processor</strong> · listening + observers</td>
|
|
<td style="padding:7px 9px;">—</td>
|
|
<td style="padding:7px 9px;"><strong>Detected → fails</strong> (normal case)</td>
|
|
<td style="padding:7px 9px;">Satoshi 2010; KAC §5</td>
|
|
</tr>
|
|
<tr>
|
|
<td style="padding:7px 9px;">BCH vendor with <strong>DSProof</strong> · listening automated for all</td>
|
|
<td style="padding:7px 9px;">—</td>
|
|
<td style="padding:7px 9px;"><strong>Detected → fails</strong> (normal case)</td>
|
|
<td style="padding:7px 9px;">DSProof</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
<p style="margin-top:8px;">The deciding variable is <strong>connectivity + active listening</strong>, not "0-conf." Residual across the defended rows: a Sybil/eclipse attacker — a far higher bar, never "impossible." Read this way, the paper says what it measured: <em>naive merchants lose; listening ones win.</em></p>
|
|
</div>
|
|
|
|
<section>
|
|
<div class="section-head"><div class="section-num">I</div><h2>The attack and its defense were both Satoshi's, in 2010.</h2></div>
|
|
<p>Two years before the 2012 paper, in the <em>"Bitcoin snack machine"</em> thread, Satoshi described the race and its answer: a payment processor connected to many nodes that broadcasts a transaction and simultaneously listens for a conflicting one.</p>
|
|
<div class="primary-quote">
|
|
The payment processor has connections with many nodes. When it gets a transaction, it blasts it out, and at the same time monitors the network for double-spends… A double-spent transaction wouldn't get very far without one of the listeners hearing it.
|
|
<span class="attribution">— Satoshi Nakamoto, 17 Jul 2010</span>
|
|
</div>
|
|
<p>The structure is a trap for the attacker: to win the mining race he must propagate the double-spend <em>widely</em> — which is exactly what many listeners <em>hear</em>. He cannot both flood it (to win) and hide it (to evade). Satoshi also fixed the ceiling, in his own words, and it must be quoted unsoftened: when challenged that this was “still not impermeable,” he replied <strong>“I didn't say impermeable, I said good-enough. The loss in practice would be far lower than with credit cards.”</strong> Risk-reduction, not impossibility.</p>
|
|
</section>
|
|
|
|
<section>
|
|
<div class="section-head"><div class="section-num">II</div><h2>Why "first-seen" doesn't, by itself, save a naive vendor.</h2></div>
|
|
<p>First-seen is <em>local to each node</em> — there is no global “first.” The attacker engineers a split-brain: send the payment only to the vendor (whose mempool now holds it and who releases goods) while flooding the conflicting transaction to the <em>miners</em>, who hold it first and confirm it. Both sides obey first-seen; their “firsts” simply disagree, and <strong>the miner, not the vendor, breaks the tie.</strong> At block level only one of the two ever confirms — the fraud is entirely off-ledger; the merchant is left holding the losing transaction. The chain never double-spends.</p>
|
|
</section>
|
|
|
|
<section>
|
|
<div class="section-head"><div class="section-num">III</div><h2>The 2012 paper: honest within scope; the fix is BCH's DSProof.</h2></div>
|
|
<p>Karame–Androulaki–Capkun (CCS 2012) ran ~500 real attempts against their <em>own, undefended</em> vendor nodes and measured 90–100% success. That result is real — and so is its conditional conclusion: <em>“unless effective detection techniques are integrated… vendors should not accept fast payments.”</em> Its §5 proposes the detection: a listening period and observers. <strong>That is Satoshi's 2010 defense, restated.</strong> Bitcoin Cash's <em>double-spend proof</em> (DSProof) is the same defense automated at the protocol layer: any node seeing two conflicting transactions floods a cryptographic alert, so every vendor is warned without running a processor. One idea, three stages — Satoshi (2010) → KAC (2012) → DSProof.</p>
|
|
<div class="callout">
|
|
<div class="callout-label">The attacker's real requirement</div>
|
|
<p>Not a full node. But not a one-line script either: KAC's own data shows reliability scales with a <em>coordinated relay fleet</em> (1 helper ≈ coin-flip against a well-connected vendor; 2 helpers ≈ guaranteed). The attack is capability-gated, and a listening vendor / DSProof defeats the basic form in the normal case. The genuine residual is a Sybil/eclipse attacker — a far higher bar, never “impossible.”</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<div class="section-head"><div class="section-num">IV</div><h2>RBF is the trivial attack — and it is BTC-only.</h2></div>
|
|
<p>The famous real-world 0-conf theft — Peter Todd against Coinbase, 2016, first try — was <em>not</em> the 2012 race. It used <strong>Replace-By-Fee</strong>: send a low-fee payment, then replace it with a higher-fee one to yourself. No topology, no race — just bump the fee. RBF is a 2016 BTC protocol feature that <strong>Bitcoin Cash explicitly rejected.</strong> So the dramatic, repeatable real-world fraud is RBF-based, on a chain BCH is not. Pointing at it to indict BCH 0-conf is RBF fraud cited against a chain without RBF.</p>
|
|
</section>
|
|
|
|
<section>
|
|
<div class="section-head"><div class="section-num">V</div><h2>The settlement model, and the word that must not be rounded up.</h2></div>
|
|
<p>0-conf / no hashpower → defeated in practice (first-seen, no RBF, DSProof) — <em>good-enough</em>. Confirmed / no hashpower → defeated. Confirmed / majority hashpower (a reorg) → <strong>irrational at scale, economically gated, priced — not impossible</strong> (Satoshi's own §6/§11 conditional; it has happened on cheap-hashpower chains, never on BTC). BCH's gate is real but <em>lower than BTC's</em> — it shares SHA-256 and runs at a fraction of BTC's hashrate, so the fleet that defends it could attack it; historically it has defended, because its major holders are aligned stakeholders. Security is the <strong>economic gate, not miner loyalty</strong>. Design rule: <strong>scale confirmations to value.</strong></p>
|
|
<div class="callout warn">
|
|
<div class="callout-label">The BCH May-2019 reorg was not a double-spend</div>
|
|
<p>It was two incumbent pools <em>coordinating</em> to reverse an opportunist's grab of anyone-can-spend SegWit-recovery coins — capability used defensively, not a profit double-spend and not an external 51% capture. It proves the capability exists; it is not an example of the attack.</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<div class="section-head"><div class="section-num">VI</div><h2>The FUD, stated precisely.</h2></div>
|
|
<p>In one line, needing no claim of intent: <strong>sound analysis, a one-sided title, and a predictable impression effect on a public that reads titles, not papers.</strong> Each of the three is independently checkable — read the title, read §4–5, look at how it is cited. Intent is the one thing that cannot be proven and the one thing the case does not need.</p>
|
|
<p>Assembled, the disqualification of “Bitcoin as cash” reads as context-stripping, not fabrication: (1) a <em>conditional</em> result is flattened into a <em>categorical</em> one; (2) the paper's own remedy and its 2010 Satoshi provenance are dropped; (3) the trivial <em>RBF</em> attack is merged with the hard <em>race</em> attack and aimed at the chain that rejected RBF; (4) RBF's adoption then ends 0-conf on BTC, making “Bitcoin isn't for payments” self-fulfilling on the chain that adopted it — while the chain that kept first-seen and added DSProof is told its payments are unsafe using the other chain's evidence.</p>
|
|
<div class="pullquote rust">
|
|
The corpus does not call any paper fraudulent. It restores the conditions, the remedy, and the chain distinction that were removed — and the verdict collapses on its own. These narratives do not survive in a neutral information environment; they propagate in a captured one. This case is a checkable specimen of that mechanism: every erased caveat sits in the primary sources. Verify, don't trust.
|
|
</div>
|
|
</section>
|
|
|
|
<section>
|
|
<div class="section-head"><div class="section-num">Sources</div><h2>Primary sources.</h2></div>
|
|
<ul style="font-size:14.5px; line-height:1.7; margin:12px 0 22px 24px; max-width:760px;">
|
|
<li>Satoshi Nakamoto, <em>“Bitcoin snack machine (fast transaction problem),”</em> bitcointalk, 17 Jul 2010 22:29:13 UTC — <strong>verified verbatim</strong>: satoshi.nakamotoinstitute.org/posts/bitcointalk/233/</li>
|
|
<li>Karame, Androulaki, Capkun, <em>Double-spending fast payments in Bitcoin,</em> ACM CCS 2012 (§4.4 experiments, §5 countermeasures). Extended: <em>Misbehavior in Bitcoin,</em> ACM TISSEC 2015.</li>
|
|
<li>Peter Todd double-spends Coinbase via RBF (2016); Cointelegraph, <em>“Real Bitcoin Double Spends Are Hard.”</em></li>
|
|
<li>BCH 2019 reorg: Bravenewcoin (<em>reorg or 51%?</em>), read.cash (<em>The year 2019 in Bitcoin Cash</em>), 2019-05-15 upgrade spec.</li>
|
|
<li>Internal: empirical chipnet test (<code>scripts/chipnet-doublespend-test.mjs</code>), <code>wiki/onchain-game-settlement-threat-model.md</code>, snapshot 0135.</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<footer>
|
|
<div>Companion note · Zero-Conf and the Double-Spend FUD · June 2026</div>
|
|
<div class="note">The whitepaper is short. The forum posts are archived. The chains are observable. The comparison is direct. Nothing here depends on trust.</div>
|
|
</footer>
|
|
|
|
</div>
|
|
</body>
|
|
</html>"""
|
|
|
|
DST.write_text(head + "\n" + body, encoding="utf-8")
|
|
print(f"wrote {DST.relative_to(ROOT)} ({len((head + body)):,} chars, {(head + body).count(chr(10)) + 1} lines)")
|