@@ -919,14 +919,16 @@ impl Drop for BackgroundProcessor {
919919
920920#[ cfg( all( feature = "std" , test) ) ]
921921mod tests {
922+ use bitcoin:: ScriptBuf ;
922923 use bitcoin:: blockdata:: constants:: { genesis_block, ChainHash } ;
923924 use bitcoin:: blockdata:: locktime:: absolute:: LockTime ;
924925 use bitcoin:: blockdata:: transaction:: { Transaction , TxOut } ;
925926 use bitcoin:: network:: constants:: Network ;
926927 use bitcoin:: secp256k1:: { SecretKey , PublicKey , Secp256k1 } ;
927- use lightning:: chain:: { BestBlock , Confirm , chainmonitor} ;
928+ use lightning:: chain:: { BestBlock , Confirm , chainmonitor, Filter } ;
928929 use lightning:: chain:: channelmonitor:: ANTI_REORG_DELAY ;
929- use lightning:: sign:: { InMemorySigner , KeysManager } ;
930+ use lightning:: chain:: chaininterface:: { ConfirmationTarget , FeeEstimator } ;
931+ use lightning:: sign:: { InMemorySigner , KeysManager , SpendableOutputDescriptor } ;
930932 use lightning:: chain:: transaction:: OutPoint ;
931933 use lightning:: events:: { Event , PathFailure , MessageSendEventsProvider , MessageSendEvent } ;
932934 use lightning:: { get_event_msg, get_event} ;
@@ -947,6 +949,7 @@ mod tests {
947949 CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE , CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE , CHANNEL_MANAGER_PERSISTENCE_KEY ,
948950 NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE , NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE , NETWORK_GRAPH_PERSISTENCE_KEY ,
949951 SCORER_PERSISTENCE_PRIMARY_NAMESPACE , SCORER_PERSISTENCE_SECONDARY_NAMESPACE , SCORER_PERSISTENCE_KEY } ;
952+ use lightning:: util:: sweep:: { OutputSweeper , OutputSpendStatus } ;
950953 use lightning_persister:: fs_store:: FilesystemStore ;
951954 use std:: collections:: VecDeque ;
952955 use std:: { fs, env} ;
@@ -1009,6 +1012,7 @@ mod tests {
10091012 logger : Arc < test_utils:: TestLogger > ,
10101013 best_block : BestBlock ,
10111014 scorer : Arc < LockingWrapper < TestScorer > > ,
1015+ sweeper : Arc < OutputSweeper < Arc < test_utils:: TestBroadcaster > , Arc < dyn Filter + Sync + Send > , Arc < FilesystemStore > , Arc < test_utils:: TestLogger > > > ,
10121016 }
10131017
10141018 impl Node {
@@ -1271,10 +1275,30 @@ mod tests {
12711275 let router = Arc :: new ( DefaultRouter :: new ( network_graph. clone ( ) , logger. clone ( ) , Arc :: clone ( & keys_manager) , scorer. clone ( ) , Default :: default ( ) ) ) ;
12721276 let chain_source = Arc :: new ( test_utils:: TestChainSource :: new ( Network :: Bitcoin ) ) ;
12731277 let kv_store = Arc :: new ( FilesystemStore :: new ( format ! ( "{}_persister_{}" , & persist_dir, i) . into ( ) ) ) ;
1278+ let now = Duration :: from_secs ( genesis_block. header . time as u64 ) ;
1279+ let keys_manager = Arc :: new ( KeysManager :: new ( & seed, now. as_secs ( ) , now. subsec_nanos ( ) ) ) ;
12741280 let chain_monitor = Arc :: new ( chainmonitor:: ChainMonitor :: new ( Some ( chain_source. clone ( ) ) , tx_broadcaster. clone ( ) , logger. clone ( ) , fee_estimator. clone ( ) , kv_store. clone ( ) ) ) ;
12751281 let best_block = BestBlock :: from_network ( network) ;
12761282 let params = ChainParameters { network, best_block } ;
12771283 let manager = Arc :: new ( ChannelManager :: new ( fee_estimator. clone ( ) , chain_monitor. clone ( ) , tx_broadcaster. clone ( ) , router. clone ( ) , logger. clone ( ) , keys_manager. clone ( ) , keys_manager. clone ( ) , keys_manager. clone ( ) , UserConfig :: default ( ) , params, genesis_block. header . time ) ) ;
1284+
1285+ let spend_fee_estimator = Arc :: clone ( & fee_estimator) ;
1286+ let spend_keys_manager = Arc :: clone ( & keys_manager) ;
1287+ let spend_outputs_callback = move |output_descriptors : & [ & SpendableOutputDescriptor ] | {
1288+ let fee_rate = spend_fee_estimator
1289+ . get_est_sat_per_1000_weight ( ConfirmationTarget :: NonAnchorChannelFee ) ;
1290+ spend_keys_manager. spend_spendable_outputs (
1291+ output_descriptors,
1292+ Vec :: new ( ) ,
1293+ ScriptBuf :: new ( ) ,
1294+ fee_rate,
1295+ None ,
1296+ & Secp256k1 :: new ( ) ,
1297+ )
1298+ } ;
1299+ let sweeper = Arc :: new ( OutputSweeper :: new ( Arc :: clone ( & tx_broadcaster) ,
1300+ Arc :: clone ( & kv_store) , best_block, None :: < Arc < dyn Filter + Sync + Send > > ,
1301+ Arc :: clone ( & logger) , spend_outputs_callback) ) ;
12781302 let p2p_gossip_sync = Arc :: new ( P2PGossipSync :: new ( network_graph. clone ( ) , Some ( chain_source. clone ( ) ) , logger. clone ( ) ) ) ;
12791303 let rapid_gossip_sync = Arc :: new ( RapidGossipSync :: new ( network_graph. clone ( ) , logger. clone ( ) ) ) ;
12801304 let msg_handler = MessageHandler {
@@ -1283,7 +1307,7 @@ mod tests {
12831307 onion_message_handler : IgnoringMessageHandler { } , custom_message_handler : IgnoringMessageHandler { }
12841308 } ;
12851309 let peer_manager = Arc :: new ( PeerManager :: new ( msg_handler, 0 , & seed, logger. clone ( ) , keys_manager. clone ( ) ) ) ;
1286- let node = Node { node : manager, p2p_gossip_sync, rapid_gossip_sync, peer_manager, chain_monitor, kv_store, tx_broadcaster, network_graph, logger, best_block, scorer } ;
1310+ let node = Node { node : manager, p2p_gossip_sync, rapid_gossip_sync, peer_manager, chain_monitor, kv_store, tx_broadcaster, network_graph, logger, best_block, scorer, sweeper } ;
12871311 nodes. push ( node) ;
12881312 }
12891313
@@ -1352,15 +1376,32 @@ mod tests {
13521376 1 => {
13531377 node. node . transactions_confirmed ( & header, & txdata, height) ;
13541378 node. chain_monitor . transactions_confirmed ( & header, & txdata, height) ;
1379+ node. sweeper . transactions_confirmed ( & header, & txdata, height) ;
13551380 } ,
13561381 x if x == depth => {
13571382 node. node . best_block_updated ( & header, height) ;
13581383 node. chain_monitor . best_block_updated ( & header, height) ;
1384+ node. sweeper . best_block_updated ( & header, height) ;
13591385 } ,
13601386 _ => { } ,
13611387 }
13621388 }
13631389 }
1390+
1391+ fn advance_chain ( node : & mut Node , num_blocks : u32 ) {
1392+ for i in 1 ..=num_blocks {
1393+ let prev_blockhash = node. best_block . block_hash ;
1394+ let height = node. best_block . height + 1 ;
1395+ let header = create_dummy_header ( prev_blockhash, height) ;
1396+ node. best_block = BestBlock :: new ( header. block_hash ( ) , height) ;
1397+ if i == num_blocks {
1398+ node. node . best_block_updated ( & header, height) ;
1399+ node. chain_monitor . best_block_updated ( & header, height) ;
1400+ node. sweeper . best_block_updated ( & header, height) ;
1401+ }
1402+ }
1403+ }
1404+
13641405 fn confirm_transaction ( node : & mut Node , tx : & Transaction ) {
13651406 confirm_transaction_depth ( node, tx, ANTI_REORG_DELAY ) ;
13661407 }
@@ -1592,6 +1633,9 @@ mod tests {
15921633 let _as_channel_update = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 1 ] . node. get_our_node_id( ) ) ;
15931634 nodes[ 1 ] . node . handle_channel_ready ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_funding) ;
15941635 let _bs_channel_update = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 0 ] . node. get_our_node_id( ) ) ;
1636+ let broadcast_funding = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
1637+ assert_eq ! ( broadcast_funding. txid( ) , funding_tx. txid( ) ) ;
1638+ assert ! ( nodes[ 0 ] . tx_broadcaster. txn_broadcasted. lock( ) . unwrap( ) . is_empty( ) ) ;
15951639
15961640 if !std:: thread:: panicking ( ) {
15971641 bg_processor. stop ( ) . unwrap ( ) ;
@@ -1617,10 +1661,65 @@ mod tests {
16171661 . recv_timeout ( Duration :: from_secs ( EVENT_DEADLINE ) )
16181662 . expect ( "Events not handled within deadline" ) ;
16191663 match event {
1620- Event :: SpendableOutputs { .. } => { } ,
1664+ Event :: SpendableOutputs { outputs, channel_id } => {
1665+ nodes[ 0 ] . sweeper . track_spendable_outputs ( outputs, channel_id, false ) ;
1666+ } ,
16211667 _ => panic ! ( "Unexpected event: {:?}" , event) ,
16221668 }
16231669
1670+ // Check we generate an initial sweeping tx.
1671+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1672+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1673+ let sweep_tx_0 = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
1674+ match tracked_output. status {
1675+ OutputSpendStatus :: PendingFirstConfirmation { latest_spending_tx, .. } => {
1676+ assert_eq ! ( sweep_tx_0. txid( ) , latest_spending_tx. txid( ) ) ;
1677+ }
1678+ _ => panic ! ( "Unexpected status" ) ,
1679+ }
1680+
1681+ // Check we regenerate and rebroadcast the sweeping tx each block.
1682+ advance_chain ( & mut nodes[ 0 ] , 1 ) ;
1683+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1684+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1685+ let sweep_tx_1 = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
1686+ match tracked_output. status {
1687+ OutputSpendStatus :: PendingFirstConfirmation { latest_spending_tx, .. } => {
1688+ assert_eq ! ( sweep_tx_1. txid( ) , latest_spending_tx. txid( ) ) ;
1689+ }
1690+ _ => panic ! ( "Unexpected status" ) ,
1691+ }
1692+ assert_ne ! ( sweep_tx_0, sweep_tx_1) ;
1693+
1694+ advance_chain ( & mut nodes[ 0 ] , 1 ) ;
1695+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1696+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1697+ let sweep_tx_2 = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
1698+ match tracked_output. status {
1699+ OutputSpendStatus :: PendingFirstConfirmation { latest_spending_tx, .. } => {
1700+ assert_eq ! ( sweep_tx_2. txid( ) , latest_spending_tx. txid( ) ) ;
1701+ }
1702+ _ => panic ! ( "Unexpected status" ) ,
1703+ }
1704+ assert_ne ! ( sweep_tx_0, sweep_tx_2) ;
1705+ assert_ne ! ( sweep_tx_1, sweep_tx_2) ;
1706+
1707+ // Check we still track the spendable outputs up to ANTI_REORG_DELAY confirmations.
1708+ confirm_transaction_depth ( & mut nodes[ 0 ] , & sweep_tx_2, 5 ) ;
1709+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1710+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1711+ match tracked_output. status {
1712+ OutputSpendStatus :: PendingThresholdConfirmations { latest_spending_tx, .. } => {
1713+ assert_eq ! ( sweep_tx_2. txid( ) , latest_spending_tx. txid( ) ) ;
1714+ }
1715+ _ => panic ! ( "Unexpected status" ) ,
1716+ }
1717+
1718+ // Check we stop tracking the spendable outputs when one of the txs reaches
1719+ // ANTI_REORG_DELAY confirmations.
1720+ confirm_transaction_depth ( & mut nodes[ 0 ] , & sweep_tx_0, ANTI_REORG_DELAY ) ;
1721+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 0 ) ;
1722+
16241723 if !std:: thread:: panicking ( ) {
16251724 bg_processor. stop ( ) . unwrap ( ) ;
16261725 }
0 commit comments