@@ -919,14 +919,16 @@ impl Drop for BackgroundProcessor {
919
919
920
920
#[ cfg( all( feature = "std" , test) ) ]
921
921
mod tests {
922
+ use bitcoin:: { ScriptBuf , Txid } ;
922
923
use bitcoin:: blockdata:: constants:: { genesis_block, ChainHash } ;
923
924
use bitcoin:: blockdata:: locktime:: absolute:: LockTime ;
924
925
use bitcoin:: blockdata:: transaction:: { Transaction , TxOut } ;
926
+ use bitcoin:: hashes:: Hash ;
925
927
use bitcoin:: network:: constants:: Network ;
926
928
use bitcoin:: secp256k1:: { SecretKey , PublicKey , Secp256k1 } ;
927
- use lightning:: chain:: { BestBlock , Confirm , chainmonitor} ;
929
+ use lightning:: chain:: { BestBlock , Confirm , chainmonitor, Filter } ;
928
930
use lightning:: chain:: channelmonitor:: ANTI_REORG_DELAY ;
929
- use lightning:: sign:: { InMemorySigner , KeysManager } ;
931
+ use lightning:: sign:: { InMemorySigner , KeysManager , ChangeDestinationSource } ;
930
932
use lightning:: chain:: transaction:: OutPoint ;
931
933
use lightning:: events:: { Event , PathFailure , MessageSendEventsProvider , MessageSendEvent } ;
932
934
use lightning:: { get_event_msg, get_event} ;
@@ -947,6 +949,7 @@ mod tests {
947
949
CHANNEL_MANAGER_PERSISTENCE_PRIMARY_NAMESPACE , CHANNEL_MANAGER_PERSISTENCE_SECONDARY_NAMESPACE , CHANNEL_MANAGER_PERSISTENCE_KEY ,
948
950
NETWORK_GRAPH_PERSISTENCE_PRIMARY_NAMESPACE , NETWORK_GRAPH_PERSISTENCE_SECONDARY_NAMESPACE , NETWORK_GRAPH_PERSISTENCE_KEY ,
949
951
SCORER_PERSISTENCE_PRIMARY_NAMESPACE , SCORER_PERSISTENCE_SECONDARY_NAMESPACE , SCORER_PERSISTENCE_KEY } ;
952
+ use lightning:: util:: sweep:: { OutputSweeper , OutputSpendStatus } ;
950
953
use lightning_persister:: fs_store:: FilesystemStore ;
951
954
use std:: collections:: VecDeque ;
952
955
use std:: { fs, env} ;
@@ -1009,6 +1012,9 @@ mod tests {
1009
1012
logger : Arc < test_utils:: TestLogger > ,
1010
1013
best_block : BestBlock ,
1011
1014
scorer : Arc < LockingWrapper < TestScorer > > ,
1015
+ sweeper : Arc < OutputSweeper < Arc < test_utils:: TestBroadcaster > , Arc < TestWallet > ,
1016
+ Arc < test_utils:: TestFeeEstimator > , Arc < dyn Filter + Sync + Send > , Arc < FilesystemStore > ,
1017
+ Arc < test_utils:: TestLogger > , Arc < KeysManager > > > ,
1012
1018
}
1013
1019
1014
1020
impl Node {
@@ -1247,6 +1253,14 @@ mod tests {
1247
1253
}
1248
1254
}
1249
1255
1256
+ struct TestWallet { }
1257
+
1258
+ impl ChangeDestinationSource for TestWallet {
1259
+ fn get_change_destination_script ( & self ) -> Result < ScriptBuf , ( ) > {
1260
+ Ok ( ScriptBuf :: new ( ) )
1261
+ }
1262
+ }
1263
+
1250
1264
fn get_full_filepath ( filepath : String , filename : String ) -> String {
1251
1265
let mut path = PathBuf :: from ( filepath) ;
1252
1266
path. push ( filename) ;
@@ -1271,10 +1285,15 @@ mod tests {
1271
1285
let router = Arc :: new ( DefaultRouter :: new ( network_graph. clone ( ) , logger. clone ( ) , Arc :: clone ( & keys_manager) , scorer. clone ( ) , Default :: default ( ) ) ) ;
1272
1286
let chain_source = Arc :: new ( test_utils:: TestChainSource :: new ( Network :: Bitcoin ) ) ;
1273
1287
let kv_store = Arc :: new ( FilesystemStore :: new ( format ! ( "{}_persister_{}" , & persist_dir, i) . into ( ) ) ) ;
1288
+ let now = Duration :: from_secs ( genesis_block. header . time as u64 ) ;
1289
+ let keys_manager = Arc :: new ( KeysManager :: new ( & seed, now. as_secs ( ) , now. subsec_nanos ( ) ) ) ;
1274
1290
let chain_monitor = Arc :: new ( chainmonitor:: ChainMonitor :: new ( Some ( chain_source. clone ( ) ) , tx_broadcaster. clone ( ) , logger. clone ( ) , fee_estimator. clone ( ) , kv_store. clone ( ) ) ) ;
1275
1291
let best_block = BestBlock :: from_network ( network) ;
1276
1292
let params = ChainParameters { network, best_block } ;
1277
1293
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 ) ) ;
1294
+ let wallet = Arc :: new ( TestWallet { } ) ;
1295
+ let sweeper = Arc :: new ( OutputSweeper :: new ( best_block, Arc :: clone ( & tx_broadcaster) , Arc :: clone ( & fee_estimator) ,
1296
+ None :: < Arc < dyn Filter + Sync + Send > > , Arc :: clone ( & keys_manager) , wallet, Arc :: clone ( & kv_store) , Arc :: clone ( & logger) ) ) ;
1278
1297
let p2p_gossip_sync = Arc :: new ( P2PGossipSync :: new ( network_graph. clone ( ) , Some ( chain_source. clone ( ) ) , logger. clone ( ) ) ) ;
1279
1298
let rapid_gossip_sync = Arc :: new ( RapidGossipSync :: new ( network_graph. clone ( ) , logger. clone ( ) ) ) ;
1280
1299
let msg_handler = MessageHandler {
@@ -1283,7 +1302,7 @@ mod tests {
1283
1302
onion_message_handler : IgnoringMessageHandler { } , custom_message_handler : IgnoringMessageHandler { }
1284
1303
} ;
1285
1304
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 } ;
1305
+ 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 } ;
1287
1306
nodes. push ( node) ;
1288
1307
}
1289
1308
@@ -1352,15 +1371,40 @@ mod tests {
1352
1371
1 => {
1353
1372
node. node . transactions_confirmed ( & header, & txdata, height) ;
1354
1373
node. chain_monitor . transactions_confirmed ( & header, & txdata, height) ;
1374
+ node. sweeper . transactions_confirmed ( & header, & txdata, height) ;
1355
1375
} ,
1356
1376
x if x == depth => {
1377
+ // We need the TestBroadcaster to know about the new height so that it doesn't think
1378
+ // we're violating the time lock requirements of transactions broadcasted at that
1379
+ // point.
1380
+ node. tx_broadcaster . blocks . lock ( ) . unwrap ( ) . push ( ( genesis_block ( Network :: Bitcoin ) , height) ) ;
1357
1381
node. node . best_block_updated ( & header, height) ;
1358
1382
node. chain_monitor . best_block_updated ( & header, height) ;
1383
+ node. sweeper . best_block_updated ( & header, height) ;
1359
1384
} ,
1360
1385
_ => { } ,
1361
1386
}
1362
1387
}
1363
1388
}
1389
+
1390
+ fn advance_chain ( node : & mut Node , num_blocks : u32 ) {
1391
+ for i in 1 ..=num_blocks {
1392
+ let prev_blockhash = node. best_block . block_hash ;
1393
+ let height = node. best_block . height + 1 ;
1394
+ let header = create_dummy_header ( prev_blockhash, height) ;
1395
+ node. best_block = BestBlock :: new ( header. block_hash ( ) , height) ;
1396
+ if i == num_blocks {
1397
+ // We need the TestBroadcaster to know about the new height so that it doesn't think
1398
+ // we're violating the time lock requirements of transactions broadcasted at that
1399
+ // point.
1400
+ node. tx_broadcaster . blocks . lock ( ) . unwrap ( ) . push ( ( genesis_block ( Network :: Bitcoin ) , height) ) ;
1401
+ node. node . best_block_updated ( & header, height) ;
1402
+ node. chain_monitor . best_block_updated ( & header, height) ;
1403
+ node. sweeper . best_block_updated ( & header, height) ;
1404
+ }
1405
+ }
1406
+ }
1407
+
1364
1408
fn confirm_transaction ( node : & mut Node , tx : & Transaction ) {
1365
1409
confirm_transaction_depth ( node, tx, ANTI_REORG_DELAY ) ;
1366
1410
}
@@ -1592,6 +1636,9 @@ mod tests {
1592
1636
let _as_channel_update = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 1 ] . node. get_our_node_id( ) ) ;
1593
1637
nodes[ 1 ] . node . handle_channel_ready ( & nodes[ 0 ] . node . get_our_node_id ( ) , & as_funding) ;
1594
1638
let _bs_channel_update = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 0 ] . node. get_our_node_id( ) ) ;
1639
+ let broadcast_funding = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
1640
+ assert_eq ! ( broadcast_funding. txid( ) , funding_tx. txid( ) ) ;
1641
+ assert ! ( nodes[ 0 ] . tx_broadcaster. txn_broadcasted. lock( ) . unwrap( ) . is_empty( ) ) ;
1595
1642
1596
1643
if !std:: thread:: panicking ( ) {
1597
1644
bg_processor. stop ( ) . unwrap ( ) ;
@@ -1617,10 +1664,95 @@ mod tests {
1617
1664
. recv_timeout ( Duration :: from_secs ( EVENT_DEADLINE ) )
1618
1665
. expect ( "Events not handled within deadline" ) ;
1619
1666
match event {
1620
- Event :: SpendableOutputs { .. } => { } ,
1667
+ Event :: SpendableOutputs { outputs, channel_id } => {
1668
+ nodes[ 0 ] . sweeper . track_spendable_outputs ( outputs, channel_id, false , Some ( 153 ) ) ;
1669
+ } ,
1621
1670
_ => panic ! ( "Unexpected event: {:?}" , event) ,
1622
1671
}
1623
1672
1673
+ // Check we don't generate an initial sweeping tx until we reach the required height.
1674
+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1675
+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1676
+ if let Some ( sweep_tx_0) = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . pop ( ) {
1677
+ assert ! ( !tracked_output. is_spent_in( & sweep_tx_0) ) ;
1678
+ match tracked_output. status {
1679
+ OutputSpendStatus :: PendingInitialBroadcast { delayed_until_height } => {
1680
+ assert_eq ! ( delayed_until_height, Some ( 153 ) ) ;
1681
+ }
1682
+ _ => panic ! ( "Unexpected status" ) ,
1683
+ }
1684
+ }
1685
+
1686
+ advance_chain ( & mut nodes[ 0 ] , 3 ) ;
1687
+
1688
+ // Check we generate an initial sweeping tx.
1689
+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1690
+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1691
+ let sweep_tx_0 = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
1692
+ match tracked_output. status {
1693
+ OutputSpendStatus :: PendingFirstConfirmation { latest_spending_tx, .. } => {
1694
+ assert_eq ! ( sweep_tx_0. txid( ) , latest_spending_tx. txid( ) ) ;
1695
+ }
1696
+ _ => panic ! ( "Unexpected status" ) ,
1697
+ }
1698
+
1699
+ // Check we regenerate and rebroadcast the sweeping tx each block.
1700
+ advance_chain ( & mut nodes[ 0 ] , 1 ) ;
1701
+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1702
+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1703
+ let sweep_tx_1 = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
1704
+ match tracked_output. status {
1705
+ OutputSpendStatus :: PendingFirstConfirmation { latest_spending_tx, .. } => {
1706
+ assert_eq ! ( sweep_tx_1. txid( ) , latest_spending_tx. txid( ) ) ;
1707
+ }
1708
+ _ => panic ! ( "Unexpected status" ) ,
1709
+ }
1710
+ assert_ne ! ( sweep_tx_0, sweep_tx_1) ;
1711
+
1712
+ advance_chain ( & mut nodes[ 0 ] , 1 ) ;
1713
+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1714
+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1715
+ let sweep_tx_2 = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . pop ( ) . unwrap ( ) ;
1716
+ match tracked_output. status {
1717
+ OutputSpendStatus :: PendingFirstConfirmation { latest_spending_tx, .. } => {
1718
+ assert_eq ! ( sweep_tx_2. txid( ) , latest_spending_tx. txid( ) ) ;
1719
+ }
1720
+ _ => panic ! ( "Unexpected status" ) ,
1721
+ }
1722
+ assert_ne ! ( sweep_tx_0, sweep_tx_2) ;
1723
+ assert_ne ! ( sweep_tx_1, sweep_tx_2) ;
1724
+
1725
+ // Check we still track the spendable outputs up to ANTI_REORG_DELAY confirmations.
1726
+ confirm_transaction_depth ( & mut nodes[ 0 ] , & sweep_tx_2, 5 ) ;
1727
+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1728
+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1729
+ match tracked_output. status {
1730
+ OutputSpendStatus :: PendingThresholdConfirmations { latest_spending_tx, .. } => {
1731
+ assert_eq ! ( sweep_tx_2. txid( ) , latest_spending_tx. txid( ) ) ;
1732
+ }
1733
+ _ => panic ! ( "Unexpected status" ) ,
1734
+ }
1735
+
1736
+ // Check we still see the transaction as confirmed if we unconfirm any untracked
1737
+ // transaction. (We previously had a bug that would mark tracked transactions as
1738
+ // unconfirmed if any transaction at an unknown block height would be unconfirmed.)
1739
+ let unconf_txid = Txid :: from_slice ( & [ 0 ; 32 ] ) . unwrap ( ) ;
1740
+ nodes[ 0 ] . sweeper . transaction_unconfirmed ( & unconf_txid) ;
1741
+
1742
+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 1 ) ;
1743
+ let tracked_output = nodes[ 0 ] . sweeper . tracked_spendable_outputs ( ) . first ( ) . unwrap ( ) . clone ( ) ;
1744
+ match tracked_output. status {
1745
+ OutputSpendStatus :: PendingThresholdConfirmations { latest_spending_tx, .. } => {
1746
+ assert_eq ! ( sweep_tx_2. txid( ) , latest_spending_tx. txid( ) ) ;
1747
+ }
1748
+ _ => panic ! ( "Unexpected status" ) ,
1749
+ }
1750
+
1751
+ // Check we stop tracking the spendable outputs when one of the txs reaches
1752
+ // ANTI_REORG_DELAY confirmations.
1753
+ confirm_transaction_depth ( & mut nodes[ 0 ] , & sweep_tx_0, ANTI_REORG_DELAY ) ;
1754
+ assert_eq ! ( nodes[ 0 ] . sweeper. tracked_spendable_outputs( ) . len( ) , 0 ) ;
1755
+
1624
1756
if !std:: thread:: panicking ( ) {
1625
1757
bg_processor. stop ( ) . unwrap ( ) ;
1626
1758
}
0 commit comments