X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=8bb49ef97d70cdb59a2c21a76bcb7aaf89313cc4;hb=520b53eb1ca3b187b664de02b095f69b37effbd5;hp=60f5dabe91b52f007608c9c0dcc237c5f35ade96;hpb=f24bbd63cc72e32efaa23844f19f4a7952fb22cb;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 60f5dabe..8bb49ef9 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -10,11 +10,11 @@ //! A bunch of useful utilities for building networks of nodes and exchanging messages between //! nodes for functional tests. -use chain::{Confirm, Listen, Watch}; +use chain::{BestBlock, Confirm, Listen, Watch}; use chain::channelmonitor::ChannelMonitor; use chain::transaction::OutPoint; use ln::{PaymentPreimage, PaymentHash, PaymentSecret}; -use ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure}; +use ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure}; use routing::router::{Route, get_route}; use routing::network_graph::{NetGraphMsgHandler, NetworkGraph}; use ln::features::{InitFeatures, InvoiceFeatures}; @@ -23,7 +23,7 @@ use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler}; use util::enforcing_trait_impls::EnforcingSigner; use util::test_utils; use util::test_utils::TestChainMonitor; -use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider}; +use util::events::{Event, MessageSendEvent, MessageSendEventsProvider}; use util::errors::APIError; use util::config::UserConfig; use util::ser::{ReadableArgs, Writeable, Readable}; @@ -39,11 +39,11 @@ use bitcoin::hash_types::BlockHash; use bitcoin::secp256k1::key::PublicKey; -use std::cell::RefCell; +use prelude::*; +use core::cell::RefCell; use std::rc::Rc; -use std::sync::Mutex; -use std::mem; -use std::collections::HashMap; +use std::sync::{Arc, Mutex}; +use core::mem; pub const CHAN_CONFIRM_DEPTH: u32 = 10; @@ -148,14 +148,14 @@ fn do_connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block, s } } node.node.test_process_background_events(); - node.blocks.borrow_mut().push((block.header, height)); + node.blocks.lock().unwrap().push((block.header, height)); } pub fn disconnect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, count: u32) { for i in 0..count { - let orig_header = node.blocks.borrow_mut().pop().unwrap(); + let orig_header = node.blocks.lock().unwrap().pop().unwrap(); assert!(orig_header.1 > 0); // Cannot disconnect genesis - let prev_header = node.blocks.borrow().last().unwrap().clone(); + let prev_header = node.blocks.lock().unwrap().last().unwrap().clone(); match *node.connect_style.borrow() { ConnectStyle::FullBlockViaListen => { @@ -177,7 +177,7 @@ pub fn disconnect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, count: u32) } pub fn disconnect_all_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) { - let count = node.blocks.borrow_mut().len() as u32 - 1; + let count = node.blocks.lock().unwrap().len() as u32 - 1; disconnect_blocks(node, count); } @@ -211,15 +211,18 @@ pub struct Node<'a, 'b: 'a, 'c: 'b> { pub network_payment_count: Rc>, pub network_chan_count: Rc>, pub logger: &'c test_utils::TestLogger, - pub blocks: RefCell>, + pub blocks: Arc>>, pub connect_style: Rc>, } impl<'a, 'b, 'c> Node<'a, 'b, 'c> { pub fn best_block_hash(&self) -> BlockHash { - self.blocks.borrow_mut().last().unwrap().0.block_hash() + self.blocks.lock().unwrap().last().unwrap().0.block_hash() } pub fn best_block_info(&self) -> (BlockHash, u32) { - self.blocks.borrow_mut().last().map(|(a, b)| (a.block_hash(), *b)).unwrap() + self.blocks.lock().unwrap().last().map(|(a, b)| (a.block_hash(), *b)).unwrap() + } + pub fn get_block_header(&self, height: u32) -> BlockHeader { + self.blocks.lock().unwrap()[height as usize].0 } } @@ -266,7 +269,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { // Check that if we serialize and then deserialize all our channel monitors we get the // same set of outputs to watch for on chain as we have now. Note that if we write // tests that fully close channels and remove the monitors at some point this may break. - let feeest = test_utils::TestFeeEstimator { sat_per_kw: 253 }; + let feeest = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }; let mut deserialized_monitors = Vec::new(); { let old_monitors = self.chain_monitor.chain_monitor.monitors.read().unwrap(); @@ -292,10 +295,11 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { <(BlockHash, ChannelManager)>::read(&mut ::std::io::Cursor::new(w.0), ChannelManagerReadArgs { default_config: *self.node.get_current_default_configuration(), keys_manager: self.keys_manager, - fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: 253 }, + fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }, chain_monitor: self.chain_monitor, tx_broadcaster: &test_utils::TestBroadcaster { - txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()) + txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()), + blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())), }, logger: &test_utils::TestLogger::new(), channel_monitors, @@ -304,7 +308,8 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { let persister = test_utils::TestPersister::new(); let broadcaster = test_utils::TestBroadcaster { - txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()) + txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()), + blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())), }; let chain_source = test_utils::TestChainSource::new(Network::Testnet); let chain_monitor = test_utils::TestChainMonitor::new(Some(&chain_source), &broadcaster, &self.logger, &feeest, &persister, &self.keys_manager); @@ -557,7 +562,7 @@ pub fn create_chan_between_nodes_with_value_confirm_second<'a, 'b, 'c>(node_recv } pub fn create_chan_between_nodes_with_value_confirm<'a, 'b, 'c, 'd>(node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, tx: &Transaction) -> ((msgs::FundingLocked, msgs::AnnouncementSignatures), [u8; 32]) { - let conf_height = std::cmp::max(node_a.best_block_info().1 + 1, node_b.best_block_info().1 + 1); + let conf_height = core::cmp::max(node_a.best_block_info().1 + 1, node_b.best_block_info().1 + 1); create_chan_between_nodes_with_value_confirm_first(node_a, node_b, tx, conf_height); confirm_transaction_at(node_a, tx, conf_height); connect_blocks(node_a, CHAN_CONFIRM_DEPTH - 1); @@ -615,8 +620,22 @@ pub fn create_announced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec>, a: usize, b: usize, ann: &msgs::ChannelAnnouncement, upd_1: &msgs::ChannelUpdate, upd_2: &msgs::ChannelUpdate) { nodes[a].node.broadcast_node_announcement([0, 0, 0], [0; 32], Vec::new()); let a_events = nodes[a].node.get_and_clear_pending_msg_events(); - assert_eq!(a_events.len(), 1); - let a_node_announcement = match a_events[0] { + assert!(a_events.len() >= 2); + + // ann should be re-generated by broadcast_node_announcement - check that we have it. + let mut found_ann_1 = false; + for event in a_events.iter() { + match event { + MessageSendEvent::BroadcastChannelAnnouncement { ref msg, .. } => { + if msg == ann { found_ann_1 = true; } + }, + MessageSendEvent::BroadcastNodeAnnouncement { .. } => {}, + _ => panic!("Unexpected event {:?}", event), + } + } + assert!(found_ann_1); + + let a_node_announcement = match a_events.last().unwrap() { MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => { (*msg).clone() }, @@ -625,8 +644,22 @@ pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec= 2); + + // ann should be re-generated by broadcast_node_announcement - check that we have it. + let mut found_ann_2 = false; + for event in b_events.iter() { + match event { + MessageSendEvent::BroadcastChannelAnnouncement { ref msg, .. } => { + if msg == ann { found_ann_2 = true; } + }, + MessageSendEvent::BroadcastNodeAnnouncement { .. } => {}, + _ => panic!("Unexpected event"), + } + } + assert!(found_ann_2); + + let b_node_announcement = match b_events.last().unwrap() { MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => { (*msg).clone() }, @@ -967,6 +1000,30 @@ macro_rules! expect_payment_sent { } } +#[cfg(test)] +macro_rules! expect_payment_failure_chan_update { + ($node: expr, $scid: expr, $chan_closed: expr) => { + let events = $node.node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::PaymentFailureNetworkUpdate { ref update } => { + match update { + &HTLCFailChannelUpdate::ChannelUpdateMessage { ref msg } if !$chan_closed => { + assert_eq!(msg.contents.short_channel_id, $scid); + assert_eq!(msg.contents.flags & 2, 0); + }, + &HTLCFailChannelUpdate::ChannelClosed { short_channel_id, is_permanent } if $chan_closed => { + assert_eq!(short_channel_id, $scid); + assert!(is_permanent); + }, + _ => panic!("Unexpected update type"), + } + }, + _ => panic!("Unexpected event"), + } + } +} + #[cfg(test)] macro_rules! expect_payment_failed { ($node: expr, $expected_payment_hash: expr, $rejected_by_dest: expr $(, $expected_error_code: expr, $expected_error_data: expr)*) => { @@ -1144,12 +1201,15 @@ pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: claim_payment_along_route(origin_node, &[expected_route], false, our_payment_preimage); } -pub const TEST_FINAL_CLTV: u32 = 50; +pub const TEST_FINAL_CLTV: u32 = 70; pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) { let net_graph_msg_handler = &origin_node.net_graph_msg_handler; let logger = test_utils::TestLogger::new(); - let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap(); + let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), + &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), + Some(&origin_node.node.list_usable_channels().iter().collect::>()), &[], + recv_value, TEST_FINAL_CLTV, &logger).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), expected_route.len()); for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) { @@ -1255,8 +1315,11 @@ pub fn fail_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: pub fn create_chanmon_cfgs(node_count: usize) -> Vec { let mut chan_mon_cfgs = Vec::new(); for i in 0..node_count { - let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())}; - let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; + let tx_broadcaster = test_utils::TestBroadcaster { + txn_broadcasted: Mutex::new(Vec::new()), + blocks: Arc::new(Mutex::new(vec![(genesis_block(Network::Testnet).header, 0)])), + }; + let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }; let chain_source = test_utils::TestChainSource::new(Network::Testnet); let logger = test_utils::TestLogger::with_id(format!("node {}", i)); let persister = test_utils::TestPersister::new(); @@ -1281,22 +1344,29 @@ pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec UserConfig { + let mut default_config = UserConfig::default(); + // Set cltv_expiry_delta slightly lower to keep the final CLTV values inside one byte in our + // tests so that our script-length checks don't fail (see ACCEPTED_HTLC_SCRIPT_WEIGHT). + default_config.channel_options.cltv_expiry_delta = 6*6; + default_config.channel_options.announced_channel = true; + default_config.peer_channel_config_limits.force_announced_channel_preference = false; + // When most of our tests were written, the default HTLC minimum was fixed at 1000. + // It now defaults to 1, so we simply set it to the expected value here. + default_config.own_channel_config.our_htlc_minimum_msat = 1000; + default_config +} + pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec>, node_config: &[Option]) -> Vec, &'b test_utils::TestBroadcaster, &'a test_utils::TestKeysInterface, &'b test_utils::TestFeeEstimator, &'b test_utils::TestLogger>> { let mut chanmgrs = Vec::new(); for i in 0..node_count { - let mut default_config = UserConfig::default(); - // Set cltv_expiry_delta slightly lower to keep the final CLTV values inside one byte in our - // tests so that our script-length checks don't fail (see ACCEPTED_HTLC_SCRIPT_WEIGHT). - default_config.channel_options.cltv_expiry_delta = 6*6; - default_config.channel_options.announced_channel = true; - default_config.peer_channel_config_limits.force_announced_channel_preference = false; - default_config.own_channel_config.our_htlc_minimum_msat = 1000; // sanitization being done by the sender, to exerce receiver logic we need to lift of limit let network = Network::Testnet; let params = ChainParameters { network, best_block: BestBlock::from_genesis(network), }; - let node = ChannelManager::new(cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, cfgs[i].logger, cfgs[i].keys_manager, if node_config[i].is_some() { node_config[i].clone().unwrap() } else { default_config }, params); + let node = ChannelManager::new(cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, cfgs[i].logger, cfgs[i].keys_manager, + if node_config[i].is_some() { node_config[i].clone().unwrap() } else { test_default_channel_config() }, params); chanmgrs.push(node); } @@ -1316,7 +1386,7 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); revoke_and_ack = Some(msg.clone()); + idx += 1; RAACommitmentOrder::RevokeAndACKFirst }, &MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); commitment_update = Some(updates.clone()); + idx += 1; RAACommitmentOrder::CommitmentFirst }, + &MessageSendEvent::SendChannelUpdate { .. } => RAACommitmentOrder::CommitmentFirst, _ => panic!("Unexpected event"), } } else { @@ -1542,16 +1619,24 @@ macro_rules! handle_chan_reestablish_msgs { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); assert!(revoke_and_ack.is_none()); revoke_and_ack = Some(msg.clone()); + idx += 1; }, &MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); assert!(commitment_update.is_none()); commitment_update = Some(updates.clone()); + idx += 1; }, + &MessageSendEvent::SendChannelUpdate { .. } => {}, _ => panic!("Unexpected event"), } } + if let Some(&MessageSendEvent::SendChannelUpdate { ref node_id, ref msg }) = msg_events.get(idx) { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + assert_eq!(msg.contents.flags & 2, 0); // "disabled" flag must not be set as we just reconnected. + } + (funding_locked, revoke_and_ack, commitment_update, order) } }