Skip to content

Commit f048a08

Browse files
Move claimable_htlcs to separate lock
1 parent 6772609 commit f048a08

File tree

1 file changed

+54
-48
lines changed

1 file changed

+54
-48
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 54 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -401,13 +401,6 @@ pub(super) struct ChannelHolder<Signer: Sign> {
401401
/// SCIDs being added once the funding transaction is confirmed at the channel's required
402402
/// confirmation depth.
403403
pub(super) short_to_chan_info: HashMap<u64, (PublicKey, [u8; 32])>,
404-
/// Map from payment hash to the payment data and any HTLCs which are to us and can be
405-
/// failed/claimed by the user.
406-
///
407-
/// Note that while this is held in the same mutex as the channels themselves, no consistency
408-
/// guarantees are made about the channels given here actually existing anymore by the time you
409-
/// go to read them!
410-
claimable_htlcs: HashMap<PaymentHash, (events::PaymentPurpose, Vec<ClaimableHTLC>)>,
411404
/// Messages to send to peers - pushed to in the same lock that they are generated in (except
412405
/// for broadcast messages, where ordering isn't as strict).
413406
pub(super) pending_msg_events: Vec<MessageSendEvent>,
@@ -691,6 +684,8 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, M, T, F, L> = ChannelManage
691684
// | |
692685
// | |__`pending_inbound_payments`
693686
// | |
687+
// | |__`claimable_htlcs`
688+
// | |
694689
// | |__`pending_outbound_payments`
695690
// | |
696691
// | |__`best_block`
@@ -762,6 +757,15 @@ pub struct ChannelManager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref,
762757
#[cfg(not(test))]
763758
forward_htlcs: Mutex<HashMap<u64, Vec<HTLCForwardInfo>>>,
764759

760+
/// Map from payment hash to the payment data and any HTLCs which are to us and can be
761+
/// failed/claimed by the user.
762+
///
763+
/// Note that, no consistency guarantees are made about the channels given here actually
764+
/// existing anymore by the time you go to read them!
765+
///
766+
/// See `ChannelManager` struct-level documentation for lock order requirements.
767+
claimable_htlcs: Mutex<HashMap<PaymentHash, (events::PaymentPurpose, Vec<ClaimableHTLC>)>>,
768+
765769
/// The set of outbound SCID aliases across all our channels, including unconfirmed channels
766770
/// and some closed channels which reached a usable state prior to being closed. This is used
767771
/// only to avoid duplicates, and is not persisted explicitly to disk, but rebuilt from the
@@ -1626,13 +1630,13 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
16261630
channel_state: Mutex::new(ChannelHolder{
16271631
by_id: HashMap::new(),
16281632
short_to_chan_info: HashMap::new(),
1629-
claimable_htlcs: HashMap::new(),
16301633
pending_msg_events: Vec::new(),
16311634
}),
16321635
outbound_scid_aliases: Mutex::new(HashSet::new()),
16331636
pending_inbound_payments: Mutex::new(HashMap::new()),
16341637
pending_outbound_payments: Mutex::new(HashMap::new()),
16351638
forward_htlcs: Mutex::new(HashMap::new()),
1639+
claimable_htlcs: Mutex::new(HashMap::new()),
16361640
id_to_peer: Mutex::new(HashMap::new()),
16371641

16381642
our_network_key: keys_manager.get_node_secret(Recipient::Node).unwrap(),
@@ -3046,9 +3050,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
30463050
mem::swap(&mut forward_htlcs, &mut self.forward_htlcs.lock().unwrap());
30473051

30483052
for (short_chan_id, mut pending_forwards) in forward_htlcs {
3049-
let mut channel_state_lock = self.channel_state.lock().unwrap();
3050-
let channel_state = &mut *channel_state_lock;
30513053
if short_chan_id != 0 {
3054+
let mut channel_state_lock = self.channel_state.lock().unwrap();
3055+
let channel_state = &mut *channel_state_lock;
30523056
let forward_chan_id = match channel_state.short_to_chan_info.get(&short_chan_id) {
30533057
Some((_cp_id, chan_id)) => chan_id.clone(),
30543058
None => {
@@ -3329,7 +3333,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33293333
payment_secret: $payment_data.payment_secret,
33303334
}
33313335
};
3332-
let (_, htlcs) = channel_state.claimable_htlcs.entry(payment_hash)
3336+
let mut claimable_htlcs = self.claimable_htlcs.lock().unwrap();
3337+
let (_, htlcs) = claimable_htlcs.entry(payment_hash)
33333338
.or_insert_with(|| (purpose(), Vec::new()));
33343339
if htlcs.len() == 1 {
33353340
if let OnionPayload::Spontaneous(_) = htlcs[0].onion_payload {
@@ -3397,7 +3402,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
33973402
check_total_value!(payment_data, payment_preimage);
33983403
},
33993404
OnionPayload::Spontaneous(preimage) => {
3400-
match channel_state.claimable_htlcs.entry(payment_hash) {
3405+
match self.claimable_htlcs.lock().unwrap().entry(payment_hash) {
34013406
hash_map::Entry::Vacant(e) => {
34023407
let purpose = events::PaymentPurpose::SpontaneousPayment(preimage);
34033408
e.insert((purpose.clone(), vec![claimable_htlc]));
@@ -3650,7 +3655,9 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
36503655
true
36513656
});
36523657

3653-
channel_state.claimable_htlcs.retain(|payment_hash, (_, htlcs)| {
3658+
mem::drop(channel_state);
3659+
3660+
self.claimable_htlcs.lock().unwrap().retain(|payment_hash, (_, htlcs)| {
36543661
if htlcs.is_empty() {
36553662
// This should be unreachable
36563663
debug_assert!(false);
@@ -3701,10 +3708,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
37013708
pub fn fail_htlc_backwards(&self, payment_hash: &PaymentHash) {
37023709
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
37033710

3704-
let removed_source = {
3705-
let mut channel_state = self.channel_state.lock().unwrap();
3706-
channel_state.claimable_htlcs.remove(payment_hash)
3707-
};
3711+
let removed_source = self.claimable_htlcs.lock().unwrap().remove(payment_hash);
37083712
if let Some((_, mut sources)) = removed_source {
37093713
for htlc in sources.drain(..) {
37103714
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
@@ -4006,7 +4010,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
40064010

40074011
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
40084012

4009-
let removed_source = self.channel_state.lock().unwrap().claimable_htlcs.remove(&payment_hash);
4013+
let removed_source = self.claimable_htlcs.lock().unwrap().remove(&payment_hash);
40104014
if let Some((payment_purpose, mut sources)) = removed_source {
40114015
assert!(!sources.is_empty());
40124016

@@ -5883,28 +5887,28 @@ where
58835887
}
58845888
true
58855889
});
5890+
}
58865891

5887-
if let Some(height) = height_opt {
5888-
channel_state.claimable_htlcs.retain(|payment_hash, (_, htlcs)| {
5889-
htlcs.retain(|htlc| {
5890-
// If height is approaching the number of blocks we think it takes us to get
5891-
// our commitment transaction confirmed before the HTLC expires, plus the
5892-
// number of blocks we generally consider it to take to do a commitment update,
5893-
// just give up on it and fail the HTLC.
5894-
if height >= htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER {
5895-
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
5896-
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(height));
5897-
5898-
timed_out_htlcs.push((HTLCSource::PreviousHopData(htlc.prev_hop.clone()), payment_hash.clone(), HTLCFailReason::Reason {
5899-
failure_code: 0x4000 | 15,
5900-
data: htlc_msat_height_data
5901-
}, HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }));
5902-
false
5903-
} else { true }
5904-
});
5905-
!htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
5892+
if let Some(height) = height_opt {
5893+
self.claimable_htlcs.lock().unwrap().retain(|payment_hash, (_, htlcs)| {
5894+
htlcs.retain(|htlc| {
5895+
// If height is approaching the number of blocks we think it takes us to get
5896+
// our commitment transaction confirmed before the HTLC expires, plus the
5897+
// number of blocks we generally consider it to take to do a commitment update,
5898+
// just give up on it and fail the HTLC.
5899+
if height >= htlc.cltv_expiry - HTLC_FAIL_BACK_BUFFER {
5900+
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
5901+
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(height));
5902+
5903+
timed_out_htlcs.push((HTLCSource::PreviousHopData(htlc.prev_hop.clone()), payment_hash.clone(), HTLCFailReason::Reason {
5904+
failure_code: 0x4000 | 15,
5905+
data: htlc_msat_height_data
5906+
}, HTLCDestination::FailedPayment { payment_hash: payment_hash.clone() }));
5907+
false
5908+
} else { true }
59065909
});
5907-
}
5910+
!htlcs.is_empty() // Only retain this entry if htlcs has at least one entry.
5911+
});
59085912
}
59095913

59105914
self.handle_init_event_channel_failures(failed_channels);
@@ -6639,16 +6643,18 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Writeable f
66396643
}
66406644
}
66416645

6642-
let channel_state = self.channel_state.lock().unwrap();
6643-
let mut htlc_purposes: Vec<&events::PaymentPurpose> = Vec::new();
6644-
(channel_state.claimable_htlcs.len() as u64).write(writer)?;
6645-
for (payment_hash, (purpose, previous_hops)) in channel_state.claimable_htlcs.iter() {
6646-
payment_hash.write(writer)?;
6647-
(previous_hops.len() as u64).write(writer)?;
6648-
for htlc in previous_hops.iter() {
6649-
htlc.write(writer)?;
6646+
let mut htlc_purposes: Vec<events::PaymentPurpose> = Vec::new();
6647+
{
6648+
let claimable_htlcs = self.claimable_htlcs.lock().unwrap();
6649+
(claimable_htlcs.len() as u64).write(writer)?;
6650+
for (payment_hash, (purpose, previous_hops)) in claimable_htlcs.iter() {
6651+
payment_hash.write(writer)?;
6652+
(previous_hops.len() as u64).write(writer)?;
6653+
for htlc in previous_hops.iter() {
6654+
htlc.write(writer)?;
6655+
}
6656+
htlc_purposes.push(purpose.clone());
66506657
}
6651-
htlc_purposes.push(purpose);
66526658
}
66536659

66546660
let per_peer_state = self.per_peer_state.write().unwrap();
@@ -7244,14 +7250,14 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
72447250
channel_state: Mutex::new(ChannelHolder {
72457251
by_id,
72467252
short_to_chan_info,
7247-
claimable_htlcs,
72487253
pending_msg_events: Vec::new(),
72497254
}),
72507255
inbound_payment_key: expanded_inbound_key,
72517256
pending_inbound_payments: Mutex::new(pending_inbound_payments),
72527257
pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()),
72537258

72547259
forward_htlcs: Mutex::new(forward_htlcs),
7260+
claimable_htlcs: Mutex::new(claimable_htlcs),
72557261
outbound_scid_aliases: Mutex::new(outbound_scid_aliases),
72567262
id_to_peer: Mutex::new(id_to_peer),
72577263
fake_scid_rand_bytes: fake_scid_rand_bytes.unwrap(),

0 commit comments

Comments
 (0)