feat(lnbits): emit NIP-40 expiration on kind-21000 RPC events
Adds a 5-minute expiration tag to every outbound RPC envelope. Belt- and-suspenders with the handler-side max_age check (aiolabs/lnbits e4b5bcd7) — the tag lets compliant relays drop expired events at the relay layer before they reach LNbits, while the handler's own time-bounds check defends against a stripped tag. Closes aiolabs/satmachineadmin#15 (S1 / G4 — no replay window on RPC events) on the ATM emission side. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fdde0ea3ad
commit
a980dcd3e9
1 changed files with 13 additions and 2 deletions
|
|
@ -366,12 +366,23 @@ export class LnbitsClient {
|
|||
// Build + sign the kind-21000 event ourselves. The server reads our
|
||||
// pubkey directly off the signature, so there's no separate
|
||||
// authIdentifier in the envelope (unlike LightningPubClient).
|
||||
//
|
||||
// NIP-40 expiration: 5 minutes past now. Defence-in-depth at the
|
||||
// relay layer — compliant relays (per NIP-40) drop expired events
|
||||
// before they reach the LNbits handler. The handler also enforces
|
||||
// its own max_age window (aiolabs/lnbits e4b5bcd7), so a replay
|
||||
// attacker can't bypass this by stripping the tag; the tag just
|
||||
// lets the relay short-circuit earlier.
|
||||
const now = Math.floor(Date.now() / 1000)
|
||||
const event = finalizeEvent(
|
||||
{
|
||||
kind: LNBITS_KIND_RPC,
|
||||
content: encrypted,
|
||||
tags: [['p', this.config.serverPubkey]],
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
tags: [
|
||||
['p', this.config.serverPubkey],
|
||||
['expiration', String(now + 300)],
|
||||
],
|
||||
created_at: now,
|
||||
},
|
||||
this.identity.privateKey,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue