Skip to content

Commit c532f20

Browse files
committed
Refactor forward_htlcs to return whether to push a forward event
When decoding pending `update_add_htlc` onions, we may need to forward HTLCs using `ChannelManager::forward_htlcs`. This may end up queueing a `PendingHTLCsForwardable` event, but we're only decoding these pending onions as a result of handling a `PendingHTLCsForwardable`, so we shouldn't have to queue another one and wait for it to be handled. By having a `forward_htlcs` variant that does not push the forward event, we can ignore the forward event push when forwarding HTLCs which we just decoded the onion for.
1 parent 47cece2 commit c532f20

File tree

3 files changed

+32
-28
lines changed

3 files changed

+32
-28
lines changed

lightning/src/ln/channelmanager.rs

+22-13
Original file line numberDiff line numberDiff line change
@@ -5343,9 +5343,14 @@ where
53435343
}
53445344
}
53455345

5346+
fn fail_htlc_backwards_internal(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) {
5347+
let push_forward_event = self.fail_htlc_backwards_internal_without_forward_event(source, payment_hash, onion_error, destination);
5348+
if push_forward_event { self.push_pending_forwards_ev(); }
5349+
}
5350+
53465351
/// Fails an HTLC backwards to the sender of it to us.
53475352
/// Note that we do not assume that channels corresponding to failed HTLCs are still available.
5348-
fn fail_htlc_backwards_internal(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) {
5353+
fn fail_htlc_backwards_internal_without_forward_event(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) -> bool {
53495354
// Ensure that no peer state channel storage lock is held when calling this function.
53505355
// This ensures that future code doesn't introduce a lock-order requirement for
53515356
// `forward_htlcs` to be locked after the `per_peer_state` peer locks, which calling
@@ -5363,12 +5368,12 @@ where
53635368
// Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called
53645369
// from block_connected which may run during initialization prior to the chain_monitor
53655370
// being fully configured. See the docs for `ChannelManagerReadArgs` for more.
5371+
let mut push_forward_event;
53665372
match source {
53675373
HTLCSource::OutboundRoute { ref path, ref session_priv, ref payment_id, .. } => {
5368-
if self.pending_outbound_payments.fail_htlc(source, payment_hash, onion_error, path,
5374+
push_forward_event = self.pending_outbound_payments.fail_htlc(source, payment_hash, onion_error, path,
53695375
session_priv, payment_id, self.probing_cookie_secret, &self.secp_ctx,
5370-
&self.pending_events, &self.logger)
5371-
{ self.push_pending_forwards_ev(); }
5376+
&self.pending_events, &self.logger);
53725377
},
53735378
HTLCSource::PreviousHopData(HTLCPreviousHopData {
53745379
ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret,
@@ -5402,9 +5407,9 @@ where
54025407
}
54035408
};
54045409

5405-
let mut push_forward_ev = self.decode_update_add_htlcs.lock().unwrap().is_empty();
5410+
push_forward_event = self.decode_update_add_htlcs.lock().unwrap().is_empty();
54065411
let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
5407-
push_forward_ev &= forward_htlcs.is_empty();
5412+
push_forward_event &= forward_htlcs.is_empty();
54085413
match forward_htlcs.entry(*short_channel_id) {
54095414
hash_map::Entry::Occupied(mut entry) => {
54105415
entry.get_mut().push(failure);
@@ -5414,14 +5419,14 @@ where
54145419
}
54155420
}
54165421
mem::drop(forward_htlcs);
5417-
if push_forward_ev { self.push_pending_forwards_ev(); }
54185422
let mut pending_events = self.pending_events.lock().unwrap();
54195423
pending_events.push_back((events::Event::HTLCHandlingFailed {
54205424
prev_channel_id: *channel_id,
54215425
failed_next_destination: destination,
54225426
}, None));
54235427
},
54245428
}
5429+
push_forward_event
54255430
}
54265431

