Skip to content

Throttle LSPS5 lifecycle cooldown resets#4668

Open
tnull wants to merge 1 commit into
lightningdevkit:mainfrom
tnull:2026-06-lsps5-webhook-cooldown
Open

Throttle LSPS5 lifecycle cooldown resets#4668
tnull wants to merge 1 commit into
lightningdevkit:mainfrom
tnull:2026-06-lsps5-webhook-cooldown

Conversation

@tnull

@tnull tnull commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

LSPS5 resets notification cooldowns when a peer reconnects so clients can receive prompt wake-ups after coming online. A peer can otherwise churn connections to clear the webhook cooldown repeatedly, turning the LSP into an amplification source for registered notification URLs.

Rate-limit how often peer lifecycle events may clear notification cooldowns while keeping the first reset immediate. Also make LSPSDateTime elapsed-time calculation directional so backwards clock movement does not make future timestamps look expired.

Co-Authored-By: HAL 9000

This finding was discovered by Project Loupe

LSPS5 resets notification cooldowns when a peer reconnects so clients can receive prompt wake-ups after coming online. A peer can otherwise churn connections to clear the webhook cooldown repeatedly, turning the LSP into an amplification source for registered notification URLs.

Rate-limit how often peer lifecycle events may clear notification cooldowns while keeping the first reset immediate. Also make LSPSDateTime elapsed-time calculation directional so backwards clock movement does not make future timestamps look expired.

Co-Authored-By: HAL 9000

This finding was discovered by Project Loupe
@ldk-reviews-bot

ldk-reviews-bot commented Jun 10, 2026

Copy link
Copy Markdown

I've assigned @wpaulino 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.

/// This is distinct from [`NOTIFICATION_COOLDOWN_TIME`]: that cooldown protects the client from
/// repeated spammy wake-ups, while this reset throttle protects registered notification URLs from
/// amplification via rapid peer connect/disconnect churn.
const NOTIFICATION_COOLDOWN_RESET_INTERVAL: Duration = Duration::from_secs(10);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Design consideration: the reset throttle (10s) is much shorter than NOTIFICATION_COOLDOWN_TIME (60s). Since each allowed reset clears last_notification_sent and lets a fresh notification through, an attacker churning connections can still force a webhook POST roughly every 10s instead of the 60s the cooldown otherwise enforces — i.e. ~6x amplification per registered URL remains possible. If the goal is to bound amplification to the cooldown, consider setting this interval to (or deriving it from) NOTIFICATION_COOLDOWN_TIME, or otherwise document why 10s is the intended floor.

@ldk-claude-review-bot

Copy link
Copy Markdown
Collaborator

Reviewed all three files in the PR. The directional duration_since change is safe (all liquidity call sites use now.duration_since(past)), the throttle logic and TLV serialization are consistent, and the tests trace correctly. No hard bugs found.

Findings

  • lightning-liquidity/src/lsps5/service.rs:93 — Design consideration: the 10s reset throttle is much shorter than the 60s NOTIFICATION_COOLDOWN_TIME, so reconnect churn can still force a webhook POST ~every 10s (~6x residual amplification per URL). Consider tying the interval to the cooldown or documenting why 10s is the intended floor.

Cross-cutting notes (not blocking)

  • last_notification_cooldown_reset uses (static_value, None) so it is not persisted and resets to None on process restart, dropping the throttle state. This matches the existing needs_persist pattern and PeerState is held in memory for the process lifetime, so it's acceptable, but worth being aware of since it's security-relevant state.
  • peer_disconnected also consumes the throttle budget. In practice the wake-up on the subsequent reconnect is still served (the disconnect already cleared the cooldown), so this is not a functional bug — just noting the disconnect reset has no client-facing benefit (peer is offline) yet uses the rate-limit window.

@ldk-reviews-bot ldk-reviews-bot requested a review from wpaulino June 10, 2026 10:43
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.

3 participants