Skip to content

Commit f9a4793

Browse files
committed
Don't hold channel_state lock for entire duration of claim_funds
When `claim_funds` has to claim multiple HTLCs as a part of a single MPP payment, it currently does so holding the `channel_state` lock for the entire duration of the claim loop. Here we swap that for taking the lock once for each HTLC. This allows us to be more flexible with locks going forward, and ultimately isn't a huge change - if our counterparty intends to force-close a channel, us choosing to ignore it by holding the `channel_state` lock for the duration of the claim isn't going to result in a commitment update, it will just result in the preimage already being in the `ChannelMonitor`.
1 parent 6262b84 commit f9a4793

File tree

1 file changed

+16
-11
lines changed

1 file changed

+16
-11
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4294,8 +4294,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
42944294
let mut expected_amt_msat = None;
42954295
let mut valid_mpp = true;
42964296
let mut errs = Vec::new();
4297-
let mut channel_state_lock = self.channel_state.lock().unwrap();
4298-
let channel_state = &mut *channel_state_lock;
4297+
let mut channel_state = Some(self.channel_state.lock().unwrap());
42994298
for htlc in sources.iter() {
43004299
let chan_id = match self.short_to_chan_info.read().unwrap().get(&htlc.prev_hop.short_channel_id) {
43014300
Some((_cp_id, chan_id)) => chan_id.clone(),
@@ -4305,7 +4304,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43054304
}
43064305
};
43074306

4308-
if let None = channel_state.by_id.get(&chan_id) {
4307+
if let None = channel_state.as_ref().unwrap().by_id.get(&chan_id) {
43094308
valid_mpp = false;
43104309
break;
43114310
}
@@ -4343,7 +4342,9 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43434342
}
43444343
if valid_mpp {
43454344
for htlc in sources.drain(..) {
4346-
match self.claim_funds_from_hop(&mut channel_state_lock, htlc.prev_hop, payment_preimage,
4345+
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
4346+
match self.claim_funds_from_hop(channel_state.take().unwrap(), htlc.prev_hop,
4347+
payment_preimage,
43474348
|_| Some(MonitorUpdateCompletionAction::PaymentClaimed { payment_hash }))
43484349
{
43494350
ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) => {
@@ -4353,7 +4354,12 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43534354
log_error!(self.logger, "Temporary failure claiming HTLC, treating as success: {}", err.err.err);
43544355
} else { errs.push((pk, err)); }
43554356
},
4356-
ClaimFundsFromHop::PrevHopForceClosed => unreachable!("We already checked for channel existence, we can't fail here!"),
4357+
ClaimFundsFromHop::PrevHopForceClosed => {
4358+
// This should be incredibly rare - we checked that all the channels were
4359+
// open above, though as we release the lock at each loop iteration it's
4360+
// still possible. We should still claim the HTLC on-chain through the
4361+
// closed-channel-update generated in claim_funds_from_hop.
4362+
},
43574363
ClaimFundsFromHop::DuplicateClaim => {
43584364
// While we should never get here in most cases, if we do, it likely
43594365
// indicates that the HTLC was timed out some time ago and is no longer
@@ -4364,7 +4370,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43644370
}
43654371
}
43664372
}
4367-
mem::drop(channel_state_lock);
4373+
mem::drop(channel_state);
43684374
if !valid_mpp {
43694375
for htlc in sources.drain(..) {
43704376
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
@@ -4385,13 +4391,13 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43854391
}
43864392

43874393
fn claim_funds_from_hop<ComplFunc: FnOnce(Option<u64>) -> Option<MonitorUpdateCompletionAction>>(&self,
4388-
channel_state_lock: &mut MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
4394+
mut channel_state_lock: MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
43894395
prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage, completion_action: ComplFunc)
43904396
-> ClaimFundsFromHop {
43914397
//TODO: Delay the claimed_funds relaying just like we do outbound relay!
43924398

43934399
let chan_id = prev_hop.outpoint.to_channel_id();
4394-
let channel_state = &mut **channel_state_lock;
4400+
let channel_state = &mut *channel_state_lock;
43954401
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(chan_id) {
43964402
match chan.get_mut().get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &self.logger) {
43974403
Ok(msgs_monitor_option) => {
@@ -4500,7 +4506,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
45004506
}
45014507
}
45024508

4503-
fn claim_funds_internal(&self, mut channel_state_lock: MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>, source: HTLCSource, payment_preimage: PaymentPreimage, forwarded_htlc_value_msat: Option<u64>, from_onchain: bool, next_channel_id: [u8; 32]) {
4509+
fn claim_funds_internal(&self, channel_state_lock: MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>, source: HTLCSource, payment_preimage: PaymentPreimage, forwarded_htlc_value_msat: Option<u64>, from_onchain: bool, next_channel_id: [u8; 32]) {
45044510
match source {
45054511
HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
45064512
mem::drop(channel_state_lock);
@@ -4547,7 +4553,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
45474553
},
45484554
HTLCSource::PreviousHopData(hop_data) => {
45494555
let prev_outpoint = hop_data.outpoint;
4550-
let res = self.claim_funds_from_hop(&mut channel_state_lock, hop_data, payment_preimage,
4556+
let res = self.claim_funds_from_hop(channel_state_lock, hop_data, payment_preimage,
45514557
|htlc_claim_value_msat| {
45524558
if let Some(forwarded_htlc_value) = forwarded_htlc_value_msat {
45534559
let fee_earned_msat = if let Some(claimed_htlc_value) = htlc_claim_value_msat {
@@ -4565,7 +4571,6 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
45654571
}})
45664572
} else { None }
45674573
});
4568-
mem::drop(channel_state_lock);
45694574
if let ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) = res {
45704575
let result: Result<(), _> = Err(err);
45714576
let _ = handle_error!(self, result, pk);

0 commit comments

Comments
 (0)