From 90eb381d6610ab5ee456aefa83f6d8aaf5abcb7b Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Wed, 7 Oct 2026 08:12:29 -0700 Subject: bolt12-test: committed regtest offer/invoice fixtures instead of a vanished scratchpad The default fixture paths pointed into an old session's scratchpad, so the test died reading them (exit 1, no output). Fresh pair from the regtest stack: offer from clc, invoice fetched by cln-ark. Network and expiry checks no longer assume mainnet or a recent wall clock. Co-Authored-By: Claude Opus 5.5 --- tools/bolt12-test.js | 11 +++++++---- tools/fixtures/bolt12-invoice.txt | 1 + tools/fixtures/bolt12-offer.txt | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 tools/fixtures/bolt12-invoice.txt create mode 100644 tools/fixtures/bolt12-offer.txt diff --git a/tools/bolt12-test.js b/tools/bolt12-test.js index 28909d3..ab5109a 100644 --- a/tools/bolt12-test.js +++ b/tools/bolt12-test.js @@ -1,6 +1,7 @@ // BOLT 12 decode + signature verification against a REAL offer/invoice pair // (fetched from a live CLN via fetchinvoice) plus tamper checks. // Run: bun tools/bolt12-test.js [offer-file invoice-file] +// Default fixtures: regtest clc offer, invoice fetched by cln-ark for 12345 msat. import { readFileSync } from 'node:fs'; import { decodeOffer, decodeBolt12Invoice, verifyOfferInvoice, encodeBech32Raw, decodeBech32Raw, @@ -14,8 +15,9 @@ const check = (name, ok, detail = '') => { const throws = (fn) => { try { fn(); return null; } catch (e) { return e.message; } }; const [offerFile, invoiceFile] = process.argv.slice(2); -const offerStr = readFileSync(offerFile || '/tmp/claude-1000/-home-adam-coinosv3/556b3f05-c728-4e11-a426-50382ad8bd8d/scratchpad/fixture-offer.txt', 'utf8').trim(); -const invStr = readFileSync(invoiceFile || '/tmp/claude-1000/-home-adam-coinosv3/556b3f05-c728-4e11-a426-50382ad8bd8d/scratchpad/fixture-invoice.txt', 'utf8').trim(); +const fixture = (name) => new URL(`fixtures/${name}`, import.meta.url).pathname; +const offerStr = readFileSync(offerFile || fixture('bolt12-offer.txt'), 'utf8').trim(); +const invStr = readFileSync(invoiceFile || fixture('bolt12-invoice.txt'), 'utf8').trim(); console.log('[codec]'); const rt = decodeBech32Raw(invStr); @@ -25,7 +27,7 @@ check('bech32 roundtrips', encodeBech32Raw('lni', rt.bytes) === invStr.toLowerCa console.log('\n[offer]'); const offer = decodeOffer(offerStr); check('decodes', !!offer.records.length, `${offer.records.length} records`); -check('mainnet', offer.network === 'mainnet'); +check('network known', ['mainnet', 'testnet', 'signet', 'regtest'].includes(offer.network), offer.network); check('describes itself', typeof offer.description === 'string', offer.description); console.log('\n[invoice]'); @@ -34,7 +36,8 @@ check('payment hash present', /^[0-9a-f]{64}$/.test(inv.paymentHash || ''), inv. check('amount = 12345 msat', inv.amountMsat === 12345n, String(inv.amountMsat)); check('amount rounds up to 13 sat', inv.amountSat === 13); check('signer named', /^[0-9a-f]{66}$/.test(inv.nodeId || ''), inv.nodeId); -check('expiry sane', inv.expiresAt > Date.now() - 86400_000, new Date(inv.expiresAt).toISOString()); +check('same network as the offer', inv.network === offer.network, inv.network); +check('expiry sane', inv.expiresAt > inv.createdAt * 1000, new Date(inv.expiresAt).toISOString()); console.log('\n[verification]'); check('real invoice verifies', throws(() => verifyOfferInvoice(offer, inv)) === null, diff --git a/tools/fixtures/bolt12-invoice.txt b/tools/fixtures/bolt12-invoice.txt new file mode 100644 index 0000000..13a6def --- /dev/null +++ b/tools/fixtures/bolt12-invoice.txt @@ -0,0 +1 @@ +lni1qqgy8t5dte5h2gyavux9d35y4ut57q3qqc3xu3s3rg94nj40zfsy866mhu5vxne6tcej5878k2mneuvgjy8s5xnrda5kummnyp3x7mr5xyezqar9wd6zqenf0p682un9zcss9v3q6z4840hdg5rr2uzyyljj9ss7m0pdhh067zljlqmapdnjxp6d2qsqvgnwgcg35z6ee2h3yczraddm72xrfua9uve2rlrm9deu7xyfzr6jqgcrj4qqtqss8d7zt6g2jadypdjye7eaynn7djwthrsk7sp0ayuancfxx23q9czx5zvq9v3q6z4840hdg5rr2uzyyljj9ss7m0pdhh067zljlqmapdnjxp6dqd6cyeyntuje3gnfs0vvk92gajtvzpgpvghsqrxplevw8h20w8a57qgrx8ull89l52lfm2kch90lzmk9jxzqeawjwf3yegx7tnazhpj3vlqsqvn87mukg4nac4x3c6tpaa486r7948h4plagkxzmyxcm7gmjd4tk4a4m449x3a4ejhp9wqyh5vm590nfc84zrsqqqqqqqqqqqqqqpgqqqqqqqqqqqqqayjedltzjqqqqqq9yq34vvcfc4qstz7ayvch6wum4523uplu9t96njk52fdv3caw39ls0mwd57jf9j0a2qgcrntsrqgqqpvppq2ezp59202lw63gxx4cygfl9ytppak7zm0wl4u9l97ph6zm8yvr5muzqgtz93zggsprllc77u9vuvle8c93svnr6wvrsxptrnq39u2shhuy56rkssg6w35cp8rsd3g2atzqcgf3kn2ehwaw08ftjc6e8gqjucmg diff --git a/tools/fixtures/bolt12-offer.txt b/tools/fixtures/bolt12-offer.txt new file mode 100644 index 0000000..3faf966 --- /dev/null +++ b/tools/fixtures/bolt12-offer.txt @@ -0,0 +1 @@ +lno1qgsqvgnwgcg35z6ee2h3yczraddm72xrfua9uve2rlrm9deu7xyfzrc2rf3k76twdaejqcn0d36rzv3qw3jhxapqve5hsar4wfj3vggzkgsdp2n6hmk52p34wpzz0efzcg0dhskmmha0p0e0sd7skeerqaxs -- cgit v1.2.3