// Verify the multi-algo PoW implementation against real mainnet headers. // // npx tsx packages/p2p/scripts/pow-vectors.ts [vectors.json] // // vectors.json: [{ h, algo, version, bits, time, raw(hex), hash }] — one // or more headers per algorithm, taken from a synced header chain. Every // header must pass checkProofOfWork, and a header with its nonce flipped // must fail (proves the hash is actually being compared, not waved // through). import { readFileSync } from 'node:fs'; import { checkProofOfWork, algoOf, powHash, targetFromBits } from '../src/pow.js'; import { decodeHeader } from '../src/messages/headers.js'; const file = process.argv[2] ?? new URL('../test/pow-vectors.json', import.meta.url); const vectors = JSON.parse(readFileSync(file, 'utf8')) as Array<{ h: number; algo: string; raw: string; bits: string }>; let fails = 0; for (const v of vectors) { const raw = Buffer.from(v.raw, 'hex'); const hdr = decodeHeader(raw); const algo = algoOf(hdr.version); const t0 = performance.now(); const res = checkProofOfWork(hdr); const ms = (performance.now() - t0).toFixed(1); // Tamper: flip one nonce bit → must fail. const bad = Buffer.from(raw); bad[76] ^= 1; const badRes = checkProofOfWork(decodeHeader(bad)); const ok = res.ok && algo === v.algo && !badRes.ok; if (!ok) fails++; const hash = powHash(raw, algo!, hdr.timestamp); console.log( `${ok ? 'PASS' : 'FAIL'} h=${v.h} ${String(v.algo).padEnd(7)} ${ms.padStart(6)}ms ` + `pow=${Buffer.from(hash).reverse().toString('hex').slice(0, 24)}… target=${targetFromBits(hdr.bits).target.toString(16).padStart(64, '0').slice(0, 24)}…` + `${res.ok ? '' : ` (${res.reason})`}${badRes.ok ? ' TAMPERED HEADER PASSED!' : ''}`, ); } console.log(fails === 0 ? `all ${vectors.length} vectors pass` : `${fails} FAILURES`); process.exit(fails === 0 ? 0 : 1);