Skip to content

Commit a6c9128

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 7fe2582 commit a6c9128

File tree

3 files changed

+32
-28
lines changed

3 files changed

+32
-28
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5355,9 +5355,14 @@ where
53555355
}
53565356
}
53575357

5358+
fn fail_htlc_backwards_internal(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) {
5359+
let push_forward_event = self.fail_htlc_backwards_internal_without_forward_event(source, payment_hash, onion_error, destination);
5360+
if push_forward_event { self.push_pending_forwards_ev(); }
5361+
}
5362+
53585363
/// Fails an HTLC backwards to the sender of it to us.
53595364
/// Note that we do not assume that channels corresponding to failed HTLCs are still available.
5360-
fn fail_htlc_backwards_internal(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) {
5365+
fn fail_htlc_backwards_internal_without_forward_event(&self, source: &HTLCSource, payment_hash: &PaymentHash, onion_error: &HTLCFailReason, destination: HTLCDestination) -> bool {
53615366
// Ensure that no peer state channel storage lock is held when calling this function.
53625367
// This ensures that future code doesn't introduce a lock-order requirement for
53635368
// `forward_htlcs` to be locked after the `per_peer_state` peer locks, which calling
@@ -5375,12 +5380,12 @@ where
53755380
// Note that we MUST NOT end up calling methods on self.chain_monitor here - we're called
53765381
// from block_connected which may run during initialization prior to the chain_monitor
53775382
// being fully configured. See the docs for `ChannelManagerReadArgs` for more.
5383+
let mut push_forward_event;
53785384
match source {
53795385
HTLCSource::OutboundRoute { ref path, ref session_priv, ref payment_id, .. } => {
5380-
if self.pending_outbound_payments.fail_htlc(source, payment_hash, onion_error, path,
5386+
push_forward_event = self.pending_outbound_payments.fail_htlc(source, payment_hash, onion_error, path,
53815387
session_priv, payment_id, self.probing_cookie_secret, &self.secp_ctx,
5382-
&self.pending_events, &self.logger)
5383-
{ self.push_pending_forwards_ev(); }
5388+
&self.pending_events, &self.logger);
53845389
},
53855390
HTLCSource::PreviousHopData(HTLCPreviousHopData {
53865391
ref short_channel_id, ref htlc_id, ref incoming_packet_shared_secret,
@@ -5414,9 +5419,9 @@ where
54145419
}
54155420
};
54165421

5417-
let mut push_forward_ev = self.decode_update_add_htlcs.lock().unwrap().is_empty();
5422+
push_forward_event = self.decode_update_add_htlcs.lock().unwrap().is_empty();
54185423
let mut forward_htlcs = self.forward_htlcs.lock().unwrap();
5419-
push_forward_ev &= forward_htlcs.is_empty();
5424+
push_forward_event &= forward_htlcs.is_empty();
54205425
match forward_htlcs.entry(*short_channel_id) {
54215426
hash_map::Entry::Occupied(mut entry) => {
54225427
entry.get_mut().push(failure);
@@ -5426,14 +5431,14 @@ where
54265431
}
54275432
}
54285433
mem::drop(forward_htlcs);
5429-
if push_forward_ev { self.push_pending_forwards_ev(); }
54305434
let mut pending_events = self.pending_events.lock().unwrap();
54315435
pending_events.push_back((events::Event::HTLCHandlingFailed {
54325436
prev_channel_id: *channel_id,
54335437
failed_next_destination: destination,
54345438
}, None));
54355439
},
54365440
}
5441+
push_forward_event
54375442
}
54385443

54395444
/// Provides a payment preimage in response to [`Event::PaymentClaimable`], generating any
@@ -7016,8 +7021,14 @@ where
70167021

70177022
#[inline]
70187023
fn forward_htlcs(&self, per_source_pending_forwards: &mut [(u64, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)]) {
7024+
let push_forward_event = self.forward_htlcs_without_forward_event(per_source_pending_forwards);
7025+
if push_forward_event { self.push_pending_forwards_ev() }
7026+
}
7027+
7028+
#[inline]
7029+
fn forward_htlcs_without_forward_event(&self, per_source_pending_forwards: &mut [(u64, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)]) -> bool {
7030+
let mut push_forward_event = false;
70197031
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 {
7020-
let mut push_forward_event = false;
70217032
let mut new_intercept_events = VecDeque::new();
70227033
let mut failed_intercept_forwards = Vec::new();
70237034
if !pending_forwards.is_empty() {
@@ -7079,9 +7090,7 @@ where
70797090
} else {
70807091
// We don't want to generate a PendingHTLCsForwardable event if only intercepted
70817092
// payments are being processed.
7082-
if forward_htlcs_empty && decode_update_add_htlcs_empty {
7083-
push_forward_event = true;
7084-
}
7093+
push_forward_event |= forward_htlcs_empty && decode_update_add_htlcs_empty;
70857094
entry.insert(vec!(HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
70867095
prev_short_channel_id, prev_funding_outpoint, prev_channel_id, prev_htlc_id, prev_user_channel_id, forward_info })));
70877096
}
@@ -7091,15 +7100,15 @@ where
70917100
}
70927101

70937102
for (htlc_source, payment_hash, failure_reason, destination) in failed_intercept_forwards.drain(..) {
7094-
self.fail_htlc_backwards_internal(&htlc_source, &payment_hash, &failure_reason, destination);
7103+
push_forward_event |= self.fail_htlc_backwards_internal_without_forward_event(&htlc_source, &payment_hash, &failure_reason, destination);
70957104
}
70967105

70977106
if !new_intercept_events.is_empty() {
70987107
let mut events = self.pending_events.lock().unwrap();
70997108
events.append(&mut new_intercept_events);
71007109
}
7101-
if push_forward_event { self.push_pending_forwards_ev() }
71027110
}
7111+
push_forward_event
71037112
}
71047113

71057114
fn push_pending_forwards_ev(&self) {

lightning/src/ln/functional_test_utils.rs

Lines changed: 1 addition & 6 deletions
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

Lines changed: 9 additions & 9 deletions
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)