Skip to content

Commit

Permalink
Add ChannelMonitor::is_fully_resolved function
Browse files Browse the repository at this point in the history
  Checks if the monitor is fully resolved. Resolved monitor is one that has claimed all of
  its ouputs and balacnes.

  This function returns true only if `get_claimable_balances` has been empty for at least
  2016 blocks.
  • Loading branch information
jbesraa committed Apr 12, 2024
1 parent 1d2a27d commit 905ead3
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 deletions lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,9 @@ pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
/// Ordering of tuple data: (their_per_commitment_point, feerate_per_kw, to_broadcaster_sats,
/// to_countersignatory_sats)
initial_counterparty_commitment_info: Option<(PublicKey, u32, u64, u64)>,

/// The first block height at which we had no remaining claimable balances.
balances_empty_height: Option<u32>,
}

/// Transaction outputs to watch for on-chain spends.
Expand Down Expand Up @@ -1145,6 +1148,7 @@ impl<Signer: WriteableEcdsaChannelSigner> Writeable for ChannelMonitorImpl<Signe
(15, self.counterparty_fulfilled_htlcs, required),
(17, self.initial_counterparty_commitment_info, option),
(19, self.channel_id, required),
(21, self.balances_empty_height, option),
});

Ok(())
Expand Down Expand Up @@ -1328,6 +1332,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
best_block,
counterparty_node_id: Some(counterparty_node_id),
initial_counterparty_commitment_info: None,
balances_empty_height: None,
})
}

Expand Down Expand Up @@ -1856,6 +1861,42 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
spendable_outputs
}

/// Checks if the monitor is fully resolved. Resolved monitor is one that has claimed all of
/// its outputs and balances (i.e. [`Self::get_claimable_balances`] returns an empty set).
///
/// This function returns true only if [`Self::get_claimable_balances`] has been empty for at least
/// 2016 blocks as an additional protection against any bugs resulting in spuriously empty balance sets.
pub fn is_fully_resolved(&self) -> bool {
let is_all_funds_claimed = self.get_claimable_balances().is_empty();
let current_height = self.current_best_block().height;
let mut inner = self.inner.lock().unwrap();

match (inner.balances_empty_height, is_all_funds_claimed) {
(Some(balances_empty_height), true) => {
// Claimed all funds, check if reached the blocks threshold.
const BLOCKS_THRESHOLD: u32 = 2016; // ~two weeks
return current_height >= balances_empty_height + BLOCKS_THRESHOLD;
},
(Some(_), false) => {
// previously assumed we claimed all funds, but we have new funds to claim.
// Should not happen in practice.
debug_assert!(is_all_funds_claimed, "Trying to check if monitor is fully resolved before all funds are claimed.");
inner.balances_empty_height = None;
return false;
},
(None, true) => {
// Claimed all funds but `balances_empty_height` is None. It is set to the
// current block height.
inner.balances_empty_height = Some(current_height);
return false;
},
(None, false) => {
// Have funds to claim.
return false;
},
}
}

#[cfg(test)]
pub fn get_counterparty_payment_script(&self) -> ScriptBuf {
self.inner.lock().unwrap().counterparty_payment_script.clone()
Expand Down Expand Up @@ -4632,6 +4673,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
let mut spendable_txids_confirmed = Some(Vec::new());
let mut counterparty_fulfilled_htlcs = Some(new_hash_map());
let mut initial_counterparty_commitment_info = None;
let mut balances_empty_height = None;
let mut channel_id = None;
read_tlv_fields!(reader, {
(1, funding_spend_confirmed, option),
Expand All @@ -4644,6 +4686,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
(15, counterparty_fulfilled_htlcs, option),
(17, initial_counterparty_commitment_info, option),
(19, channel_id, option),
(21, balances_empty_height, option),
});

// `HolderForceClosedWithInfo` replaced `HolderForceClosed` in v0.0.122. If we have both
Expand Down Expand Up @@ -4722,6 +4765,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
best_block,
counterparty_node_id,
initial_counterparty_commitment_info,
balances_empty_height,
})))
}
}
Expand Down

0 comments on commit 905ead3

Please sign in to comment.