From 1f95a4f0c829436d9030501530a682d2e7841279 Mon Sep 17 00:00:00 2001 From: Danny Morabito Date: Sat, 22 Feb 2025 14:30:46 +0100 Subject: [PATCH] pow all notes --- consts.ts | 20 ++++++++++++++++++++ index.ts | 12 +++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 consts.ts diff --git a/consts.ts b/consts.ts new file mode 100644 index 0000000..cb2ce39 --- /dev/null +++ b/consts.ts @@ -0,0 +1,20 @@ +/** + * Minimum required Proof of Work (PoW) difficulty for note acceptance. + * + * Notes with PoW below this threshold will be rejected without decryption attempts. + * This threshold serves as a DoS protection mechanism for the CCN in case of + * public key compromise. + */ +export const MIN_POW = 8; + +/** + * Target Proof of Work (PoW) difficulty for relay-generated notes. + * + * Defines the PoW difficulty level that the relay will compute when generating + * and encrypting its own notes before broadcasting them to the network. + * + * Expected Performance on modern hardware (2025): + * - Difficulty 8: ~1ms + * - Difficulty 21: ~5-6 seconds + */ +export const POW_TO_MINE = 10; diff --git a/index.ts b/index.ts index 3a81e31..7cfb67a 100644 --- a/index.ts +++ b/index.ts @@ -20,6 +20,7 @@ import { Database } from "jsr:@db/sqlite"; import { mixQuery, sql, sqlPartial } from "./utils/queries.ts"; import { log, setupLogger } from "./utils/logs.ts"; import { getEveFilePath } from "./utils/files.ts"; +import { MIN_POW, POW_TO_MINE } from "./consts.ts"; await setupLogger(); @@ -111,6 +112,7 @@ async function createEncryptedEvent( const ccnPubKey = await getCCNPubkey(); const ccnPrivateKey = await getCCNPrivateKey(); const randomPrivateKey = nostrTools.generateSecretKey(); + const randomPrivateKeyPubKey = nostrTools.getPublicKey(randomPrivateKey); const conversationKey = nip44.getConversationKey(randomPrivateKey, ccnPubKey); const sealTemplate = { kind: 13, @@ -124,8 +126,10 @@ async function createEncryptedEvent( created_at: randomTimeUpTo2DaysInThePast(), content: nip44.encrypt(JSON.stringify(seal), conversationKey), tags: [["p", ccnPubKey]], + pubkey: randomPrivateKeyPubKey, }; - const giftWrap = nostrTools.finalizeEvent(giftWrapTemplate, randomPrivateKey); + const minedGiftWrap = nostrTools.nip13.minePow(giftWrapTemplate, POW_TO_MINE); + const giftWrap = nostrTools.finalizeEvent(minedGiftWrap, randomPrivateKey); return giftWrap; } @@ -138,6 +142,12 @@ async function decryptEvent( throw new Error("Cannot decrypt event -- not a gift wrap"); } + const pow = nostrTools.nip13.getPow(event.id); + + if (pow < MIN_POW) { + throw new Error("Cannot decrypt event -- PoW too low"); + } + const conversationKey = nip44.getConversationKey(ccnPrivkey, event.pubkey); const seal = JSON.parse(nip44.decrypt(event.content, conversationKey)); if (!seal) throw new Error("Cannot decrypt event -- no seal");