diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/payments.ts | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/lib/payments.ts b/lib/payments.ts index 380b5e7b..01492975 100644 --- a/lib/payments.ts +++ b/lib/payments.ts @@ -1,6 +1,21 @@ import config from "$config"; +import { existsSync } from "fs"; import api from "$lib/api"; import { archive, db, g, ga, gf, s, sa } from "$lib/db"; + +// External-withdrawal lockfiles. Out-of-band emergency stop: nobal.sh (or a +// human) can `touch /home/adam/locks/<type>.locked` on the host, which is +// bind-mounted into this container at /locks. Existence of /locks/<type>.locked +// (or /locks/ALL.locked) blocks all external sends of that type. Lives outside +// db so it can't be disabled by a db-write vector (May 18 /gateway lesson). +// +// Internal payments are never blocked by these — receives and internal +// transfers between coinos users keep working with the site fully online. +const isWithdrawLocked = (type: string): string | null => { + if (existsSync("/locks/ALL.locked")) return "ALL"; + if (existsSync(`/locks/${type}.locked`)) return type; + return null; +}; import { generate } from "$lib/invoices"; import ln from "$lib/ln"; import { err, l, warn } from "$lib/logging"; @@ -102,6 +117,16 @@ export const debit = async ({ (await g("hardfreeze")) || ((await g("freeze")) && type !== PaymentType.internal); + // Out-of-band withdrawal lock (file-based, can't be defeated by db writes). + // Internal sends are exempt — they don't touch external wallets. + if (type !== PaymentType.internal) { + const lockedKind = isWithdrawLocked(type); + if (lockedKind) { + warn("Blocking", user.username, amount, hash, user.id, type, "withdraw-lock", lockedKind); + fail("External withdrawals temporarily disabled"); + } + } + if (frozen || (amount > userLimit && !whitelisted)) { warn("Blocking", user.username, amount, hash, user.id, type, frozen, userLimit); fail("Problem sending payment"); |
