deviant/scripts/spv-asert-live-smoke.mjs
Local Dev ced2eda48d @
chore: checkpoint in-flight work across domains

Sweep of accumulated uncommitted work on design/dex-p2p-architecture into
one checkpoint (multiple sessions share this tree). Main areas:

- anthemus: covenant-wiring follow-ups (engine, ExchangePanel), AgoraScreen seam
- spv: ServerPool + p2p header transport (pool.ts, core/spv/*), wallet.ts wiring
- walletconnect: responder/useConnect updates + connect-responder-compat test
- wallet: send-tier-a rework + swap.ts, plus send-tier-a unit tests
- asm: chipnet throughput/stress harness (scripts/chipnet-asm-*) + ASM_Native docs
- app UI: screens/* and shell.css touch-ups; sat -> bits copy migration
- docs: new snapshots (INDEX regenerated), Parameters (WalletConnect/SSH/ASM),
  KnowledgeBase, WALLET-COORDINATION changelog

Checkpoint only; not a release. Secrets (Keys/, .chipnet-keys*, .env) remain
gitignored and were verified absent from the staged set.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
2026-08-14 02:00:43 +02:00

95 lines
5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* spv-asert-live-smoke.mjs — S1b against REAL consensus data on BOTH networks:
*
* MAINNET: build a verified window over live mainnet WSS servers and ASERT-validate every
* header in it. Mainnet difficulty genuinely moves block-to-block and has no min-difficulty
* exceptions — if our aserti3-2d disagrees with what miners actually produced under consensus
* rules, this fails. Also reports how many headers match the required bits EXACTLY in compact
* form (the re-anchoring drift the tolerance exists for).
*
* CHIPNET: the full startSpv boot with ASERT on — status().asert must be valid.
*
* Run: node --import tsx scripts/spv-asert-live-smoke.mjs
*/
import { startSpv } from '../shells/app/src/core/spv/session';
import { validateWindow, targetToCompact, asertTarget, ASERT_MAINNET } from '../shells/app/src/core/spv/asert';
import { bitsToTarget } from '../shells/app/src/core/spv/headers';
let ok = true;
// ── mainnet: the real consensus check ────────────────────────────────────────
console.log('MAINNET — building a 120-block verified window over live WSS servers…');
const main = startSpv('mainnet', { targetLive: 3, quorum: 2, windowDepth: 120 });
try {
const w = await main.ready;
const st = main.status();
console.log(` window ${w.anchor} → ${w.tip} · live: ${st.liveServers.length} servers · divergences ${st.divergences}`);
const report = main.verifier.asertReport;
if (!report) throw new Error('no asert report');
console.log(` ASERT: checked ${report.checked} · ok ${report.ok} · min-diff ${report.minDifficulty} · mismatches ${report.mismatches.length}`);
if (!report.valid) { ok = false; console.log(' ❌ mismatches:', JSON.stringify(report.mismatches.slice(0, 5))); }
else console.log(' ✅ every mainnet header in the window carries the ASERT-required difficulty');
// measure the ACTUAL re-anchoring drift: max relative |required − claimed| / claimed.
// (Exact-compact agreement is rare BY DESIGN — consensus computes from the 2020 anchor, we
// re-anchor in-window, and the fixed-point fractional parts land differently in the last
// mantissa bits. What matters is that the drift is orders of magnitude below the tolerance.)
const entries = main.verifier['chain'].range();
const refIdx = 1;
const ref = entries[refIdx];
let exact = 0; let total = 0; let maxDriftNum = 0n; let maxDriftDen = 1n;
for (let i = refIdx + 1; i < entries.length; i++) {
const required = asertTarget(
bitsToTarget(ref.bits),
BigInt(entries[i - 1].time - entries[refIdx - 1].time),
BigInt(entries[i].height - ref.height - 1),
ASERT_MAINNET,
);
const claimed = bitsToTarget(entries[i].bits);
const diff = required > claimed ? required - claimed : claimed - required;
if (diff * maxDriftDen > maxDriftNum * claimed) { maxDriftNum = diff; maxDriftDen = claimed; }
total++;
if (targetToCompact(required) === entries[i].bits) exact++;
}
const maxDriftPpm = Number((maxDriftNum * 1_000_000n) / maxDriftDen);
console.log(` re-anchoring drift: max ${maxDriftPpm} ppm (tolerance 3906 ppm = 1/256) · exact-compact ${exact}/${total}`);
if (maxDriftPpm >= 3906) { ok = false; console.log(' ❌ drift at/above tolerance'); }
} catch (e) {
ok = false;
console.log(' ❌ mainnet leg failed:', e?.message ?? e);
} finally {
main.stop();
}
// ── chipnet: the wired boot with ASERT on (falls back to the app's electrum transport
// when the public WSS endpoints are down — same ASERT code, different pipe) ──────────
console.log('\nCHIPNET — startSpv with ASERT (min-difficulty rule in force)…');
const chip = startSpv('chipnet', { targetLive: 3, quorum: 2 });
let chipReport = null;
try {
await chip.ready;
chipReport = chip.status().asert;
} catch {
console.log(" (public WSS endpoints unreachable — validating via the app's electrum transport instead)");
const { ElectrumNetworkProvider } = await import('cashscript');
const { SpvVerifier } = await import('../shells/app/src/core/spv/verifier');
const { ASERT_CHIPNET } = await import('../shells/app/src/core/spv/asert');
const v = SpvVerifier.fromProvider(new ElectrumNetworkProvider('chipnet'), 210, { asert: ASERT_CHIPNET });
await v.init();
chipReport = v.asertReport && {
valid: v.asertReport.valid, checked: v.asertReport.checked, ok: v.asertReport.ok,
minDifficulty: v.asertReport.minDifficulty, mismatches: v.asertReport.mismatches.length, rejections: v.asertRejections,
};
} finally {
chip.stop();
}
console.log(` ASERT: ${JSON.stringify(chipReport)}`);
if (!chipReport?.valid) { ok = false; console.log(' ❌ chipnet window failed ASERT validation'); }
else console.log(` ✅ chipnet window valid (${chipReport.ok} conforming, ${chipReport.minDifficulty} legitimate min-difficulty blocks)`);
console.log(ok
? '\nS1b LIVE: our aserti3-2d agrees with real consensus on mainnet AND the chipnet boot validates.'
: '\nS1b LIVE: FAILURES above.');
process.exit(ok ? 0 : 1);