@@ -1778,6 +1778,130 @@ fn test_restored_packages_retry() {
1778
1778
do_test_restored_packages_retry ( true ) ;
1779
1779
}
1780
1780
1781
+ fn do_test_monitor_rebroadcast_pending_claims ( anchors : bool ) {
1782
+ // Test that we will retry broadcasting pending claims for a force-closed channel on every
1783
+ // `ChainMonitor::rebroadcast_pending_claims` call.
1784
+ if anchors {
1785
+ assert ! ( cfg!( anchors) ) ;
1786
+ }
1787
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
1788
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
1789
+ let mut config = test_default_channel_config ( ) ;
1790
+ if anchors {
1791
+ #[ cfg( anchors) ] {
1792
+ config. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
1793
+ }
1794
+ }
1795
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ Some ( config) , Some ( config) ] ) ;
1796
+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
1797
+
1798
+ let ( _, _, _, chan_id, funding_tx) = create_chan_between_nodes_with_value (
1799
+ & nodes[ 0 ] , & nodes[ 1 ] , 1_000_000 , 500_000_000
1800
+ ) ;
1801
+ const HTLC_AMT_MSAT : u64 = 1_000_000 ;
1802
+ const HTLC_AMT_SAT : u64 = HTLC_AMT_MSAT / 1000 ;
1803
+ route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] ] , HTLC_AMT_MSAT ) ;
1804
+
1805
+ let htlc_expiry = nodes[ 0 ] . best_block_info ( ) . 1 + TEST_FINAL_CLTV + 1 ;
1806
+
1807
+ let commitment_txn = get_local_commitment_txn ! ( & nodes[ 0 ] , & chan_id) ;
1808
+ assert_eq ! ( commitment_txn. len( ) , if anchors { 1 /* commitment tx only */ } else { 2 /* commitment and htlc timeout tx */ } ) ;
1809
+ check_spends ! ( & commitment_txn[ 0 ] , & funding_tx) ;
1810
+ mine_transaction ( & nodes[ 0 ] , & commitment_txn[ 0 ] ) ;
1811
+ check_closed_broadcast ! ( & nodes[ 0 ] , true ) ;
1812
+ check_closed_event ( & nodes[ 0 ] , 1 , ClosureReason :: CommitmentTxConfirmed , false ) ;
1813
+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
1814
+
1815
+ // Set up a helper closure we'll use throughout our test. We should only expect retries without
1816
+ // bumps if fees have not increased after a block has been connected (assuming the height timer
1817
+ // re-evaluates at every block) or after `ChainMonitor::rebroadcast_pending_claims` is called.
1818
+ let mut prev_htlc_tx_feerate = None ;
1819
+ let mut check_htlc_retry = |should_retry : bool , should_bump : bool | {
1820
+ let htlc_tx_feerate = if anchors {
1821
+ assert ! ( nodes[ 0 ] . tx_broadcaster. txn_broadcast( ) . is_empty( ) ) ;
1822
+ let mut events = nodes[ 0 ] . chain_monitor . chain_monitor . get_and_clear_pending_events ( ) ;
1823
+ assert_eq ! ( events. len( ) , if should_retry { 1 } else { 0 } ) ;
1824
+ if !should_retry {
1825
+ return ;
1826
+ }
1827
+ #[ allow( unused_assignments) ]
1828
+ let mut feerate = 0 ;
1829
+ #[ cfg( anchors) ] {
1830
+ let ( htlcs, htlc_tx_feerate) = if let Event :: BumpTransaction ( BumpTransactionEvent :: HTLCResolution {
1831
+ target_feerate_sat_per_1000_weight, htlc_descriptors, ..
1832
+ } ) = events. pop ( ) . unwrap ( ) {
1833
+ ( htlc_descriptors, target_feerate_sat_per_1000_weight)
1834
+ } else { panic ! ( "unexpected event" ) ; } ;
1835
+ assert_eq ! ( htlcs. len( ) , 1 ) ;
1836
+ assert_eq ! ( htlcs[ 0 ] . commitment_txid, commitment_txn[ 0 ] . txid( ) ) ;
1837
+ assert ! ( ( htlcs[ 0 ] . htlc. transaction_output_index. unwrap( ) as usize ) < commitment_txn[ 0 ] . output. len( ) ) ;
1838
+ feerate = htlc_tx_feerate as u64 ;
1839
+ }
1840
+ feerate
1841
+ } else {
1842
+ assert ! ( nodes[ 0 ] . chain_monitor. chain_monitor. get_and_clear_pending_events( ) . is_empty( ) ) ;
1843
+ let txn = nodes[ 0 ] . tx_broadcaster . txn_broadcast ( ) ;
1844
+ assert_eq ! ( txn. len( ) , if should_retry { 1 } else { 0 } ) ;
1845
+ if !should_retry {
1846
+ return ;
1847
+ }
1848
+ check_spends ! ( txn[ 0 ] , commitment_txn[ 0 ] ) ;
1849
+ let htlc_tx_fee = HTLC_AMT_SAT - txn[ 0 ] . output [ 0 ] . value ;
1850
+ htlc_tx_fee * 1000 / txn[ 0 ] . weight ( ) as u64
1851
+ } ;
1852
+ if should_bump {
1853
+ assert ! ( htlc_tx_feerate > prev_htlc_tx_feerate. unwrap( ) ) ;
1854
+ } else if let Some ( prev_feerate) = prev_htlc_tx_feerate. take ( ) {
1855
+ assert ! ( htlc_tx_feerate <= prev_feerate) ;
1856
+ }
1857
+ prev_htlc_tx_feerate = Some ( htlc_tx_feerate) ;
1858
+ } ;
1859
+
1860
+ // Connect blocks up to one before the HTLC expires. This should not result in a claim/retry.
1861
+ connect_blocks ( & nodes[ 0 ] , htlc_expiry - nodes[ 0 ] . best_block_info ( ) . 1 - 2 ) ;
1862
+ check_htlc_retry ( false , false ) ;
1863
+
1864
+ // Connect one more block, producing our first claim.
1865
+ connect_blocks ( & nodes[ 0 ] , 1 ) ;
1866
+ check_htlc_retry ( true , false ) ;
1867
+
1868
+ // Connect one more block, expecting a retry with a fee bump. Unfortunately, we cannot bump HTLC
1869
+ // transactions pre-anchors.
1870
+ connect_blocks ( & nodes[ 0 ] , 1 ) ;
1871
+ check_htlc_retry ( true , anchors) ;
1872
+
1873
+ // Trigger a call and we should have another retry, but without a bump.
1874
+ nodes[ 0 ] . chain_monitor . chain_monitor . rebroadcast_pending_claims ( ) ;
1875
+ check_htlc_retry ( true , false ) ;
1876
+
1877
+ // Double the feerate and trigger a call, expecting a fee-bumped retry.
1878
+ * nodes[ 0 ] . fee_estimator . sat_per_kw . lock ( ) . unwrap ( ) *= 2 ;
1879
+ nodes[ 0 ] . chain_monitor . chain_monitor . rebroadcast_pending_claims ( ) ;
1880
+ check_htlc_retry ( true , anchors) ;
1881
+
1882
+ // Connect one more block, expecting a retry with a fee bump. Unfortunately, we cannot bump HTLC
1883
+ // transactions pre-anchors.
1884
+ connect_blocks ( & nodes[ 0 ] , 1 ) ;
1885
+ check_htlc_retry ( true , anchors) ;
1886
+
1887
+ if !anchors {
1888
+ // Mine the HTLC transaction to ensure we don't retry claims while they're confirmed.
1889
+ mine_transaction ( & nodes[ 0 ] , & commitment_txn[ 1 ] ) ;
1890
+ if nodes[ 0 ] . connect_style . borrow ( ) . updates_best_block_first ( ) {
1891
+ check_htlc_retry ( true , false ) ;
1892
+ }
1893
+ nodes[ 0 ] . chain_monitor . chain_monitor . rebroadcast_pending_claims ( ) ;
1894
+ check_htlc_retry ( false , false ) ;
1895
+ }
1896
+ }
1897
+
1898
+ #[ test]
1899
+ fn test_monitor_timer_based_claim ( ) {
1900
+ do_test_monitor_rebroadcast_pending_claims ( false ) ;
1901
+ #[ cfg( anchors) ]
1902
+ do_test_monitor_rebroadcast_pending_claims ( true ) ;
1903
+ }
1904
+
1781
1905
#[ cfg( anchors) ]
1782
1906
#[ test]
1783
1907
fn test_yield_anchors_events ( ) {
0 commit comments