fix(backend): pin per-key kind:24133 subscription to explicit relays (#21)
Some checks failed
Docker image / build-and-push-image (push) Has been cancelled
Some checks failed
Docker image / build-and-push-image (push) Has been cancelled
`Backend.start()` calls `this.ndk.subscribe(filter, opts)` to listen for NIP-46 events targeted at each unlocked key's pubkey (kind:24133 with `#p=[localUser.pubkey]`). Pre-fix this subscription opts didn't pin a relay set, so NDK 3.x's outbox routing kicked in: it looked up the `localUser.pubkey`'s NIP-65 relay list (kind:10002) to decide where to send the REQ. Newly-provisioned bunker keys have no kind:10002 published yet, so NDK's subscription manager queued the REQ waiting for a relay list that would never arrive — the subscription never landed on the wire. The user-visible symptom: every NIP-46 RPC from lnbits to a freshly- provisioned key (`connect`, `get_public_key`, `sign_event`, the `nip04_*` / `nip44_*` family) was published into the relay, the relay tried to route, found no subscribed peer matching `["p", new_key_pubkey]`, and emitted "Filter didn't match". The lnbits-side RPC then timed out at 15s, breaking eager merchant provisioning (aiolabs/lnbits#46) and satmachineadmin's per-cassette `nip44_decrypt` polling. Reproduced + diagnosed by patching the lnbits `nostrrelay` extension's `_handle_request` to log incoming REQ filters: only the admin subscription (`{kinds:[24133,24134], #p:[bunker_admin_pubkey]}` from `AdminInterface.connect()`) appeared on the wire. The per-key Backend filters from `Backend.start()` did not. Fix: pass `relayUrls: this.ndk.explicitRelayUrls` in the subscription opts. `relayUrls` was added in NDK 2.13.0 as the supported way to bypass outbox routing per subscription; the relay set built from these URLs matches what the rest of the daemon uses (admin RPC channel + every per-key Backend channel), so events flow through the same connection the admin interface already established. Verified on the regtest dev stack with bunker enabled, fresh signup provisioning a new key + immediately publishing a kind:30017 stall via NIP-46 sign_event: POST /auth/register → HTTP 200 in 1.1s stalls.event_id = 8a2eb20b929… (populated by bunker signature) relay sees: nostr event: [30017, <new-key-pubkey>, '{...store...}'] Pre-fix this same flow timed out at `NsecBunkerTimeoutError: no NIP-46 response for 'sign_event' within 15.0s`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
dad42a7669
commit
59e90d07c0
1 changed files with 25 additions and 1 deletions
|
|
@ -45,12 +45,36 @@ export class Backend extends NDKNip46Backend {
|
||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
this.localUser = await this.signer.user();
|
this.localUser = await this.signer.user();
|
||||||
await new Promise<void>((resolve) => {
|
await new Promise<void>((resolve) => {
|
||||||
|
// Pin this subscription to the daemon's explicit relays via
|
||||||
|
// `relayUrls`. Without that, NDK 3.x's outbox routing tries to
|
||||||
|
// resolve the relay set from `this.localUser.pubkey`'s NIP-65
|
||||||
|
// relay list (kind:10002). Newly-provisioned bunker keys have
|
||||||
|
// no published kind:10002 yet, so NDK's subscription manager
|
||||||
|
// queues the REQ waiting for a relay list that will never
|
||||||
|
// arrive — the kind:24133 subscription never lands on the
|
||||||
|
// wire, and inbound NIP-46 events (sign_event, get_public_key,
|
||||||
|
// nip44_*) targeted at this key get dropped by the relay
|
||||||
|
// with "Filter didn't match" because the bunker isn't actually
|
||||||
|
// subscribed for them.
|
||||||
|
//
|
||||||
|
// `relayUrls` was added in NDK 2.13.0 as the supported way to
|
||||||
|
// bypass outbox routing per subscription (see
|
||||||
|
// NDKSubscriptionOptions.relayUrls in @nostr-dev-kit/ndk).
|
||||||
|
// The relay set built from these URLs matches what the rest
|
||||||
|
// of the bunker uses (admin RPC channel + per-key Backend
|
||||||
|
// channels alike), so events flow through the same connection
|
||||||
|
// the admin interface already established.
|
||||||
|
//
|
||||||
|
// See aiolabs/nsecbunkerd#21.
|
||||||
const sub = this.ndk.subscribe(
|
const sub = this.ndk.subscribe(
|
||||||
{
|
{
|
||||||
kinds: [24133],
|
kinds: [24133],
|
||||||
"#p": [this.localUser!.pubkey],
|
"#p": [this.localUser!.pubkey],
|
||||||
},
|
},
|
||||||
{ closeOnEose: false }
|
{
|
||||||
|
closeOnEose: false,
|
||||||
|
relayUrls: this.ndk.explicitRelayUrls,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
sub.on("event", (e: any) => this.handleIncomingEvent(e));
|
sub.on("event", (e: any) => this.handleIncomingEvent(e));
|
||||||
sub.on("eose", () => resolve());
|
sub.on("eose", () => resolve());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue