From 85c03c11394aeb86606f838c079ac17c7ec864d5 Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Tue, 10 Dec 2019 17:25:27 -0500 Subject: [PATCH] Add test_bump_txn_sanitize_tracking_maps Extend test visibility of claim-tracking maps to do so. Cover both "If 2 claimable-outpoint-spending txn are in 1 block, clean up properly" and "Clean up claimable_outpoints when pending_claim_requests is cleaned" fix commits in same patchset. --- lightning/src/ln/channelmonitor.rs | 8 ++++- lightning/src/ln/functional_tests.rs | 46 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index 154d8ccf7..d83171bd1 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -513,7 +513,7 @@ enum OnchainEvent { /// Higher-level cache structure needed to re-generate bumped claim txn if needed #[derive(Clone, PartialEq)] -struct ClaimTxBumpMaterial { +pub struct ClaimTxBumpMaterial { // At every block tick, used to check if pending claiming tx is taking too // much time for confirmation and we need to bump it. height_timer: u32, @@ -621,6 +621,9 @@ pub struct ChannelMonitor { // Key is identifier of the pending claim request, i.e the txid of the initial claiming transaction generated by // us and is immutable until all outpoint of the claimable set are post-anti-reorg-delay solved. // Entry is cache of elements need to generate a bumped claiming transaction (see ClaimTxBumpMaterial) + #[cfg(test)] // Used in functional_test to verify sanitization + pub pending_claim_requests: HashMap, + #[cfg(not(test))] pending_claim_requests: HashMap, // Used to link outpoints claimed in a connected block to a pending claim request. @@ -629,6 +632,9 @@ pub struct ChannelMonitor { // is txid of the initial claiming transaction and is immutable until outpoint is // post-anti-reorg-delay solved, confirmaiton_block is used to erase entry if // block with output gets disconnected. + #[cfg(test)] // Used in functional_test to verify sanitization + pub claimable_outpoints: HashMap, + #[cfg(not(test))] claimable_outpoints: HashMap, // Used to track onchain events, i.e transactions parts of channels confirmed on chain, on which diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 65fdb2192..3be08a372 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -6762,3 +6762,49 @@ fn test_set_outpoints_partial_claiming() { node_txn.clear(); } } + +#[test] +fn test_bump_txn_sanitize_tracking_maps() { + // Sanitizing pendning_claim_request and claimable_outpoints used to be buggy, + // verify we clean then right after expiration of ANTI_REORG_DELAY. + + let nodes = create_network(2, &[None, None]); + + let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000, LocalFeatures::new(), LocalFeatures::new()); + // Lock HTLC in both directions + let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0; + route_payment(&nodes[1], &vec!(&nodes[0])[..], 9_000_000).0; + + let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone(); + assert_eq!(revoked_local_txn[0].input.len(), 1); + assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid()); + + // Revoke local commitment tx + claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 9_000_000); + + // Broadcast set of revoked txn on A + let header_128 = connect_blocks(&nodes[0].block_notifier, 128, 0, false, Default::default()); + let header_129 = BlockHeader { version: 0x20000000, prev_blockhash: header_128, merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[0].block_notifier.block_connected(&Block { header: header_129, txdata: vec![revoked_local_txn[0].clone()] }, 129); + check_closed_broadcast!(nodes[0]); + let penalty_txn = { + let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); + assert_eq!(node_txn.len(), 7); + check_spends!(node_txn[0], revoked_local_txn[0].clone()); + check_spends!(node_txn[1], revoked_local_txn[0].clone()); + check_spends!(node_txn[2], revoked_local_txn[0].clone()); + let penalty_txn = vec![node_txn[0].clone(), node_txn[1].clone(), node_txn[2].clone()]; + node_txn.clear(); + penalty_txn + }; + let header_130 = BlockHeader { version: 0x20000000, prev_blockhash: header_129.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + nodes[0].block_notifier.block_connected(&Block { header: header_130, txdata: penalty_txn }, 130); + connect_blocks(&nodes[0].block_notifier, 5, 130, false, header_130.bitcoin_hash()); + { + let monitors = nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap(); + if let Some(monitor) = monitors.get(&OutPoint::new(chan.3.txid(), 0)) { + assert!(monitor.pending_claim_requests.is_empty()); + assert!(monitor.claimable_outpoints.is_empty()); + } + } +} -- 2.39.5