aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2025-09-29 21:47:18 -0700
committerAdam Soltys <[email protected]>2025-09-29 21:50:57 -0700
commit481dec5b1cfa2a085dda500ce0c390b38cb4a8b0 (patch)
tree892efd033af9e889ca60cb816183deb0f2e8c2ef /lib
parentc901c9571ff9406188a8bbb68c701ad3b21c24eb (diff)
downloadcoinos-server-481dec5b1cfa2a085dda500ce0c390b38cb4a8b0.tar.gz
coinos-server-481dec5b1cfa2a085dda500ce0c390b38cb4a8b0.zip
rotate server key
Diffstat (limited to 'lib')
-rw-r--r--lib/nostr.ts9
-rw-r--r--lib/notifications.ts6
-rw-r--r--lib/nwc.ts41
3 files changed, 46 insertions, 10 deletions
diff --git a/lib/nostr.ts b/lib/nostr.ts
index 4c28ebc9..1d4ab56f 100644
--- a/lib/nostr.ts
+++ b/lib/nostr.ts
@@ -16,7 +16,12 @@ export const serverSecret = bytesToHex(
nip19.decode(config.nostrKey).data as Uint8Array,
);
+export const serverSecret2 = bytesToHex(
+ nip19.decode(config.nostrKey2).data as Uint8Array,
+);
+
export const serverPubkey = getPublicKey(serverSecret);
+export const serverPubkey2 = getPublicKey(serverSecret2);
const alwaysTrue: any = (t: Event) => {
t[Symbol("verified")] = true;
@@ -42,7 +47,7 @@ export async function publish(ev, url = config.nostr) {
export async function handleZap(invoice, sender = undefined) {
try {
- const pubkey = serverPubkey;
+ const pubkey = serverPubkey2;
const zapreq = JSON.parse(invoice.description);
if (!zapreq.tags || zapreq.tags.length === 0) {
@@ -95,7 +100,7 @@ export async function handleZap(invoice, sender = undefined) {
tags.push(["preimage", invoice.payment_preimage]);
const ev = { pubkey, kind, created_at, content, tags };
- const signed = await finalizeEvent(ev, serverSecret);
+ const signed = await finalizeEvent(ev, serverSecret2);
l("sending receipt");
diff --git a/lib/notifications.ts b/lib/notifications.ts
index d5b4f73f..31175916 100644
--- a/lib/notifications.ts
+++ b/lib/notifications.ts
@@ -4,7 +4,7 @@ import ln from "$lib/ln";
import { err, l, warn } from "$lib/logging";
import { mail, templates } from "$lib/mail";
import mqtt from "$lib/mqtt";
-import { publish, serverSecret } from "$lib/nostr";
+import { publish, serverSecret2 } from "$lib/nostr";
import { emit } from "$lib/sockets";
import { f, fiat, fmt, getUser, link, nada, t } from "$lib/utils";
import { hexToBytes } from "@noble/hashes/utils";
@@ -108,7 +108,7 @@ export const nwcNotify = async (p) => {
notification,
});
- const content = await nip04.encrypt(serverSecret, pubkey, payload);
+ const content = await nip04.encrypt(serverSecret2, pubkey, payload);
const unsigned = {
content,
@@ -117,7 +117,7 @@ export const nwcNotify = async (p) => {
created_at: Math.floor(Date.now() / 1000),
};
- const event = finalizeEvent(unsigned, hexToBytes(serverSecret));
+ const event = finalizeEvent(unsigned, hexToBytes(serverSecret2));
publish(event).catch(nada);
}
diff --git a/lib/nwc.ts b/lib/nwc.ts
index 4439ead4..13ae2666 100644
--- a/lib/nwc.ts
+++ b/lib/nwc.ts
@@ -3,7 +3,13 @@ import { db, g } from "$lib/db";
import { generate } from "$lib/invoices";
import ln from "$lib/ln";
import { err, l, warn } from "$lib/logging";
-import { handleZap, serverPubkey, serverSecret } from "$lib/nostr";
+import {
+ handleZap,
+ serverPubkey,
+ serverPubkey2,
+ serverSecret,
+ serverSecret2,
+} from "$lib/nostr";
import { sendInternal, sendKeysend, sendLightning } from "$lib/payments";
import { fail, getInvoice, sleep } from "$lib/utils";
import rpc from "@coinos/rpc";
@@ -12,6 +18,11 @@ import { Relay } from "nostr";
import { finalizeEvent, nip04 } from "nostr-tools";
import type { UnsignedEvent } from "nostr-tools";
+const serverKeys = {
+ [serverPubkey]: serverSecret,
+ [serverPubkey2]: serverSecret2,
+};
+
const result = (result) => ({ result });
const error = (error) => ({ error });
const bc = rpc(config.bitcoin);
@@ -32,7 +43,7 @@ export default () => {
const r = new Relay("ws://sf:7777");
r.on("open", async (_) => {
- r.subscribe("nwc", { kinds: [23194], "#p": [serverPubkey] });
+ r.subscribe("nwc", { kinds: [23194], "#p": [serverPubkey, serverPubkey2] });
const info = await finalizeEvent(
{
created_at: Math.floor(Date.now() / 1000),
@@ -46,16 +57,34 @@ export default () => {
hexToBytes(serverSecret),
);
r.send(["EVENT", info]);
+
+ const info2 = await finalizeEvent(
+ {
+ created_at: Math.floor(Date.now() / 1000),
+ kind: 13194,
+ tags: [
+ ["p", serverPubkey2],
+ ["notifications", "payment_received payment_sent"],
+ ],
+ content: methods.join(" "),
+ },
+ hexToBytes(serverSecret2),
+ );
+ r.send(["EVENT", info2]);
});
r.on("event", async (sub, ev) => {
try {
if (sub !== "nwc") return;
if (await db.sIsMember("handled", ev.id)) return;
+
db.sAdd("handled", ev.id);
let { content, pubkey } = ev;
+ const pk = ev.tags.find((t) => t[0] === "p")[1];
+ console.log(pk);
+ const sk = serverKeys[pk];
const { params, method } = JSON.parse(
- await nip04.decrypt(serverSecret, pubkey, content),
+ await nip04.decrypt(sk, pubkey, content),
);
// console.log("nwc", method, params, pubkey);
@@ -69,7 +98,7 @@ export default () => {
const result = await handle(method, params, ev, app, user);
const payload = JSON.stringify({ result_type: method, ...result });
- content = await nip04.encrypt(serverSecret, pubkey, payload);
+ content = await nip04.encrypt(sk, pubkey, payload);
let response: UnsignedEvent = {
created_at: Math.floor(Date.now() / 1000),
@@ -82,9 +111,10 @@ export default () => {
content,
};
- response = await finalizeEvent(response, hexToBytes(serverSecret));
+ response = await finalizeEvent(response, hexToBytes(sk));
r.send(["EVENT", response]);
} catch (e) {
+ console.log("BOOM", e);
err(
"problem with nwc",
pubkey,
@@ -94,6 +124,7 @@ export default () => {
);
}
} catch (e) {
+ console.log("BOOM2", e);
err("problem with nwc", e.message);
}
});