Skip to content

Commit a44f951

Browse files
committed
Add ChannelMonitor::is_fully_resolved function
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.
1 parent 9cc0e98 commit a44f951

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

lightning/src/chain/channelmonitor.rs

+41
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,9 @@ pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
934934
/// Ordering of tuple data: (their_per_commitment_point, feerate_per_kw, to_broadcaster_sats,
935935
/// to_countersignatory_sats)
936936
initial_counterparty_commitment_info: Option<(PublicKey, u32, u64, u64)>,
937+
938+
/// The first block height at which we had no remaining claimable balances.
939+
balances_empty_height: Option<u32>,
937940
}
938941

939942
/// Transaction outputs to watch for on-chain spends.
@@ -1327,6 +1330,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
13271330
best_block,
13281331
counterparty_node_id: Some(counterparty_node_id),
13291332
initial_counterparty_commitment_info: None,
1333+
balances_empty_height: None,
13301334
})
13311335
}
13321336

@@ -1855,6 +1859,42 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
18551859
spendable_outputs
18561860
}
18571861

1862+
/// Checks if the monitor is fully resolved. Resolved monitor is one that has claimed all of
1863+
/// its ouputs and balacnes.
1864+
///
1865+
/// This function returns true only if `get_claimable_balances` has been empty for at least
1866+
/// 2016 blocks.
1867+
pub(crate) fn is_fully_resolved(&self) -> bool {
1868+
let is_all_funds_claimed = self.get_claimable_balances().is_empty();
1869+
let current_height = self.current_best_block().height;
1870+
let mut inner = self.inner.lock().unwrap();
1871+
1872+
match (inner.balances_empty_height, is_all_funds_claimed) {
1873+
(Some(h), true) => {
1874+
// Claimed all funds, Check if reached the threshold.
1875+
let threshold = 2016; // two weeks
1876+
return current_height >= h + threshold;
1877+
},
1878+
(Some(_), false) => {
1879+
// previously assumed we claimed all funds, but we have new funds to claim.
1880+
// Should not happen in practice.
1881+
debug_assert!(!is_all_funds_claimed, "Trying to check if monitor is fully resolved before all funds are claimed. Aborting.");
1882+
inner.balances_empty_height = None;
1883+
return false;
1884+
},
1885+
(None, true) => {
1886+
// Claimed all funds but `balances_empty_height` is None. It is set to the
1887+
// current block height.
1888+
inner.balances_empty_height = Some(current_height);
1889+
return false;
1890+
},
1891+
(None, false) => {
1892+
// Have funds to claim.
1893+
return false;
1894+
},
1895+
}
1896+
}
1897+
18581898
#[cfg(test)]
18591899
pub fn get_counterparty_payment_script(&self) -> ScriptBuf {
18601900
self.inner.lock().unwrap().counterparty_payment_script.clone()
@@ -4721,6 +4761,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
47214761
best_block,
47224762
counterparty_node_id,
47234763
initial_counterparty_commitment_info,
4764+
balances_empty_height: None,
47244765
})))
47254766
}
47264767
}

lightning/src/ln/monitor_tests.rs

+3
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,9 @@ fn do_chanmon_claim_value_coop_close(anchors: bool) {
259259

260260
check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 1000000);
261261
check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 1000000);
262+
263+
assert!(nodes[0].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
264+
assert!(nodes[1].chain_monitor.chain_monitor.get_and_clear_pending_events().is_empty());
262265
}
263266

264267
#[test]

0 commit comments

Comments
 (0)