From 940fc7a305d2ead9bd2f858f1210b294832a69ff Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 26 Mar 2024 17:35:08 -0500 Subject: [PATCH 1/3] Add DVM module, process domain name requests --- src/pipeline.ts | 2 + src/pipeline/DVM.ts | 107 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 src/pipeline/DVM.ts diff --git a/src/pipeline.ts b/src/pipeline.ts index 1f34b0f2..f1875701 100644 --- a/src/pipeline.ts +++ b/src/pipeline.ts @@ -6,6 +6,7 @@ import { deleteAttachedMedia } from '@/db/unattached-media.ts'; import { Debug, LNURL, type NostrEvent } from '@/deps.ts'; import { DittoEvent } from '@/interfaces/DittoEvent.ts'; import { isEphemeralKind } from '@/kinds.ts'; +import { DVM } from '@/pipeline/DVM.ts'; import { getAuthor } from '@/queries.ts'; import { updateStats } from '@/stats.ts'; import { purifyEvent } from '@/storages/hydrate.ts'; @@ -36,6 +37,7 @@ async function handleEvent(event: DittoEvent, signal: AbortSignal): Promise { + if (event.kind < 5000 || event.kind > 5999) { + throw new Error('Unsupported event kind'); + } + + switch (event.kind) { + case 5950: + await DVM.nameRegistration(event); + break; + } + } + + static async nameRegistration(event: NostrEvent): Promise { + const admin = await new AdminSigner().getPublicKey(); + + if (event.kind !== 5950 && event.pubkey !== admin) { + throw new Error('Only NIP-05 job requests are permitted'); + } + + const input = event.tags.find(([name]) => name === 'i')?.[1]; + const tagged = !!event.tags.find(([name, value]) => name === 'p' && value === admin); + + if (!input || !NIP05.regex().test(input)) { + return DVM.feedback(event, 'error', `Invalid name: ${input}`); + } + + const [user, host] = input.split('@'); + const nip05 = `${user}@${host}`; + + if ((Conf.url.host !== host) && tagged) { + return DVM.feedback(event, 'error', `Unsupported domain: ${host}`); + } + + if (user === '_') { + return DVM.feedback(event, 'error', `Forbidden user: ${user}`); + } + + const [label] = await eventsDB.query([{ + kinds: [1985], + authors: [admin], + '#L': ['nip05'], + '#l': [nip05], + }]); + + if (label) { + return DVM.feedback(event, 'error', `Name already taken: ${nip05}`); + } + + await DVM.label(nip05, event.pubkey); + await DVM.result(event, nip05); + } + + static async feedback( + event: NostrEvent, + status: 'payment-required' | 'processing' | 'error' | 'success' | 'partial', + info = '', + ): Promise { + const feedback = await new AdminSigner().signEvent({ + kind: 7000, + content: '', + tags: [ + ['status', status, info], + ['e', event.id], + ['p', event.pubkey], + ], + created_at: Math.floor(Date.now() / 1000), + }); + return pipeline.handleEvent(feedback, AbortSignal.timeout(1000)); + } + + static async label(nip05: string, pubkey: string): Promise { + const label = await new AdminSigner().signEvent({ + kind: 1985, + tags: [ + ['L', 'nip05'], + ['l', nip05], + ['p', pubkey], + ], + content: '', + created_at: Math.floor(Date.now() / 1000), + }); + return pipeline.handleEvent(label, AbortSignal.timeout(1000)); + } + + static async result(event: NostrEvent, nip05: string): Promise { + const result = await new AdminSigner().signEvent({ + kind: 6950, + content: nip05, + tags: [ + ['request', JSON.stringify(event)], + ['i', nip05, 'text'], + ['e', event.id], + ['p', event.pubkey], + ], + created_at: Math.floor(Date.now() / 1000), + }); + return pipeline.handleEvent(result, AbortSignal.timeout(1000)); + } +} From 29a63f262f08b1e4ee0d245ca43a9b8a60501f65 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 26 Mar 2024 21:10:59 -0500 Subject: [PATCH 2/3] Log relay error, remove unnecessary DVM conditional --- src/controllers/nostr/relay.ts | 1 + src/pipeline/DVM.ts | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/controllers/nostr/relay.ts b/src/controllers/nostr/relay.ts index 56b6e512..f6952221 100644 --- a/src/controllers/nostr/relay.ts +++ b/src/controllers/nostr/relay.ts @@ -85,6 +85,7 @@ function connectStream(socket: WebSocket) { send(['OK', event.id, false, e.message]); } else { send(['OK', event.id, false, 'error: something went wrong']); + console.error(e); } } } diff --git a/src/pipeline/DVM.ts b/src/pipeline/DVM.ts index 8f225192..decfd0f8 100644 --- a/src/pipeline/DVM.ts +++ b/src/pipeline/DVM.ts @@ -20,11 +20,6 @@ export class DVM { static async nameRegistration(event: NostrEvent): Promise { const admin = await new AdminSigner().getPublicKey(); - - if (event.kind !== 5950 && event.pubkey !== admin) { - throw new Error('Only NIP-05 job requests are permitted'); - } - const input = event.tags.find(([name]) => name === 'i')?.[1]; const tagged = !!event.tags.find(([name, value]) => name === 'p' && value === admin); From 0fde577149234a7a5f5028c4216284eff5bfce42 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Tue, 26 Mar 2024 21:42:17 -0500 Subject: [PATCH 3/3] EventsDB: fix the tag queries bug, DVM: remove unnecessary conditional --- src/pipeline/DVM.ts | 4 ---- src/storages/events-db.ts | 14 ++++++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/pipeline/DVM.ts b/src/pipeline/DVM.ts index decfd0f8..542aa75f 100644 --- a/src/pipeline/DVM.ts +++ b/src/pipeline/DVM.ts @@ -7,10 +7,6 @@ import { eventsDB } from '@/storages.ts'; export class DVM { static async event(event: NostrEvent): Promise { - if (event.kind < 5000 || event.kind > 5999) { - throw new Error('Unsupported event kind'); - } - switch (event.kind) { case 5950: await DVM.nameRegistration(event); diff --git a/src/storages/events-db.ts b/src/storages/events-db.ts index f29137f8..22d08a9b 100644 --- a/src/storages/events-db.ts +++ b/src/storages/events-db.ts @@ -181,13 +181,15 @@ class EventsDB implements NStore { query = query.limit(filter.limit!); break; } + } - if (key.startsWith('#')) { - const tag = key.replace(/^#/, ''); - const value = filter[key as `#${string}`] as string[]; - query = query - .leftJoin('tags', 'tags.event_id', 'events.id') - .where('tags.tag', '=', tag) + const joinedQuery = query.leftJoin('tags', 'tags.event_id', 'events.id'); + + for (const [key, value] of Object.entries(filter)) { + if (key.startsWith('#') && Array.isArray(value)) { + const name = key.replace(/^#/, ''); + query = joinedQuery + .where('tags.tag', '=', name) .where('tags.value', 'in', value); } }