aboutsummaryrefslogtreecommitdiffstats
path: root/lib/lightning.ts
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-07-30 10:28:23 -0700
committerAdam Soltys <[email protected]>2026-07-30 10:38:43 -0700
commitfd1617ea66e01557e71debc7e45ca08cfe01bf70 (patch)
tree8c3600a86d60dc7731130397c98e818970d63990 /lib/lightning.ts
parentf5a5b1ff856efcd2849275a301daabb80ef76638 (diff)
downloadcoinos-server-fd1617ea66e01557e71debc7e45ca08cfe01bf70.tar.gz
coinos-server-fd1617ea66e01557e71debc7e45ca08cfe01bf70.zip
mint/lightning: refuse caller-supplied invoices, tiered fees, log hygiene
- invoices: reject caller-supplied bolt11/bolt12; the server always mints its own. Closes the invoice-registration path behind the shared-node credit and payment-hijack vectors. - lightning: skip mint-owned invoices (lbl* label) in the paid-invoice listener. - payments: lightning free-tier fee credit, withheld for flagged high-throughput (ln:nofree) accounts which pay an elevated rate; the failed-send reversal restores credit at the same rate. freezeCheck made crash-resilient. Lightning and bolt12 sends stay pending until the preimage settles. - payments (route): validate payment-request / invoice input types. - logging: collapse repeated xpay failure lines into one. Co-Authored-By: Claude Opus 4.8 <[email protected]>
Diffstat (limited to 'lib/lightning.ts')
-rw-r--r--lib/lightning.ts10
1 files changed, 10 insertions, 0 deletions
diff --git a/lib/lightning.ts b/lib/lightning.ts
index 8935f2ce..cf099b23 100644
--- a/lib/lightning.ts
+++ b/lib/lightning.ts
@@ -42,6 +42,7 @@ export async function listenForLightning() {
const inv = await lnListen.waitanyinvoice(payIndex);
const {
+ label,
local_offer_id,
bolt11,
bolt12,
@@ -77,6 +78,15 @@ export async function listenForLightning() {
try {
if (!preimage) return;
+ // The mint (nutshell) shares this cl node, so waitanyinvoice also fires for
+ // mint-quote invoices. Those are owned by the mint (it issues ecash for
+ // them) and must NOT credit a coinos balance — otherwise a single payment
+ // is credited twice (coinos balance + ecash = double-mint exploit). The
+ // mint labels its invoices "lbl<random>"; coinos labels are
+ // "<uuid> <username> <ts>". Never credit a mint-owned invoice.
+ if (typeof label === "string" && label.startsWith("lbl"))
+ return warn("skipping mint-owned invoice (not a coinos deposit)", label, bolt11);
+
const invoice = await getInvoice(bolt11 ?? local_offer_id ?? bolt12);
if (!invoice) return warn("received lightning with no invoice", bolt11);