Add test_data_loss_protect
[rust-lightning] / src / ln / functional_tests.rs
index 2c44b701d890778e302218ce8eb02a4bb22e237f..9debe08fa28889f74dc97379b1412a27eca32eb2 100644 (file)
@@ -3,12 +3,13 @@
 //! claim outputs on-chain.
 
 use chain::transaction::OutPoint;
-use chain::chaininterface::{ChainListener, ChainWatchInterface};
-use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor};
+use chain::chaininterface::{ChainListener, ChainWatchInterface, ChainWatchInterfaceUtil};
+use chain::keysinterface::{KeysInterface, SpendableOutputDescriptor, KeysManager};
+use chain::keysinterface;
 use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
 use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT};
 use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY};
-use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT};
+use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT, Channel, ChannelError};
 use ln::onion_utils;
 use ln::router::{Route, RouteHop};
 use ln::msgs;
@@ -18,6 +19,7 @@ use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsPro
 use util::errors::APIError;
 use util::ser::{Writeable, ReadableArgs};
 use util::config::UserConfig;
+use util::logger::Logger;
 
 use bitcoin::util::hash::BitcoinHash;
 use bitcoin_hashes::sha256d::Hash as Sha256dHash;
@@ -39,7 +41,7 @@ use secp256k1::key::{PublicKey,SecretKey};
 
 use std::collections::{BTreeSet, HashMap, HashSet};
 use std::default::Default;
-use std::sync::Arc;
+use std::sync::{Arc, Mutex};
 use std::sync::atomic::Ordering;
 use std::mem;
 
