Skip to content

Commit 98f71f5

Browse files
committed
Add onchain_payment_required method
We previously had no way to reject requests in case the LSP requires onchain payment while the client not providing `refund_onchain_address`. Here we add a method allowing to do so.
1 parent c0cef54 commit 98f71f5

3 files changed

Lines changed: 58 additions & 7 deletions

File tree

lightning-liquidity/src/lsps1/event.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,8 +170,10 @@ pub enum LSPS1ServiceEvent {
170170
order: LSPS1OrderParams,
171171
/// The address we need to send onchain refunds to in case channel opening fails.
172172
///
173-
/// Please note that you can't offer onchain payments if this was not provided by the
174-
/// client.
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
175177
refund_onchain_address: Option<Address>,
176178
},
177179
}

lightning-liquidity/src/lsps1/msgs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub(crate) const LSPS1_CREATE_ORDER_METHOD_NAME: &str = "lsps1.create_order";
3131
pub(crate) const LSPS1_GET_ORDER_METHOD_NAME: &str = "lsps1.get_order";
3232

3333
pub(crate) const _LSPS1_CREATE_ORDER_REQUEST_INVALID_PARAMS_ERROR_CODE: i32 = -32602;
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;
3535
pub(crate) const LSPS1_GET_ORDER_REQUEST_ORDER_NOT_FOUND_ERROR_CODE: i32 = 101;
3636
pub(crate) const LSPS1_CREATE_ORDER_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE: i32 = 102;
3737

lightning-liquidity/src/lsps1/service.rs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use super::msgs::{
2323
LSPS1ChannelInfo, LSPS1CreateOrderRequest, LSPS1CreateOrderResponse, LSPS1GetInfoResponse,
2424
LSPS1GetOrderRequest, LSPS1Message, LSPS1Options, LSPS1OrderId, LSPS1OrderParams,
2525
LSPS1PaymentInfo, LSPS1PaymentState, LSPS1Request, LSPS1Response,
26-
LSPS1_CREATE_ORDER_REQUEST_ORDER_MISMATCH_ERROR_CODE,
26+
LSPS1_CREATE_ORDER_REQUEST_OPTION_MISMATCH_ERROR_CODE,
2727
LSPS1_CREATE_ORDER_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE,
2828
LSPS1_GET_ORDER_REQUEST_ORDER_NOT_FOUND_ERROR_CODE,
2929
};
@@ -291,7 +291,7 @@ where
291291

292292
if !is_valid(&params.order, &self.config.supported_options) {
293293
let response = LSPS1Response::CreateOrderError(LSPSResponseError {
294-
code: LSPS1_CREATE_ORDER_REQUEST_ORDER_MISMATCH_ERROR_CODE,
294+
code: LSPS1_CREATE_ORDER_REQUEST_OPTION_MISMATCH_ERROR_CODE,
295295
message: "Order does not match options supported by LSP server".to_string(),
296296
data: Some(format!("Supported options are {:?}", &self.config.supported_options)),
297297
});
@@ -337,7 +337,8 @@ where
337337
/// Should be called in response to receiving a [`LSPS1ServiceEvent::RequestForPaymentDetails`] event.
338338
///
339339
/// Note that the provided `payment_details` can't include the onchain payment variant if the
340-
/// user didn't provide a `refund_onchain_address`.
340+
/// user didn't provide a `refund_onchain_address`. If you *require* onchain payments, you need
341+
/// to call [`Self::onchain_payments_required`] to reject the request.
341342
///
342343
/// [`LSPS1ServiceEvent::RequestForPaymentDetails`]: crate::lsps1::event::LSPS1ServiceEvent::RequestForPaymentDetails
343344
pub async fn send_payment_details(
@@ -496,6 +497,45 @@ where
496497
}
497498
}
498499

500+
/// Used by LSP to inform a client that an order was rejected because they require onchain
501+
/// payments and the client didn't provide a `refund_onchain_address`.
502+
///
503+
/// Should be called in response to receiving a [`LSPS1ServiceEvent::RequestForPaymentDetails`]
504+
/// event if the LSP requires onchain payments and `refund_onchain_address` is `None`.
505+
///
506+
/// [`LSPS1ServiceEvent::RequestForPaymentDetails`]: crate::lsps1::event::LSPS1ServiceEvent::RequestForPaymentDetails
507+
pub fn onchain_payments_required(
508+
&self, counterparty_node_id: PublicKey, request_id: LSPSRequestId,
509+
) -> Result<(), APIError> {
510+
let mut message_queue_notifier = self.pending_messages.notifier();
511+
512+
match self.per_peer_state.read().unwrap().get(&counterparty_node_id) {
513+
Some(inner_state_lock) => {
514+
let mut peer_state_lock = inner_state_lock.lock().unwrap();
515+
peer_state_lock.remove_request(&request_id).map_err(|e| {
516+
debug_assert!(false, "Failed to send response due to: {}", e);
517+
let err = format!("Failed to send response due to: {}", e);
518+
APIError::APIMisuseError { err }
519+
})?;
520+
521+
let response = LSPS1Response::CreateOrderError(LSPSResponseError {
522+
code: LSPS1_CREATE_ORDER_REQUEST_OPTION_MISMATCH_ERROR_CODE,
523+
message:
524+
"We require onchain payment but no `refund_onchain_address` was provided"
525+
.to_string(),
526+
data: None,
527+
});
528+
529+
let msg = LSPS1Message::Response(request_id, response).into();
530+
message_queue_notifier.enqueue(&counterparty_node_id, msg);
531+
Ok(())
532+
},
533+
None => Err(APIError::APIMisuseError {
534+
err: format!("No state for the counterparty exists: {}", counterparty_node_id),
535+
}),
536+
}
537+
}
538+
499539
fn handle_get_order_request(
500540
&self, request_id: LSPSRequestId, counterparty_node_id: &PublicKey,
501541
params: LSPS1GetOrderRequest,
@@ -640,7 +680,6 @@ where
640680
/// Marks an order as failed and refunded.
641681
///
642682
/// This should be called when:
643-
/// - We require onchain payment and the client didn't provide a `refund_onchain_address`.
644683
/// - The order expires without payment
645684
/// - The channel open fails after payment and the LSP must refund
646685
pub async fn order_failed_and_refunded(
@@ -782,6 +821,16 @@ where
782821
self.inner.invalid_token_provided(counterparty_node_id, request_id)
783822
}
784823

824+
/// Used by LSP to inform a client that an order was rejected because they require onchain
825+
/// payments and the client didn't provide a `refund_onchain_address`.
826+
///
827+
/// Wraps [`LSPS1ServiceHandler::onchain_payments_required`].
828+
pub fn onchain_payments_required(
829+
&self, counterparty_node_id: PublicKey, request_id: LSPSRequestId,
830+
) -> Result<(), APIError> {
831+
self.inner.onchain_payments_required(counterparty_node_id, request_id)
832+
}
833+
785834
/// Marks an order as paid after payment has been received.
786835
///
787836
/// Wraps [`LSPS1ServiceHandler::order_payment_received`].

0 commit comments

Comments
 (0)