Skip to content

Commit

Permalink
Revert "Merge branch 'main' of https://github.com/Cameri/nostream"
Browse files Browse the repository at this point in the history
This reverts commit 246eb61, reversing
changes made to cc7ba4b.
  • Loading branch information
imksoo committed Jan 14, 2024
1 parent 246eb61 commit af4d295
Show file tree
Hide file tree
Showing 34 changed files with 1,252 additions and 1,466 deletions.
3 changes: 0 additions & 3 deletions CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,3 @@ Running `nostream` for the first time creates the settings file in `<project_roo
| limits.message.rateLimits[].period | Rate limit period in milliseconds. |
| limits.message.rateLimits[].rate | Maximum number of messages during period. |
| limits.message.ipWhitelist | List of IPs (IPv4 or IPv6) to ignore rate limits. |
| limits.admissionCheck.rateLimits[].period | Rate limit period in milliseconds. |
| limits.admissionCheck.rateLimits[].rate | Maximum number of admission checks during period. |
| limits.admissionCheck.ipWhitelist | List of IPs (IPv4 or IPv6) to ignore rate limits. |
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ NIPs with a relay-specific implementation are listed here.
- [x] NIP-16: Event Treatment
- [x] NIP-20: Command Results
- [x] NIP-22: Event `created_at` Limits
- [ ] NIP-26: Delegated Event Signing (REMOVED)
- [x] NIP-26: Delegated Event Signing
- [x] NIP-28: Public Chat
- [x] NIP-33: Parameterized Replaceable Events
- [x] NIP-40: Expiration Timestamp
Expand Down
18 changes: 0 additions & 18 deletions migrations/20240111204900_remove_delegator_from_events_table.js

This file was deleted.

1,790 changes: 606 additions & 1,184 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nostream",
"version": "2.0.0",
"version": "1.25.2",
"description": "A Nostr relay written in Typescript.",
"supportedNips": [
1,
Expand All @@ -13,6 +13,7 @@
16,
20,
22,
26,
28,
33,
40
Expand Down Expand Up @@ -72,7 +73,7 @@
"devDependencies": {
"@commitlint/cli": "17.2.0",
"@commitlint/config-conventional": "17.2.0",
"@cucumber/cucumber": "10.2.1",
"@cucumber/cucumber": "8.7.0",
"@cucumber/pretty-formatter": "1.0.0",
"@semantic-release/commit-analyzer": "9.0.2",
"@semantic-release/git": "10.0.1",
Expand Down Expand Up @@ -115,7 +116,7 @@
},
"dependencies": {
"@noble/secp256k1": "1.7.1",
"axios": "1.6.5",
"axios": "1.2.6",
"bech32": "2.0.0",
"body-parser": "1.20.1",
"debug": "4.3.4",
Expand Down
9 changes: 0 additions & 9 deletions resources/default-settings.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,6 @@ limits:
- "::1"
- "10.10.10.1"
- "::ffff:10.10.10.1"
admissionCheck:
rateLimits:
- description: 30 admission checks/min or 1 check every 2 seconds
period: 60000
rate: 30
ipWhitelist:
- "::1"
- "10.10.10.1"
- "::ffff:10.10.10.1"
connection:
rateLimits:
- period: 1000
Expand Down
7 changes: 6 additions & 1 deletion src/@types/event.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ContextMetadata, EventId, Pubkey, Tag } from './base'
import { ContextMetadataKey, EventDeduplicationMetadataKey, EventExpirationTimeMetadataKey, EventKinds } from '../constants/base'
import { ContextMetadataKey, EventDeduplicationMetadataKey, EventDelegatorMetadataKey, EventExpirationTimeMetadataKey, EventKinds } from '../constants/base'

export interface BaseEvent {
id: EventId
Expand All @@ -21,6 +21,10 @@ export type UnsignedEvent = Omit<Event, 'sig'>

export type UnidentifiedEvent = Omit<UnsignedEvent, 'id'>

export interface DelegatedEvent extends Event {
[EventDelegatorMetadataKey]?: Pubkey
}

export interface ExpiringEvent extends Event {
[EventExpirationTimeMetadataKey]?: number
}
Expand All @@ -38,6 +42,7 @@ export interface DBEvent {
event_content: string
event_tags: Tag[]
event_signature: Buffer
event_delegator?: Buffer | null
event_deduplication?: string | null
first_seen: Date
deleted_at?: Date
Expand Down
1 change: 1 addition & 0 deletions src/@types/repositories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export interface IEventRepository {
create(event: Event): Promise<number>
upsert(event: Event): Promise<number>
findByFilters(filters: SubscriptionFilter[]): IQueryResult<DBEvent[]>
insertStubs(pubkey: string, eventIdsToDelete: EventId[]): Promise<number>
deleteByPubkeyAndIds(pubkey: Pubkey, ids: EventId[]): Promise<number>
}

Expand Down
6 changes: 0 additions & 6 deletions src/@types/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,8 @@ export interface InvoiceLimits {
ipWhitelist?: string[]
}

export interface AdmissionCheckLimits {
rateLimits: RateLimit[]
ipWhitelist?: string[]
}

export interface Limits {
invoice?: InvoiceLimits
admissionCheck?: AdmissionCheckLimits
connection?: ConnectionLimits
client?: ClientLimits
event?: EventLimits
Expand Down
2 changes: 1 addition & 1 deletion src/@types/subscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type SubscriptionId = string

export interface SubscriptionFilter {
ids?: EventId[]
kinds?: (EventKinds | number)[]
kinds?: EventKinds[]
since?: number
until?: number
authors?: Pubkey[]
Expand Down
2 changes: 2 additions & 0 deletions src/constants/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export enum EventTags {
Event = 'e',
Pubkey = 'p',
// Multicast = 'm',
Delegation = 'delegation',
Deduplication = 'd',
Expiration = 'expiration',
Invoice = 'bolt11',
Expand All @@ -48,6 +49,7 @@ export enum PaymentsProcessors {
LNBITS = 'lnbits',
}

export const EventDelegatorMetadataKey = Symbol('Delegator')
export const EventDeduplicationMetadataKey = Symbol('Deduplication')
export const ContextMetadataKey = Symbol('Context')
export const EventExpirationTimeMetadataKey = Symbol('Expiration')
70 changes: 0 additions & 70 deletions src/controllers/admission/get-admission-check-controller.ts

This file was deleted.

This file was deleted.

21 changes: 21 additions & 0 deletions src/factories/delegated-event-strategy-factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { isDeleteEvent, isEphemeralEvent, isReplaceableEvent } from '../utils/event'
import { DefaultEventStrategy } from '../handlers/event-strategies/default-event-strategy'
import { EphemeralEventStrategy } from '../handlers/event-strategies/ephemeral-event-strategy'
import { Event } from '../@types/event'
import { Factory } from '../@types/base'
import { IEventRepository } from '../@types/repositories'
import { IEventStrategy } from '../@types/message-handlers'
import { IWebSocketAdapter } from '../@types/adapters'

export const delegatedEventStrategyFactory = (
eventRepository: IEventRepository,
): Factory<IEventStrategy<Event, Promise<void>>, [Event, IWebSocketAdapter]> =>
([event, adapter]: [Event, IWebSocketAdapter]) => {
if (isEphemeralEvent(event)) {
return new EphemeralEventStrategy(adapter)
} else if (isReplaceableEvent(event) || isDeleteEvent(event)) {
return
}

return new DefaultEventStrategy(adapter, eventRepository)
}
15 changes: 14 additions & 1 deletion src/factories/message-handler-factory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { IEventRepository, IUserRepository } from '../@types/repositories'
import { IncomingMessage, MessageType } from '../@types/messages'
import { createSettings } from './settings-factory'
import { DelegatedEventMessageHandler } from '../handlers/delegated-event-message-handler'
import { delegatedEventStrategyFactory } from './delegated-event-strategy-factory'
import { EventMessageHandler } from '../handlers/event-message-handler'
import { eventStrategyFactory } from './event-strategy-factory'
import { isDelegatedEvent } from '../utils/event'
import { IWebSocketAdapter } from '../@types/adapters'
import { slidingWindowRateLimiterFactory } from './rate-limiter-factory'
import { SubscribeMessageHandler } from '../handlers/subscribe-message-handler'
Expand All @@ -15,6 +18,16 @@ export const messageHandlerFactory = (
switch (message[0]) {
case MessageType.EVENT:
{
if (isDelegatedEvent(message[1])) {
return new DelegatedEventMessageHandler(
adapter,
delegatedEventStrategyFactory(eventRepository),
userRepository,
createSettings,
slidingWindowRateLimiterFactory,
)
}

return new EventMessageHandler(
adapter,
eventStrategyFactory(eventRepository),
Expand All @@ -26,7 +39,7 @@ export const messageHandlerFactory = (
case MessageType.REQ:
return new SubscribeMessageHandler(adapter, eventRepository, createSettings)
case MessageType.CLOSE:
return new UnsubscribeMessageHandler(adapter)
return new UnsubscribeMessageHandler(adapter,)
default:
throw new Error(`Unknown message type: ${String(message[0]).substring(0, 64)}`)
}
Expand Down
75 changes: 75 additions & 0 deletions src/handlers/delegated-event-message-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { EventDelegatorMetadataKey, EventTags } from '../constants/base'
import { createCommandResult } from '../utils/messages'
import { createLogger } from '../factories/logger-factory'
import { DelegatedEvent } from '../@types/event'
import { EventMessageHandler } from './event-message-handler'
import { IMessageHandler } from '../@types/message-handlers'
import { IncomingEventMessage } from '../@types/messages'
import { isDelegatedEventValid } from '../utils/event'
import { WebSocketAdapterEvent } from '../constants/adapter'

const debug = createLogger('delegated-event-message-handler')

export class DelegatedEventMessageHandler extends EventMessageHandler implements IMessageHandler {
public async handleMessage(message: IncomingEventMessage): Promise<void> {
const [, event] = message

let reason = await this.isEventValid(event)
if (reason) {
debug('event %s rejected: %s', event.id, reason)
this.webSocket.emit(WebSocketAdapterEvent.Message, createCommandResult(event.id, false, reason))
return
}

if (await this.isRateLimited(event)) {
debug('event %s rejected: rate-limited')
this.webSocket.emit(WebSocketAdapterEvent.Message, createCommandResult(event.id, false, 'rate-limited: slow down'))
return
}

reason = this.canAcceptEvent(event)
if (reason) {
debug('event %s rejected: %s', event.id, reason)
this.webSocket.emit(WebSocketAdapterEvent.Message, createCommandResult(event.id, false, reason))
return
}

reason = await this.isUserAdmitted(event)
if (reason) {
debug('event %s rejected: %s', event.id, reason)
this.webSocket.emit(WebSocketAdapterEvent.Message, createCommandResult(event.id, false, reason))
return
}

const [, delegator] = event.tags.find((tag) => tag.length === 4 && tag[0] === EventTags.Delegation)
const delegatedEvent: DelegatedEvent = {
...event,
[EventDelegatorMetadataKey]: delegator,
}

const strategy = this.strategyFactory([delegatedEvent, this.webSocket])

if (typeof strategy?.execute !== 'function') {
this.webSocket.emit(WebSocketAdapterEvent.Message, createCommandResult(event.id, false, 'error: event not supported'))
return
}

try {
await strategy.execute(delegatedEvent)
} catch (error) {
console.error('error handling message', message, error)
this.webSocket.emit(WebSocketAdapterEvent.Message, createCommandResult(event.id, false, 'error: unable to process event'))
}
}

protected async isEventValid(event: DelegatedEvent): Promise<string | undefined> {
const reason = await super.isEventValid(event)
if (reason) {
return reason
}

if (!await isDelegatedEventValid(event)) {
return 'invalid: delegation verification failed'
}
}
}
Loading

0 comments on commit af4d295

Please sign in to comment.