Skip to content

Commit 5786674

Browse files
Merge pull request #3619 from TheBlueMatt/2025-02-merge-chanmon-lockdown
Only generate a post-close lock ChannelMonitorUpdate if we need one
2 parents 47cb737 + cd2e169 commit 5786674

File tree

2 files changed

+42
-45
lines changed

2 files changed

+42
-45
lines changed

lightning/src/chain/channelmonitor.rs

Lines changed: 40 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,8 +1536,8 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
15361536
fn provide_latest_holder_commitment_tx(
15371537
&self, holder_commitment_tx: HolderCommitmentTransaction,
15381538
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
1539-
) -> Result<(), ()> {
1540-
self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs, &Vec::new(), Vec::new()).map_err(|_| ())
1539+
) {
1540+
self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs, &Vec::new(), Vec::new())
15411541
}
15421542

15431543
/// This is used to provide payment preimage(s) out-of-band during startup without updating the
@@ -1774,10 +1774,14 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitor<Signer> {
17741774
self.inner.lock().unwrap().get_cur_holder_commitment_number()
17751775
}
17761776

1777-
/// Gets whether we've been notified that this channel is closed by the `ChannelManager` (i.e.
1778-
/// via a [`ChannelMonitorUpdateStep::ChannelForceClosed`]).
1779-
pub(crate) fn offchain_closed(&self) -> bool {
1780-
self.inner.lock().unwrap().lockdown_from_offchain
1777+
/// Fetches whether this monitor has marked the channel as closed and will refuse any further
1778+
/// updates to the commitment transactions.
1779+
///
1780+
/// It can be marked closed in a few different ways, including via a
1781+
/// [`ChannelMonitorUpdateStep::ChannelForceClosed`] or if the channel has been closed
1782+
/// on-chain.
1783+
pub(crate) fn no_further_updates_allowed(&self) -> bool {
1784+
self.inner.lock().unwrap().no_further_updates_allowed()
17811785
}
17821786

17831787
/// Gets the `node_id` of the counterparty for this channel.
@@ -2938,7 +2942,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
29382942
/// is important that any clones of this channel monitor (including remote clones) by kept
29392943
/// up-to-date as our holder commitment transaction is updated.
29402944
/// Panics if set_on_holder_tx_csv has never been called.
2941-
fn provide_latest_holder_commitment_tx(&mut self, holder_commitment_tx: HolderCommitmentTransaction, mut htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>, claimed_htlcs: &[(SentHTLCId, PaymentPreimage)], nondust_htlc_sources: Vec<HTLCSource>) -> Result<(), &'static str> {
2945+
fn provide_latest_holder_commitment_tx(&mut self, holder_commitment_tx: HolderCommitmentTransaction, mut htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>, claimed_htlcs: &[(SentHTLCId, PaymentPreimage)], nondust_htlc_sources: Vec<HTLCSource>) {
29422946
if htlc_outputs.iter().any(|(_, s, _)| s.is_some()) {
29432947
// If we have non-dust HTLCs in htlc_outputs, ensure they match the HTLCs in the
29442948
// `holder_commitment_tx`. In the future, we'll no longer provide the redundant data
@@ -3015,10 +3019,6 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
30153019
}
30163020
self.counterparty_fulfilled_htlcs.insert(*claimed_htlc_id, *claimed_preimage);
30173021
}
3018-
if self.holder_tx_signed {
3019-
return Err("Latest holder commitment signed has already been signed, update is rejected");
3020-
}
3021-
Ok(())
30223022
}
30233023

30243024
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
@@ -3239,11 +3239,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
32393239
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, claimed_htlcs, nondust_htlc_sources } => {
32403240
log_trace!(logger, "Updating ChannelMonitor with latest holder commitment transaction info");
32413241
if self.lockdown_from_offchain { panic!(); }
3242-
if let Err(e) = self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone(), &claimed_htlcs, nondust_htlc_sources.clone()) {
3243-
log_error!(logger, "Providing latest holder commitment transaction failed/was refused:");
3244-
log_error!(logger, " {}", e);
3245-
ret = Err(());
3246-
}
3242+
self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone(), &claimed_htlcs, nondust_htlc_sources.clone());
32473243
}
32483244
ChannelMonitorUpdateStep::LatestCounterpartyCommitmentTXInfo { commitment_txid, htlc_outputs, commitment_number, their_per_commitment_point, .. } => {
32493245
log_trace!(logger, "Updating ChannelMonitor with latest counterparty commitment transaction info");
@@ -3323,12 +3319,16 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
33233319
}
33243320
}
33253321

3326-
if ret.is_ok() && (self.funding_spend_seen || self.lockdown_from_offchain || self.holder_tx_signed) && is_pre_close_update {
3322+
if ret.is_ok() && self.no_further_updates_allowed() && is_pre_close_update {
33273323
log_error!(logger, "Refusing Channel Monitor Update as counterparty attempted to update commitment after funding was spent");
33283324
Err(())
33293325
} else { ret }
33303326
}
33313327

