Skip to content

Commit 5f794d3

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 e008be3 commit 5f794d3

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
@@ -4147,8 +4147,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
41474147
let mut expected_amt_msat = None;
41484148
let mut valid_mpp = true;
41494149
let mut errs = Vec::new();
4150-
let mut channel_state_lock = self.channel_state.lock().unwrap();
4151-
let channel_state = &mut *channel_state_lock;
4150+
let mut channel_state = Some(self.channel_state.lock().unwrap());
41524151
for htlc in sources.iter() {
41534152
let chan_id = match self.short_to_chan_info.read().unwrap().get(&htlc.prev_hop.short_channel_id) {
41544153
Some((_cp_id, chan_id)) => chan_id.clone(),
@@ -4158,7 +4157,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
41584157
}
41594158
};
41604159

4161-
if let None = channel_state.by_id.get(&chan_id) {
4160+
if let None = channel_state.as_ref().unwrap().by_id.get(&chan_id) {
41624161
valid_mpp = false;
41634162
break;
41644163
}
@@ -4196,7 +4195,9 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
41964195
}
41974196
if valid_mpp {
41984197
for htlc in sources.drain(..) {
4199-
match self.claim_funds_from_hop(&mut channel_state_lock, htlc.prev_hop, payment_preimage,
4198+
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
4199+
match self.claim_funds_from_hop(channel_state.take().unwrap(), htlc.prev_hop,
4200+
payment_preimage,
42004201
|_| Some(MonitorUpdateCompletionAction::PaymentClaimed { payment_hash }))
42014202
{
42024203
ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) => {
@@ -4206,7 +4207,12 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
42064207
log_error!(self.logger, "Temporary failure claiming HTLC, treating as success: {}", err.err.err);
42074208
} else { errs.push((pk, err)); }
42084209
},
4209-
ClaimFundsFromHop::PrevHopForceClosed => unreachable!("We already checked for channel existence, we can't fail here!"),
4210+
ClaimFundsFromHop::PrevHopForceClosed => {
4211+
// This should be incredibly rare - we checked that all the channels were
4212+
// open above, though as we release the lock at each loop iteration it's
4213+
// still possible. We should still claim the HTLC on-chain through the
4214+
// closed-channel-update generated in claim_funds_from_hop.
4215+
},
42104216
ClaimFundsFromHop::DuplicateClaim => {
42114217
// While we should never get here in most cases, if we do, it likely
42124218
// indicates that the HTLC was timed out some time ago and is no longer
@@ -4217,7 +4223,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
42174223
}
42184224
}
42194225
}
4220-
mem::drop(channel_state_lock);
4226+
mem::drop(channel_state);
42214227
if !valid_mpp {
42224228
for htlc in sources.drain(..) {
42234229
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
@@ -4238,13 +4244,13 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
42384244
}
42394245

42404246
fn claim_funds_from_hop<ComplFunc: FnOnce(Option<u64>) -> Option<MonitorUpdateCompletionAction>>(&self,
4241-
channel_state_lock: &mut MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
4247+
mut channel_state_lock: MutexGuard<ChannelHolder<<K::Target as KeysInterface>::Signer>>,
42424248
prev_hop: HTLCPreviousHopData, payment_preimage: PaymentPreimage, completion_action: ComplFunc)
42434249
-> ClaimFundsFromHop {
42444250
//TODO: Delay the claimed_funds relaying just like we do outbound relay!
42454251

42464252
let chan_id = prev_hop.outpoint.to_channel_id();
4247-
let channel_state = &mut **channel_state_lock;
4253+
let channel_state = &mut *channel_state_lock;
42484254
if let hash_map::Entry::Occupied(mut chan) = channel_state.by_id.entry(chan_id) {
42494255
match chan.get_mut().get_update_fulfill_htlc_and_commit(prev_hop.htlc_id, payment_preimage, &self.logger) {
42504256
Ok(msgs_monitor_option) => {
@@ -4354,7 +4360,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
43544360
}
43554361
}
43564362

4357-
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]) {
4363+
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]) {
43584364
match source {
43594365
HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => {
43604366
mem::drop(channel_state_lock);
@@ -4401,7 +4407,7 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
44014407
},
44024408
HTLCSource::PreviousHopData(hop_data) => {
44034409
let prev_outpoint = hop_data.outpoint;
4404-
let res = self.claim_funds_from_hop(&mut channel_state_lock, hop_data, payment_preimage,
4410+
let res = self.claim_funds_from_hop(channel_state_lock, hop_data, payment_preimage,
44054411
|htlc_claim_value_msat| {
44064412
if let Some(forwarded_htlc_value) = forwarded_htlc_value_msat {
44074413
let fee_earned_msat = if let Some(claimed_htlc_value) = htlc_claim_value_msat {
@@ -4419,7 +4425,6 @@ impl<M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelManager<M, T, K, F
44194425
}})
44204426
} else { None }
44214427
});
4422-
mem::drop(channel_state_lock);
44234428
if let ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) = res {
44244429
let result: Result<(), _> = Err(err);
44254430
let _ = handle_error!(self, result, pk);

0 commit comments

Comments
 (0)