Skip to content

Commit 5be5c6c

Browse files
committed
Add LSPS5 (bLIP-55) webhook notification support
Implement the bLIP-55 / LSPS5 webhook registration protocol on top of the multi-LSP liquidity module (src/liquidity/{client,service}). Client side, exposed via Node::liquidity().lsps5(): - set_webhook / list_webhooks / remove_webhook to manage webhook registrations with an LSP. - When no node_id is given, set_webhook and remove_webhook fan out to every LSPS5-capable LSP so a webhook can be configured once across all configured LSPs; set_webhook returns one result per LSP that accepted the registration and remove_webhook returns the LSPs it was removed from. Service side, enabled via Builder::enable_liquidity_provider_lsps5(): - Deliver outgoing webhook notifications over HTTP in response to LSPS5ServiceEvent::SendWebhookNotification. - Automatically send an onion-message-incoming notification when an intercepted onion message targets a client that is currently offline (wired from LdkEvent::OnionMessageIntercepted, gated on peer connectivity). Wires the feature through the UniFFI bindings and adds LSPS5-specific Error variants.
1 parent d9b8f7b commit 5be5c6c

11 files changed

Lines changed: 1095 additions & 15 deletions

File tree

bindings/ldk_node.udl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ interface Node {
113113
OnchainPayment onchain_payment();
114114
UnifiedPayment unified_payment();
115115
Liquidity liquidity();
116+
LSPS5Liquidity lsps5_liquidity();
116117
[Throws=NodeError]
117118
void lnurl_auth(string lnurl);
118119
[Throws=NodeError]
@@ -184,6 +185,8 @@ typedef interface UnifiedPayment;
184185

185186
typedef interface Liquidity;
186187

188+
typedef interface LSPS5Liquidity;
189+
187190
[Error]
188191
enum NodeError {
189192
"AlreadyRunning",
@@ -249,6 +252,9 @@ enum NodeError {
249252
"InvalidLnurl",
250253
"ChainSourceNotSupported",
251254
"InvalidPayerProof",
255+
"LiquiditySetWebhookFailed",
256+
"LiquidityRemoveWebhookFailed",
257+
"LiquidityListWebhooksFailed"
252258
};
253259

254260
typedef dictionary NodeStatus;

src/builder.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,8 @@ use crate::runtime::{Runtime, RuntimeSpawner};
8383
use crate::tx_broadcaster::TransactionBroadcaster;
8484
use crate::types::{
8585
AsyncPersister, ChainMonitor, ChannelManager, DynStore, DynStoreRef, DynStoreWrapper,
86-
GossipSync, Graph, HRNResolver, KeysManager, MessageRouter, OnionMessenger, PaymentStore,
87-
PeerManager, PendingPaymentStore,
86+
GossipSync, Graph, HRNResolver, KeysManager, LSPS5ServiceConfig, MessageRouter, OnionMessenger,
87+
PaymentStore, PeerManager, PendingPaymentStore,
8888
};
8989
use crate::wallet::persist::{read_address_pool, KVStoreWalletPersister};
9090
use crate::wallet::Wallet;
@@ -127,10 +127,12 @@ struct PathfindingScoresSyncConfig {
127127

128128
#[derive(Debug, Clone, Default)]
129129
struct LiquiditySourceConfig {
130-
// Acts for both LSPS1 and LSPS2 clients connecting to the given service.
130+
// Acts for LSPS1, LSPS2 and LSPS5 clients connecting to the given service.
131131
lsp_nodes: Vec<LspConfig>,
132132
// Act as an LSPS2 service.
133133
lsps2_service: Option<LSPS2ServiceConfig>,
134+
// Act as an LSPS5 service.
135+
lsps5_service: Option<LSPS5ServiceConfig>,
134136
}
135137

136138
#[derive(Clone)]
@@ -522,6 +524,21 @@ impl NodeBuilder {
522524
self
523525
}
524526

527+
/// Configures the [`Node`] instance to provide an [bLIP-55 / LSPS5] service, enabling clients
528+
/// to register webhooks for push notifications.
529+
///
530+
/// **Caution**: LSP service support is in **alpha** and is considered an experimental feature.
531+
///
532+
/// [bLIP-55 / LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
533+
pub fn enable_liquidity_provider_lsps5(
534+
&mut self, lsps5_service_config: LSPS5ServiceConfig,
535+
) -> &mut Self {
536+
let liquidity_source_config =
537+
self.liquidity_source_config.get_or_insert(LiquiditySourceConfig::default());
538+
liquidity_source_config.lsps5_service = Some(lsps5_service_config);
539+
self
540+
}
541+
525542
/// Sets the used storage directory path.
526543
pub fn set_storage_dir_path(&mut self, storage_dir_path: String) -> &mut Self {
527544
self.config.storage_dir_path = storage_dir_path;
@@ -1122,6 +1139,16 @@ impl ArcedNodeBuilder {
11221139
self.inner.write().expect("lock").enable_liquidity_provider(lsps2_service_config);
11231140
}
11241141

1142+
/// Configures the [`Node`] instance to provide an [bLIP-55 / LSPS5] service, enabling clients
1143+
/// to register webhooks for push notifications.
1144+
///
1145+
/// **Caution**: LSP service support is in **alpha** and is considered an experimental feature.
1146+
///
1147+
/// [bLIP-55 / LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
1148+
pub fn enable_liquidity_provider_lsps5(&self, lsps5_service_config: LSPS5ServiceConfig) {
1149+
self.inner.write().expect("lock").enable_liquidity_provider_lsps5(lsps5_service_config);
1150+
}
1151+
11251152
/// Sets the used storage directory path.
11261153
pub fn set_storage_dir_path(&self, storage_dir_path: String) {
11271154
self.inner.write().expect("lock").set_storage_dir_path(storage_dir_path);
@@ -2166,6 +2193,10 @@ fn build_with_store_internal(
21662193
lsc.lsps2_service.as_ref().map(|config| {
21672194
liquidity_source_builder.lsps2_service(promise_secret, config.clone())
21682195
});
2196+
2197+
lsc.lsps5_service
2198+
.as_ref()
2199+
.map(|config| liquidity_source_builder.lsps5_service(config.clone()));
21692200
}
21702201

21712202
let liquidity_source = runtime
@@ -2225,6 +2256,8 @@ fn build_with_store_internal(
22252256

22262257
liquidity_source.lsps2_service().set_peer_manager(Arc::downgrade(&peer_manager));
22272258

2259+
liquidity_source.lsps5_service().set_peer_manager(Arc::downgrade(&peer_manager));
2260+
22282261
let connection_manager = Arc::new(ConnectionManager::new(
22292262
Arc::clone(&peer_manager),
22302263
config.tor_config.clone(),

src/error.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,12 @@ pub enum Error {
143143
ChainSourceNotSupported,
144144
/// The provided payer proof is invalid.
145145
InvalidPayerProof,
146+
/// Failed to set a webhook with the LSP.
147+
LiquiditySetWebhookFailed,
148+
/// Failed to remove a webhook with the LSP.
149+
LiquidityRemoveWebhookFailed,
150+
/// Failed to list webhooks with the LSP.
151+
LiquidityListWebhooksFailed,
146152
}
147153

148154
impl fmt::Display for Error {
@@ -233,6 +239,15 @@ impl fmt::Display for Error {
233239
write!(f, "The configured chain source is not supported.")
234240
},
235241
Self::InvalidPayerProof => write!(f, "The provided payer proof is invalid."),
242+
Self::LiquiditySetWebhookFailed => {
243+
write!(f, "Failed to set a webhook with the LSP.")
244+
},
245+
Self::LiquidityRemoveWebhookFailed => {
246+
write!(f, "Failed to remove a webhook with the LSP.")
247+
},
248+
Self::LiquidityListWebhooksFailed => {
249+
write!(f, "Failed to list webhooks with the LSP.")
250+
},
236251
}
237252
}
238253
}

src/event.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2083,6 +2083,8 @@ where
20832083
} else {
20842084
log_error!(self.logger, "Onion message intercepted for unknown SCID");
20852085
}
2086+
2087+
self.liquidity_source.lsps5_service().notify_onion_message_incoming(peer_node_id);
20862088
},
20872089
LdkEvent::OnionMessagePeerConnected { peer_node_id } => {
20882090
if let Some(om_mailbox) = self.om_mailbox.as_ref() {

0 commit comments

Comments
 (0)