@@ -1727,7 +1729,15 @@ fn channel_monitor_network_test() {
 fn test_justice_tx() {
        // Test justice txn built on revoked HTLC-Success tx, against both sides
 
-       let nodes = create_network(2, &[None, None]);
+       let mut alice_config = UserConfig::new();
+       alice_config.channel_options.announced_channel = true;
+       alice_config.peer_channel_config_limits.force_announced_channel_preference = false;
+       alice_config.own_channel_config.our_to_self_delay = 6 * 24 * 5;
+       let mut bob_config = UserConfig::new();
+       bob_config.channel_options.announced_channel = true;
+       bob_config.peer_channel_config_limits.force_announced_channel_preference = false;
+       bob_config.own_channel_config.our_to_self_delay = 6 * 24 * 3;
+       let nodes = create_network(2, &[Some(alice_config), Some(bob_config)]);
        // Create some new channels:
        let chan_5 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
 
@@ -5664,8 +5674,8 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
 
        let bs_dust_limit = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().our_dust_limit_satoshis;
 
-       let (payment_preimage_1, dust_hash) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
-       let (payment_preimage_2, non_dust_hash) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
+       let (_payment_preimage_1, dust_hash) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
+       let (_payment_preimage_2, non_dust_hash) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
 
        let as_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
        let bs_commitment_tx = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_local_commitment_txn.clone();
@@ -5879,3 +5889,171 @@ fn test_upfront_shutdown_script() {
                _ => panic!("Unexpected event"),
        }
 }
+
+#[test]
+fn test_user_configurable_csv_delay() {
+       // We test our channel constructors yield errors when we pass them absurd csv delay
+
+       let mut low_our_to_self_config = UserConfig::new();
+       low_our_to_self_config.own_channel_config.our_to_self_delay = 6;
+       let mut high_their_to_self_config = UserConfig::new();
+       high_their_to_self_config.peer_channel_config_limits.their_to_self_delay = 100;
+       let nodes = create_network(2, &[Some(high_their_to_self_config.clone()), None]);
+
+       // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in Channel::new_outbound()
+       let keys_manager: Arc<KeysInterface> = Arc::new(KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new()), 10, 20));
+       if let Err(error) = Channel::new_outbound(&test_utils::TestFeeEstimator { sat_per_kw: 253 }, &keys_manager, nodes[1].node.get_our_node_id(), 1000000, 1000000, 0, Arc::new(test_utils::TestLogger::new()), &low_our_to_self_config) {
+               match error {
+                       APIError::APIMisuseError { err } => { assert_eq!(err, "Configured with an unreasonable our_to_self_delay putting user funds at risks"); },
+                       _ => panic!("Unexpected event"),
+               }
+       } else { assert!(false) }
+
+       // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in Channel::new_from_req()
+       nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42).unwrap();
+       let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
+       open_channel.to_self_delay = 200;
+       if let Err(error) = Channel::new_from_req(&test_utils::TestFeeEstimator { sat_per_kw: 253 }, &keys_manager, nodes[1].node.get_our_node_id(), LocalFeatures::new(), &open_channel, 0, Arc::new(test_utils::TestLogger::new()), &low_our_to_self_config) {
+               match error {
+                       ChannelError::Close(err) => { assert_eq!(err, "Configured with an unreasonable our_to_self_delay putting user funds at risks"); },
+                       _ => panic!("Unexpected event"),
+               }
+       } else { assert!(false); }
+
+       // We test msg.to_self_delay <= config.their_to_self_delay is enforced in Chanel::accept_channel()
+       nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 1000000, 1000000, 42).unwrap();
+       nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), LocalFeatures::new(), &get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id())).unwrap();
+       let mut accept_channel = get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
+       accept_channel.to_self_delay = 200;
+       if let Err(error) = nodes[0].node.handle_accept_channel(&nodes[1].node.get_our_node_id(), LocalFeatures::new(), &accept_channel) {
+               if let Some(error) = error.action {
+                       match error {
+                               ErrorAction::SendErrorMessage { msg } => {
+                                       assert_eq!(msg.data,"They wanted our payments to be delayed by a needlessly long period");
+                               },
+                               _ => { assert!(false); }
+                       }
+               } else { assert!(false); }
+       } else { assert!(false); }
+
+       // We test msg.to_self_delay <= config.their_to_self_delay is enforced in Channel::new_from_req()
+       nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42).unwrap();
+       let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
+       open_channel.to_self_delay = 200;
+       if let Err(error) = Channel::new_from_req(&test_utils::TestFeeEstimator { sat_per_kw: 253 }, &keys_manager, nodes[1].node.get_our_node_id(), LocalFeatures::new(), &open_channel, 0, Arc::new(test_utils::TestLogger::new()), &high_their_to_self_config) {
+               match error {
+                       ChannelError::Close(err) => { assert_eq!(err, "They wanted our payments to be delayed by a needlessly long period"); },
+                       _ => panic!("Unexpected event"),
+               }
+       } else { assert!(false); }
+}
+
+#[test]
+fn test_data_loss_protect() {
+       // We want to be sure that :
+       // * we don't broadcast our Local Commitment Tx in case of fallen behind
+       // * we close channel in case of detecting other being fallen behind
+       // * we are able to claim our own outputs thanks to remote my_current_per_commitment_point
+       let mut nodes = create_network(2, &[None, None]);
+
+       let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, LocalFeatures::new(), LocalFeatures::new());
+
+       // Cache node A state before any channel update
+       let previous_node_state = nodes[0].node.encode();
+       let mut previous_chan_monitor_state = test_utils::TestVecWriter(Vec::new());
+       nodes[0].chan_monitor.simple_monitor.monitors.lock().unwrap().iter().next().unwrap().1.write_for_disk(&mut previous_chan_monitor_state).unwrap();
+
+       send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
+       send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000);
+
+       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
+       nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), false);
+
+       // Restore node A from previous state
+       let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::with_id(format!("node {}", 0)));
+       let chan_monitor = <(Sha256dHash, ChannelMonitor)>::read(&mut ::std::io::Cursor::new(previous_chan_monitor_state.0), Arc::clone(&logger)).unwrap().1;
+       let chain_monitor = Arc::new(ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
+       let tx_broadcaster = Arc::new(test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())});
+       let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 });
+       let monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone(), logger.clone(), feeest.clone()));
+       let mut channel_monitors = HashMap::new();
+       channel_monitors.insert(OutPoint { txid: chan.3.txid(), index: 0 }, &chan_monitor);
+       let node_state_0 = <(Sha256dHash, ChannelManager)>::read(&mut ::std::io::Cursor::new(previous_node_state), ChannelManagerReadArgs {
+               keys_manager: Arc::new(keysinterface::KeysManager::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger), 42, 21)),
+               fee_estimator: feeest.clone(),
+               monitor: monitor.clone(),
+               chain_monitor: chain_monitor.clone(),
+               logger: Arc::clone(&logger),
+               tx_broadcaster,
+               default_config: UserConfig::new(),
+               channel_monitors: &channel_monitors
+       }).unwrap().1;
+       nodes[0].node = Arc::new(node_state_0);
+       monitor.add_update_monitor(OutPoint { txid: chan.3.txid(), index: 0 }, chan_monitor.clone()).is_ok();
+       nodes[0].chan_monitor = monitor;
+       nodes[0].chain_monitor = chain_monitor;
+       check_added_monitors!(nodes[0], 1);
+
+       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id());
+       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id());
+
+       let reestablish_0 = get_chan_reestablish_msgs!(nodes[1], nodes[0]);
+
+       // Check we update monitor following learning of per_commitment_point from B
+       if let Err(err) = nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &reestablish_0[0])  {
+               if let Some(error) = err.action {
+                       match error {
+                               ErrorAction::SendErrorMessage { msg } => {
+                                       assert_eq!(msg.data, "We have fallen behind - we have received proof that if we broadcast remote is going to claim our funds - we can't do any automated broadcasting");
+                               },
+                               _ => panic!("Unexpected event!"),
+                       }
+               } else { assert!(false); }
+       } else { assert!(false); }
+       check_added_monitors!(nodes[0], 1);
+
+       {
+               let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
+               assert_eq!(node_txn.len(), 0);
+       }
+
+       let mut reestablish_1 = Vec::with_capacity(1);
+       for msg in nodes[0].node.get_and_clear_pending_msg_events() {
+               if let MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } = msg {
+                       assert_eq!(*node_id, nodes[1].node.get_our_node_id());
+                       reestablish_1.push(msg.clone());
+               } else if let MessageSendEvent::BroadcastChannelUpdate { .. } = msg {
+               } else {
+                       panic!("Unexpected event")
+               }
+       }
+
+       // Check we close channel detecting A is fallen-behind
+       if let Err(err) = nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &reestablish_1[0]) {
+               if let Some(error) = err.action {
+                       match error {
+                               ErrorAction::SendErrorMessage { msg } => {
+                                       assert_eq!(msg.data, "Peer attempted to reestablish channel with a very old local commitment transaction"); },
+                               _ => panic!("Unexpected event!"),
+                       }
+               } else { assert!(false); }
+       } else { assert!(false); }
+
+       let events = nodes[1].node.get_and_clear_pending_msg_events();
+       assert_eq!(events.len(), 1);
+       match events[0] {
+               MessageSendEvent::BroadcastChannelUpdate { .. } => {},
+               _ => panic!("Unexpected event"),
+       }
+
+       // Check A is able to claim to_remote output
+       let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
+       assert_eq!(node_txn.len(), 1);
+       check_spends!(node_txn[0], chan.3.clone());
+       assert_eq!(node_txn[0].output.len(), 2);
+       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[0].clone()]}, 1);
+       let spend_txn = check_spendable_outputs!(nodes[0], 1);
+       assert_eq!(spend_txn.len(), 1);
+       check_spends!(spend_txn[0], node_txn[0].clone());
+}