Skip to content

End event streams when their macaroon is revoked or expires - #303

Open
benthecarman wants to merge 4 commits into
lightningdevkit:mainfrom
benthecarman:fix-64-close-event-streams-revocation
Open

benthecarman wants to merge 4 commits into
lightningdevkit:mainfrom
benthecarman:fix-64-close-event-streams-revocation

Conversation

@benthecarman

@benthecarman benthecarman commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Based on #300

Event streams were only authorized when they were opened, so revoking a macaroon or hitting a time-before expiry blocked new requests but an open stream kept forwarding events (including payment preimages) until the client disconnected.

Now the stream helper rechecks the credential before each event, on revocation, and at expiry, and ends the stream with UNAUTHENTICATED.

Found by Project Loupe

benthecarman and others added 4 commits September 29, 2026 15:00
Move the SubscribeEvents streaming loop out of the request dispatch
match into its own function so it can be reused by additional event
streaming RPCs. No behavior change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
SubscribeEvents delivers every event, so clients that only care about
one kind of event have to receive and discard everything else. Add
SubscribeChannelEvents, SubscribePaymentEvents, and
SubscribeForwardingEvents RPCs, which stream only the matching subset
of events. SubscribeEvents is unchanged.

Channel events are ChannelStateChanged, SpliceNegotiated, and
SpliceNegotiationFailed. Payment events are PaymentReceived,
PaymentSuccessful, PaymentFailed, and PaymentClaimable. Forwarding
events are PaymentForwarded; they get their own stream because they
are the highest-volume event on a routing node and are not this
node's own payments.

Based on an earlier contribution that added an event kind filter to
SubscribeEventsRequest; reworked into separate RPCs per review.

Co-authored-by: Ekong Jemimah <ekongjemimah@gmail.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pay --wait only looks at PaymentSuccessful and PaymentFailed events,
so subscribe to payment events rather than every server event.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Event subscriptions were authorized only when they started. After a
root was revoked or a time-before caveat passed, new requests were
rejected, but an open stream kept forwarding events, including
payment preimages, until the client disconnected.

The shared event stream helper now rechecks the credential against
the store before forwarding each event and after the subscriber lags,
so every subscription kind is covered. Revocation notifies open
streams and the earliest expiry arms a timer, so idle streams also
close promptly. A failed check ends the stream with UNAUTHENTICATED
("Macaroon revoked" or "Macaroon expired").

The recheck shares its root and caveat checks with request admission
so the two cannot drift apart, and takes only the roots read lock.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ldk-reviews-bot

ldk-reviews-bot commented Oct 6, 2026 •

Copy link
Copy Markdown

I've assigned @valentinewallace as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants