Skip to content

Commit 383ef94

Browse files
f - refactor claim_funds to only hold channel_state when necessary
1 parent c709bd4 commit 383ef94

File tree

1 file changed

+64
-63
lines changed

1 file changed

+64
-63
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 64 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4111,8 +4111,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
41114111

41124112
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(&self.total_consistency_lock, &self.persistence_notifier);
41134113

4114-
let mut channel_state = Some(self.channel_state.lock().unwrap());
4115-
let removed_source = channel_state.as_mut().unwrap().claimable_htlcs.remove(&payment_hash);
4114+
let removed_source = self.channel_state.lock().unwrap().claimable_htlcs.remove(&payment_hash);
41164115
if let Some((payment_purpose, mut sources)) = removed_source {
41174116
assert!(!sources.is_empty());
41184117

@@ -4130,72 +4129,77 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
41304129
let mut claimable_amt_msat = 0;
41314130
let mut expected_amt_msat = None;
41324131
let mut valid_mpp = true;
4133-
for htlc in sources.iter() {
4134-
if let None = channel_state.as_ref().unwrap().short_to_chan_info.get(&htlc.prev_hop.short_channel_id) {
4135-
valid_mpp = false;
4136-
break;
4137-
}
4138-
if expected_amt_msat.is_some() && expected_amt_msat != Some(htlc.total_msat) {
4139-
log_error!(self.logger, "Somehow ended up with an MPP payment with different total amounts - this should not be reachable!");
4140-
debug_assert!(false);
4141-
valid_mpp = false;
4142-
break;
4143-
}
4144-
expected_amt_msat = Some(htlc.total_msat);
4145-
if let OnionPayload::Spontaneous(_) = &htlc.onion_payload {
4146-
// We don't currently support MPP for spontaneous payments, so just check
4147-
// that there's one payment here and move on.
4148-
if sources.len() != 1 {
4149-
log_error!(self.logger, "Somehow ended up with an MPP spontaneous payment - this should not be reachable!");
4132+
let mut errs = Vec::new();
4133+
let mut claimed_any_htlcs = false;
4134+
{
4135+
let mut channel_state_lock = self.channel_state.lock().unwrap();
4136+
let channel_state = &mut *channel_state_lock;
4137+
for htlc in sources.iter() {
4138+
if let None = channel_state.short_to_chan_info.get(&htlc.prev_hop.short_channel_id) {
4139+
valid_mpp = false;
4140+
break;
4141+
}
4142+
if expected_amt_msat.is_some() && expected_amt_msat != Some(htlc.total_msat) {
4143+
log_error!(self.logger, "Somehow ended up with an MPP payment with different total amounts - this should not be reachable!");
41504144
debug_assert!(false);
41514145
valid_mpp = false;
41524146
break;
41534147
}
4154-
}
4148+
expected_amt_msat = Some(htlc.total_msat);
4149+
if let OnionPayload::Spontaneous(_) = &htlc.onion_payload {
4150+
// We don't currently support MPP for spontaneous payments, so just check
4151+
// that there's one payment here and move on.
4152+
if sources.len() != 1 {
4153+
log_error!(self.logger, "Somehow ended up with an MPP spontaneous payment - this should not be reachable!");
4154+
debug_assert!(false);
4155+
valid_mpp = false;
4156+
break;
4157+
}
4158+
}
41554159

4156-
claimable_amt_msat += htlc.value;
4157-
}
4158-
if sources.is_empty() || expected_amt_msat.is_none() {
4159-
log_info!(self.logger, "Attempted to claim an incomplete payment which no longer had any available HTLCs!");
4160-
return;
4161-
}
4162-
if claimable_amt_msat != expected_amt_msat.unwrap() {
4163-
log_info!(self.logger, "Attempted to claim an incomplete payment, expected {} msat, had {} available to claim.",
4164-
expected_amt_msat.unwrap(), claimable_amt_msat);
4165-
return;
4160+
claimable_amt_msat += htlc.value;
4161+
}
4162+
if sources.is_empty() || expected_amt_msat.is_none() {
4163+
log_info!(self.logger, "Attempted to claim an incomplete payment which no longer had any available HTLCs!");
4164+
return;
4165+
}
4166+
if claimable_amt_msat != expected_amt_msat.unwrap() {
4167+
log_info!(self.logger, "Attempted to claim an incomplete payment, expected {} msat, had {} available to claim.",
4168+
expected_amt_msat.unwrap(), claimable_amt_msat);
4169+
return;
4170+
}
4171+
if valid_mpp {
4172+
for htlc in sources.drain(..) {
4173+
match self.claim_funds_from_hop(&mut channel_state_lock, htlc.prev_hop, payment_preimage) {
4174+
ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) => {
4175+
if let msgs::ErrorAction::IgnoreError = err.err.action {
4176+
// We got a temporary failure updating monitor, but will claim the
4177+
// HTLC when the monitor updating is restored (or on chain).
4178+
log_error!(self.logger, "Temporary failure claiming HTLC, treating as success: {}", err.err.err);
4179+
claimed_any_htlcs = true;
4180+
} else { errs.push((pk, err)); }
4181+
},
4182+
ClaimFundsFromHop::PrevHopForceClosed => unreachable!("We already checked for channel existence, we can't fail here!"),
4183+
ClaimFundsFromHop::DuplicateClaim => {
4184+
// While we should never get here in most cases, if we do, it likely
4185+
// indicates that the HTLC was timed out some time ago and is no longer
4186+
// available to be claimed. Thus, it does not make sense to set
4187+
// `claimed_any_htlcs`.
4188+
},
4189+
ClaimFundsFromHop::Success(_) => claimed_any_htlcs = true,
4190+
}
4191+
}
4192+
}
41664193
}
4167-
4168-
let mut errs = Vec::new();
4169-
let mut claimed_any_htlcs = false;
4170-
for htlc in sources.drain(..) {
4171-
if !valid_mpp {
4172-
if channel_state.is_none() { channel_state = Some(self.channel_state.lock().unwrap()); }
4194+
if !valid_mpp {
4195+
for htlc in sources.drain(..) {
41734196
let mut htlc_msat_height_data = byte_utils::be64_to_array(htlc.value).to_vec();
41744197
htlc_msat_height_data.extend_from_slice(&byte_utils::be32_to_array(
4175-
self.best_block.read().unwrap().height()));
4198+
self.best_block.read().unwrap().height()));
41764199
self.fail_htlc_backwards_internal(
4177-
HTLCSource::PreviousHopData(htlc.prev_hop), &payment_hash,
4178-
HTLCFailReason::Reason { failure_code: 0x4000|15, data: htlc_msat_height_data },
4179-
HTLCDestination::FailedPayment { payment_hash } );
4180-
} else {
4181-
match self.claim_funds_from_hop(channel_state.as_mut().unwrap(), htlc.prev_hop, payment_preimage) {
4182-
ClaimFundsFromHop::MonitorUpdateFail(pk, err, _) => {
4183-
if let msgs::ErrorAction::IgnoreError = err.err.action {
4184-
// We got a temporary failure updating monitor, but will claim the
4185-
// HTLC when the monitor updating is restored (or on chain).
4186-
log_error!(self.logger, "Temporary failure claiming HTLC, treating as success: {}", err.err.err);
4187-
claimed_any_htlcs = true;
4188-
} else { errs.push((pk, err)); }
4189-
},
4190-
ClaimFundsFromHop::PrevHopForceClosed => unreachable!("We already checked for channel existence, we can't fail here!"),
4191-
ClaimFundsFromHop::DuplicateClaim => {
4192-
// While we should never get here in most cases, if we do, it likely
4193-
// indicates that the HTLC was timed out some time ago and is no longer
4194-
// available to be claimed. Thus, it does not make sense to set
4195-
// `claimed_any_htlcs`.
4196-
},
4197-
ClaimFundsFromHop::Success(_) => claimed_any_htlcs = true,
4198-
}
4200+
HTLCSource::PreviousHopData(htlc.prev_hop), &payment_hash,
4201+
HTLCFailReason::Reason { failure_code: 0x4000|15, data: htlc_msat_height_data },
4202+
HTLCDestination::FailedPayment { payment_hash } );
41994203
}
42004204
}
42014205

@@ -4207,10 +4211,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
42074211
});
42084212
}
42094213

4210-
// Now that we've done the entire above loop in one lock, we can handle any errors
4211-
// which were generated.
4212-
channel_state.take();
4213-
4214+
// Now we can handle any errors which were generated.
42144215
for (counterparty_node_id, err) in errs.drain(..) {
42154216
let res: Result<(), _> = Err(err);
42164217
let _ = handle_error!(self, res, counterparty_node_id);

0 commit comments

Comments
 (0)