@@ -934,6 +934,9 @@ pub(crate) struct ChannelMonitorImpl<Signer: WriteableEcdsaChannelSigner> {
934
934
/// Ordering of tuple data: (their_per_commitment_point, feerate_per_kw, to_broadcaster_sats,
935
935
/// to_countersignatory_sats)
936
936
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 > ,
937
940
}
938
941
939
942
/// Transaction outputs to watch for on-chain spends.
@@ -1327,6 +1330,7 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
1327
1330
best_block,
1328
1331
counterparty_node_id : Some ( counterparty_node_id) ,
1329
1332
initial_counterparty_commitment_info : None ,
1333
+ balances_empty_height : None ,
1330
1334
} )
1331
1335
}
1332
1336
@@ -1855,6 +1859,42 @@ impl<Signer: WriteableEcdsaChannelSigner> ChannelMonitor<Signer> {
1855
1859
spendable_outputs
1856
1860
}
1857
1861
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
+
1858
1898
#[ cfg( test) ]
1859
1899
pub fn get_counterparty_payment_script ( & self ) -> ScriptBuf {
1860
1900
self . inner . lock ( ) . unwrap ( ) . counterparty_payment_script . clone ( )
@@ -4721,6 +4761,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
4721
4761
best_block,
4722
4762
counterparty_node_id,
4723
4763
initial_counterparty_commitment_info,
4764
+ balances_empty_height : None ,
4724
4765
} ) ) )
4725
4766
}
4726
4767
}
0 commit comments