[LSPS5] Change notification cooldown time to 1 minute, also update docs.
What changed, and why it matters
This commit changes the LSPS5 webhook notification cooldown from 1 hour to 1 minute. The shorter cooldown means the same type of notification can be sent to a client's webhooks far more frequently. This is not a code vulnerability in itself, but it increases the risk of accidental or intentional notification spam, which could stress webhook endpoints, generate extra network traffic, and make it easier to overwhelm a receiving service. The change is purely a configuration/default-value adjustment with documentation and test updates.
Review whether a 1-minute cooldown aligns with operational expectations for webhook recipients. If the shorter window is intentional, consider adding complementary limits such as per-method max notifications per longer window, per-URL backpressure, or exponential backoff on failures to avoid abuse or accidental amplification. Monitor for increased webhook traffic after upgrade.
Security signals we found
Rate-limiting threshold relaxed by 60x (1 hour -> 1 minute)
Webhook notification spam now easier due to shorter cooldown
No input validation or additional throttling added to compensate
Public constant change affects default behavior of LSPS5 service notifications
Evidence from the diff
The patch renames DEFAULT_NOTIFICATION_COOLDOWN_HOURS to NOTIFICATION_COOLDOWN_TIME and reduces its value from Duration::from_secs(60 * 60) (1 hour) to Duration::from_secs(60) (1 minute). The constant is used in LSPS5Service::send_notifications_to_client_webhooks to decide whether a notification of the same method was sent too recently and should be rate-limited. All doc links and the integration test that advances the mock clock past the cooldown were updated to match the new constant. No logic changes were made beyond the duration value and rename.
Changed components
lightning-liquidity/src/lsps5/service.rslightning-liquidity/src/lsps5/msgs.rslightning-liquidity/tests/lsps5_integration_tests.rsInspect captured patch +15 / −15
diff --git a/lightning-liquidity/src/lsps5/msgs.rs b/lightning-liquidity/src/lsps5/msgs.rs
index c61bc2b..ada1f26 100644
--- a/lightning-liquidity/src/lsps5/msgs.rs
+++ b/lightning-liquidity/src/lsps5/msgs.rs
@@ -109,9 +109,9 @@ pub enum LSPS5ProtocolError {
/// A notification was sent too frequently.
///
/// This error indicates that the LSP is sending notifications
- /// too quickly, violating the notification cooldown [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`]
+ /// too quickly, violating the notification cooldown [`NOTIFICATION_COOLDOWN_TIME`]
///
- /// [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`]: super::service::DEFAULT_NOTIFICATION_COOLDOWN_HOURS
+ /// [`NOTIFICATION_COOLDOWN_TIME`]: super::service::NOTIFICATION_COOLDOWN_TIME
SlowDownError,
}
diff --git a/lightning-liquidity/src/lsps5/service.rs b/lightning-liquidity/src/lsps5/service.rs
index e0fb3ab..2b86ad3 100644
--- a/lightning-liquidity/src/lsps5/service.rs
+++ b/lightning-liquidity/src/lsps5/service.rs
@@ -68,8 +68,8 @@ pub struct LSPS5ServiceConfig {
/// Default maximum number of webhooks allowed per client.
pub const DEFAULT_MAX_WEBHOOKS_PER_CLIENT: u32 = 10;
-/// Default notification cooldown time in hours.
-pub const DEFAULT_NOTIFICATION_COOLDOWN_HOURS: Duration = Duration::from_secs(60 * 60); // 1 hour
+/// Default notification cooldown time in minutes.
+pub const NOTIFICATION_COOLDOWN_TIME: Duration = Duration::from_secs(60); // 1 minute
// Default configuration for LSPS5 service.
impl Default for LSPS5ServiceConfig {
@@ -330,13 +330,13 @@ where
/// node key, and enqueues HTTP POSTs to all registered webhook URLs for that client.
///
/// This may fail if a similar notification was sent too recently,
- /// violating the notification cooldown period defined in [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`].
+ /// violating the notification cooldown period defined in [`NOTIFICATION_COOLDOWN_TIME`].
///
/// # Parameters
/// - `client_id`: the client's node-ID whose webhooks should be invoked.
///
/// [`WebhookNotificationMethod::LSPS5PaymentIncoming`]: super::msgs::WebhookNotificationMethod::LSPS5PaymentIncoming
- /// [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`]: super::service::DEFAULT_NOTIFICATION_COOLDOWN_HOURS
+ /// [`NOTIFICATION_COOLDOWN_TIME`]: super::service::NOTIFICATION_COOLDOWN_TIME
pub fn notify_payment_incoming(&self, client_id: PublicKey) -> Result<(), LSPS5ProtocolError> {
let notification = WebhookNotification::payment_incoming();
self.send_notifications_to_client_webhooks(client_id, notification)
@@ -351,14 +351,14 @@ where
/// registered webhooks.
///
/// This may fail if a similar notification was sent too recently,
- /// violating the notification cooldown period defined in [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`].
+ /// violating the notification cooldown period defined in [`NOTIFICATION_COOLDOWN_TIME`].
///
/// # Parameters
/// - `client_id`: the client's node-ID whose webhooks should be invoked.
/// - `timeout`: the block height at which the channel contract will expire.
///
/// [`WebhookNotificationMethod::LSPS5ExpirySoon`]: super::msgs::WebhookNotificationMethod::LSPS5ExpirySoon
- /// [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`]: super::service::DEFAULT_NOTIFICATION_COOLDOWN_HOURS
+ /// [`NOTIFICATION_COOLDOWN_TIME`]: super::service::NOTIFICATION_COOLDOWN_TIME
pub fn notify_expiry_soon(
&self, client_id: PublicKey, timeout: u32,
) -> Result<(), LSPS5ProtocolError> {
@@ -373,13 +373,13 @@ where
/// signs it, and sends it to all of the client's registered webhook URLs.
///
/// This may fail if a similar notification was sent too recently,
- /// violating the notification cooldown period defined in [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`].
+ /// violating the notification cooldown period defined in [`NOTIFICATION_COOLDOWN_TIME`].
///
/// # Parameters
/// - `client_id`: the client's node-ID whose webhooks should be invoked.
///
/// [`WebhookNotificationMethod::LSPS5LiquidityManagementRequest`]: super::msgs::WebhookNotificationMethod::LSPS5LiquidityManagementRequest
- /// [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`]: super::service::DEFAULT_NOTIFICATION_COOLDOWN_HOURS
+ /// [`NOTIFICATION_COOLDOWN_TIME`]: super::service::NOTIFICATION_COOLDOWN_TIME
pub fn notify_liquidity_management_request(
&self, client_id: PublicKey,
) -> Result<(), LSPS5ProtocolError> {
@@ -394,13 +394,13 @@ where
/// notification, signs it, and enqueues HTTP POSTs to each registered webhook.
///
/// This may fail if a similar notification was sent too recently,
- /// violating the notification cooldown period defined in [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`].
+ /// violating the notification cooldown period defined in [`NOTIFICATION_COOLDOWN_TIME`].
///
/// # Parameters
/// - `client_id`: the client's node-ID whose webhooks should be invoked.
///
/// [`WebhookNotificationMethod::LSPS5OnionMessageIncoming`]: super::msgs::WebhookNotificationMethod::LSPS5OnionMessageIncoming
- /// [`DEFAULT_NOTIFICATION_COOLDOWN_HOURS`]: super::service::DEFAULT_NOTIFICATION_COOLDOWN_HOURS
+ /// [`NOTIFICATION_COOLDOWN_TIME`]: super::service::NOTIFICATION_COOLDOWN_TIME
pub fn notify_onion_message_incoming(
&self, client_id: PublicKey,
) -> Result<(), LSPS5ProtocolError> {
@@ -429,7 +429,7 @@ where
.last_notification_sent
.get(¬ification.method)
.map(|last_sent| now.duration_since(&last_sent))
- .map_or(false, |duration| duration < DEFAULT_NOTIFICATION_COOLDOWN_HOURS)
+ .map_or(false, |duration| duration < NOTIFICATION_COOLDOWN_TIME)
});
if rate_limit_applies {
diff --git a/lightning-liquidity/tests/lsps5_integration_tests.rs b/lightning-liquidity/tests/lsps5_integration_tests.rs
index 61e7c12..9035755 100644
--- a/lightning-liquidity/tests/lsps5_integration_tests.rs
+++ b/lightning-liquidity/tests/lsps5_integration_tests.rs
@@ -19,7 +19,7 @@ use lightning_liquidity::lsps5::msgs::{
WebhookNotificationMethod,
};
use lightning_liquidity::lsps5::service::{
- LSPS5ServiceConfig, DEFAULT_MAX_WEBHOOKS_PER_CLIENT, DEFAULT_NOTIFICATION_COOLDOWN_HOURS,
+ LSPS5ServiceConfig, DEFAULT_MAX_WEBHOOKS_PER_CLIENT, NOTIFICATION_COOLDOWN_TIME,
};
use lightning_liquidity::lsps5::service::{
MIN_WEBHOOK_RETENTION_DAYS, PRUNE_STALE_WEBHOOKS_INTERVAL_DAYS,
@@ -1119,7 +1119,7 @@ fn test_send_notifications_and_peer_connected_resets_cooldown() {
}
// 4. Advance time past cooldown and ensure payment_incoming can be sent again
- mock_time_provider.advance_time(DEFAULT_NOTIFICATION_COOLDOWN_HOURS.as_secs() + 1);
+ mock_time_provider.advance_time(NOTIFICATION_COOLDOWN_TIME.as_secs() + 1);
let _ = service_handler.notify_payment_incoming(client_node_id);
let event = service_node.liquidity_manager.next_event().unwrap();
Why this scored 21/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.