X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_tests.rs;h=4ad777f5b6275cc957d5528cf62f4818db049f28;hb=7d8dc7ac1a05606e6422e0b4126b95717adc075d;hp=9a0c06e776cf4db266050b7986d08dc7fab67d2b;hpb=5e8b6833339a67f2f9a498db74b43ef93629755c;p=rust-lightning diff --git a/lightning/src/ln/functional_tests.rs b/lightning/src/ln/functional_tests.rs index 9a0c06e7..4ad777f5 100644 --- a/lightning/src/ln/functional_tests.rs +++ b/lightning/src/ln/functional_tests.rs @@ -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}; @@ -1568,18 +1569,8 @@ fn test_fee_spike_violation_fails_htlc() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known()); - let logger = test_utils::TestLogger::new(); - - macro_rules! get_route_and_payment_hash { - ($recv_value: expr) => {{ - let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[1]); - let net_graph_msg_handler = &nodes[0].net_graph_msg_handler.network_graph.read().unwrap(); - let route = get_route(&nodes[0].node.get_our_node_id(), net_graph_msg_handler, &nodes.last().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap(); - (route, payment_hash, payment_preimage) - }} - } - let (route, payment_hash, _) = get_route_and_payment_hash!(3460001); + let (route, payment_hash, _) = get_route_and_payment_hash!(nodes[0], nodes[1], 3460001); // Need to manually create the update_add_htlc message to go around the channel reserve check in send_htlc() let secp_ctx = Secp256k1::new(); let session_priv = SecretKey::from_slice(&[42; 32]).expect("RNG is bad!"); @@ -1708,18 +1699,8 @@ fn test_chan_reserve_violation_outbound_htlc_inbound_chan() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let _ = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known()); - let logger = test_utils::TestLogger::new(); - macro_rules! get_route_and_payment_hash { - ($recv_value: expr) => {{ - let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[1]); - let net_graph_msg_handler = &nodes[1].net_graph_msg_handler; - let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.first().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap(); - (route, payment_hash, payment_preimage) - }} - } - - let (route, our_payment_hash, _) = get_route_and_payment_hash!(4843000); + let (route, our_payment_hash, _) = get_route_and_payment_hash!(nodes[1], nodes[0], 4843000); unwrap_send_err!(nodes[1].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err }, assert_eq!(err, "Cannot send value that would put counterparty balance under holder-announced channel reserve value")); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); @@ -1740,18 +1721,8 @@ fn test_chan_reserve_violation_inbound_htlc_outbound_channel() { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known()); - let logger = test_utils::TestLogger::new(); - - macro_rules! get_route_and_payment_hash { - ($recv_value: expr) => {{ - let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[1]); - let net_graph_msg_handler = &nodes[0].net_graph_msg_handler; - let route = get_route(&nodes[1].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.first().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap(); - (route, payment_hash, payment_preimage) - }} - } - let (route, payment_hash, _) = get_route_and_payment_hash!(1000); + let (route, payment_hash, _) = get_route_and_payment_hash!(nodes[1], nodes[0], 1000); // Need to manually create the update_add_htlc message to go around the channel reserve check in send_htlc() let secp_ctx = Secp256k1::new(); let session_priv = SecretKey::from_slice(&[42; 32]).unwrap(); @@ -1836,16 +1807,6 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::known(), InitFeatures::known()); let _ = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 100000, 95000000, InitFeatures::known(), InitFeatures::known()); - let logger = test_utils::TestLogger::new(); - - macro_rules! get_route_and_payment_hash { - ($recv_value: expr) => {{ - let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[0]); - let net_graph_msg_handler = &nodes[0].net_graph_msg_handler; - let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.last().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap(); - (route, payment_hash, payment_preimage) - }} - } let feemsat = 239; let total_routing_fee_msat = (nodes.len() - 2) as u64 * feemsat; @@ -1858,7 +1819,7 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { let amt_msat_1 = recv_value_1 + total_routing_fee_msat; // Add a pending HTLC. - let (route_1, our_payment_hash_1, _) = get_route_and_payment_hash!(amt_msat_1); + let (route_1, our_payment_hash_1, _) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat_1); let payment_event_1 = { nodes[0].node.send_payment(&route_1, our_payment_hash_1, &None).unwrap(); check_added_monitors!(nodes[0], 1); @@ -1873,7 +1834,7 @@ fn test_chan_reserve_violation_inbound_htlc_inbound_chan() { let commit_tx_fee_2_htlcs = commit_tx_fee_msat(feerate, 2); let recv_value_2 = chan_stat.value_to_self_msat - amt_msat_1 - chan_stat.channel_reserve_msat - total_routing_fee_msat - commit_tx_fee_2_htlcs + 1; let amt_msat_2 = recv_value_2 + total_routing_fee_msat; - let (route_2, _, _) = get_route_and_payment_hash!(amt_msat_2); + let (route_2, _, _) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat_2); // Need to manually create the update_add_htlc message to go around the channel reserve check in send_htlc() let secp_ctx = Secp256k1::new(); @@ -1931,7 +1892,6 @@ fn test_channel_reserve_holding_cell_htlcs() { let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); let chan_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 190000, 1001, InitFeatures::known(), InitFeatures::known()); let chan_2 = create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 190000, 1001, InitFeatures::known(), InitFeatures::known()); - let logger = test_utils::TestLogger::new(); let mut stat01 = get_channel_value_stat!(nodes[0], chan_1.2); let mut stat11 = get_channel_value_stat!(nodes[1], chan_1.2); @@ -1939,15 +1899,6 @@ fn test_channel_reserve_holding_cell_htlcs() { let mut stat12 = get_channel_value_stat!(nodes[1], chan_2.2); let mut stat22 = get_channel_value_stat!(nodes[2], chan_2.2); - macro_rules! get_route_and_payment_hash { - ($recv_value: expr) => {{ - let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[0]); - let net_graph_msg_handler = &nodes[0].net_graph_msg_handler; - let route = get_route(&nodes[0].node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &nodes.last().unwrap().node.get_our_node_id(), None, None, &Vec::new(), $recv_value, TEST_FINAL_CLTV, &logger).unwrap(); - (route, payment_hash, payment_preimage) - }} - } - macro_rules! expect_forward { ($node: expr) => {{ let mut events = $node.node.get_and_clear_pending_msg_events(); @@ -1966,7 +1917,7 @@ fn test_channel_reserve_holding_cell_htlcs() { // attempt to send amt_msat > their_max_htlc_value_in_flight_msat { - let (mut route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_0); + let (mut route, our_payment_hash, _) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_0); route.paths[0].last_mut().unwrap().fee_msat += 1; assert!(route.paths[0].iter().rev().skip(1).all(|h| h.fee_msat == feemsat)); unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err }, @@ -2018,7 +1969,7 @@ fn test_channel_reserve_holding_cell_htlcs() { let recv_value_1 = (stat01.value_to_self_msat - stat01.channel_reserve_msat - total_fee_msat - commit_tx_fee_2_htlcs)/2; let amt_msat_1 = recv_value_1 + total_fee_msat; - let (route_1, our_payment_hash_1, our_payment_preimage_1) = get_route_and_payment_hash!(recv_value_1); + let (route_1, our_payment_hash_1, our_payment_preimage_1) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_1); let payment_event_1 = { nodes[0].node.send_payment(&route_1, our_payment_hash_1, &None).unwrap(); check_added_monitors!(nodes[0], 1); @@ -2032,7 +1983,7 @@ fn test_channel_reserve_holding_cell_htlcs() { // channel reserve test with htlc pending output > 0 let recv_value_2 = stat01.value_to_self_msat - amt_msat_1 - stat01.channel_reserve_msat - total_fee_msat - commit_tx_fee_2_htlcs; { - let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_2 + 1); + let (route, our_payment_hash, _) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_2 + 1); unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err }, assert!(regex::Regex::new(r"Cannot send value that would put our balance under counterparty-announced channel reserve value \(\d+\)").unwrap().is_match(err))); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); @@ -2049,7 +2000,7 @@ fn test_channel_reserve_holding_cell_htlcs() { } // now see if they go through on both sides - let (route_21, our_payment_hash_21, our_payment_preimage_21) = get_route_and_payment_hash!(recv_value_21); + let (route_21, our_payment_hash_21, our_payment_preimage_21) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_21); // but this will stuck in the holding cell nodes[0].node.send_payment(&route_21, our_payment_hash_21, &None).unwrap(); check_added_monitors!(nodes[0], 0); @@ -2058,14 +2009,14 @@ fn test_channel_reserve_holding_cell_htlcs() { // test with outbound holding cell amount > 0 { - let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_22+1); + let (route, our_payment_hash, _) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22+1); unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { ref err }, assert!(regex::Regex::new(r"Cannot send value that would put our balance under counterparty-announced channel reserve value \(\d+\)").unwrap().is_match(err))); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); nodes[0].logger.assert_log_contains("lightning::ln::channelmanager".to_string(), "Cannot send value that would put our balance under counterparty-announced channel reserve value".to_string(), 2); } - let (route_22, our_payment_hash_22, our_payment_preimage_22) = get_route_and_payment_hash!(recv_value_22); + let (route_22, our_payment_hash_22, our_payment_preimage_22) = get_route_and_payment_hash!(nodes[0], nodes[2], recv_value_22); // this will also stuck in the holding cell nodes[0].node.send_payment(&route_22, our_payment_hash_22, &None).unwrap(); check_added_monitors!(nodes[0], 0); @@ -8225,7 +8176,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 +8235,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 +8261,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 +8287,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 +8300,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 +8778,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); +}