Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Commit 0150b0a

Browse files
committed
Check variable-amount payments against {min,max}_payment_size_msat
Previously, we would open a channel of arbitrary size if the user didn't supply the optional `payment_size_msat`, i.e., would use `no-MPP+var-invoice` mode. Here, we make sure to check the resulting `expected_payment_size_msat` would always adhere to our set limits and fail the HTLC otherwise.
1 parent 5e0076c commit 0150b0a

File tree

1 file changed

+37
-12
lines changed

1 file changed

+37
-12
lines changed

src/lsps2/service.rs

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ impl OutboundJITChannelState {
9393
}
9494
}
9595

96-
fn htlc_intercepted(&self, htlc: InterceptedHTLC) -> Result<Self, ChannelStateError> {
96+
fn htlc_intercepted(
97+
&self, htlc: InterceptedHTLC, config: &LSPS2ServiceConfig,
98+
) -> Result<Self, ChannelStateError> {
9799
match self {
98100
OutboundJITChannelState::AwaitingPayment {
99101
htlcs,
@@ -107,24 +109,46 @@ impl OutboundJITChannelState {
107109
let total_expected_outbound_amount_msat =
108110
htlcs.iter().map(|htlc| htlc.expected_outbound_amount_msat).sum();
109111

110-
let expected_payment_size_msat =
111-
payment_size_msat.unwrap_or(total_expected_outbound_amount_msat);
112+
let (expected_payment_size_msat, mpp_mode) =
113+
if let Some(payment_size_msat) = payment_size_msat {
114+
(*payment_size_msat, true)
115+
} else {
116+
debug_assert_eq!(htlcs.len(), 1);
117+
if htlcs.len() != 1 {
118+
return Err(ChannelStateError(
119+
format!("Paying via multiple HTLCs is disallowed in \"no-MPP+var-invoice\" mode.")
120+
));
121+
}
122+
(total_expected_outbound_amount_msat, false)
123+
};
124+
125+
if expected_payment_size_msat < config.min_payment_size_msat
126+
|| expected_payment_size_msat > config.max_payment_size_msat
127+
{
128+
return Err(ChannelStateError(
129+
format!("Payment size violates our limits: expected_payment_size_msat = {}, min_payment_size_msat = {}, max_payment_size_msat = {}",
130+
expected_payment_size_msat,
131+
config.min_payment_size_msat,
132+
config.max_payment_size_msat
133+
)));
134+
}
112135

113136
let opening_fee_msat = compute_opening_fee(
114137
expected_payment_size_msat,
115138
*min_fee_msat,
116139
(*proportional_fee).into(),
117140
).ok_or(ChannelStateError(
118-
format!("Could not compute valid opening fee with min_fee_msat = {}, proportional = {}, and total_expected_outbound_amount_msat = {}",
141+
format!("Could not compute valid opening fee with min_fee_msat = {}, proportional = {}, and expected_payment_size_msat = {}",
119142
min_fee_msat,
120143
proportional_fee,
121-
total_expected_outbound_amount_msat
144+
expected_payment_size_msat
122145
)
123146
))?;
124147

125148
let amt_to_forward_msat =
126149
expected_payment_size_msat.saturating_sub(opening_fee_msat);
127150

151+
// Go ahead and open the channel if we intercepted sufficient HTLCs.
128152
if total_expected_outbound_amount_msat >= expected_payment_size_msat
129153
&& amt_to_forward_msat > 0
130154
{
@@ -134,21 +158,22 @@ impl OutboundJITChannelState {
134158
amt_to_forward_msat,
135159
})
136160
} else {
137-
// payment size being specified means MPP is supported
138-
if payment_size_msat.is_some() {
161+
if mpp_mode {
139162
Ok(OutboundJITChannelState::AwaitingPayment {
140163
min_fee_msat: *min_fee_msat,
141164
proportional_fee: *proportional_fee,
142165
htlcs,
143166
payment_size_msat: *payment_size_msat,
144167
})
145168
} else {
146-
Err(ChannelStateError("HTLC is too small to pay opening fee".to_string()))
169+
Err(ChannelStateError(
170+
"Intercepted HTLC is too small to pay opening fee".to_string(),
171+
))
147172
}
148173
}
149174
}
150175
state => Err(ChannelStateError(format!(
151-
"Invoice params received when JIT Channel was in state: {:?}",
176+
"Intercepted HTLC when JIT Channel was in state: {:?}",
152177
state
153178
))),
154179
}
@@ -186,9 +211,9 @@ impl OutboundJITChannel {
186211
}
187212

188213
fn htlc_intercepted(
189-
&mut self, htlc: InterceptedHTLC,
214+
&mut self, htlc: InterceptedHTLC, config: &LSPS2ServiceConfig,
190215
) -> Result<Option<(u64, u64)>, LightningError> {
191-
self.state = self.state.htlc_intercepted(htlc)?;
216+
self.state = self.state.htlc_intercepted(htlc, config)?;
192217

193218
match &self.state {
194219
OutboundJITChannelState::AwaitingPayment { .. } => {
@@ -447,7 +472,7 @@ where
447472
peer_state.outbound_channels_by_intercept_scid.get_mut(&intercept_scid)
448473
{
449474
let htlc = InterceptedHTLC { intercept_id, expected_outbound_amount_msat };
450-
match jit_channel.htlc_intercepted(htlc) {
475+
match jit_channel.htlc_intercepted(htlc, &self.config) {
451476
Ok(Some((opening_fee_msat, amt_to_forward_msat))) => {
452477
self.enqueue_event(Event::LSPS2Service(
453478
LSPS2ServiceEvent::OpenChannel {

0 commit comments

Comments
 (0)