Skip to content

Commit f0c6dfb

Browse files
Move claimable_htlcs to separate lock
1 parent 505102d commit f0c6dfb

File tree

1 file changed

+71
-67
lines changed

1 file changed

+71
-67
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 71 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -395,13 +395,6 @@ pub(super) enum RAACommitmentOrder {
395395
// Note this is only exposed in cfg(test):
396396
pub(super) struct ChannelHolder<Signer: Sign> {
397397
pub(super) by_id: HashMap<[u8; 32], Channel<Signer>>,
398-
/// Map from payment hash to the payment data and any HTLCs which are to us and can be
399-
/// failed/claimed by the user.
400-
///
401-
/// Note that while this is held in the same mutex as the channels themselves, no consistency
402-
/// guarantees are made about the channels given here actually existing anymore by the time you
403-
/// go to read them!
404-
claimable_htlcs: HashMap<PaymentHash, (events::PaymentPurpose, Vec<ClaimableHTLC>)>,
405398
/// Messages to send to peers - pushed to in the same lock that they are generated in (except
406399
/// for broadcast messages, where ordering isn't as strict).
407400
pub(super) pending_msg_events: Vec<MessageSendEvent>,
@@ -682,6 +675,8 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, M, T, F, L> = ChannelManage
682675
// | |
683676
// | |__`pending_inbound_payments`
684677
// | |
678+
// | |__`claimable_htlcs`
679+
// | |
685680
// | |__`pending_outbound_payments`
686681
// | |
687682
// | |__`best_block`
@@ -753,6 +748,15 @@ pub struct ChannelManager<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
753748
#[cfg(not(test))]
754749
forward_htlcs: Mutex<HashMap<u64, Vec<HTLCForwardInfo>>>,
755750

751+
/// Map from payment hash to the payment data and any HTLCs which are to us and can be
752+
/// failed/claimed by the user.
753+
///
754+
/// Note that, no consistency guarantees are made about the channels given here actually
755+
/// existing anymore by the time you go to read them!
756+
///
757+
/// See `ChannelManager` struct-level documentation for lock order requirements.
758+
claimable_htlcs: Mutex<HashMap<PaymentHash, (events::PaymentPurpose, Vec<ClaimableHTLC>)>>,
759+
756760
/// The set of outbound SCID aliases across all our channels, including unconfirmed channels
757761
/// and some closed channels which reached a usable state prior to being closed. This is used
758762
/// only to avoid duplicates, and is not persisted explicitly to disk, but rebuilt from the
@@ -1657,13 +1661,13 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
16571661

16581662
channel_state: Mutex::new(ChannelHolder{
16591663
by_id: HashMap::new(),
1660-
claimable_htlcs: HashMap::new(),
16611664
pending_msg_events: Vec::new(),
16621665
}),
16631666
outbound_scid_aliases: Mutex::new(HashSet::new()),
16641667
pending_inbound_payments: Mutex::new(HashMap::new()),
16651668
pending_outbound_payments: Mutex::new(HashMap::new()),
16661669
forward_htlcs: Mutex::new(HashMap::new()),
1670+
claimable_htlcs: Mutex::new(HashMap::new()),
16671671
id_to_peer: Mutex::new(HashMap::new()),
16681672
short_to_chan_info: FairRwLock::new(HashMap::new()),
16691673

@@ -3142,8 +3146,6 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
31423146
mem::swap(&mut forward_htlcs, &mut self.forward_htlcs.lock().unwrap());
31433147

31443148
for (short_chan_id, mut pending_forwards) in forward_htlcs {
3145-
let mut channel_state_lock = self.channel_state.lock().unwrap();
3146-
let channel_state = &mut *channel_state_lock;
31473149
if short_chan_id != 0 {
31483150
macro_rules! forwarding_channel_not_found {
31493151
() => {
@@ -3242,6 +3244,8 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
32423244
continue;
32433245
}
32443246
};
3247+
let mut channel_state_lock = self.channel_state.lock().unwrap();
3248+
let channel_state = &mut *channel_state_lock;
32453249
match channel_state.by_id.entry(forward_chan_id) {
32463250
hash_map::Entry::Vacant(_) => {
32473251
forwarding_channel_not_found!();
@@ -3434,7 +3438,8 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
34343438
payment_secret: $payment_data.payment_secret,
34353439
}
34363440
};
3437-
let (_, htlcs) = channel_state.claimable_htlcs.entry(payment_hash)
3441+
let mut claimable_htlcs = self.claimable_htlcs.lock().unwrap();
3442+
let (_, htlcs) = claimable_htlcs.entry(payment_hash)
34383443
.or_insert_with(|| (purpose(), Vec::new()));
34393444
if htlcs.len() == 1 {
34403445
if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
@@ -3502,7 +3507,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
35023507
check_total_value!(payment_data, payment_preimage);
35033508
},
35043509
OnionPayload::Spontaneous(preimage) => {
3505-
match channel_state.claimable_htlcs.entry(payment_hash) {
3510+
match self.claimable_htlcs.lock().unwrap().entry(payment_hash) {
35063511
hash_map::Entry::Vacant(e) => {
35073512
let purpose = events::PaymentPurpose::SpontaneousPayment(preimage);
35083513
e.insert((purpose.clone(), vec![claimable_htlc]));
@@ -3791,29 +3796,29 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
37913796

37923797
true
37933798
});
3799+
}
37943800

3795-
channel_state.claimable_htlcs.retain(|payment_hash, (_, htlcs)| {
3796-
if htlcs.is_empty() {
3797-
// This should be unreachable
3798-
debug_assert!(false);
3801+
self.claimable_htlcs.lock().unwrap().retain(|payment_hash, (_, htlcs)| {
3802+
if htlcs.is_empty() {
3803+
// This should be unreachable
3804+
debug_assert!(false);
3805+
return false;
3806+
}
3807+
if let OnionPayload::Invoice { .. } = htlcs[0].onion_payload {
3808+
// Check if we've received all the parts we need for an MPP (the value of the parts adds to total_msat).
3809+
// In this case we're not going to handle any timeouts of the parts here.
3810+
if htlcs[0].total_msat == htlcs.iter().fold(0, |total, htlc| total + htlc.value) {
3811+
return true;
3812+
} else if htlcs.into_iter().any(|htlc| {
3813+
htlc.timer_ticks += 1;
3814+
return htlc.timer_ticks >= MPP_TIMEOUT_TICKS
3815+
}) {
3816+
timed_out_mpp_htlcs.extend(htlcs.into_iter().map(|htlc| (htlc.prev_hop.clone(), payment_hash.clone())));
37993817
return false;
38003818
}
3801-
if let OnionPayload::Invoice { .. } = htlcs[0].onion_payload {
3802-
// Check if we've received all the parts we need for an MPP (the value of the parts adds to total_msat).
3803-
// In this case we're not going to handle any timeouts of the parts here.
3804-
if htlcs[0].total_msat == htlcs.iter().fold(0, |total, htlc| total + htlc.value) {
3805-
return true;
3806-
} else if htlcs.into_iter().any(|htlc| {
3807-
htlc.timer_ticks += 1;
3808-
return htlc.timer_ticks >= MPP_TIMEOUT_TICKS
3809-
}) {
3810-
timed_out_mpp_htlcs.extend(htlcs.into_iter().map(|htlc| (htlc.prev_hop.clone(), payment_hash.clone())));
3811-
return false;
3812-
}
3813-
}
3814-
true
3815-
});
3816-
}
3819+
}
3820+
true
3821+
});
38173822

38183823
for htlc_source in timed_out_mpp_htlcs.drain(..) {
38193824
let receiver = HTLCDestination::FailedPayment { payment_hash: htlc_source.1 };
@@ -3846,10 +3851,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
38463851
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) {
38473852
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
38483853

3849-
let removed_source = {
3850-
let mut channel_state = self.channel_state.lock().unwrap();
3851-
channel_state.claimable_htlcs.remove(payment_hash)
3852-
};
3854+
let removed_source = self.claimable_htlcs.lock().unwrap().remove(payment_hash);
38533855
if let Some((_, mut sources)) = removed_source {
38543856
for htlc in sources.drain(..) {
38553857
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
@@ -4151,7 +4153,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
41514153

41524154
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
41534155

4154-
let removed_source = self.channel_state.lock().unwrap().claimable_htlcs.remove(&payment_hash);
4156+
let removed_source = self.claimable_htlcs.lock().unwrap().remove(&payment_hash);
41554157
if let Some((payment_purpose, mut sources)) = removed_source {
41564158
assert!(!sources.is_empty());
41574159

@@ -6019,28 +6021,28 @@ where
60196021
}
60206022
true
60216023
});
6024+
}
60226025

6023-
if let Some(height) = height_opt {
6024-
channel_state.claimable_htlcs.retain(|payment_hash, (_, htlcs)| {
6025-
htlcs.retain(|htlc| {
6026-
// If height is approaching the number of blocks we think it takes us to get
6027-
// our commitment transaction confirmed before the HTLC expires, plus the
6028-
// number of blocks we generally consider it to take to do a commitment update,
6029-
// just give up on it and fail the HTLC.
6030-
if height >= htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER {
6031-
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
6032-
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(height));
6033-
6034-
timed_out_htlcs.push((HTLCSource::PreviousHopData(htlc.prev_hop.clone()), payment_hash.clone(), HTLCFailReason::Reason {
6035-
failure_code: 0x4000 | 15,
6036-
data: htlc_msat_height_data
6037-
}, HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }));
6038-
false
6039-
} else { true }
6040-
});
6041-
!htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
6026+
if let Some(height) = height_opt {
6027+
self.claimable_htlcs.lock().unwrap().retain(|payment_hash, (_, htlcs)| {
6028+
htlcs.retain(|htlc| {
6029+
// If height is approaching the number of blocks we think it takes us to get
6030+
// our commitment transaction confirmed before the HTLC expires, plus the
6031+
// number of blocks we generally consider it to take to do a commitment update,
6032+
// just give up on it and fail the HTLC.
6033+
if height >= htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER {
6034+
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
6035+
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(height));
6036+
6037+
timed_out_htlcs.push((HTLCSource::PreviousHopData(htlc.prev_hop.clone()), payment_hash.clone(), HTLCFailReason::Reason {
6038+
failure_code: 0x4000 | 15,
6039+
data: htlc_msat_height_data
6040+
}, HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }));
6041+
false
6042+
} else { true }
60426043
});
6043-
}
6044+
!htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
6045+
});
60446046
}
60456047

60466048
self.handle_init_event_channel_failures(failed_channels);
@@ -6775,16 +6777,18 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable for ChannelMana
67756777
}
67766778
}
67776779

6778-
let channel_state = self.channel_state.lock().unwrap();
6779-
let mut htlc_purposes: Vec<&events::PaymentPurpose> = Vec::new();
6780-
(channel_state.claimable_htlcs.len() as u64).write(writer)?;
6781-
for (payment_hash, (purpose, previous_hops)) in channel_state.claimable_htlcs.iter() {
6782-
payment_hash.write(writer)?;
6783-
(previous_hops.len() as u64).write(writer)?;
6784-
for htlc in previous_hops.iter() {
6785-
htlc.write(writer)?;
6780+
let mut htlc_purposes: Vec<events::PaymentPurpose> = Vec::new();
6781+
{
6782+
let claimable_htlcs = self.claimable_htlcs.lock().unwrap();
6783+
(claimable_htlcs.len() as u64).write(writer)?;
6784+
for (payment_hash, (purpose, previous_hops)) in claimable_htlcs.iter() {
6785+
payment_hash.write(writer)?;
6786+
(previous_hops.len() as u64).write(writer)?;
6787+
for htlc in previous_hops.iter() {
6788+
htlc.write(writer)?;
6789+
}
6790+
htlc_purposes.push(purpose.clone());
67866791
}
6787-
htlc_purposes.push(purpose);
67886792
}
67896793

67906794
let per_peer_state = self.per_peer_state.write().unwrap();
@@ -7389,14 +7393,14 @@ impl<'a, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
73897393

73907394
channel_state: Mutex::new(ChannelHolder {
73917395
by_id,
7392-
claimable_htlcs,
73937396
pending_msg_events: Vec::new(),
73947397
}),
73957398
inbound_payment_key: expanded_inbound_key,
73967399
pending_inbound_payments: Mutex::new(pending_inbound_payments),
73977400
pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()),
73987401

73997402
forward_htlcs: Mutex::new(forward_htlcs),
7403+
claimable_htlcs: Mutex::new(claimable_htlcs),
74007404
outbound_scid_aliases: Mutex::new(outbound_scid_aliases),
74017405
id_to_peer: Mutex::new(id_to_peer),
74027406
short_to_chan_info: FairRwLock::new(short_to_chan_info),

0 commit comments

Comments
 (0)