Skip to content

Commit a506e9c

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 38c6c7d commit a506e9c

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
@@ -4300,8 +4300,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43004300
let mut expected_amt_msat = None;
43014301
let mut valid_mpp = true;
43024302
let mut errs = Vec::new();
4303-
let mut channel_state_lock = self.channel_state.lock().unwrap();
4304-
let channel_state = &mut *channel_state_lock;
4303+
let mut channel_state = Some(self.channel_state.lock().unwrap());
43054304
for htlc in sources.iter() {
43064305
let chan_id = match self.short_to_chan_info.read().unwrap().get(&htlc.prev_hop.short_channel_id) {
43074306
Some((_cp_id, chan_id)) => chan_id.clone(),
@@ -4311,7 +4310,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43114310
}
43124311
};
43134312

4314-
if let None = channel_state.by_id.get(&chan_id) {
4313+
if let None = channel_state.as_ref().unwrap().by_id.get(&chan_id) {
43154314
valid_mpp = false;
43164315
break;
43174316
}
@@ -4349,7 +4348,9 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43494348
}
43504349
if valid_mpp {
43514350
for htlc in sources.drain(..) {
4352-
match self.claim_funds_from_hop(&mut channel_state_lock, htlc.prev_hop, payment_preimage,
4351+
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
4352+
match self.claim_funds_from_hop(channel_state.take().unwrap(), htlc.prev_hop,
4353+
payment_preimage,
43534354
|_| Some(MonitorUpdateCompletionAction::PaymentClaimed { payment_hash }))
43544355
{
43554356
ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) => {
@@ -4359,7 +4360,12 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43594360
log_error!(self.logger, "Temporary failure claiming HTLC, treating as success: {}", err.err.err);
43604361
} else { errs.push((pk, err)); }
43614362
},
4362-
ClaimFundsFromHop::PrevHopForceClosed => unreachable!("We already checked for channel existence, we can't fail here!"),
4363+
ClaimFundsFromHop::PrevHopForceClosed => {
4364+
// This should be incredibly rare - we checked that all the channels were
4365+
// open above, though as we release the lock at each loop iteration it's
4366+
// still possible. We should still claim the HTLC on-chain through the
4367+
// closed-channel-update generated in claim_funds_from_hop.
4368+
},
43634369
ClaimFundsFromHop::DuplicateClaim => {
43644370
// While we should never get here in most cases, if we do, it likely
43654371
// indicates that the HTLC was timed out some time ago and is no longer
@@ -4370,7 +4376,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43704376
}
43714377
}
43724378
}
4373-
mem::drop(channel_state_lock);
4379+
mem::drop(channel_state);
43744380
if !valid_mpp {
43754381
for htlc in sources.drain(..) {
43764382
let mut htlc_msat_height_data = htlc.value.to_be_bytes().to_vec();
@@ -4390,13 +4396,13 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43904396
}
43914397

43924398
fn claim_funds_from_hop<ComplFunc: FnOnce(Option<u64>) -> Option<MonitorUpdateCompletionAction>>(&self,
4393-
channel_state_lock: &mut MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
4399+
mut channel_state_lock: MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
43944400
prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage, completion_action: ComplFunc)
43954401
-> ClaimFundsFromHop {
43964402
//TODO: Delay the claimed_funds relaying just like we do outbound relay!
43974403

43984404
let chan_id = prev_hop.outpoint.to_channel_id();
4399-
let channel_state = &mut **channel_state_lock;
4405+
let channel_state = &mut *channel_state_lock;
44004406
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(chan_id) {
44014407
match chan.get_mut().get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &self.logger) {
44024408
Ok(msgs_monitor_option) => {
@@ -4505,7 +4511,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
45054511
}
45064512
}
45074513

4508-
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]) {
4514+
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]) {
45094515
match source {
45104516
HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
45114517
mem::drop(channel_state_lock);
@@ -4552,7 +4558,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
45524558
},
45534559
HTLCSource::PreviousHopData(hop_data) => {
45544560
let prev_outpoint = hop_data.outpoint;
4555-
let res = self.claim_funds_from_hop(&mut channel_state_lock, hop_data, payment_preimage,
4561+
let res = self.claim_funds_from_hop(channel_state_lock, hop_data, payment_preimage,
45564562
|htlc_claim_value_msat| {
45574563
if let Some(forwarded_htlc_value) = forwarded_htlc_value_msat {
45584564
let fee_earned_msat = if let Some(claimed_htlc_value) = htlc_claim_value_msat {
@@ -4570,7 +4576,6 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
45704576
}})
45714577
} else { None }
45724578
});
4573-
mem::drop(channel_state_lock);
45744579
if let ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) = res {
45754580
let result: Result<(), _> = Err(err);
45764581
let _ = handle_error!(self, result, pk);

0 commit comments

Comments
 (0)