Skip to content

LSPS2: Add support for ongoing proportional fees #3846

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

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lightning-liquidity/src/lsps2/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ where
request_id,
counterparty_node_id: *counterparty_node_id,
opening_fee_params_menu: result.opening_fee_params_menu,
ongoing_proportional: result.ongoing_proportional,
});
},
None => {
Expand Down
2 changes: 2 additions & 0 deletions lightning-liquidity/src/lsps2/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ pub enum LSPS2ClientEvent {
/// The menu of fee parameters the LSP is offering at this time.
/// You must select one of these if you wish to proceed.
opening_fee_params_menu: Vec<LSPS2OpeningFeeParams>,
/// A flag indicating whether the LSP will collect ongoing proportional fees after the initial channel is opened.
ongoing_proportional: bool,
},
/// Provides the necessary information to generate a payable invoice that then may be given to
/// the payer.
Expand Down
9 changes: 7 additions & 2 deletions lightning-liquidity/src/lsps2/msgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ pub struct LSPS2OpeningFeeParams {
pub struct LSPS2GetInfoResponse {
/// A set of opening fee parameters.
pub opening_fee_params_menu: Vec<LSPS2OpeningFeeParams>,
/// A flag for whether ongoing proportional fees will be collected.
pub ongoing_proportional: bool,
}

/// A request to buy a JIT channel.
Expand Down Expand Up @@ -348,6 +350,7 @@ mod tests {
let max_client_to_self_delay = 128;
let min_payment_size_msat = 1;
let max_payment_size_msat = 100_000_000;
let ongoing_proportional = true;

let raw = LSPS2RawOpeningFeeParams {
min_fee_msat,
Expand Down Expand Up @@ -382,7 +385,7 @@ mod tests {
assert_eq!(buy_request_variable, serde_json::from_str(json_str).unwrap());

// Check we still deserialize correctly if payment_size_msat is 'null'.
let json_str = r#"{"opening_fee_params":{"max_client_to_self_delay":128,"max_payment_size_msat":"100000000","min_fee_msat":"100","min_lifetime":144,"min_payment_size_msat":"1","promise":"1134a5c51e3ba2e8f4259610d5e12c1bf4c50ddcd3f8af563e0a00d1fff41dea","proportional":21,"valid_until":"2023-05-20T08:30:45Z"},"payment_size_msat":null}"#;
let json_str = r#"{"opening_fee_params":{"max_client_to_self_delay":128,"max_payment_size_msat":"100000000","min_fee_msat":"100","min_lifetime":144,"min_payment_size_msat":"1","promise":"1134a5c51e3ba2e8f4259610d5e12c1bf4c50ddcd3f8af563e0a00d1fff41dea","proportional":21,"valid_until":"2023-05-20T08:30:45Z"},"ongoing_proportional":true,"payment_size_msat":null}"#;
assert_eq!(buy_request_variable, serde_json::from_str(json_str).unwrap());
}

Expand Down Expand Up @@ -411,7 +414,8 @@ mod tests {
"max_payment_size_msat": "1000000",
"promise": "abcdefghijklmnopqrstuvwxyz"
}
]
],
"ongoing_proportional": true
}"#;
let _get_info_response: LSPS2GetInfoResponse = serde_json::from_str(json_str).unwrap();

Expand All @@ -426,6 +430,7 @@ mod tests {
"max_payment_size_msat": "1000000",
"promise": "abcdefghijklmnopqrstuvwxyz"
},
"ongoing_proportional": true,
"payment_size_msat": "42000"
}"#;
let _buy_request: LSPS2BuyRequest = serde_json::from_str(json_str).unwrap();
Expand Down
3 changes: 2 additions & 1 deletion lightning-liquidity/src/lsps2/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,7 +634,7 @@ where
/// [`LSPS2ServiceEvent::GetInfo`]: crate::lsps2::event::LSPS2ServiceEvent::GetInfo
pub fn opening_fee_params_generated(
&self, counterparty_node_id: &PublicKey, request_id: LSPSRequestId,
opening_fee_params_menu: Vec<LSPS2RawOpeningFeeParams>,
opening_fee_params_menu: Vec<LSPS2RawOpeningFeeParams>, ongoing_proportional: bool,
) -> Result<(), APIError> {
let (result, response) = {
let outer_state_lock = self.per_peer_state.read().unwrap();
Expand All @@ -652,6 +652,7 @@ where
param.into_opening_fee_params(&self.config.promise_secret)
})
.collect(),
ongoing_proportional,
});
(Ok(()), Some(response))
},
Expand Down
22 changes: 21 additions & 1 deletion lightning-liquidity/tests/lsps2_integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,11 +154,14 @@ fn invoice_generation_flow() {
max_payment_size_msat: 100_000_000,
};

let ongoing_proportional = true;

service_handler
.opening_fee_params_generated(
&client_node_id,
get_info_request_id.clone(),
vec![raw_opening_params],
ongoing_proportional,
)
.unwrap();
let get_info_response = get_lsps_message!(service_node, client_node_id);
Expand All @@ -174,9 +177,11 @@ fn invoice_generation_flow() {
request_id,
counterparty_node_id,
opening_fee_params_menu,
ongoing_proportional,
}) => {
assert_eq!(request_id, get_info_request_id);
assert_eq!(counterparty_node_id, service_node_id);
assert_eq!(ongoing_proportional, ongoing_proportional);
let opening_fee_params = opening_fee_params_menu.first().unwrap().clone();
assert!(is_valid_opening_fee_params(&opening_fee_params, &promise_secret));
opening_fee_params
Expand Down Expand Up @@ -282,11 +287,15 @@ fn channel_open_failed() {
min_payment_size_msat: 1,
max_payment_size_msat: 100_000_000,
};

let ongoing_proportional = true;

service_handler
.opening_fee_params_generated(
&client_node_id,
get_info_request_id.clone(),
vec![raw_opening_params],
ongoing_proportional,
)
.unwrap();

Expand Down Expand Up @@ -430,11 +439,14 @@ fn channel_open_abandoned() {
min_payment_size_msat: 1,
max_payment_size_msat: 100_000_000,
};
let ongoing_proportional = true;

service_handler
.opening_fee_params_generated(
&client_node_id,
get_info_request_id.clone(),
vec![raw_opening_params],
ongoing_proportional,
)
.unwrap();

Expand Down Expand Up @@ -584,9 +596,15 @@ fn max_total_requests_buy_rejected() {
min_payment_size_msat: 1,
max_payment_size_msat: 100_000_000,
};
let ongoing_proportional = true;

service_handler
.opening_fee_params_generated(&special_node_id, request_id, vec![raw_opening_params])
.opening_fee_params_generated(
&special_node_id,
request_id,
vec![raw_opening_params],
ongoing_proportional,
)
.unwrap();
} else {
panic!("Unexpected event");
Expand Down Expand Up @@ -713,11 +731,13 @@ fn invalid_token_flow() {
min_payment_size_msat: 1,
max_payment_size_msat: 100_000_000,
};
let ongoing_proportional = true;

let result = service_handler.opening_fee_params_generated(
&client_node_id,
request_id.clone(),
vec![raw_opening_params],
ongoing_proportional,
);

assert!(result.is_err(), "Request should have been removed from pending_requests");
Expand Down
Loading