Skip to content

Commit b360839

Browse files
committed
Move receiving HTLCs to a receive_htlcs field
Previously, we'd store receiving HTLCs side-by-side with HTLCs forwards in the `forwards_htlcs` field under SCID 0. Here, we opt to split out a separate `receive_htlcs` field, also omitting the 0 magic value.
1 parent b8baee9 commit b360839

File tree

2 files changed

+105
-73
lines changed

2 files changed

+105
-73
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,9 +2459,10 @@ where
24592459
// `total_consistency_lock`
24602460
// |
24612461
// |__`forward_htlcs`
2462-
// | |
24632462
// | |__`pending_intercepted_htlcs`
24642463
// |
2464+
// |__`receive_htlcs`
2465+
// |
24652466
// |__`decode_update_add_htlcs`
24662467
// |
24672468
// |__`per_peer_state`
@@ -2537,7 +2538,7 @@ pub struct ChannelManager<
25372538
/// See `ChannelManager` struct-level documentation for lock order requirements.
25382539
pending_outbound_payments: OutboundPayments,
25392540

2540-
/// SCID/SCID Alias -> forward infos. Key of 0 means payments received.
2541+
/// SCID/SCID Alias -> forward infos.
25412542
///
25422543
/// Note that because we may have an SCID Alias as the key we can have two entries per channel,
25432544
/// though in practice we probably won't be receiving HTLCs for a channel both via the alias
@@ -2556,7 +2557,13 @@ pub struct ChannelManager<
25562557
///
25572558
/// See `ChannelManager` struct-level documentation for lock order requirements.
25582559
pending_intercepted_htlcs: Mutex<HashMap<InterceptId, PendingAddHTLCInfo>>,
2559-
2560+
/// Storage for HTLCs that are meant for us.
2561+
///
2562+
/// See `ChannelManager` struct-level documentation for lock order requirements.
2563+
#[cfg(test)]
2564+
pub(super) receive_htlcs: Mutex<Vec<HTLCForwardInfo>>,
2565+
#[cfg(not(test))]
2566+
receive_htlcs: Mutex<Vec<HTLCForwardInfo>>,
25602567
/// SCID/SCID Alias -> pending `update_add_htlc`s to decode.
25612568
///
25622569
/// Note that because we may have an SCID Alias as the key we can have two entries per channel,
@@ -3738,6 +3745,7 @@ where
37383745
outbound_scid_aliases: Mutex::new(new_hash_set()),
37393746
pending_outbound_payments: OutboundPayments::new(new_hash_map()),
37403747
forward_htlcs: Mutex::new(new_hash_map()),
3748+
receive_htlcs: Mutex::new(Vec::new()),
37413749
decode_update_add_htlcs: Mutex::new(new_hash_map()),
37423750
claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: new_hash_map(), pending_claiming_payments: new_hash_map() }),
37433751
pending_intercepted_htlcs: Mutex::new(new_hash_map()),
@@ -6355,6 +6363,9 @@ where
63556363
if !self.forward_htlcs.lock().unwrap().is_empty() {
63566364
return true;
63576365
}
6366+
if !self.receive_htlcs.lock().unwrap().is_empty() {
6367+
return true;
6368+
}
63586369
if !self.decode_update_add_htlcs.lock().unwrap().is_empty() {
63596370
return true;
63606371
}
@@ -6402,22 +6413,18 @@ where
64026413

64036414
for (short_chan_id, mut pending_forwards) in forward_htlcs {
64046415
should_persist = NotifyOption::DoPersist;
6405-
if short_chan_id != 0 {
6406-
self.process_forward_htlcs(
6407-
short_chan_id,
6408-
&mut pending_forwards,
6409-
&mut failed_forwards,
6410-
&mut phantom_receives,
6411-
);
6412-
} else {
6413-
self.process_receive_htlcs(
6414-
&mut pending_forwards,
6415-
&mut new_events,
6416-
&mut failed_forwards,
6417-
);
6418-
}
6416+
self.process_forward_htlcs(
6417+
short_chan_id,
6418+
&mut pending_forwards,
6419+
&mut failed_forwards,
6420+
&mut phantom_receives,
6421+
);
64196422
}
64206423

