Skip to content

Commit 4991205

Browse files
authored
Merge pull request #4282 from tnull/2025-11-lsps1-refactor
`lightning-liquidity`: Refactor LSPS1 service-side
2 parents 2c09092 + 47e5c04 commit 4991205

19 files changed

Lines changed: 3031 additions & 602 deletions

File tree

ci/ci-tests-cfg-flags.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,4 @@ RUSTFLAGS="--cfg=taproot" cargo test --quiet --color always -p lightning
99
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
1010
RUSTFLAGS="--cfg=simple_close" cargo test --quiet --color always -p lightning
1111
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
12-
RUSTFLAGS="--cfg=lsps1_service" cargo test --quiet --color always -p lightning-liquidity
13-
[ "$CI_MINIMIZE_DISK_USAGE" != "" ] && cargo clean
1412
RUSTFLAGS="--cfg=peer_storage" cargo test --quiet --color always -p lightning

fuzz/src/lsps_message.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ pub fn do_test(data: &[u8]) {
8282
Arc::clone(&keys_manager),
8383
Arc::clone(&keys_manager),
8484
Arc::clone(&manager),
85-
None::<Arc<dyn Filter + Send + Sync>>,
86-
None,
8785
kv_store,
8886
Arc::clone(&tx_broadcaster),
8987
None,

lightning-background-processor/src/lib.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,6 @@ pub const NO_LIQUIDITY_MANAGER: Option<
464464
NodeSigner = &(dyn lightning::sign::NodeSigner + Send + Sync),
465465
AChannelManager = DynChannelManager,
466466
CM = &DynChannelManager,
467-
C = &(dyn chain::Filter + Send + Sync),
468467
K = &DummyKVStore,
469468
TimeProvider = dyn lightning_liquidity::utils::time::TimeProvider + Send + Sync,
470469
TP = &(dyn lightning_liquidity::utils::time::TimeProvider + Send + Sync),
@@ -486,7 +485,6 @@ pub const NO_LIQUIDITY_MANAGER_SYNC: Option<
486485
NodeSigner = &(dyn lightning::sign::NodeSigner + Send + Sync),
487486
AChannelManager = DynChannelManager,
488487
CM = &DynChannelManager,
489-
C = &(dyn chain::Filter + Send + Sync),
490488
KVStoreSync = dyn lightning::util::persist::KVStoreSync + Send + Sync,
491489
KS = &(dyn lightning::util::persist::KVStoreSync + Send + Sync),
492490
TimeProvider = dyn lightning_liquidity::utils::time::TimeProvider + Send + Sync,
@@ -829,7 +827,7 @@ use futures_util::{dummy_waker, Joiner, OptionalSelector, Selector, SelectorOutp
829827
/// # type P2PGossipSync<UL> = lightning::routing::gossip::P2PGossipSync<Arc<NetworkGraph>, Arc<UL>, Arc<Logger>>;
830828
/// # type ChannelManager<B, F, FE> = lightning::ln::channelmanager::SimpleArcChannelManager<ChainMonitor<B, F, FE>, B, FE, Logger>;
831829
/// # type OnionMessenger<B, F, FE> = lightning::onion_message::messenger::OnionMessenger<Arc<lightning::sign::KeysManager>, Arc<lightning::sign::KeysManager>, Arc<Logger>, Arc<ChannelManager<B, F, FE>>, Arc<lightning::onion_message::messenger::DefaultMessageRouter<Arc<NetworkGraph>, Arc<Logger>, Arc<lightning::sign::KeysManager>>>, Arc<ChannelManager<B, F, FE>>, lightning::ln::peer_handler::IgnoringMessageHandler, lightning::ln::peer_handler::IgnoringMessageHandler, lightning::ln::peer_handler::IgnoringMessageHandler>;
832-
/// # type LiquidityManager<B, F, FE> = lightning_liquidity::LiquidityManager<Arc<lightning::sign::KeysManager>, Arc<lightning::sign::KeysManager>, Arc<ChannelManager<B, F, FE>>, Arc<F>, Arc<Store>, Arc<DefaultTimeProvider>, Arc<B>>;
830+
/// # type LiquidityManager<B, F, FE> = lightning_liquidity::LiquidityManager<Arc<lightning::sign::KeysManager>, Arc<lightning::sign::KeysManager>, Arc<ChannelManager<B, F, FE>>, Arc<Store>, Arc<DefaultTimeProvider>, Arc<B>>;
833831
/// # type Scorer = RwLock<lightning::routing::scoring::ProbabilisticScorer<Arc<NetworkGraph>, Arc<Logger>>>;
834832
/// # type PeerManager<B, F, FE, UL> = lightning::ln::peer_handler::SimpleArcPeerManager<SocketDescriptor, ChainMonitor<B, F, FE>, B, FE, Arc<UL>, Logger, F, StoreSync>;
835833
/// # type OutputSweeper<B, D, FE, F, O> = lightning::util::sweep::OutputSweeper<Arc<B>, Arc<D>, Arc<FE>, Arc<F>, Arc<Store>, Arc<Logger>, Arc<O>>;
@@ -1898,7 +1896,7 @@ mod tests {
18981896
use core::sync::atomic::{AtomicBool, Ordering};
18991897
use lightning::chain::channelmonitor::ANTI_REORG_DELAY;
19001898
use lightning::chain::transaction::OutPoint;
1901-
use lightning::chain::{chainmonitor, BestBlock, Confirm, Filter};
1899+
use lightning::chain::{chainmonitor, BestBlock, Confirm};
19021900
use lightning::events::{Event, PathFailure, ReplayEvent};
19031901
use lightning::ln::channelmanager;
19041902
use lightning::ln::channelmanager::{
@@ -2054,7 +2052,6 @@ mod tests {
20542052
Arc<KeysManager>,
20552053
Arc<KeysManager>,
20562054
Arc<ChannelManager>,
2057-
Arc<dyn Filter + Sync + Send>,
20582055
Arc<Persister>,
20592056
DefaultTimeProvider,
20602057
Arc<test_utils::TestBroadcaster>,
@@ -2513,8 +2510,6 @@ mod tests {
25132510
Arc::clone(&keys_manager),
25142511
Arc::clone(&keys_manager),
25152512
Arc::clone(&manager),
2516-
None,
2517-
None,
25182513
Arc::clone(&kv_store),
25192514
Arc::clone(&tx_broadcaster),
25202515
None,
@@ -2910,10 +2905,10 @@ mod tests {
29102905
let kv_store = KVStoreSyncWrapper(kv_store_sync);
29112906

29122907
// Yes, you can unsafe { turn off the borrow checker }
2913-
let lm_async: &'static LiquidityManager<_, _, _, _, _, _, _> = unsafe {
2908+
let lm_async: &'static LiquidityManager<_, _, _, _, _, _> = unsafe {
29142909
&*(nodes[0].liquidity_manager.get_lm_async()
2915-
as *const LiquidityManager<_, _, _, _, _, _, _>)
2916-
as &'static LiquidityManager<_, _, _, _, _, _, _>
2910+
as *const LiquidityManager<_, _, _, _, _, _>)
2911+
as &'static LiquidityManager<_, _, _, _, _, _>
29172912
};
29182913
let sweeper_async: &'static OutputSweeper<_, _, _, _, _, _, _> = unsafe {
29192914
&*(nodes[0].sweeper.sweeper_async() as *const OutputSweeper<_, _, _, _, _, _, _>)
@@ -3435,10 +3430,10 @@ mod tests {
34353430
let kv_store = KVStoreSyncWrapper(kv_store_sync);
34363431

34373432
// Yes, you can unsafe { turn off the borrow checker }
3438-
let lm_async: &'static LiquidityManager<_, _, _, _, _, _, _> = unsafe {
3433+
let lm_async: &'static LiquidityManager<_, _, _, _, _, _> = unsafe {
34393434
&*(nodes[0].liquidity_manager.get_lm_async()
3440-
as *const LiquidityManager<_, _, _, _, _, _, _>)
3441-
as &'static LiquidityManager<_, _, _, _, _, _, _>
3435+
as *const LiquidityManager<_, _, _, _, _, _>)
3436+
as &'static LiquidityManager<_, _, _, _, _, _>
34423437
};
34433438
let sweeper_async: &'static OutputSweeper<_, _, _, _, _, _, _> = unsafe {
34443439
&*(nodes[0].sweeper.sweeper_async() as *const OutputSweeper<_, _, _, _, _, _, _>)
@@ -3662,10 +3657,10 @@ mod tests {
36623657
let (exit_sender, exit_receiver) = tokio::sync::watch::channel(());
36633658

36643659
// Yes, you can unsafe { turn off the borrow checker }
3665-
let lm_async: &'static LiquidityManager<_, _, _, _, _, _, _> = unsafe {
3660+
let lm_async: &'static LiquidityManager<_, _, _, _, _, _> = unsafe {
36663661
&*(nodes[0].liquidity_manager.get_lm_async()
3667-
as *const LiquidityManager<_, _, _, _, _, _, _>)
3668-
as &'static LiquidityManager<_, _, _, _, _, _, _>
3662+
as *const LiquidityManager<_, _, _, _, _, _>)
3663+
as &'static LiquidityManager<_, _, _, _, _, _>
36693664
};
36703665
let sweeper_async: &'static OutputSweeper<_, _, _, _, _, _, _> = unsafe {
36713666
&*(nodes[0].sweeper.sweeper_async() as *const OutputSweeper<_, _, _, _, _, _, _>)

lightning-liquidity/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ parking_lot = { version = "0.12", default-features = false }
4646
level = "forbid"
4747
# When adding a new cfg attribute, ensure that it is added to this list.
4848
check-cfg = [
49-
"cfg(lsps1_service)",
5049
"cfg(c_bindings)",
5150
"cfg(backtrace)",
5251
"cfg(ldk_bench)",

lightning-liquidity/src/events/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ pub enum LiquidityEvent {
3333
/// An LSPS1 (Channel Request) client event.
3434
LSPS1Client(lsps1::event::LSPS1ClientEvent),
3535
/// An LSPS1 (Channel Request) server event.
36-
#[cfg(lsps1_service)]
3736
LSPS1Service(lsps1::event::LSPS1ServiceEvent),
3837
/// An LSPS2 (JIT Channel) client event.
3938
LSPS2Client(lsps2::event::LSPS2ClientEvent),
@@ -57,7 +56,6 @@ impl From<lsps1::event::LSPS1ClientEvent> for LiquidityEvent {
5756
}
5857
}
5958

60-
#[cfg(lsps1_service)]
6159
impl From<lsps1::event::LSPS1ServiceEvent> for LiquidityEvent {
6260
fn from(event: lsps1::event::LSPS1ServiceEvent) -> Self {
6361
Self::LSPS1Service(event)

lightning-liquidity/src/lsps1/event.rs

Lines changed: 11 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use super::msgs::{LSPS1ChannelInfo, LSPS1Options, LSPS1OrderParams, LSPS1Payment
1515
use crate::lsps0::ser::{LSPSRequestId, LSPSResponseError};
1616

1717
use bitcoin::secp256k1::PublicKey;
18+
use bitcoin::Address;
1819

1920
/// An event which an bLIP-51 / LSPS1 client should take some action in response to.
2021
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -142,7 +143,6 @@ pub enum LSPS1ClientEvent {
142143
}
143144

144145
/// An event which an LSPS1 server should take some action in response to.
145-
#[cfg(lsps1_service)]
146146
#[derive(Clone, Debug, PartialEq, Eq)]
147147
pub enum LSPS1ServiceEvent {
148148
/// A client has selected the parameters to use from the supported options of the LSP
@@ -152,9 +152,13 @@ pub enum LSPS1ServiceEvent {
152152
/// send order parameters including the details regarding the
153153
/// payment and order id for this order for the client.
154154
///
155+
/// You should call [`LSPS1ServiceHandler::invalid_token_provided`] if the token provided as
156+
/// part of the order parameters is invalid.
157+
///
155158
/// **Note: ** This event will *not* be persisted across restarts.
156159
///
157160
/// [`LSPS1ServiceHandler::send_payment_details`]: crate::lsps1::service::LSPS1ServiceHandler::send_payment_details
161+
/// [`LSPS1ServiceHandler::invalid_token_provided`]: crate::lsps1::service::LSPS1ServiceHandler::invalid_token_provided
158162
RequestForPaymentDetails {
159163
/// An identifier that must be passed to [`LSPS1ServiceHandler::send_payment_details`].
160164
///
@@ -164,36 +168,12 @@ pub enum LSPS1ServiceEvent {
164168
counterparty_node_id: PublicKey,
165169
/// The order requested by the client.
166170
order: LSPS1OrderParams,
167-
},
168-
/// A request from client to check the status of the payment.
169-
///
170-
/// An event to poll for checking payment status either onchain or lightning.
171-
///
172-
/// You must call [`LSPS1ServiceHandler::update_order_status`] to update the client
173-
/// regarding the status of the payment and order.
174-
///
175-
/// **Note: ** This event will *not* be persisted across restarts.
176-
///
177-
/// [`LSPS1ServiceHandler::update_order_status`]: crate::lsps1::service::LSPS1ServiceHandler::update_order_status
178-
CheckPaymentConfirmation {
179-
/// An identifier that must be passed to [`LSPS1ServiceHandler::update_order_status`].
171+
/// The address we need to send onchain refunds to in case channel opening fails.
180172
///
181-
/// [`LSPS1ServiceHandler::update_order_status`]: crate::lsps1::service::LSPS1ServiceHandler::update_order_status
182-
request_id: LSPSRequestId,
183-
/// The node id of the client making the information request.
184-
counterparty_node_id: PublicKey,
185-
/// The order id of order with pending payment.
186-
order_id: LSPS1OrderId,
187-
},
188-
/// If error is encountered, refund the amount if paid by the client.
189-
///
190-
/// **Note: ** This event will *not* be persisted across restarts.
191-
Refund {
192-
/// An identifier.
193-
request_id: LSPSRequestId,
194-
/// The node id of the client making the information request.
195-
counterparty_node_id: PublicKey,
196-
/// The order id of the refunded order.
197-
order_id: LSPS1OrderId,
173+
/// If this is `None` and you *require* onchain payment, you should call
174+
/// [`LSPS1ServiceHandler::onchain_payments_required`] to reject the request.
175+
///
176+
/// [`LSPS1ServiceHandler::onchain_payments_required`]: crate::lsps1::service::LSPS1ServiceHandler::onchain_payments_required
177+
refund_onchain_address: Option<Address>,
198178
},
199179
}

lightning-liquidity/src/lsps1/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
pub mod client;
1313
pub mod event;
1414
pub mod msgs;
15-
#[cfg(lsps1_service)]
15+
pub(crate) mod peer_state;
1616
pub mod service;

lightning-liquidity/src/lsps1/msgs.rs

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ use crate::lsps0::ser::{
1919
};
2020

2121
use bitcoin::{Address, FeeRate, OutPoint};
22-
2322
use lightning::offers::offer::Offer;
23+
use lightning::util::ser::{Readable, Writeable};
24+
use lightning::{impl_writeable_tlv_based, impl_writeable_tlv_based_enum};
2425
use lightning_invoice::Bolt11Invoice;
2526

2627
use serde::{Deserialize, Serialize};
@@ -30,13 +31,31 @@ pub(crate) const LSPS1_CREATE_ORDER_METHOD_NAME: &str = "lsps1.create_order";
3031
pub(crate) const LSPS1_GET_ORDER_METHOD_NAME: &str = "lsps1.get_order";
3132

3233
pub(crate) const _LSPS1_CREATE_ORDER_REQUEST_INVALID_PARAMS_ERROR_CODE: i32 = -32602;
33-
#[cfg(lsps1_service)]
34-
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_ORDER_MISMATCH_ERROR_CODE: i32 = 100;
34+
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_OPTION_MISMATCH_ERROR_CODE: i32 = 100;
35+
pub(crate) const LSPS1_GET_ORDER_REQUEST_ORDER_NOT_FOUND_ERROR_CODE: i32 = 101;
36+
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE: i32 = 102;
3537

3638
/// The identifier of an order.
3739
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Hash)]
3840
pub struct LSPS1OrderId(pub String);
3941

42+
impl Writeable for LSPS1OrderId {
43+
fn write<W: lightning::util::ser::Writer>(
44+
&self, writer: &mut W,
45+
) -> Result<(), lightning::io::Error> {
46+
self.0.write(writer)
47+
}
48+
}
49+
50+
impl Readable for LSPS1OrderId {
51+
fn read<R: bitcoin::io::Read>(
52+
reader: &mut R,
53+
) -> Result<Self, lightning::ln::msgs::DecodeError> {
54+
let inner = Readable::read(reader)?;
55+
Ok(Self(inner))
56+
}
57+
}
58+
4059
/// A request made to an LSP to retrieve the supported options.
4160
///
4261
/// Please refer to the [bLIP-51 / LSPS1
@@ -126,6 +145,16 @@ pub struct LSPS1OrderParams {
126145
pub announce_channel: bool,
127146
}
128147

148+
impl_writeable_tlv_based!(LSPS1OrderParams, {
149+
(0, lsp_balance_sat, required),
150+
(2, client_balance_sat, required),
151+
(4, required_channel_confirmations, required),
152+
(6, funding_confirms_within_blocks, required),
153+
(8, channel_expiry_blocks, required),
154+
(10, token, option),
155+
(12, announce_channel, required),
156+
});
157+
129158
/// A response to a [`LSPS1CreateOrderRequest`].
130159
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
131160
pub struct LSPS1CreateOrderResponse {
@@ -156,6 +185,12 @@ pub enum LSPS1OrderState {
156185
Failed,
157186
}
158187

188+
impl_writeable_tlv_based_enum!(LSPS1OrderState,
189+
(0, Created) => {},
190+
(2, Completed) => {},
191+
(4, Failed) => {}
192+
);
193+
159194
/// Details regarding how to pay for an order.
160195
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
161196
pub struct LSPS1PaymentInfo {
@@ -167,6 +202,12 @@ pub struct LSPS1PaymentInfo {
167202
pub onchain: Option<LSPS1OnchainPaymentInfo>,
168203
}
169204

205+
impl_writeable_tlv_based!(LSPS1PaymentInfo, {
206+
(0, bolt11, option),
207+
(2, bolt12, option),
208+
(4, onchain, option),
209+
});
210+
170211
/// A Lightning payment using BOLT 11.
171212
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
172213
pub struct LSPS1Bolt11PaymentInfo {
@@ -184,6 +225,14 @@ pub struct LSPS1Bolt11PaymentInfo {
184225
pub invoice: Bolt11Invoice,
185226
}
186227

228+
impl_writeable_tlv_based!(LSPS1Bolt11PaymentInfo, {
229+
(0, state, required),
230+
(2, expires_at, required),
231+
(4, fee_total_sat, required),
232+
(6, order_total_sat, required),
233+
(8, invoice, required),
234+
});
235+
187236
/// A Lightning payment using BOLT 12.
188237
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
189238
pub struct LSPS1Bolt12PaymentInfo {
@@ -202,6 +251,14 @@ pub struct LSPS1Bolt12PaymentInfo {
202251
pub offer: Offer,
203252
}
204253

254+
impl_writeable_tlv_based!(LSPS1Bolt12PaymentInfo, {
255+
(0, state, required),
256+
(2, expires_at, required),
257+
(4, fee_total_sat, required),
258+
(6, order_total_sat, required),
259+
(8, offer, required),
260+
});
261+
205262
/// An onchain payment.
206263
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
207264
pub struct LSPS1OnchainPaymentInfo {
@@ -233,6 +290,17 @@ pub struct LSPS1OnchainPaymentInfo {
233290
pub refund_onchain_address: Option<Address>,
234291
}
235292

293+
impl_writeable_tlv_based!(LSPS1OnchainPaymentInfo, {
294+
(0, state, required),
295+
(2, expires_at, required),
296+
(4, fee_total_sat, required),
297+
(6, order_total_sat, required),
298+
(8, address, required),
299+
(10, min_onchain_payment_confirmations, option),
300+
(12, min_fee_for_0conf, required),
301+
(14, refund_onchain_address, option),
302+
});
303+
236304
/// The state of a payment.
237305
///
238306
/// *Note*: Previously, the spec also knew a `CANCELLED` state for BOLT11 payments, which has since
@@ -242,24 +310,24 @@ pub struct LSPS1OnchainPaymentInfo {
242310
pub enum LSPS1PaymentState {
243311
/// A payment is expected.
244312
ExpectPayment,
245-
/// A sufficient payment has been received.
313+
/// A payment has been received but the channel has not yet been opened.
314+
///
315+
/// This indicates the LSP has received the payment (e.g., Lightning HTLC held,
316+
/// or on-chain transaction detected) but has not yet published the funding transaction.
317+
Hold,
318+
/// A sufficient payment has been received and the channel has been opened.
246319
Paid,
247320
/// The payment has been refunded.
248321
#[serde(alias = "CANCELLED")]
249322
Refunded,
250323
}
251324

252-
/// Details regarding a detected on-chain payment.
253-
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
254-
pub struct LSPS1OnchainPayment {
255-
/// The outpoint of the payment.
256-
pub outpoint: String,
257-
/// The amount of satoshi paid.
258-
#[serde(with = "string_amount")]
259-
pub sat: u64,
260-
/// Indicates if the LSP regards the transaction as sufficiently confirmed.
261-
pub confirmed: bool,
262-
}
325+
impl_writeable_tlv_based_enum!(LSPS1PaymentState,
326+
(0, ExpectPayment) => {},
327+
(2, Hold) => {},
328+
(4, Paid) => {},
329+
(6, Refunded) => {}
330+
);
263331

264332
/// Details regarding the state of an ordered channel.
265333
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
@@ -272,6 +340,12 @@ pub struct LSPS1ChannelInfo {
272340
pub expires_at: LSPSDateTime,
273341
}
274342

343+
impl_writeable_tlv_based!(LSPS1ChannelInfo, {
344+
(0, funded_at, required),
345+
(2, funding_outpoint, required),
346+
(4, expires_at, required),
347+
});
348+
275349
/// A request made to an LSP to retrieve information about an previously made order.
276350
///
277351
/// Please refer to the [bLIP-51 / LSPS1

0 commit comments

Comments
 (0)