feat(nostr): daemon pull-loop — receive over Nostr, completing RFC-007 D3 (#227)#332
Merged
Conversation
The receive half of the Nostr transport (send-path landed in #322). The daemon's `run_sync_pull` now, after the HTTP-slot pull, also pulls Nostr-delivered events: - For each relay a peer is reachable on (`peers[*].nostr_transport.relay` — in the common symmetric pairing, exactly where a peer publishes our inbound), it pulls events `#p`-tagged to our npub, `kind:1`. - Each is transport-verified (`nostr_event::verify_and_decode` — recompute the NIP-01 id + check the schnorr sig) and the inner signed wire event is fed through the SAME `crate::pull::process_events` path as HTTP-pulled events — so the inner Ed25519 signature, trust pin, and inbox dedup are all reused, not reimplemented. Transport-verified here, identity-verified there. - Cursor None: Nostr re-pulls a recent window each cycle; process_events dedups by event_id, so repeats are free. Per-relay errors are logged + skipped (one dead relay can't black-hole the others). - Sync wrapper over async NostrWs via a one-shot runtime block_on (the daemon loop is sync) — same bridge as the send path. Together with #322, a `transport: nostr` peer now fully round-trips through the daemon. Strictly additive: a no-op when not `wire enroll nostr`'d or no peer carries a nostr transport, so the HTTP-slot pull is byte-identical. `nostr_relays_from_peers` (distinct, skips transportless/empty) is pure + unit-tested; the decode + process_events layers are already covered by their own tests + the nostr_ws mock-relay tests. 599 lib tests green; clippy clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Deploying wireup-landing with
|
| Latest commit: |
5962c97
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://d6a744ba.wireup-landing.pages.dev |
| Branch Preview URL: | https://feat-nostr-pull-loop-d3.wireup-landing.pages.dev |
This was referenced Jun 16, 2026
laulpogan
added a commit
that referenced
this pull request
Jun 16, 2026
…en asymmetric (#333) Follow-up to #332. The pull-loop pulled only from `peers[*].nostr_transport.relay` (the relays we reach *peers* on), which is correct only when both sides paired over the same relay. A peer sends to us by publishing to a relay *we're* reachable on — not necessarily one we reach them on. So record that: - `endpoints::pin_self_nostr_relay` / `self_nostr_relays` — a deduped `self.nostr_relays[]` set (additive on the self block; composes with the existing slot fields). - `wire nostr pair`/`accept`/`fetch --relay X` now record X as a relay we're reachable on (accept folds it into its existing relay-state RMW). - `relay::nostr_relays_from_peers` now unions `self.nostr_relays[]` (the authoritative "where peers publish our inbound" set) with the peer-transport relays (still covers the symmetric case before a self-relay is recorded). Net: a `transport: nostr` peer round-trips regardless of pairing symmetry. Still additive — no nostr relay recorded → empty pull set → HTTP path byte-identical. Unit tests: `self_nostr_relay_roundtrips_and_dedups` (roundtrip, dedup, empty, doesn't clobber other self keys) + the relay-helper test now asserts the self∪peer union + dedup. 600 lib tests green; clippy clean. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The receive half of the Nostr transport — the last RFC-007 D3 piece. Send-path landed in #322; this completes the round-trip.
run_sync_pullnow, after the HTTP-slot pull, also pulls Nostr-delivered events:peers[*].nostr_transport.relay— in the common symmetric pairing, exactly where a peer publishes our inbound), pull events#p-tagged to our npub,kind:1.verify_and_decode— recompute the NIP-01 id + check the schnorr sig); the inner signed wire event is fed through the sameprocess_eventspath as HTTP-pulled events — so the inner Ed25519 signature, trust pin, and inbox dedup are all reused, not reimplemented. (Transport-verified here, identity-verified there.)NostrWsvia a one-shot runtimeblock_on(the daemon loop is sync) — same bridge as the send path.Together with #322, a
transport: nostrpeer now fully round-trips through the daemon.Safety
Strictly additive: a no-op when this session isn't
wire enroll nostr'd or no peer carries anostr_transport→ the HTTP-slot pull is byte-identical. The security model holds: transport-verified at pull, identity-verified (Ed25519 + trust) inprocess_events, exactly like HTTP events.Tests
nostr_relays_from_peers(distinct, skips transportless/empty, empty-state no-op) is pure + unit-tested; the decode +process_eventslayers are covered by their own tests + thenostr_wsmock-relay tests. 599 lib tests green; clippy-D warningsclean.Note / follow-up
Pull set = the relays peers are reachable on, which is correct for symmetric same-relay pairing (the
wire nostr pair/accept --relay Xflow). A fully asymmetric setup (peer publishes to a relay we don't pair them on) would need a persisted "self nostr relay" set — tracked as a follow-up, not needed for the dogfood path. Live public-relay e2e (AC-3) remains a manualwire nostrvalidation.🤖 Generated with Claude Code