54275432
/// Provides a payment preimage in response to [`Event::PaymentClaimable`], generating any
@@ -6994,8 +6999,14 @@ where
69946999

69957000
#[inline]
69967001
fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)]) {
7002+
let push_forward_event = self.forward_htlcs_without_forward_event(per_source_pending_forwards);
7003+
if push_forward_event { self.push_pending_forwards_ev() }
7004+
}
7005+
7006+
#[inline]
7007+
fn forward_htlcs_without_forward_event(&self, per_source_pending_forwards: &mut [(u64, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)]) -> bool {
7008+
let mut push_forward_event = false;
69977009
for &mut (prev_short_channel_id, prev_funding_outpoint, prev_channel_id, prev_user_channel_id, ref mut pending_forwards) in per_source_pending_forwards {
6998-
let mut push_forward_event = false;
69997010
let mut new_intercept_events = VecDeque::new();
70007011
let mut failed_intercept_forwards = Vec::new();
70017012
if !pending_forwards.is_empty() {
@@ -7057,9 +7068,7 @@ where
70577068
} else {
70587069
// We don't want to generate a PendingHTLCsForwardable event if only intercepted
70597070
// payments are being processed.
7060-
if forward_htlcs_empty && decode_update_add_htlcs_empty {
7061-
push_forward_event = true;
7062-
}
7071+
push_forward_event |= forward_htlcs_empty && decode_update_add_htlcs_empty;
70637072
entry.insert(vec!(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
70647073
prev_short_channel_id, prev_funding_outpoint, prev_channel_id, prev_htlc_id, prev_user_channel_id, forward_info })));
70657074
}
@@ -7069,15 +7078,15 @@ where
70697078
}
70707079

70717080
for (htlc_source, payment_hash, failure_reason, destination) in failed_intercept_forwards.drain(..) {
7072-
self.fail_htlc_backwards_internal(&htlc_source, &payment_hash, &failure_reason, destination);
7081+
push_forward_event |= self.fail_htlc_backwards_internal_without_forward_event(&htlc_source, &payment_hash, &failure_reason, destination);
70737082
}
70747083

70757084
if !new_intercept_events.is_empty() {
70767085
let mut events = self.pending_events.lock().unwrap();
70777086
events.append(&mut new_intercept_events);
70787087
}
7079-
if push_forward_event { self.push_pending_forwards_ev() }
70807088
}
7089+
push_forward_event
70817090
}
70827091

