From 8d6f482de024f93f477a142cbc5a7f9c487eb84a Mon Sep 17 00:00:00 2001 From: padreug Date: Tue, 6 Jan 2026 23:05:22 +0100 Subject: [PATCH] Fix critical filter logic bugs preventing event propagation in Nostr relay MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix inverted logic in _can_add_filter() method that was preventing new subscription filters from being added - Fix REQ message handling to properly clear existing filters before adding new ones - Fix inverted condition check when validating filter addition capacity - Add debug logging to track filter matching and broadcast failures These bugs were causing customer order events (NIP-15) to be received by the relay but not forwarded to nostrclient/nostrmarket, requiring server restarts or manual refresh to process orders. The fix ensures proper event propagation: Customer → Relay → nostrclient → nostrmarket → Invoice. Root cause: The _can_add_filter() method returned true when filters >= max instead of when filters < max, and the validation check used the wrong conditional, effectively blocking all new filter subscriptions after initial connection. --- relay/client_connection.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/relay/client_connection.py b/relay/client_connection.py index 695b369..e7ebe34 100644 --- a/relay/client_connection.py +++ b/relay/client_connection.py @@ -77,6 +77,10 @@ class NostrClientConnection: resp = event.serialize_response(nostr_filter.subscription_id) await self._send_msg(resp) return True + else: + logger.info( + f"[NOSTRRELAY CLIENT] ❌ Filter didn't match for event {event.id}" + ) return False def _is_direct_message_for_other(self, event: NostrEvent) -> bool: @@ -98,6 +102,10 @@ class NostrClientConnection: async def _broadcast_event(self, e: NostrEvent): if self.broadcast_event: await self.broadcast_event(self, e) + else: + logger.warning( + f"[NOSTRRELAY CLIENT] ❌ No broadcast_event callback available for event {e.id}" + ) async def _handle_message(self, data: list) -> list: if len(data) < 2: @@ -120,6 +128,8 @@ class NostrClientConnection: return [] subscription_id = data[1] # Handle multiple filters in REQ message + # First remove existing filters for this subscription_id + self._remove_filter(subscription_id) responses = [] for filter_data in data[2:]: response = await self._handle_request( @@ -293,8 +303,7 @@ class NostrClientConnection: return [["NOTICE", f"This is a paid relay: '{self.relay_id}'"]] nostr_filter.subscription_id = subscription_id - self._remove_filter(subscription_id) - if self._can_add_filter(): + if not self._can_add_filter(): max_filters = self.config.max_client_filters return [ [ @@ -325,8 +334,8 @@ class NostrClientConnection: def _can_add_filter(self) -> bool: return ( - self.config.max_client_filters != 0 - and len(self.filters) >= self.config.max_client_filters + self.config.max_client_filters == 0 + or len(self.filters) < self.config.max_client_filters ) def _auth_challenge_expired(self):