6424+
let mut receive_htlcs = Vec::new();
6425+
mem::swap(&mut receive_htlcs, &mut self.receive_htlcs.lock().unwrap());
6426+
self.process_receive_htlcs(receive_htlcs, &mut new_events, &mut failed_forwards);
6427+
64216428
let best_block_height = self.best_block.read().unwrap().height;
64226429
let needs_persist = self.pending_outbound_payments.check_retry_payments(
64236430
&self.router,
@@ -6929,11 +6936,11 @@ where
69296936
}
69306937

69316938
fn process_receive_htlcs(
6932-
&self, pending_forwards: &mut Vec<HTLCForwardInfo>,
6939+
&self, receive_htlcs: Vec<HTLCForwardInfo>,
69336940
new_events: &mut VecDeque<(Event, Option<EventCompletionAction>)>,
69346941
failed_forwards: &mut Vec<FailedHTLCForward>,
69356942
) {
6936-
'next_forwardable_htlc: for forward_info in pending_forwards.drain(..) {
6943+
'next_forwardable_htlc: for forward_info in receive_htlcs.into_iter() {
69376944
match forward_info {
69386945
HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo {
69396946
prev_short_channel_id,
@@ -10346,8 +10353,21 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1034610353
let scid = match forward_info.routing {
1034710354
PendingHTLCRouting::Forward { short_channel_id, .. } => short_channel_id,
1034810355
PendingHTLCRouting::TrampolineForward { .. } => 0,
10349-
PendingHTLCRouting::Receive { .. } => 0,
10350-
PendingHTLCRouting::ReceiveKeysend { .. } => 0,
10356+
PendingHTLCRouting::Receive { .. }
10357+
| PendingHTLCRouting::ReceiveKeysend { .. } => {
10358+
self.receive_htlcs.lock().unwrap().push(HTLCForwardInfo::AddHTLC(
10359+
PendingAddHTLCInfo {
10360+
prev_short_channel_id,
10361+
prev_counterparty_node_id,
10362+
prev_funding_outpoint,
10363+
prev_channel_id,
10364+
prev_htlc_id,
10365+
prev_user_channel_id,
10366+
forward_info,
10367+
},
10368+
));
10369+
continue;
10370+
},
1035110371
};
1035210372
// Pull this now to avoid introducing a lock order with `forward_htlcs`.
1035310373
let is_our_scid = self.short_to_chan_info.read().unwrap().contains_key(&scid);
@@ -15091,6 +15111,8 @@ where
1509115111
}
1509215112
}
1509315113

15114+
let receive_htlcs = self.receive_htlcs.lock().unwrap();
15115+
1509415116
let mut decode_update_add_htlcs_opt = None;
1509515117
let decode_update_add_htlcs = self.decode_update_add_htlcs.lock().unwrap();
1509615118
if !decode_update_add_htlcs.is_empty() {
@@ -15258,6 +15280,7 @@ where
1525815280
(17, in_flight_monitor_updates, option),
1525915281
(19, peer_storage_dir, optional_vec),
1526015282
(21, self.flow.writeable_async_receive_offer_cache(), required),
15283+
(23, *receive_htlcs, required_vec),
1526115284
});
1526215285

