aboutsummaryrefslogtreecommitdiffstats
path: root/node_modules/express/lib/express.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/express/lib/express.js')
0 files changed, 0 insertions, 0 deletions
/* Name.Constant */ .highlight .nd { color: #555 } /* Name.Decorator */ .highlight .ne { color: #B06; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #06B; font-weight: bold } /* Name.Function */ .highlight .nl { color: #369; font-style: italic } /* Name.Label */ .highlight .nn { color: #B06; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #369; font-weight: bold } /* Name.Property */ .highlight .nt { color: #B06; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #369 } /* Name.Variable */ .highlight .ow { color: #080 } /* Operator.Word */ .highlight .w { color: #BBB } /* Text.Whitespace */ .highlight .mb { color: #00D; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #00D; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #00D; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #00D; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #00D; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #D20; background-color: #FFF0F0 } /* Literal.String.Affix */ .highlight .sb { color: #D20; background-color: #FFF0F0 } /* Literal.String.Backtick */ .highlight .sc { color: #D20; background-color: #FFF0F0 } /* Literal.String.Char */ .highlight .dl { color: #D20; background-color: #FFF0F0 } /* Literal.String.Delimiter */ .highlight .sd { color: #D20; background-color: #FFF0F0 } /* Literal.String.Doc */ .highlight .s2 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Double */ .highlight .se { color: #04D; background-color: #FFF0F0 } /* Literal.String.Escape */ .highlight .sh { color: #D20; background-color: #FFF0F0 } /* Literal.String.Heredoc */ .highlight .si { color: #33B; background-color: #FFF0F0 } /* Literal.String.Interpol */ .highlight .sx { color: #2B2; background-color: #F0FFF0 } /* Literal.String.Other */ .highlight .sr { color: #080; background-color: #FFF0FF } /* Literal.String.Regex */ .highlight .s1 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Single */ .highlight .ss { color: #A60; background-color: #FFF0F0 } /* Literal.String.Symbol */ .highlight .bp { color: #038 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #06B; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #369 } /* Name.Variable.Class */ .highlight .vg { color: #D70 } /* Name.Variable.Global */ .highlight .vi { color: #33B } /* Name.Variable.Instance */ .highlight .vm { color: #369 } /* Name.Variable.Magic */ .highlight .il { color: #00D; font-weight: bold } /* Literal.Number.Integer.Long */
// 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,
} from '../src/bolt12.js';

let fails = 0;
const check = (name, ok, detail = '') => {
  console.log(` ${ok ? '✓' : '✗'} ${name}${detail ? ' — ' + String(detail).slice(0, 140) : ''}`);
  if (!ok) fails++;
};
const throws = (fn) => { try { fn(); return null; } catch (e) { return e.message; } };

const [offerFile, invoiceFile] = process.argv.slice(2);
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);
check('lni hrp', rt.hrp === 'lni');
check('bech32 roundtrips', encodeBech32Raw('lni', rt.bytes) === invStr.toLowerCase());

console.log('\n[offer]');
const offer = decodeOffer(offerStr);
check('decodes', !!offer.records.length, `${offer.records.length} records`);
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]');
const inv = decodeBolt12Invoice(invStr);
check('payment hash present', /^[0-9a-f]{64}$/.test(inv.paymentHash || ''), inv.paymentHash);
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('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,
  throws(() => verifyOfferInvoice(offer, inv)) || 'ok');

// tamper with the amount TLV: signature must fail
const tampered = decodeBolt12Invoice(invStr);
const amtRec = tampered.records.find((r) => r.type === 170);
amtRec.raw[amtRec.raw.length - 1] ^= 1;
check('tampered amount rejected', /signature/.test(throws(() => verifyOfferInvoice(offer, tampered)) || ''));

// swap in a different offer description: mirror check must fail
const wrongOffer = decodeOffer(offerStr);
const descRec = wrongOffer.records.find((r) => r.type === 10);
if (descRec) {
  descRec.raw[descRec.raw.length - 1] ^= 1;
  check('mismatched offer rejected', /match/.test(throws(() => verifyOfferInvoice(wrongOffer, inv)) || ''));
}

// forged signer: issuer pin must fail
const forged = decodeBolt12Invoice(invStr);
forged.nodeId = '02' + '11'.repeat(32);
check('wrong signer rejected', /wrong node|signature/.test(throws(() => verifyOfferInvoice(offer, forged)) || ''));

console.log(fails ? `\n❌ ${fails} failure(s)` : '\n✅ bolt12 verifies');
process.exit(fails ? 1 : 0);