Skip to content

Commit 3bec7cf

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 6d82647 commit 3bec7cf

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
@@ -4287,8 +4287,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
42874287
let mut expected_amt_msat = None;
42884288
let mut valid_mpp = true;
42894289
let mut errs = Vec::new();
4290-
let mut channel_state_lock = self.channel_state.lock().unwrap();
4291-
let channel_state = &mut *channel_state_lock;
4290+
let mut channel_state = Some(self.channel_state.lock().unwrap());
42924291
for htlc in sources.iter() {
42934292
let chan_id = match self.short_to_chan_info.read().unwrap().get(&htlc.prev_hop.short_channel_id) {
42944293
Some((_cp_id, chan_id)) => chan_id.clone(),
@@ -4298,7 +4297,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
42984297
}
42994298
};
43004299

4301-
if let None = channel_state.by_id.get(&chan_id) {
4300+
if let None = channel_state.as_ref().unwrap().by_id.get(&chan_id) {
43024301
valid_mpp = false;
43034302
break;
43044303
}
@@ -4336,7 +4335,9 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43364335
}
43374336
if valid_mpp {
43384337
for htlc in sources.drain(..) {
4339-
match self.claim_funds_from_hop(&mut channel_state_lock, htlc.prev_hop, payment_preimage,
4338+
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
4339+
match self.claim_funds_from_hop(channel_state.take().unwrap(), htlc.prev_hop,
4340+
payment_preimage,
43404341
|_| Some(MonitorUpdateCompletionAction::PaymentClaimed { payment_hash }))
43414342
{
43424343
ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) => {
@@ -4346,7 +4347,12 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43464347
log_error!(self.logger, "Temporary failure claiming HTLC, treating as success: {}", err.err.err);
43474348
} else { errs.push((pk, err)); }
43484349
},
4349-
ClaimFundsFromHop::PrevHopForceClosed => unreachable!("We already checked for channel existence, we can't fail here!"),
4350+
ClaimFundsFromHop::PrevHopForceClosed => {
4351+
// This should be incredibly rare - we checked that all the channels were
4352+
// open above, though as we release the lock at each loop iteration it's
4353+
// still possible. We should still claim the HTLC on-chain through the
4354+
// closed-channel-update generated in claim_funds_from_hop.
4355+
},
43504356
ClaimFundsFromHop::DuplicateClaim => {
43514357
// While we should never get here in most cases, if we do, it likely
43524358
// indicates that the HTLC was timed out some time ago and is no longer
@@ -4357,7 +4363,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43574363
}
43584364
}
43594365
}
4360-
mem::drop(channel_state_lock);
4366+
mem::drop(channel_state);
43614367
if !valid_mpp {
43624368
for htlc in sources.drain(..) {
43634369
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
@@ -4378,13 +4384,13 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43784384
}
43794385

43804386
fn claim_funds_from_hop<ComplFunc: FnOnce(Option<u64>) -> Option<MonitorUpdateCompletionAction>>(&self,
4381-
channel_state_lock: &mut MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
4387+
mut channel_state_lock: MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
43824388
prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage, completion_action: ComplFunc)
43834389
-> ClaimFundsFromHop {
43844390
//TODO: Delay the claimed_funds relaying just like we do outbound relay!
43854391

43864392
let chan_id = prev_hop.outpoint.to_channel_id();
4387-
let channel_state = &mut **channel_state_lock;
4393+
let channel_state = &mut *channel_state_lock;
43884394
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(chan_id) {
43894395
match chan.get_mut().get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &self.logger) {
43904396
Ok(msgs_monitor_option) => {
@@ -4494,7 +4500,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
44944500
}
44954501
}
44964502

4497-
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]) {
4503+
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]) {
44984504
match source {
44994505
HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
45004506
mem::drop(channel_state_lock);
@@ -4541,7 +4547,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
45414547
},
45424548
HTLCSource::PreviousHopData(hop_data) => {
45434549
let prev_outpoint = hop_data.outpoint;
4544-
let res = self.claim_funds_from_hop(&mut channel_state_lock, hop_data, payment_preimage,
4550+
let res = self.claim_funds_from_hop(channel_state_lock, hop_data, payment_preimage,
45454551
|htlc_claim_value_msat| {
45464552
if let Some(forwarded_htlc_value) = forwarded_htlc_value_msat {
45474553
let fee_earned_msat = if let Some(claimed_htlc_value) = htlc_claim_value_msat {
@@ -4559,7 +4565,6 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
45594565
}})
45604566
} else { None }
45614567
});
4562-
mem::drop(channel_state_lock);
45634568
if let ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) = res {
45644569
let result: Result<(), _> = Err(err);
45654570
let _ = handle_error!(self, result, pk);

0 commit comments

Comments
 (0)