70837092
fn push_pending_forwards_ev(&self) {

lightning/src/ln/functional_test_utils.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -1827,14 +1827,9 @@ macro_rules! expect_htlc_handling_failed_destinations {
18271827
/// there are any [`Event::HTLCHandlingFailed`] events their [`HTLCDestination`] is included in the
18281828
/// `expected_failures` set.
18291829
pub fn expect_pending_htlcs_forwardable_conditions(events: Vec<Event>, expected_failures: &[HTLCDestination]) {
1830-
match events[0] {
1831-
Event::PendingHTLCsForwardable { .. } => { },
1832-
_ => panic!("Unexpected event {:?}", events),
1833-
};
1834-
18351830
let count = expected_failures.len() + 1;
18361831
assert_eq!(events.len(), count);
1837-
1832+
assert!(events.iter().find(|event| matches!(event, Event::PendingHTLCsForwardable { .. })).is_some());
18381833
if expected_failures.len() > 0 {
18391834
expect_htlc_handling_failed_destinations!(events, expected_failures)
18401835
}

lightning/src/ln/functional_tests.rs

+9-9
Original file line numberDiff line numberDiff line change
@@ -2750,7 +2750,7 @@ fn claim_htlc_outputs_single_tx() {
27502750
check_added_monitors!(nodes[1], 1);
27512751
check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed, [nodes[0].node.get_our_node_id()], 100000);
27522752
let mut events = nodes[0].node.get_and_clear_pending_events();
2753-
expect_pending_htlcs_forwardable_from_events!(nodes[0], events[0..1], true);
2753+
expect_pending_htlcs_forwardable_conditions(events[0..2].to_vec(), &[HTLCDestination::FailedPayment { payment_hash: payment_hash_2 }]);
27542754
match events.last().unwrap() {
27552755
Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {}
27562756
_ => panic!("Unexpected event"),
@@ -3312,13 +3312,13 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
33123312
let events = nodes[1].node.get_and_clear_pending_events();
33133313
assert_eq!(events.len(), 2);
33143314
match events[0] {
3315-
Event::PendingHTLCsForwardable { .. } => { },
3316-
_ => panic!("Unexpected event"),
3317-
};
3318-
match events[1] {
33193315
Event::HTLCHandlingFailed { .. } => { },
33203316
_ => panic!("Unexpected event"),
33213317
}
3318+
match events[1] {
3319+
Event::PendingHTLCsForwardable { .. } => { },
3320+
_ => panic!("Unexpected event"),
3321+
};
33223322
// Deliberately don't process the pending fail-back so they all fail back at once after
33233323
// block connection just like the !deliver_bs_raa case
33243324
}
@@ -5351,7 +5351,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
53515351
connect_blocks(&nodes[2], ANTI_REORG_DELAY - 1);
53525352
check_closed_broadcast!(nodes[2], true);
53535353
if deliver_last_raa {
5354-
expect_pending_htlcs_forwardable_from_events!(nodes[2], events[0..1], true);
5354+
expect_pending_htlcs_forwardable_from_events!(nodes[2], events[1..2], true);
53555355

53565356
let expected_destinations: Vec<HTLCDestination> = repeat(HTLCDestination::NextHopChannel { node_id: Some(nodes[3].node.get_our_node_id()), channel_id: chan_2_3.2 }).take(3).collect();
53575357
expect_htlc_handling_failed_destinations!(nodes[2].node.get_and_clear_pending_events(), expected_destinations);
@@ -6182,7 +6182,7 @@ fn test_fail_holding_cell_htlc_upon_free_multihop() {
61826182
// nodes[1]'s ChannelManager will now signal that we have HTLC forwards to process.
61836183
let process_htlc_forwards_event = nodes[1].node.get_and_clear_pending_events();
61846184
assert_eq!(process_htlc_forwards_event.len(), 2);
6185-
match &process_htlc_forwards_event[0] {
6185+
match &process_htlc_forwards_event[1] {
61866186
&Event::PendingHTLCsForwardable { .. } => {},
61876187
_ => panic!("Unexpected event"),
61886188
}
@@ -7543,7 +7543,7 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
75437543
let route_params = RouteParameters::from_payment_params_and_value(payment_params, 3_000_000);
75447544
let route = get_route(&nodes[1].node.get_our_node_id(), &route_params, &nodes[1].network_graph.read_only(), None,
75457545
nodes[0].logger, &scorer, &Default::default(), &random_seed_bytes).unwrap();
7546-
send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000);
7546+
let failed_payment_hash = send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000).1;
75477547

75487548
let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan.2);
75497549
assert_eq!(revoked_local_txn[0].input.len(), 1);
@@ -7582,7 +7582,7 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
75827582
let block_129 = create_dummy_block(block_11.block_hash(), 42, vec![revoked_htlc_txn[0].clone(), revoked_htlc_txn[1].clone()]);
75837583
connect_block(&nodes[0], &block_129);
75847584
let events = nodes[0].node.get_and_clear_pending_events();
7585-
expect_pending_htlcs_forwardable_from_events!(nodes[0], events[0..1], true);
7585+
expect_pending_htlcs_forwardable_conditions(events[0..2].to_vec(), &[HTLCDestination::FailedPayment { payment_hash: failed_payment_hash }]);
75867586
match events.last().unwrap() {
75877587
Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {}
75887588
_ => panic!("Unexpected event"),

0 commit comments

Comments
 (0)