Skip to content

Commit 3f2e232

Browse files
committed
LSPS2: Introduce MAX_PENDING_REQUESTS_PER_PEER service limit
We introduce a new `MAX_PENDING_REQUESTS_PER_PEER` limit for the number of pending (get_info and buy) requests per peer.
1 parent 7e42b36 commit 3f2e232

File tree

2 files changed

+88
-31
lines changed

2 files changed

+88
-31
lines changed

lightning-liquidity/src/lsps0/ser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ pub(crate) const JSONRPC_ERROR_FIELD_KEY: &str = "error";
4141
pub(crate) const JSONRPC_INVALID_MESSAGE_ERROR_CODE: i32 = -32700;
4242
pub(crate) const JSONRPC_INVALID_MESSAGE_ERROR_MESSAGE: &str = "parse error";
4343

44-
pub(crate) const _LSPS0_CLIENT_REJECTED_ERROR_CODE: i32 = 1;
44+
pub(crate) const LSPS0_CLIENT_REJECTED_ERROR_CODE: i32 = 1;
4545

4646
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
4747
pub(crate) enum LSPSMethod {

lightning-liquidity/src/lsps2/service.rs

Lines changed: 87 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
//! Contains the main LSPS2 server-side object, [`LSPS2ServiceHandler`].
1111
1212
use crate::events::{Event, EventQueue};
13-
use crate::lsps0::ser::{ProtocolMessageHandler, RequestId, ResponseError};
13+
use crate::lsps0::ser::{
14+
ProtocolMessageHandler, RequestId, ResponseError, LSPS0_CLIENT_REJECTED_ERROR_CODE,
15+
};
1416
use crate::lsps2::event::LSPS2ServiceEvent;
1517
use crate::lsps2::payment_queue::{InterceptedHTLC, PaymentQueue};
1618
use crate::lsps2::utils::{compute_opening_fee, is_valid_opening_fee_params};
@@ -40,6 +42,8 @@ use crate::lsps2::msgs::{
4042
LSPS2_GET_INFO_REQUEST_UNRECOGNIZED_OR_STALE_TOKEN_ERROR_CODE,
4143
};
4244

45+
const MAX_PENDING_REQUESTS_PER_PEER: usize = 10;
46+
4347
/// Server-side configuration options for JIT channels.
4448
#[derive(Clone, Debug)]
4549
pub struct LSPS2ServiceConfig {
@@ -982,21 +986,49 @@ where
982986
fn handle_get_info_request(
983987
&self, request_id: RequestId, counterparty_node_id: &PublicKey, params: GetInfoRequest,
984988
) -> Result<(), LightningError> {
985-
let mut outer_state_lock = self.per_peer_state.write().unwrap();
986-
let inner_state_lock: &mut Mutex<PeerState> =
987-
outer_state_lock.entry(*counterparty_node_id).or_insert(Mutex::new(PeerState::new()));
988-
let mut peer_state_lock = inner_state_lock.lock().unwrap();
989-
peer_state_lock
990-
.pending_requests
991-
.insert(request_id.clone(), LSPS2Request::GetInfo(params.clone()));
992-
993-
let event = Event::LSPS2Service(LSPS2ServiceEvent::GetInfo {
994-
request_id,
995-
counterparty_node_id: *counterparty_node_id,
996-
token: params.token,
997-
});
998-
self.pending_events.enqueue(event);
999-
Ok(())
989+
let (result, response) = {
990+
let mut outer_state_lock = self.per_peer_state.write().unwrap();
991+
let inner_state_lock: &mut Mutex<PeerState> = outer_state_lock
992+
.entry(*counterparty_node_id)
993+
.or_insert(Mutex::new(PeerState::new()));
994+
let mut peer_state_lock = inner_state_lock.lock().unwrap();
995+
if peer_state_lock.pending_requests.len() < MAX_PENDING_REQUESTS_PER_PEER {
996+
peer_state_lock
997+
.pending_requests
998+
.insert(request_id.clone(), LSPS2Request::GetInfo(params.clone()));
999+
1000+
let event = Event::LSPS2Service(LSPS2ServiceEvent::GetInfo {
1001+
request_id,
1002+
counterparty_node_id: *counterparty_node_id,
1003+
token: params.token,
1004+
});
1005+
self.pending_events.enqueue(event);
1006+
(Ok(()), None)
1007+
} else {
1008+
let response = LSPS2Response::GetInfoError(ResponseError {
1009+
code: LSPS0_CLIENT_REJECTED_ERROR_CODE,
1010+
message: "Reached maximum number of pending requests. Please try again later."
1011+
.to_string(),
1012+
data: None,
1013+
});
1014+
let msg = Some(LSPS2Message::Response(request_id, response).into());
1015+
1016+
let err = format!(
1017+
"Peer {} reached maximum number of pending requests: {}",
1018+
counterparty_node_id, MAX_PENDING_REQUESTS_PER_PEER
1019+
);
1020+
1021+
let result =
1022+
Err(LightningError { err, action: ErrorAction::IgnoreAndLog(Level::Debug) });
1023+
(result, msg)
1024+
}
1025+
};
1026+
1027+
if let Some(msg) = response {
1028+
self.pending_messages.enqueue(counterparty_node_id, msg);
1029+
}
1030+
1031+
result
10001032
}
10011033

10021034
fn handle_buy_request(
@@ -1070,7 +1102,6 @@ where
10701102
}
10711103

10721104
// TODO: if payment_size_msat is specified, make sure our node has sufficient incoming liquidity from public network to receive it.
1073-
10741105
if !is_valid_opening_fee_params(&params.opening_fee_params, &self.config.promise_secret) {
10751106
let response = LSPS2Response::BuyError(ResponseError {
10761107
code: LSPS2_BUY_REQUEST_INVALID_OPENING_FEE_PARAMS_ERROR_CODE,
@@ -1085,26 +1116,52 @@ where
10851116
});
10861117
}
10871118

1088-
{
1119+
let (result, response) = {
10891120
let mut outer_state_lock = self.per_peer_state.write().unwrap();
10901121
let inner_state_lock = outer_state_lock
10911122
.entry(*counterparty_node_id)
10921123
.or_insert(Mutex::new(PeerState::new()));
10931124
let mut peer_state_lock = inner_state_lock.lock().unwrap();
1094-
peer_state_lock
1095-
.pending_requests
1096-
.insert(request_id.clone(), LSPS2Request::Buy(params.clone()));
1097-
}
10981125

1099-
let event = Event::LSPS2Service(LSPS2ServiceEvent::BuyRequest {
1100-
request_id,
1101-
counterparty_node_id: *counterparty_node_id,
1102-
opening_fee_params: params.opening_fee_params,
1103-
payment_size_msat: params.payment_size_msat,
1104-
});
1105-
self.pending_events.enqueue(event);
1126+
if peer_state_lock.pending_requests.len() < MAX_PENDING_REQUESTS_PER_PEER {
1127+
peer_state_lock
1128+
.pending_requests
1129+
.insert(request_id.clone(), LSPS2Request::Buy(params.clone()));
11061130

1107-
Ok(())
1131+
let event = Event::LSPS2Service(LSPS2ServiceEvent::BuyRequest {
1132+
request_id,
1133+
counterparty_node_id: *counterparty_node_id,
1134+
opening_fee_params: params.opening_fee_params,
1135+
payment_size_msat: params.payment_size_msat,
1136+
});
1137+
self.pending_events.enqueue(event);
1138+
1139+
(Ok(()), None)
1140+
} else {
1141+
let response = LSPS2Response::BuyError(ResponseError {
1142+
code: LSPS0_CLIENT_REJECTED_ERROR_CODE,
1143+
message: "Reached maximum number of pending requests. Please try again later."
1144+
.to_string(),
1145+
data: None,
1146+
});
1147+
let msg = Some(LSPS2Message::Response(request_id, response).into());
1148+
1149+
let err = format!(
1150+
"Peer {} reached maximum number of pending requests: {}",
1151+
counterparty_node_id, MAX_PENDING_REQUESTS_PER_PEER
1152+
);
1153+
let result =
1154+
Err(LightningError { err, action: ErrorAction::IgnoreAndLog(Level::Debug) });
1155+
1156+
(result, msg)
1157+
}
1158+
};
1159+
1160+
if let Some(msg) = response {
1161+
self.pending_messages.enqueue(counterparty_node_id, msg);
1162+
}
1163+
1164+
result
11081165
}
11091166
}
11101167

0 commit comments

Comments
 (0)