Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 480
lightning-liquidity: Refactor LSPS1 service-side#4282
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
TheBlueMatt
merged 35 commits into
lightningdevkit:main
from
tnull:2025-11-lsps1-refactorMar 18, 2026
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
a024a76
LSPS1: Add initial integration test
martinsaposnic 9a64a65
Cleanup unused code
tnull 0d7408b
Drop `chain_source` from `LSPS1ServiceHandler`
tnull 8ad5101
Drop `Listen`/`Confirm`/etc from `LiquidityManager`
tnull c6465f2
Move `PeerState` and related types to `peer_state.rs` module
tnull fa867c2
Drop bogus channel state handling
tnull 0c8e26a
Replace `insert_outbound_channel` with `PeerState::new_order`
tnull bc8deb3
Use `PeerState::{get_order, has_active_orders}` instead of map
tnull 1513004
Use `PeerState::{register,remove}_request` instead of map access
tnull 9cc5257
Drop `OutboundCRChannel`
tnull eb21bfd
Actually remember the order state in `ChannelOrder`
tnull 5db2fcc
`LSPS1ServiceHandler`: Use `TimeProvider` when creating new orders
tnull 7adf954
Require `supported_options` in `LSPS1ServiceConfig`
tnull a7f3888
Respond to `GetOrder` requests from our saved state
tnull 38775f7
Add serialization logic for LSPS1 `PeerState` types
tnull d33a701
Implement `LSPS1ServiceHandler` persistence and state pruning
tnull 58faa5e
Read persisted LSPS1ServiceHandler state on startup
tnull b7b2f7e
Add test case asserting `LSPS1ServiceState` is persisted across restarts
tnull 8304ebe
Add some checks on provided payment details
tnull d210b88
Don't hold write lock in `LSPS{1,2}ServiceHandler::peer_disconnected`
tnull f043b2e
Add `invalid_token_provided` API method
tnull be5c2c1
Add test case for `invalid_token_provided` flow
tnull 2322385
Drop `lsps1_service` cfg flag
tnull ed9a867
Fix clippy lints
tnull c7db17d
Refactor `ChannelOrder` to use `ChannelOrderState` state machine
tnull c5139d0
Add integration tests for LSPS1 order state transition API
tnull 2484873
Add integration test for expired order pruning
tnull 029ad80
Drop unused `LSPS1OnchainPayment` type
tnull 36e1198
Add `Hold` payment state per bLIP-51 spec
tnull c0cef54
Drop unused `LSPS1ServiceEvent::Refund` event
tnull 98f71f5
Add `onchain_payment_required` method
tnull b272235
Limit pending requests and peers in LSPS1 service
tnull 15dbb21
Reject clients if request registration failed (e.g., duplicative Id)
tnull 4bec6db
Validate all common fields in LSPS1 `is_valid` order check
tnull 47e5c04
Reset `persistence_in_flight` counter on error in LSPS1/LSPS2
tnull File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -12,5 +12,5 @@ | ||
| pub mod client; | ||
| pub mod event; | ||
| pub mod msgs; | ||
| #[cfg(lsps1_service)] | ||
| pub(crate) mod peer_state; | ||
| pub mod service; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -19,8 +19,9 @@ use crate::lsps0::ser::{ | ||
| }; | ||
| use bitcoin::{Address, FeeRate, OutPoint}; | ||
| use lightning::offers::offer::Offer; | ||
| use lightning::util::ser::{Readable, Writeable}; | ||
| use lightning::{impl_writeable_tlv_based, impl_writeable_tlv_based_enum}; | ||
| use lightning_invoice::Bolt11Invoice; | ||
| use serde::{Deserialize, Serialize}; | ||
| @@ -30,13 +31,31 @@ pub(crate) const LSPS1_CREATE_ORDER_METHOD_NAME: &str = "lsps1.create_order"; | ||
| pub(crate) const LSPS1_GET_ORDER_METHOD_NAME: &str = "lsps1.get_order"; | ||
| pub(crate) const _LSPS1_CREATE_ORDER_REQUEST_INVALID_PARAMS_ERROR_CODE: i32 = -32602; | ||
| #[cfg(lsps1_service)] | ||
| pub(crate) const LSPS1_CREATE_ORDER_REQUEST_ORDER_MISMATCH_ERROR_CODE: i32 = 100; | ||
| pub(crate) const LSPS1_CREATE_ORDER_REQUEST_OPTION_MISMATCH_ERROR_CODE: i32 = 100; | ||
| pub(crate) const LSPS1_GET_ORDER_REQUEST_ORDER_NOT_FOUND_ERROR_CODE: i32 = 101; | ||
| pub(crate) const LSPS1_CREATE_ORDER_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE: i32 = 102; | ||
| /// The identifier of an order. | ||
| #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Hash)] | ||
| pub struct LSPS1OrderId(pub String); | ||
| impl Writeable for LSPS1OrderId { | ||
| fn write<W: lightning::util::ser::Writer>( | ||
| &self, writer: &mut W, | ||
| ) -> Result<(), lightning::io::Error> { | ||
| self.0.write(writer) | ||
| } | ||
| } | ||
| impl Readable for LSPS1OrderId { | ||
| fn read<R: bitcoin::io::Read>( | ||
| reader: &mut R, | ||
| ) -> Result<Self, lightning::ln::msgs::DecodeError> { | ||
| let inner = Readable::read(reader)?; | ||
| Ok(Self(inner)) | ||
| } | ||
| } | ||
| /// A request made to an LSP to retrieve the supported options. | ||
| /// | ||
| /// Please refer to the [bLIP-51 / LSPS1 | ||
| @@ -126,6 +145,16 @@ pub struct LSPS1OrderParams { | ||
| pub announce_channel: bool, | ||
| } | ||
| impl_writeable_tlv_based!(LSPS1OrderParams, { | ||
| (0, lsp_balance_sat, required), | ||
| (2, client_balance_sat, required), | ||
| (4, required_channel_confirmations, required), | ||
| (6, funding_confirms_within_blocks, required), | ||
| (8, channel_expiry_blocks, required), | ||
| (10, token, option), | ||
| (12, announce_channel, required), | ||
| }); | ||
| /// A response to a [`LSPS1CreateOrderRequest`]. | ||
| #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
| pub struct LSPS1CreateOrderResponse { | ||
| @@ -156,6 +185,12 @@ pub enum LSPS1OrderState { | ||
| Failed, | ||
| } | ||
| impl_writeable_tlv_based_enum!(LSPS1OrderState, | ||
| (0, Created) => {}, | ||
| (2, Completed) => {}, | ||
| (4, Failed) => {} | ||
| ); | ||
| /// Details regarding how to pay for an order. | ||
| #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
| pub struct LSPS1PaymentInfo { | ||
| @@ -167,6 +202,12 @@ pub struct LSPS1PaymentInfo { | ||
| pub onchain: Option<LSPS1OnchainPaymentInfo>, | ||
| } | ||
| impl_writeable_tlv_based!(LSPS1PaymentInfo, { | ||
| (0, bolt11, option), | ||
| (2, bolt12, option), | ||
| (4, onchain, option), | ||
| }); | ||
| /// A Lightning payment using BOLT 11. | ||
| #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
| pub struct LSPS1Bolt11PaymentInfo { | ||
| @@ -184,6 +225,14 @@ pub struct LSPS1Bolt11PaymentInfo { | ||
| pub invoice: Bolt11Invoice, | ||
| } | ||
| impl_writeable_tlv_based!(LSPS1Bolt11PaymentInfo, { | ||
| (0, state, required), | ||
| (2, expires_at, required), | ||
| (4, fee_total_sat, required), | ||
| (6, order_total_sat, required), | ||
| (8, invoice, required), | ||
| }); | ||
| /// A Lightning payment using BOLT 12. | ||
| #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
| pub struct LSPS1Bolt12PaymentInfo { | ||
| @@ -202,6 +251,14 @@ pub struct LSPS1Bolt12PaymentInfo { | ||
| pub offer: Offer, | ||
| } | ||
| impl_writeable_tlv_based!(LSPS1Bolt12PaymentInfo, { | ||
| (0, state, required), | ||
| (2, expires_at, required), | ||
| (4, fee_total_sat, required), | ||
| (6, order_total_sat, required), | ||
| (8, offer, required), | ||
| }); | ||
| /// An onchain payment. | ||
| #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
| pub struct LSPS1OnchainPaymentInfo { | ||
| @@ -233,6 +290,17 @@ pub struct LSPS1OnchainPaymentInfo { | ||
| pub refund_onchain_address: Option<Address>, | ||
| } | ||
| impl_writeable_tlv_based!(LSPS1OnchainPaymentInfo, { | ||
| (0, state, required), | ||
| (2, expires_at, required), | ||
| (4, fee_total_sat, required), | ||
| (6, order_total_sat, required), | ||
| (8, address, required), | ||
| (10, min_onchain_payment_confirmations, option), | ||
| (12, min_fee_for_0conf, required), | ||
| (14, refund_onchain_address, option), | ||
| }); | ||
| /// The state of a payment. | ||
| /// | ||
| /// *Note*: Previously, the spec also knew a `CANCELLED` state for BOLT11 payments, which has since | ||
| @@ -242,24 +310,24 @@ pub struct LSPS1OnchainPaymentInfo { | ||
| pub enum LSPS1PaymentState { | ||
| /// A payment is expected. | ||
| ExpectPayment, | ||
| /// A sufficient payment has been received. | ||
| /// A payment has been received but the channel has not yet been opened. | ||
| /// | ||
| /// This indicates the LSP has received the payment (e.g., Lightning HTLC held, | ||
| /// or on-chain transaction detected) but has not yet published the funding transaction. | ||
| Hold, | ||
| /// A sufficient payment has been received and the channel has been opened. | ||
| Paid, | ||
| /// The payment has been refunded. | ||
| #[serde(alias = "CANCELLED")] | ||
| Refunded, | ||
| } | ||
tnull marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| /// Details regarding a detected on-chain payment. | ||
| #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
| pub struct LSPS1OnchainPayment { | ||
| /// The outpoint of the payment. | ||
| pub outpoint: String, | ||
| /// The amount of satoshi paid. | ||
| #[serde(with = "string_amount")] | ||
| pub sat: u64, | ||
| /// Indicates if the LSP regards the transaction as sufficiently confirmed. | ||
| pub confirmed: bool, | ||
| } | ||
| impl_writeable_tlv_based_enum!(LSPS1PaymentState, | ||
| (0, ExpectPayment) => {}, | ||
| (2, Hold) => {}, | ||
| (4, Paid) => {}, | ||
| (6, Refunded) => {} | ||
| ); | ||
| /// Details regarding the state of an ordered channel. | ||
| #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] | ||
| @@ -272,6 +340,12 @@ pub struct LSPS1ChannelInfo { | ||
| pub expires_at: LSPSDateTime, | ||
| } | ||
| impl_writeable_tlv_based!(LSPS1ChannelInfo, { | ||
| (0, funded_at, required), | ||
| (2, funding_outpoint, required), | ||
| (4, expires_at, required), | ||
| }); | ||
| /// A request made to an LSP to retrieve information about an previously made order. | ||
| /// | ||
| /// Please refer to the [bLIP-51 / LSPS1 | ||
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Oops, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.