- #[test]
- fn channel_monitor_network_test() {
- // Simple test which builds a network of ChannelManagers, connects them to each other, and
- // tests that ChannelMonitor is able to recover from various states.
- let nodes = create_network(5);
-
- // Create some initial channels
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
- let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
- let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3);
- let chan_4 = create_announced_chan_between_nodes(&nodes, 3, 4);
-
- // Rebalance the network a bit by relaying one payment through all the channels...
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
- send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
-
- // Simple case with no pending HTLCs:
- nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), true);
- {
- let mut node_txn = test_txn_broadcast(&nodes[1], &chan_1, None, HTLCType::NONE);
- let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1);
- test_txn_broadcast(&nodes[0], &chan_1, None, HTLCType::NONE);
- }
- get_announce_close_broadcast_events(&nodes, 0, 1);
- assert_eq!(nodes[0].node.list_channels().len(), 0);
- assert_eq!(nodes[1].node.list_channels().len(), 1);
-
- // One pending HTLC is discarded by the force-close:
- let payment_preimage_1 = route_payment(&nodes[1], &vec!(&nodes[2], &nodes[3])[..], 3000000).0;
-
- // Simple case of one pending HTLC to HTLC-Timeout
- nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), true);
- {
- let mut node_txn = test_txn_broadcast(&nodes[1], &chan_2, None, HTLCType::TIMEOUT);
- let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[2].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn.drain(..).next().unwrap()] }, 1);
- test_txn_broadcast(&nodes[2], &chan_2, None, HTLCType::NONE);
- }
- get_announce_close_broadcast_events(&nodes, 1, 2);
- assert_eq!(nodes[1].node.list_channels().len(), 0);
- assert_eq!(nodes[2].node.list_channels().len(), 1);
-
- macro_rules! claim_funds {
- ($node: expr, $prev_node: expr, $preimage: expr) => {
- {
- assert!($node.node.claim_funds($preimage));
- {
- let mut added_monitors = $node.chan_monitor.added_monitors.lock().unwrap();
- assert_eq!(added_monitors.len(), 1);
- added_monitors.clear();
- }
-
- let events = $node.node.get_and_clear_pending_events();
- assert_eq!(events.len(), 1);
- match events[0] {
- Event::UpdateHTLCs { ref node_id, updates: msgs::CommitmentUpdate { ref update_add_htlcs, ref update_fail_htlcs, .. } } => {
- assert!(update_add_htlcs.is_empty());
- assert!(update_fail_htlcs.is_empty());
- assert_eq!(*node_id, $prev_node.node.get_our_node_id());
- },
- _ => panic!("Unexpected event"),
- };
- }
- }
- }
-
- // nodes[3] gets the preimage, but nodes[2] already disconnected, resulting in a nodes[2]
- // HTLC-Timeout and a nodes[3] claim against it (+ its own announces)
- nodes[2].node.peer_disconnected(&nodes[3].node.get_our_node_id(), true);
- {
- let node_txn = test_txn_broadcast(&nodes[2], &chan_3, None, HTLCType::TIMEOUT);
-
- // Claim the payment on nodes[3], giving it knowledge of the preimage
- claim_funds!(nodes[3], nodes[2], payment_preimage_1);
-
- let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[3].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, 1);
-
- check_preimage_claim(&nodes[3], &node_txn);
- }
- get_announce_close_broadcast_events(&nodes, 2, 3);
- assert_eq!(nodes[2].node.list_channels().len(), 0);
- assert_eq!(nodes[3].node.list_channels().len(), 1);
-
- // One pending HTLC to time out:
- let payment_preimage_2 = route_payment(&nodes[3], &vec!(&nodes[4])[..], 3000000).0;
-
- {
- let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[3].chain_monitor.block_connected_checked(&header, 1, &Vec::new()[..], &[0; 0]);
- for i in 2..TEST_FINAL_CLTV - 3 {
- header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[3].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]);
- }
-
- let node_txn = test_txn_broadcast(&nodes[3], &chan_4, None, HTLCType::TIMEOUT);
-
- // Claim the payment on nodes[4], giving it knowledge of the preimage
- claim_funds!(nodes[4], nodes[3], payment_preimage_2);
-
- header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[4].chain_monitor.block_connected_checked(&header, 1, &Vec::new()[..], &[0; 0]);
- for i in 2..TEST_FINAL_CLTV - 3 {
- header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[4].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]);
- }
-
- test_txn_broadcast(&nodes[4], &chan_4, None, HTLCType::SUCCESS);
-
- header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[4].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[0].clone()] }, TEST_FINAL_CLTV - 5);
-
- check_preimage_claim(&nodes[4], &node_txn);
- }
- get_announce_close_broadcast_events(&nodes, 3, 4);
- assert_eq!(nodes[3].node.list_channels().len(), 0);
- assert_eq!(nodes[4].node.list_channels().len(), 0);
-
- // Create some new channels:
- let chan_5 = create_announced_chan_between_nodes(&nodes, 0, 1);
-
- // A pending HTLC which will be revoked:
- let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
- // Get the will-be-revoked local txn from nodes[0]
- let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.last_local_commitment_txn.clone();
- assert_eq!(revoked_local_txn.len(), 2); // First commitment tx, then HTLC tx
- assert_eq!(revoked_local_txn[0].input.len(), 1);
- assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_5.3.txid());
- assert_eq!(revoked_local_txn[0].output.len(), 2); // Only HTLC and output back to 0 are present
- assert_eq!(revoked_local_txn[1].input.len(), 1);
- assert_eq!(revoked_local_txn[1].input[0].previous_output.txid, revoked_local_txn[0].txid());
- assert_eq!(revoked_local_txn[1].input[0].witness.last().unwrap().len(), 133); // HTLC-Timeout
- // Revoke the old state
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3);
-
- {
- let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
- {
- let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert_eq!(node_txn.len(), 3);
- assert_eq!(node_txn.pop().unwrap(), node_txn[0]); // An outpoint registration will result in a 2nd block_connected
- assert_eq!(node_txn[0].input.len(), 2); // We should claim the revoked output and the HTLC output
-
- let mut funding_tx_map = HashMap::new();
- funding_tx_map.insert(revoked_local_txn[0].txid(), revoked_local_txn[0].clone());
- node_txn[0].verify(&funding_tx_map).unwrap();
- node_txn.swap_remove(0);
- }
- test_txn_broadcast(&nodes[1], &chan_5, None, HTLCType::NONE);
-
- nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
- let node_txn = test_txn_broadcast(&nodes[0], &chan_5, Some(revoked_local_txn[0].clone()), HTLCType::TIMEOUT);
- header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![node_txn[1].clone()] }, 1);
- test_revoked_htlc_claim_txn_broadcast(&nodes[1], node_txn[1].clone());
- }
- get_announce_close_broadcast_events(&nodes, 0, 1);
- assert_eq!(nodes[0].node.list_channels().len(), 0);
- assert_eq!(nodes[1].node.list_channels().len(), 0);
- }
-
- #[test]
- fn revoked_output_claim() {
- // Simple test to ensure a node will claim a revoked output when a stale remote commitment
- // transaction is broadcast by its counterparty
- let nodes = create_network(2);
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
- // node[0] is gonna to revoke an old state thus node[1] should be able to claim the revoked output
- let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
- assert_eq!(revoked_local_txn.len(), 1);
- // Only output is the full channel value back to nodes[0]:
- assert_eq!(revoked_local_txn[0].output.len(), 1);
- // Send a payment through, updating everyone's latest commitment txn
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 5000000);
-
- // Inform nodes[1] that nodes[0] broadcast a stale tx
- let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
- let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert_eq!(node_txn.len(), 3); // nodes[1] will broadcast justice tx twice, and its own local state once
-
- assert_eq!(node_txn[0], node_txn[2]);
-
- let mut revoked_tx_map = HashMap::new();
- revoked_tx_map.insert(revoked_local_txn[0].txid(), revoked_local_txn[0].clone());
- node_txn[0].verify(&revoked_tx_map).unwrap();
-
- revoked_tx_map.clear();
- revoked_tx_map.insert(chan_1.3.txid(), chan_1.3.clone());
- node_txn[1].verify(&revoked_tx_map).unwrap();
-
- // Inform nodes[0] that a watchtower cheated on its behalf, so it will force-close the chan
- nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
- get_announce_close_broadcast_events(&nodes, 0, 1);
- }
-
- #[test]
- fn claim_htlc_outputs_shared_tx() {
- // Node revoked old state, htlcs haven't time out yet, claim them in shared justice tx
- let nodes = create_network(2);
-
- // Create some new channel:
- let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
-
- // Rebalance the network to generate htlc in the two directions
- send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
- // node[0] is gonna to revoke an old state thus node[1] should be able to claim both offered/received HTLC outputs on top of commitment tx
- let payment_preimage_1 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
- let _payment_preimage_2 = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000).0;
-
- // Get the will-be-revoked local txn from node[0]
- let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
- assert_eq!(revoked_local_txn.len(), 2); // commitment tx + 1 HTLC-Timeout tx
- assert_eq!(revoked_local_txn[0].input.len(), 1);
- assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
- assert_eq!(revoked_local_txn[1].input.len(), 1);
- assert_eq!(revoked_local_txn[1].input[0].previous_output.txid, revoked_local_txn[0].txid());
- assert_eq!(revoked_local_txn[1].input[0].witness.last().unwrap().len(), 133); // HTLC-Timeout
-
- //Revoke the old state
- claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1);
-
- {
- let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-
- nodes[0].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
-
- nodes[1].chain_monitor.block_connected_with_filtering(&Block { header, txdata: vec![revoked_local_txn[0].clone()] }, 1);
- let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
- assert_eq!(node_txn.len(), 4);
-
- let mut revoked_tx_map = HashMap::new();
- revoked_tx_map.insert(revoked_local_txn[0].txid(), revoked_local_txn[0].clone());
-
- assert_eq!(node_txn[0].input.len(), 3); // Claim the revoked output + both revoked HTLC outputs
- node_txn[0].verify(&revoked_tx_map).unwrap();
- assert_eq!(node_txn[0], node_txn[3]); // justice tx is duplicated due to block re-scanning
-
- let mut witness_lens = BTreeSet::new();
- witness_lens.insert(node_txn[0].input[0].witness.last().unwrap().len());
- witness_lens.insert(node_txn[0].input[1].witness.last().unwrap().len());
- witness_lens.insert(node_txn[0].input[2].witness.last().unwrap().len());
- assert_eq!(witness_lens.len(), 3);
- assert_eq!(*witness_lens.iter().skip(0).next().unwrap(), 77); // revoked to_local
- assert_eq!(*witness_lens.iter().skip(1).next().unwrap(), 133); // revoked offered HTLC
- assert_eq!(*witness_lens.iter().skip(2).next().unwrap(), 138); // revoked received HTLC
-
- // Next nodes[1] broadcasts its current local tx state:
- assert_eq!(node_txn[1].input.len(), 1);
- assert_eq!(node_txn[1].input[0].previous_output.txid, chan_1.3.txid()); //Spending funding tx unique txouput, tx broadcasted by ChannelManager
-
- assert_eq!(node_txn[2].input.len(), 1);
- let witness_script = node_txn[2].clone().input[0].witness.pop().unwrap();
- assert_eq!(witness_script.len(), 133); //Spending an offered htlc output
- assert_eq!(node_txn[2].input[0].previous_output.txid, node_txn[1].txid());
- assert_ne!(node_txn[2].input[0].previous_output.txid, node_txn[0].input[0].previous_output.txid);
- assert_ne!(node_txn[2].input[0].previous_output.txid, node_txn[0].input[1].previous_output.txid);