Skip to content

Commit b09ccd1

Browse files
committed
Consider HTLC in-flight count limits when assembling a route
When calculating the amount available to send for the next HTLC, if we over-count we may create routes which are not actually usable. Historically this has been an issue, which we resolve over a few commits. Here we consider the number of in-flight HTLCs which we are allowed to push towards a counterparty at once, setting the available balance to zero if we cannot push any further HTLCs. We also add some testing when sending to ensure that send failures are accounted for in our balance calculations.
1 parent e43cfbd commit b09ccd1

File tree

2 files changed

+16
-6
lines changed

2 files changed

+16
-6
lines changed

lightning/src/ln/channel.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2725,17 +2725,22 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
27252725
available_capacity_msat = capacity_minus_commitment_fee_msat as u64;
27262726
}
27272727
}
2728+
2729+
available_capacity_msat = cmp::min(available_capacity_msat,
2730+
self.counterparty_max_htlc_value_in_flight_msat - outbound_stats.pending_htlcs_value_msat);
2731+
2732+
if outbound_stats.pending_htlcs + 1 > self.counterparty_max_accepted_htlcs as u32 {
2733+
available_capacity_msat = 0;
2734+
}
2735+
27282736
AvailableBalances {
27292737
inbound_capacity_msat: cmp::max(self.channel_value_satoshis as i64 * 1000
27302738
- self.value_to_self_msat as i64
27312739
- self.get_inbound_pending_htlc_stats(None).pending_htlcs_value_msat as i64
27322740
- self.holder_selected_channel_reserve_satoshis as i64 * 1000,
27332741
0) as u64,
27342742
outbound_capacity_msat,
2735-
next_outbound_htlc_limit_msat: cmp::max(cmp::min(available_capacity_msat as i64,
2736-
self.counterparty_max_htlc_value_in_flight_msat as i64
2737-
- outbound_stats.pending_htlcs_value_msat as i64),
2738-
0) as u64,
2743+
next_outbound_htlc_limit_msat: available_capacity_msat,
27392744
balance_msat,
27402745
}
27412746
}
@@ -5885,10 +5890,12 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
58855890
let inbound_stats = self.get_inbound_pending_htlc_stats(None);
58865891
let outbound_stats = self.get_outbound_pending_htlc_stats(None);
58875892
if outbound_stats.pending_htlcs + 1 > self.counterparty_max_accepted_htlcs as u32 {
5893+
debug_assert!(amount_msat > self.get_available_balances().next_outbound_htlc_limit_msat);
58885894
return Err(ChannelError::Ignore(format!("Cannot push more than their max accepted HTLCs ({})", self.counterparty_max_accepted_htlcs)));
58895895
}
58905896
// Check their_max_htlc_value_in_flight_msat
58915897
if outbound_stats.pending_htlcs_value_msat + amount_msat > self.counterparty_max_htlc_value_in_flight_msat {
5898+
debug_assert!(amount_msat > self.get_available_balances().next_outbound_htlc_limit_msat);
58925899
return Err(ChannelError::Ignore(format!("Cannot send value that would put us over the max HTLC value in flight our peer will accept ({})", self.counterparty_max_htlc_value_in_flight_msat)));
58935900
}
58945901

lightning/src/ln/functional_tests.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,9 @@ fn holding_cell_htlc_counting() {
11021102
create_announced_chan_between_nodes(&nodes, 0, 1);
11031103
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
11041104

1105+
// Fetch a route in advance as we will be unable to once we're unable to send.
1106+
let (route, payment_hash_1, _, payment_secret_1) = get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
1107+
11051108
let mut payments = Vec::new();
11061109
for _ in 0..50 {
11071110
let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
@@ -1119,7 +1122,6 @@ fn holding_cell_htlc_counting() {
11191122
// There is now one HTLC in an outbound commitment transaction and (OUR_MAX_HTLCS - 1) HTLCs in
11201123
// the holding cell waiting on B's RAA to send. At this point we should not be able to add
11211124
// another HTLC.
1122-
let (route, payment_hash_1, _, payment_secret_1) = get_route_and_payment_hash!(nodes[1], nodes[2], 100000);
11231125
{
11241126
unwrap_send_err!(nodes[1].node.send_payment_with_route(&route, payment_hash_1,
11251127
RecipientOnionFields::secret_only(payment_secret_1), PaymentId(payment_hash_1.0)
@@ -6112,6 +6114,8 @@ fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increment()
61126114
let max_accepted_htlcs = nodes[1].node.per_peer_state.read().unwrap().get(&nodes[0].node.get_our_node_id())
61136115
.unwrap().lock().unwrap().channel_by_id.get(&chan.2).unwrap().counterparty_max_accepted_htlcs as u64;
61146116

6117+
// Fetch a route in advance as we will be unable to once we're unable to send.
6118+
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
61156119
for i in 0..max_accepted_htlcs {
61166120
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
61176121
let payment_event = {
@@ -6135,7 +6139,6 @@ fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increment()
61356139
expect_pending_htlcs_forwardable!(nodes[1]);
61366140
expect_payment_claimable!(nodes[1], our_payment_hash, our_payment_secret, 100000);
61376141
}
6138-
let (route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], 100000);
61396142
unwrap_send_err!(nodes[0].node.send_payment_with_route(&route, our_payment_hash,
61406143
RecipientOnionFields::secret_only(our_payment_secret), PaymentId(our_payment_hash.0)
61416144
), true, APIError::ChannelUnavailable { ref err },

0 commit comments

Comments
 (0)