3328+
fn no_further_updates_allowed(&self) -> bool {
3329+
self.funding_spend_seen || self.lockdown_from_offchain || self.holder_tx_signed
3330+
}
3331+
33323332
fn get_latest_update_id(&self) -> u64 {
33333333
self.latest_update_id
33343334
}
@@ -3918,35 +3918,32 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
39183918
}
39193919
}
39203920
}
3921-
if self.holder_tx_signed {
3922-
// If we've signed, we may have broadcast either commitment (prev or current), and
3923-
// attempted to claim from it immediately without waiting for a confirmation.
3924-
if self.current_holder_commitment_tx.txid != *confirmed_commitment_txid {
3921+
// Cancel any pending claims for any holder commitments in case they had previously
3922+
// confirmed or been signed (in which case we will start attempting to claim without
3923+
// waiting for confirmation).
3924+
if self.current_holder_commitment_tx.txid != *confirmed_commitment_txid {
3925+
log_trace!(logger, "Canceling claims for previously broadcast holder commitment {}",
3926+
self.current_holder_commitment_tx.txid);
3927+
let mut outpoint = BitcoinOutPoint { txid: self.current_holder_commitment_tx.txid, vout: 0 };
3928+
for (htlc, _, _) in &self.current_holder_commitment_tx.htlc_outputs {
3929+
if let Some(vout) = htlc.transaction_output_index {
3930+
outpoint.vout = vout;
3931+
self.onchain_tx_handler.abandon_claim(&outpoint);
3932+
}
3933+
}
3934+
}
3935+
if let Some(prev_holder_commitment_tx) = &self.prev_holder_signed_commitment_tx {
3936+
if prev_holder_commitment_tx.txid != *confirmed_commitment_txid {
39253937
log_trace!(logger, "Canceling claims for previously broadcast holder commitment {}",
3926-
self.current_holder_commitment_tx.txid);
3927-
let mut outpoint = BitcoinOutPoint { txid: self.current_holder_commitment_tx.txid, vout: 0 };
3928-
for (htlc, _, _) in &self.current_holder_commitment_tx.htlc_outputs {
3938+
prev_holder_commitment_tx.txid);
3939+
let mut outpoint = BitcoinOutPoint { txid: prev_holder_commitment_tx.txid, vout: 0 };
3940+
for (htlc, _, _) in &prev_holder_commitment_tx.htlc_outputs {
39293941
if let Some(vout) = htlc.transaction_output_index {
39303942
outpoint.vout = vout;
39313943
self.onchain_tx_handler.abandon_claim(&outpoint);
39323944
}
39333945
}
39343946
}
3935-
if let Some(prev_holder_commitment_tx) = &self.prev_holder_signed_commitment_tx {
3936-
if prev_holder_commitment_tx.txid != *confirmed_commitment_txid {
3937-
log_trace!(logger, "Canceling claims for previously broadcast holder commitment {}",
3938-
prev_holder_commitment_tx.txid);
3939-
let mut outpoint = BitcoinOutPoint { txid: prev_holder_commitment_tx.txid, vout: 0 };
3940-
for (htlc, _, _) in &prev_holder_commitment_tx.htlc_outputs {
3941-
if let Some(vout) = htlc.transaction_output_index {
3942-
outpoint.vout = vout;
3943-
self.onchain_tx_handler.abandon_claim(&outpoint);
3944-
}
3945-
}
3946-
}
3947-
}
3948-
} else {
3949-
// No previous claim.
39503947
}
39513948
}
39523949

@@ -4282,7 +4279,7 @@ impl<Signer: EcdsaChannelSigner> ChannelMonitorImpl<Signer> {
42824279
}
42834280
}
42844281

4285-
if self.lockdown_from_offchain || self.funding_spend_seen || self.holder_tx_signed {
4282+
if self.no_further_updates_allowed() {
42864283
// Fail back HTLCs on backwards channels if they expire within
42874284
// `LATENCY_GRACE_PERIOD_BLOCKS` blocks and the channel is closed (i.e. we're at a
42884285
// point where no further off-chain updates will be accepted). If we haven't seen the
@@ -5440,7 +5437,7 @@ mod tests {
54405437
let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, &mut htlcs);
54415438

54425439
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(),
5443-
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect()).unwrap();
5440+
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect());
54445441
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"1").to_byte_array()),
54455442
preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key, &logger);
54465443
monitor.provide_latest_counterparty_commitment_tx(Txid::from_byte_array(Sha256::hash(b"2").to_byte_array()),
@@ -5478,7 +5475,7 @@ mod tests {
54785475
let mut htlcs = preimages_slice_to_htlcs!(preimages[0..5]);
54795476
let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, &mut htlcs);
54805477
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(),
5481-
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect()).unwrap();
5478+
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect());
54825479
secret[0..32].clone_from_slice(&<Vec<u8>>::from_hex("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
54835480
monitor.provide_secret(281474976710653, secret.clone()).unwrap();
54845481
assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 12);
@@ -5489,7 +5486,7 @@ mod tests {
54895486
let mut htlcs = preimages_slice_to_htlcs!(preimages[0..3]);
54905487
let dummy_commitment_tx = HolderCommitmentTransaction::dummy(0, &mut htlcs);
54915488
monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx,
5492-
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect()).unwrap();
5489+
htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect());
54935490
secret[0..32].clone_from_slice(&<Vec<u8>>::from_hex("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
54945491
monitor.provide_secret(281474976710652, secret.clone()).unwrap();
54955492
assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 5);

lightning/src/ln/channelmanager.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13763,8 +13763,8 @@ where
1376313763
// claim.
1376413764
// Note that a `ChannelMonitor` is created with `update_id` 0 and after we
1376513765
// provide it with a closure update its `update_id` will be at 1.
13766-
if !monitor.offchain_closed() || monitor.get_latest_update_id() > 1 {
13767-
should_queue_fc_update = !monitor.offchain_closed();
13766+
if !monitor.no_further_updates_allowed() || monitor.get_latest_update_id() > 1 {
13767+
should_queue_fc_update = !monitor.no_further_updates_allowed();
1376813768
let mut latest_update_id = monitor.get_latest_update_id();
1376913769
if should_queue_fc_update {
1377013770
latest_update_id += 1;

0 commit comments

Comments
 (0)