1526315286
Ok(())
@@ -15818,6 +15841,7 @@ where
1581815841
const MAX_ALLOC_SIZE: usize = 1024 * 64;
1581915842
let forward_htlcs_count: u64 = Readable::read(reader)?;
1582015843
let mut forward_htlcs = hash_map_with_capacity(cmp::min(forward_htlcs_count as usize, 128));
15844+
let mut legacy_receive_htlcs: Vec<HTLCForwardInfo> = Vec::new();
1582115845
for _ in 0..forward_htlcs_count {
1582215846
let short_channel_id = Readable::read(reader)?;
1582315847
let pending_forwards_count: u64 = Readable::read(reader)?;
@@ -15826,7 +15850,26 @@ where
1582615850
MAX_ALLOC_SIZE / mem::size_of::<HTLCForwardInfo>(),
1582715851
));
1582815852
for _ in 0..pending_forwards_count {
15829-
pending_forwards.push(Readable::read(reader)?);
15853+
let pending_htlc = Readable::read(reader)?;
15854+
// Prior to LDK 0.2, Receive HTLCs used to be stored in `forward_htlcs` under SCID == 0. Here we migrate
15855+
// the old data if necessary.
15856+
if short_channel_id == 0 {
15857+
match pending_htlc {
15858+
HTLCForwardInfo::AddHTLC(ref htlc_info) => {
15859+
if matches!(
15860+
htlc_info.forward_info.routing,
15861+
PendingHTLCRouting::Receive { .. }
15862+
| PendingHTLCRouting::ReceiveKeysend { .. }
15863+
) {
15864+
legacy_receive_htlcs.push(pending_htlc);
15865+
continue;
15866+
}
15867+
},
15868+
_ => {},
15869+
}
15870+
}
15871+
15872+
pending_forwards.push(pending_htlc);
1583015873
}
1583115874
forward_htlcs.insert(short_channel_id, pending_forwards);
1583215875
}
@@ -15943,6 +15986,7 @@ where
1594315986
let mut inbound_payment_id_secret = None;
1594415987
let mut peer_storage_dir: Option<Vec<(PublicKey, Vec<u8>)>> = None;
1594515988
let mut async_receive_offer_cache: AsyncReceiveOfferCache = AsyncReceiveOfferCache::new();
15989+
let mut receive_htlcs = None;
1594615990
read_tlv_fields!(reader, {
1594715991
(1, pending_outbound_payments_no_retry, option),
1594815992
(2, pending_intercepted_htlcs, option),
@@ -15961,8 +16005,10 @@ where
1596116005
(17, in_flight_monitor_updates, option),
1596216006
(19, peer_storage_dir, optional_vec),
1596316007
(21, async_receive_offer_cache, (default_value, async_receive_offer_cache)),
16008+
(23, receive_htlcs, optional_vec),
1596416009
});
1596516010
let mut decode_update_add_htlcs = decode_update_add_htlcs.unwrap_or_else(|| new_hash_map());
16011+
let receive_htlcs = receive_htlcs.unwrap_or_else(|| legacy_receive_htlcs);
1596616012
let peer_storage_dir: Vec<(PublicKey, Vec<u8>)> = peer_storage_dir.unwrap_or_else(Vec::new);
1596716013
if fake_scid_rand_bytes.is_none() {
1596816014
fake_scid_rand_bytes = Some(args.entropy_source.get_secure_random_bytes());
@@ -16791,6 +16837,7 @@ where
1679116837
pending_intercepted_htlcs: Mutex::new(pending_intercepted_htlcs.unwrap()),
1679216838

1679316839
forward_htlcs: Mutex::new(forward_htlcs),
16840+
receive_htlcs: Mutex::new(receive_htlcs),
1679416841
decode_update_add_htlcs: Mutex::new(decode_update_add_htlcs),
1679516842
claimable_payments: Mutex::new(ClaimablePayments {
1679616843
claimable_payments,

lightning/src/ln/payment_tests.rs

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -636,30 +636,23 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() {
636636
nodes[3].node.process_pending_update_add_htlcs();
637637

638638
assert!(nodes[3].node.get_and_clear_pending_msg_events().is_empty());
639-
assert_eq!(nodes[3].node.forward_htlcs.lock().unwrap().len(), 1);
640-
if let Some((_, pending_forwards)) =
641-
nodes[3].node.forward_htlcs.lock().unwrap().iter_mut().next()
642-
{
643-
assert_eq!(pending_forwards.len(), 1);
644-
match pending_forwards.get_mut(0).unwrap() {
645-
&mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => {
646-
match forward_info.routing {
647-
PendingHTLCRouting::ReceiveKeysend { ref mut payment_data, .. } => {
648-
*payment_data = Some(msgs::FinalOnionHopData {
649-
payment_secret: PaymentSecret([42; 32]),
650-
total_msat: amount * 2,
651-
});
652-
},
653-
_ => panic!("Expected PendingHTLCRouting::ReceiveKeysend"),
654-
}
655-
},
656-
_ => {
657-
panic!("Unexpected HTLCForwardInfo");
658-
},
659-
}
660-
} else {
661-
panic!("Expected pending receive");
662-
};
639+
assert_eq!(nodes[3].node.receive_htlcs.lock().unwrap().len(), 1);
640+
match nodes[3].node.receive_htlcs.lock().unwrap().get_mut(0).unwrap() {
641+
&mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => {
642+
match forward_info.routing {
643+
PendingHTLCRouting::ReceiveKeysend { ref mut payment_data, .. } => {
644+
*payment_data = Some(msgs::FinalOnionHopData {
645+
payment_secret: PaymentSecret([42; 32]),
646+
total_msat: amount * 2,
647+
});
648+
},
649+
_ => panic!("Expected PendingHTLCRouting::ReceiveKeysend"),
650+
}
651+
},
652+
_ => {
653+
panic!("Unexpected HTLCForwardInfo");
654+
},
655+
}
663656
nodes[3].node.process_pending_htlc_forwards();
664657

665658
// Pay along nodes[2]
@@ -687,34 +680,26 @@ fn test_reject_mpp_keysend_htlc_mismatching_secret() {
687680
let update_add_3 = update_3.update_add_htlcs[0].clone();
688681
nodes[3].node.handle_update_add_htlc(node_c_id, &update_add_3);
689682
commitment_signed_dance!(nodes[3], nodes[2], update_3.commitment_signed, false, true);
690-
expect_htlc_failure_conditions(nodes[3].node.get_and_clear_pending_events(), &[]);
691-
nodes[3].node.process_pending_update_add_htlcs();
692-
683+
assert!(nodes[3].node.get_and_clear_pending_events().is_empty());
693684
assert!(nodes[3].node.get_and_clear_pending_msg_events().is_empty());
694-
assert_eq!(nodes[3].node.forward_htlcs.lock().unwrap().len(), 1);
695-
if let Some((_, pending_forwards)) =
696-
nodes[3].node.forward_htlcs.lock().unwrap().iter_mut().next()
697-
{
698-
assert_eq!(pending_forwards.len(), 1);
699-
match pending_forwards.get_mut(0).unwrap() {
700-
&mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => {
701-
match forward_info.routing {
702-
PendingHTLCRouting::ReceiveKeysend { ref mut payment_data, .. } => {
703-
*payment_data = Some(msgs::FinalOnionHopData {
704-
payment_secret: PaymentSecret([43; 32]), // Doesn't match the secret used above
705-
total_msat: amount * 2,
706-
});
707-
},
708-
_ => panic!("Expected PendingHTLCRouting::ReceiveKeysend"),
709-
}
710-
},
711-
_ => {
712-
panic!("Unexpected HTLCForwardInfo");
713-
},
714-
}
715-
} else {
716-
panic!("Expected pending receive");
717-
};
685+
nodes[3].node.process_pending_update_add_htlcs();
686+
assert_eq!(nodes[3].node.receive_htlcs.lock().unwrap().len(), 1);
687+
match nodes[3].node.receive_htlcs.lock().unwrap().get_mut(0).unwrap() {
688+
&mut HTLCForwardInfo::AddHTLC(PendingAddHTLCInfo { ref mut forward_info, .. }) => {
689+
match forward_info.routing {
690+
PendingHTLCRouting::ReceiveKeysend { ref mut payment_data, .. } => {
691+
*payment_data = Some(msgs::FinalOnionHopData {
692+
payment_secret: PaymentSecret([43; 32]), // Doesn't match the secret used above
693+
total_msat: amount * 2,
694+
});
695+
},
696+
_ => panic!("Expected PendingHTLCRouting::ReceiveKeysend"),
697+
}
698+
},
699+
_ => {
700+
panic!("Unexpected HTLCForwardInfo");
701+
},
702+
}
718703
nodes[3].node.process_pending_htlc_forwards();
719704
let fail_type = HTLCHandlingFailureType::Receive { payment_hash };
720705
expect_and_process_pending_htlcs_and_htlc_handling_failed(&nodes[3], &[fail_type]);

0 commit comments

Comments
 (0)