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> @
69 lines
3.2 KiB
JavaScript
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); });
|