Merge pull request #897 from TheBlueMatt/2021-04-fix-ci
[rust-lightning] / lightning / src / ln / functional_tests.rs
index 9a0c06e776cf4db266050b7986d08dc7fab67d2b..7a39db2f312b1bf97b7a340906d55018b6d13e53 100644 (file)
@@ -12,6 +12,7 @@
 //! claim outputs on-chain.
 
 use chain;
+use chain::Listen;
 use chain::Watch;
 use chain::channelmonitor;
 use chain::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
@@ -8225,7 +8226,7 @@ fn test_update_err_monitor_lockdown() {
                watchtower
        };
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       watchtower.chain_monitor.block_connected(&header, &[], 200);
+       watchtower.chain_monitor.block_connected(&Block { header, txdata: vec![] }, 200);
 
        // Try to update ChannelMonitor
        assert!(nodes[1].node.claim_funds(preimage, &None, 9_000_000));
@@ -8284,7 +8285,7 @@ fn test_concurrent_monitor_claim() {
                watchtower
        };
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       watchtower_alice.chain_monitor.block_connected(&header, &vec![], CHAN_CONFIRM_DEPTH + 1 + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
+       watchtower_alice.chain_monitor.block_connected(&Block { header, txdata: vec![] }, CHAN_CONFIRM_DEPTH + 1 + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
 
        // Watchtower Alice should have broadcast a commitment/HTLC-timeout
        {
@@ -8310,7 +8311,7 @@ fn test_concurrent_monitor_claim() {
                watchtower
        };
        let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
-       watchtower_bob.chain_monitor.block_connected(&header, &vec![], CHAN_CONFIRM_DEPTH + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
+       watchtower_bob.chain_monitor.block_connected(&Block { header, txdata: vec![] }, CHAN_CONFIRM_DEPTH + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
 
        // Route another payment to generate another update with still previous HTLC pending
        let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
@@ -8336,7 +8337,8 @@ fn test_concurrent_monitor_claim() {
        check_added_monitors!(nodes[0], 1);
 
        //// Provide one more block to watchtower Bob, expect broadcast of commitment and HTLC-Timeout
-       watchtower_bob.chain_monitor.block_connected(&header, &vec![], CHAN_CONFIRM_DEPTH + 1 + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
+       let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+       watchtower_bob.chain_monitor.block_connected(&Block { header, txdata: vec![] }, CHAN_CONFIRM_DEPTH + 1 + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
 
        // Watchtower Bob should have broadcast a commitment/HTLC-timeout
        let bob_state_y;
@@ -8348,7 +8350,8 @@ fn test_concurrent_monitor_claim() {
        };
 
        // We confirm Bob's state Y on Alice, she should broadcast a HTLC-timeout
-       watchtower_alice.chain_monitor.block_connected(&header, &vec![(0, &bob_state_y)], CHAN_CONFIRM_DEPTH + 2 + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
+       let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
+       watchtower_alice.chain_monitor.block_connected(&Block { header, txdata: vec![bob_state_y.clone()] }, CHAN_CONFIRM_DEPTH + 2 + TEST_FINAL_CLTV + LATENCY_GRACE_PERIOD_BLOCKS);
        {
                let htlc_txn = chanmon_cfgs[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
                // We broadcast twice the transaction, once due to the HTLC-timeout, once due
@@ -8825,3 +8828,53 @@ fn test_error_chans_closed() {
        assert_eq!(nodes[0].node.list_usable_channels().len(), 1);
        assert!(nodes[0].node.list_usable_channels()[0].channel_id == chan_3.2);
 }
+
+#[test]
+fn test_invalid_funding_tx() {
+       // Test that we properly handle invalid funding transactions sent to us from a peer.
+       //
+       // Previously, all other major lightning implementations had failed to properly sanitize
+       // funding transactions from their counterparties, leading to a multi-implementation critical
+       // security vulnerability (though we always sanitized properly, we've previously had
+       // un-released crashes in the sanitization process).
+       let chanmon_cfgs = create_chanmon_cfgs(2);
+       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
+       let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
+
+       nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 10_000, 42, None).unwrap();
+       nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()));
+       nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()));
+
+       let (temporary_channel_id, mut tx, _) = create_funding_transaction(&nodes[0], 100_000, 42);
+       for output in tx.output.iter_mut() {
+               // Make the confirmed funding transaction have a bogus script_pubkey
+               output.script_pubkey = bitcoin::Script::new();
+       }
+
+       nodes[0].node.funding_transaction_generated_unchecked(&temporary_channel_id, tx.clone(), 0).unwrap();
+       nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()));
+       check_added_monitors!(nodes[1], 1);
+
+       nodes[0].node.handle_funding_signed(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingSigned, nodes[0].node.get_our_node_id()));
+       check_added_monitors!(nodes[0], 1);
+
+       let events_1 = nodes[0].node.get_and_clear_pending_events();
+       assert_eq!(events_1.len(), 0);
+
+       assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
+       assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx);
+       nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clear();
+
+       confirm_transaction_at(&nodes[1], &tx, 1);
+       check_added_monitors!(nodes[1], 1);
+       let events_2 = nodes[1].node.get_and_clear_pending_msg_events();
+       assert_eq!(events_2.len(), 1);
+       if let MessageSendEvent::HandleError { node_id, action } = &events_2[0] {
+               assert_eq!(*node_id, nodes[0].node.get_our_node_id());
+               if let msgs::ErrorAction::SendErrorMessage { msg } = action {
+                       assert_eq!(msg.data, "funding tx had wrong script/value or output index");
+               } else { panic!(); }
+       } else { panic!(); }
+       assert_eq!(nodes[1].node.list_channels().len(), 0);
+}