mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 05:45:18 +00:00
The single global inbound consumer serialized ALL relay traffic behind one Schnorr-verification queue, so a burst of EVENT frames from one busy/malicious relay stalled DMs, OKs, EOSEs, and events from every other relay (codex P2). Give each relay connection its own bounded AsyncStream + detached serial consumer instead: N relays verify in parallel while each relay's frames stay in arrival order (per-relay ordering preserves the per-subscription ordering that actually matters, since a subscription's events for a relay all arrive on that relay's socket). Continuations live in a lock-guarded Sendable router so the non-isolated socket receive callback can route a frame to the right relay stream with no per-frame main hop; the main actor owns pipeline start/teardown, wired into connect, disconnect, panic wipe, per-relay disconnect, retry, and the default-relay revoke path. Streams use .bufferingNewest so a relay flooding faster than it verifies sheds its OWN oldest frames — it can neither exhaust memory nor starve other relays. Security invariants are unchanged: signature verified exactly once, off main; dedup pre-check-before / record-after-verify (forged copies still can't poison the dedup set); the atomic main-actor check-and-record in deliverVerifiedInboundEvent; the inner NIP-17 seal check untouched. Tests: existing per-relay in-order-delivery and tampered-signature dedup-poison tests still pass; add a cross-relay non-blocking test proving a large backlog on relay A does not delay a later frame on relay B. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>