Skip to content

Commit aab6332

Browse files
fixups addressing comments. list of changes:
- get rid of dos_protection_enforcer. logic will go inside lsps5/service - improve naming conventions so it's clearer - do not log on level info for possible spam - make the dos protections enabled by default
1 parent 6cebc12 commit aab6332

File tree

6 files changed

+289
-120
lines changed

6 files changed

+289
-120
lines changed

lightning-liquidity/src/dos_protection_enforcer.rs

Lines changed: 0 additions & 62 deletions
This file was deleted.

lightning-liquidity/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ mod prelude {
5858
pub(crate) use lightning::util::hash_tables::*;
5959
}
6060

61-
pub mod dos_protection_enforcer;
6261
pub mod events;
6362
pub mod lsps0;
6463
pub mod lsps1;

lightning-liquidity/src/lsps2/service.rs

Lines changed: 81 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ struct ForwardPaymentAction(ChannelId, FeePayment);
108108
struct ForwardHTLCsAction(ChannelId, Vec<InterceptedHTLC>);
109109

110110
/// The different states a requested JIT channel can be in.
111-
#[derive(Debug)]
112-
enum OutboundJITChannelState {
111+
#[derive(Clone, Debug, PartialEq, Eq)]
112+
pub(crate) enum OutboundJITChannelState {
113113
/// The JIT channel SCID was created after a buy request, and we are awaiting an initial payment
114114
/// of sufficient size to open the channel.
115115
PendingInitialPayment { payment_queue: PaymentQueue },
@@ -134,6 +134,30 @@ enum OutboundJITChannelState {
134134
PaymentForwarded { channel_id: ChannelId },
135135
}
136136

137+
impl OutboundJITChannelState {
138+
fn ord_index(&self) -> u8 {
139+
match self {
140+
OutboundJITChannelState::PendingInitialPayment { .. } => 0,
141+
OutboundJITChannelState::PendingChannelOpen { .. } => 1,
142+
OutboundJITChannelState::PendingPaymentForward { .. } => 2,
143+
OutboundJITChannelState::PendingPayment { .. } => 3,
144+
OutboundJITChannelState::PaymentForwarded { .. } => 4,
145+
}
146+
}
147+
}
148+
149+
impl PartialOrd for OutboundJITChannelState {
150+
fn partial_cmp(&self, other: &Self) -> Option<CmpOrdering> {
151+
Some(self.cmp(other))
152+
}
153+
}
154+
155+
impl Ord for OutboundJITChannelState {
156+
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
157+
self.ord_index().cmp(&other.ord_index())
158+
}
159+
}
160+
137161
impl OutboundJITChannelState {
138162
fn new() -> Self {
139163
OutboundJITChannelState::PendingInitialPayment { payment_queue: PaymentQueue::new() }
@@ -427,10 +451,6 @@ impl OutboundJITChannel {
427451
matches!(self.state, OutboundJITChannelState::PendingInitialPayment { .. })
428452
}
429453

430-
fn is_pending_channel_open(&self) -> bool {
431-
matches!(self.state, OutboundJITChannelState::PendingChannelOpen { .. })
432-
}
433-
434454
fn is_prunable(&self) -> bool {
435455
// We deem an OutboundJITChannel prunable if our offer expired and we haven't intercepted
436456
// any HTLCs initiating the flow yet.
@@ -576,18 +596,15 @@ where
576596
&self.config
577597
}
578598

579-
pub(crate) fn has_pending_channel_open_request(
599+
pub(crate) fn highest_state_for_peer(
580600
&self, counterparty_node_id: &PublicKey,
581-
) -> bool {
601+
) -> Option<OutboundJITChannelState> {
582602
let outer_state_lock = self.per_peer_state.read().unwrap();
583603
if let Some(inner_state_lock) = outer_state_lock.get(counterparty_node_id) {
584604
let peer_state = inner_state_lock.lock().unwrap();
585-
peer_state
586-
.outbound_channels_by_intercept_scid
587-
.values()
588-
.any(|c| c.is_pending_channel_open())
605+
peer_state.outbound_channels_by_intercept_scid.values().map(|c| c.state.clone()).max()
589606
} else {
590-
false
607+
None
591608
}
592609
}
593610

@@ -1924,4 +1941,55 @@ mod tests {
19241941
);
19251942
}
19261943
}
1944+
1945+
#[test]
1946+
fn highest_state_for_peer_orders() {
1947+
let opening_fee_params = LSPS2OpeningFeeParams {
1948+
min_fee_msat: 0,
1949+
proportional: 0,
1950+
valid_until: LSPSDateTime::from_str("1970-01-01T00:00:00Z").unwrap(),
1951+
min_lifetime: 0,
1952+
max_client_to_self_delay: 0,
1953+
min_payment_size_msat: 0,
1954+
max_payment_size_msat: 0,
1955+
promise: String::new(),
1956+
};
1957+
1958+
let mut map = new_hash_map();
1959+
map.insert(
1960+
0,
1961+
OutboundJITChannel {
1962+
state: OutboundJITChannelState::PendingInitialPayment {
1963+
payment_queue: PaymentQueue::new(),
1964+
},
1965+
user_channel_id: 0,
1966+
opening_fee_params: opening_fee_params.clone(),
1967+
payment_size_msat: None,
1968+
},
1969+
);
1970+
map.insert(
1971+
1,
1972+
OutboundJITChannel {
1973+
state: OutboundJITChannelState::PendingChannelOpen {
1974+
payment_queue: PaymentQueue::new(),
1975+
opening_fee_msat: 0,
1976+
},
1977+
user_channel_id: 1,
1978+
opening_fee_params: opening_fee_params.clone(),
1979+
payment_size_msat: None,
1980+
},
1981+
);
1982+
map.insert(
1983+
2,
1984+
OutboundJITChannel {
1985+
state: OutboundJITChannelState::PaymentForwarded { channel_id: ChannelId([0; 32]) },
1986+
user_channel_id: 2,
1987+
opening_fee_params,
1988+
payment_size_msat: None,
1989+
},
1990+
);
1991+
1992+
let max_state = map.values().map(|c| c.state.clone()).max().unwrap();
1993+
assert!(matches!(max_state, OutboundJITChannelState::PaymentForwarded { .. }));
1994+
}
19271995
}

lightning-liquidity/src/lsps5/service.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::prelude::*;
2222
use crate::sync::{Arc, Mutex};
2323
use crate::utils::time::TimeProvider;
2424

25+
use crate::lsps2::service::OutboundJITChannelState;
2526
use bitcoin::secp256k1::PublicKey;
2627

2728
use lightning::ln::channelmanager::AChannelManager;
@@ -64,8 +65,6 @@ struct StoredWebhook {
6465
pub struct LSPS5ServiceConfig {
6566
/// Maximum number of webhooks allowed per client.
6667
pub max_webhooks_per_client: u32,
67-
/// Require an existing channel or active LSPS1/LSPS2 flow before accepting requests.
68-
pub enforce_dos_protections: bool,
6968
}
7069

7170
/// Default maximum number of webhooks allowed per client.
@@ -76,10 +75,7 @@ pub const DEFAULT_NOTIFICATION_COOLDOWN_HOURS: Duration = Duration::from_secs(60
7675
// Default configuration for LSPS5 service.
7776
impl Default for LSPS5ServiceConfig {
7877
fn default() -> Self {
79-
Self {
80-
max_webhooks_per_client: DEFAULT_MAX_WEBHOOKS_PER_CLIENT,
81-
enforce_dos_protections: true,
82-
}
78+
Self { max_webhooks_per_client: DEFAULT_MAX_WEBHOOKS_PER_CLIENT }
8379
}
8480
}
8581

@@ -155,9 +151,26 @@ where
155151
}
156152
}
157153

158-
/// Returns a reference to the used config.
159-
pub fn config(&self) -> &LSPS5ServiceConfig {
160-
&self.config
154+
/// Returns whether a request from the given client should be accepted.
155+
///
156+
/// Prior activity includes an existing open channel, an active LSPS1 flow,
157+
/// or an LSPS2 flow that has progressed to at least
158+
/// [`OutboundJITChannelState::PendingChannelOpen`].
159+
pub(crate) fn can_accept_request(
160+
&self, client_id: &PublicKey, lsps2_max_state: Option<OutboundJITChannelState>,
161+
lsps1_has_activity: bool,
162+
) -> bool {
163+
self.client_has_open_channel(client_id)
164+
|| lsps1_has_activity
165+
|| lsps2_max_state.map_or(false, |s| {
166+
matches!(
167+
s,
168+
OutboundJITChannelState::PendingChannelOpen { .. }
169+
| OutboundJITChannelState::PendingPaymentForward { .. }
170+
| OutboundJITChannelState::PendingPayment { .. }
171+
| OutboundJITChannelState::PaymentForwarded { .. }
172+
)
173+
})
161174
}
162175

163176
fn check_prune_stale_webhooks(&self) {

lightning-liquidity/src/manager.rs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use alloc::string::ToString;
22
use alloc::vec::Vec;
33

4-
use crate::dos_protection_enforcer::DosProtectionEnforcer;
54
use crate::events::{EventQueue, LiquidityEvent};
65
use crate::lsps0::client::LSPS0ClientHandler;
76
use crate::lsps0::msgs::LSPS0Message;
@@ -484,18 +483,6 @@ where
484483
self.pending_events.get_and_clear_pending_events()
485484
}
486485

487-
fn peer_is_engaged(&self, peer: &PublicKey) -> bool {
488-
let lsps5_engaged =
489-
self.lsps5_service_handler.as_ref().map_or(false, |h| h.is_engaged(peer));
490-
let lsps2_engaged =
491-
self.lsps2_service_handler.as_ref().map_or(false, |h| h.is_engaged(peer));
492-
#[cfg(lsps1_service)]
493-
let lsps1_engaged = self.lsps1_service_handler.as_ref().map_or(false, |h| h.is_engaged(peer));
494-
#[cfg(not(lsps1_service))]
495-
let lsps1_engaged = false;
496-
lsps5_engaged || lsps2_engaged || lsps1_engaged
497-
}
498-
499486
fn handle_lsps_message(
500487
&self, msg: LSPSMessage, sender_node_id: &PublicKey,
501488
) -> Result<(), lightning::ln::msgs::LightningError> {
@@ -572,17 +559,32 @@ where
572559
LSPSMessage::LSPS5(msg @ LSPS5Message::Request(..)) => {
573560
match &self.lsps5_service_handler {
574561
Some(lsps5_service_handler) => {
575-
if lsps5_service_handler.config().enforce_dos_protections {
576-
if !self.peer_is_engaged(sender_node_id) {
577-
return Err(LightningError {
562+
let lsps2_max_state = self
563+
.lsps2_service_handler
564+
.as_ref()
565+
.and_then(|h| h.highest_state_for_peer(sender_node_id));
566+
#[cfg(lsps1_service)]
567+
let lsps1_has_active_requests = self
568+
.lsps1_service_handler
569+
.as_ref()
570+
.map_or(false, |h| h.has_active_requests(sender_node_id));
571+
#[cfg(not(lsps1_service))]
572+
let lsps1_has_active_requests = false;
573+
574+
if !lsps5_service_handler.can_accept_request(
575+
sender_node_id,
576+
lsps2_max_state,
577+
lsps1_has_active_requests,
578+
) {
579+
return Err(LightningError {
578580
err: format!(
579-
"Rejecting LSPS5 request from {:?} without existing engagement",
581+
"Rejecting LSPS5 request from {:?} without prior activity (requires open channel or active LSPS1 or LSPS2 flow)",
580582
sender_node_id
581583
),
582-
action: ErrorAction::IgnoreAndLog(Level::Info),
584+
action: ErrorAction::IgnoreAndLog(Level::Debug),
583585
});
584-
}
585586
}
587+
586588
lsps5_service_handler.handle_message(msg, sender_node_id)?;
587589
},
588590
None => {

0 commit comments

Comments
 (0)