deviant/scripts/spv-p2p-headersync-chipnet.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

69 lines
3.2 KiB
JavaScript

#!/usr/bin/env node
/**
* spv-p2p-headersync-chipnet.mjs — Phase 1a end-to-end demo.
*
* Anchors at a real chipnet checkpoint (from test/fixtures/spv-chipnet.json)
* and pulls all headers up to the live tip via getheaders/headers from
* ≥1 chipnet peer, feeding the existing HeaderChain (PoW + link + anchor
* validated on every append).
*
* Proves the transport-independent core actually walks the chain end-to-end,
* not just handshakes. Runs against real network — not part of vitest.
*/
// Run via tsx so the TS imports resolve without a build step:
// node --import tsx scripts/spv-p2p-headersync-chipnet.mjs
// or: npx tsx scripts/spv-p2p-headersync-chipnet.mjs
import dns from 'node:dns/promises';
import { NETWORKS } from '../shells/app/src/core/spv/p2p/wire.ts';
import { NodeNetTransport } from '../shells/app/src/core/spv/p2p/transport-node.ts';
import { syncHeaders } from '../shells/app/src/core/spv/p2p/header-sync.ts';
// Real chipnet checkpoint from test/fixtures/spv-chipnet.json (2026-07-26).
// syncHeaders() re-derives the hash from headerHex and passes it into
// HeaderChain, which pins the anchor.
const ANCHOR = {
height: 315684,
headerHex: '0000002021cd2665f2a91a793add02d2722b3103ef24a6d796d79244c125be4b00000000029c1f97ee4286151c0440ee3f35cfbbe9369a7998b938aa96b6ed48c78c87050d26616a15b66a1c12b6850c',
};
async function resolveSeeds(seeds, per = 3) {
const out = new Set();
for (const s of seeds) {
try {
const ips = await dns.resolve4(s);
for (const ip of ips.slice(0, per)) out.add(ip);
} catch { /* seed unreachable, skip */ }
}
return [...out];
}
async function main() {
console.log(`Phase 1a end-to-end — chipnet header sync from checkpoint ${ANCHOR.height}\n`);
const hosts = await resolveSeeds(NETWORKS.chipnet.seeds, 3);
console.log(`Resolved ${hosts.length} chipnet peers: ${hosts.join(', ')}\n`);
if (hosts.length === 0) { console.error('no peers resolved'); process.exit(1); }
const t0 = Date.now();
const result = await syncHeaders({
transport: new NodeNetTransport(),
network: NETWORKS.chipnet,
anchor: ANCHOR,
peerHosts: hosts,
minPeers: Math.min(2, hosts.length),
maxHeaders: 5000,
onProgress: ({ height, peers, batch }) => console.log(` batch ${batch}: height=${height} peers-live=${peers}`),
onDropped: (host, reason) => console.log(` ✗ dropped ${host}: ${reason}`),
});
const dt = Date.now() - t0;
console.log(`\n✅ synced ${result.chain.height - ANCHOR.height} headers in ${dt} ms`);
console.log(` tip height = ${result.chain.height}`);
console.log(` tip hash = ${result.chain.tip?.hash}`);
console.log(` cumulative work = ${result.chain.tip?.cumWork.toString()}`);
console.log(` leader = ${result.syncedFromHost}`);
console.log(` peers handshook = ${result.peersHandshook.length} spread=${result.tipSpread}`);
for (const p of result.peersHandshook) console.log(` • ${p.host} ${p.userAgent} h=${p.startHeight}`);
console.log(` batches = ${result.batches}`);
}
main().catch((e) => { console.error('FAILED:', e?.message ?? e); if (e?.stack) console.error(e.stack); process.exit(1); });