X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=54d199a26f83f85cec4567baa1b1fae45d9e6faa;hb=c242003dd3c430a8395af1e48bd1e5c1f5ed94ae;hp=2cada934e56cab6515a58f6f00ef3bc08c56f7f2;hpb=70acdf93d1280e77b5aa9385a25702b1f7915c50;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 2cada934..54d199a2 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -24,10 +24,10 @@ use util::enforcing_trait_impls::EnforcingSigner; use util::scid_utils; use util::test_utils; use util::test_utils::{panicking, TestChainMonitor}; -use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose}; +use util::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose}; use util::errors::APIError; use util::config::UserConfig; -use util::ser::{ReadableArgs, Writeable, Readable}; +use util::ser::{ReadableArgs, Writeable}; use bitcoin::blockdata::block::{Block, BlockHeader}; use bitcoin::blockdata::constants::genesis_block; @@ -46,6 +46,7 @@ use core::cell::RefCell; use alloc::rc::Rc; use sync::{Arc, Mutex}; use core::mem; +use core::iter::repeat; pub const CHAN_CONFIRM_DEPTH: u32 = 10; @@ -257,7 +258,6 @@ pub struct TestChanMonCfg { pub persister: test_utils::TestPersister, pub logger: test_utils::TestLogger, pub keys_manager: test_utils::TestKeysInterface, - pub network_graph: NetworkGraph, } pub struct NodeCfg<'a> { @@ -267,7 +267,7 @@ pub struct NodeCfg<'a> { pub chain_monitor: test_utils::TestChainMonitor<'a>, pub keys_manager: &'a test_utils::TestKeysInterface, pub logger: &'a test_utils::TestLogger, - pub network_graph: &'a NetworkGraph, + pub network_graph: NetworkGraph<&'a test_utils::TestLogger>, pub node_seed: [u8; 32], pub features: InitFeatures, } @@ -278,8 +278,8 @@ pub struct Node<'a, 'b: 'a, 'c: 'b> { pub chain_monitor: &'b test_utils::TestChainMonitor<'c>, pub keys_manager: &'b test_utils::TestKeysInterface, pub node: &'a ChannelManager, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'c test_utils::TestLogger>, - pub network_graph: &'c NetworkGraph, - pub gossip_sync: P2PGossipSync<&'c NetworkGraph, &'c test_utils::TestChainSource, &'c test_utils::TestLogger>, + pub network_graph: &'b NetworkGraph<&'c test_utils::TestLogger>, + pub gossip_sync: P2PGossipSync<&'b NetworkGraph<&'c test_utils::TestLogger>, &'c test_utils::TestChainSource, &'c test_utils::TestLogger>, pub node_seed: [u8; 32], pub network_payment_count: Rc>, pub network_chan_count: Rc>, @@ -311,7 +311,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { { let mut w = test_utils::TestVecWriter(Vec::new()); self.network_graph.write(&mut w).unwrap(); - let network_graph_deser = ::read(&mut io::Cursor::new(&w.0)).unwrap(); + let network_graph_deser = >::read(&mut io::Cursor::new(&w.0), self.logger).unwrap(); assert!(network_graph_deser == *self.network_graph); let gossip_sync = P2PGossipSync::new( &network_graph_deser, Some(self.chain_source), self.logger @@ -353,6 +353,11 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { } } + let broadcaster = test_utils::TestBroadcaster { + txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()), + blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())), + }; + // Before using all the new monitors to check the watch outpoints, use the full set of // them to ensure we can write and reload our ChannelManager. { @@ -368,20 +373,13 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { keys_manager: self.keys_manager, 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()), - blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())), - }, + tx_broadcaster: &broadcaster, logger: &self.logger, channel_monitors, }).unwrap(); } let persister = test_utils::TestPersister::new(); - let broadcaster = test_utils::TestBroadcaster { - 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); for deserialized_monitor in deserialized_monitors.drain(..) { @@ -773,7 +771,7 @@ pub fn create_announced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a Vec>, a: usize, b: usize, channel_value: u64, push_msat: u64, a_flags: InitFeatures, b_flags: InitFeatures) -> (msgs::ChannelReady, Transaction) { let mut no_announce_cfg = test_default_channel_config(); - no_announce_cfg.channel_options.announced_channel = false; + no_announce_cfg.channel_handshake_config.announced_channel = false; nodes[a].node.create_channel(nodes[b].node.get_our_node_id(), channel_value, push_msat, 42, Some(no_announce_cfg)).unwrap(); let open_channel = get_event_msg!(nodes[a], MessageSendEvent::SendOpenChannel, nodes[b].node.get_our_node_id()); nodes[b].node.handle_open_channel(&nodes[a].node.get_our_node_id(), a_flags, &open_channel); @@ -1188,7 +1186,7 @@ macro_rules! commitment_signed_dance { { commitment_signed_dance!($node_a, $node_b, $commitment_signed, $fail_backwards, true); if $fail_backwards { - $crate::expect_pending_htlcs_forwardable!($node_a); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!($node_a, vec![$crate::util::events::HTLCDestination::NextHopChannel{ node_id: Some($node_b.node.get_our_node_id()), channel_id: $commitment_signed.channel_id }]); check_added_monitors!($node_a, 1); let channel_state = $node_a.node.channel_state.lock().unwrap(); @@ -1256,23 +1254,72 @@ macro_rules! get_route_and_payment_hash { } #[macro_export] -/// Clears (and ignores) a PendingHTLCsForwardable event -macro_rules! expect_pending_htlcs_forwardable_ignore { - ($node: expr) => {{ +macro_rules! expect_pending_htlcs_forwardable_conditions { + ($node: expr, $expected_failures: expr) => {{ + let expected_failures = $expected_failures; let events = $node.node.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); match events[0] { $crate::util::events::Event::PendingHTLCsForwardable { .. } => { }, _ => panic!("Unexpected event"), }; + + let count = expected_failures.len() + 1; + assert_eq!(events.len(), count); + + if expected_failures.len() > 0 { + expect_htlc_handling_failed_destinations!(events, expected_failures) + } }} } +#[macro_export] +macro_rules! expect_htlc_handling_failed_destinations { + ($events: expr, $expected_failures: expr) => {{ + for event in $events { + match event { + $crate::util::events::Event::PendingHTLCsForwardable { .. } => { }, + $crate::util::events::Event::HTLCHandlingFailed { ref failed_next_destination, .. } => { + assert!($expected_failures.contains(&failed_next_destination)) + }, + _ => panic!("Unexpected destination"), + } + } + }} +} + +#[macro_export] +/// Clears (and ignores) a PendingHTLCsForwardable event +macro_rules! expect_pending_htlcs_forwardable_ignore { + ($node: expr) => {{ + expect_pending_htlcs_forwardable_conditions!($node, vec![]); + }}; +} + +#[macro_export] +/// Clears (and ignores) PendingHTLCsForwardable and HTLCHandlingFailed events +macro_rules! expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore { + ($node: expr, $expected_failures: expr) => {{ + expect_pending_htlcs_forwardable_conditions!($node, $expected_failures); + }}; +} + #[macro_export] /// Handles a PendingHTLCsForwardable event macro_rules! expect_pending_htlcs_forwardable { ($node: expr) => {{ - $crate::expect_pending_htlcs_forwardable_ignore!($node); + expect_pending_htlcs_forwardable_ignore!($node); + $node.node.process_pending_htlc_forwards(); + + // Ensure process_pending_htlc_forwards is idempotent. + $node.node.process_pending_htlc_forwards(); + }}; +} + +#[macro_export] +/// Handles a PendingHTLCsForwardable and HTLCHandlingFailed event +macro_rules! expect_pending_htlcs_forwardable_and_htlc_handling_failed { + ($node: expr, $expected_failures: expr) => {{ + expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!($node, $expected_failures); $node.node.process_pending_htlc_forwards(); // Ensure process_pending_htlc_forwards is idempotent. @@ -1493,7 +1540,7 @@ pub fn expect_payment_failed_conditions<'a, 'b, 'c, 'd, 'e>( let mut events = node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); let expected_payment_id = match events.pop().unwrap() { - Event::PaymentPathFailed { payment_hash, rejected_by_dest, path, retry, payment_id, network_update, + Event::PaymentPathFailed { payment_hash, rejected_by_dest, path, retry, payment_id, network_update, short_channel_id, #[cfg(test)] error_code, #[cfg(test)] @@ -1503,6 +1550,9 @@ pub fn expect_payment_failed_conditions<'a, 'b, 'c, 'd, 'e>( assert!(retry.is_some(), "expected retry.is_some()"); assert_eq!(retry.as_ref().unwrap().final_value_msat, path.last().unwrap().fee_msat, "Retry amount should match last hop in path"); assert_eq!(retry.as_ref().unwrap().payment_params.payee_pubkey, path.last().unwrap().pubkey, "Retry payee node_id should match last hop in path"); + if let Some(scid) = short_channel_id { + assert!(retry.as_ref().unwrap().payment_params.previously_failed_channels.contains(&scid)); + } #[cfg(test)] { @@ -1690,7 +1740,16 @@ pub fn do_claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, ($node: expr, $prev_node: expr, $next_node: expr, $new_msgs: expr) => { { $node.node.handle_update_fulfill_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); - let fee = $node.node.channel_state.lock().unwrap().by_id.get(&next_msgs.as_ref().unwrap().0.channel_id).unwrap().config.forwarding_fee_base_msat; + let fee = { + let channel_state = $node.node.channel_state.lock().unwrap(); + let channel = channel_state + .by_id.get(&next_msgs.as_ref().unwrap().0.channel_id).unwrap(); + if let Some(prev_config) = channel.prev_config() { + prev_config.forwarding_fee_base_msat + } else { + channel.config().forwarding_fee_base_msat + } + }; expect_payment_forwarded!($node, $next_node, $prev_node, Some(fee as u64), false, false); expected_total_fee_msat += fee as u64; check_added_monitors!($node, 1); @@ -1805,7 +1864,8 @@ pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe assert_eq!(path.last().unwrap().node.get_our_node_id(), expected_paths[0].last().unwrap().node.get_our_node_id()); } expected_paths[0].last().unwrap().node.fail_htlc_backwards(&our_payment_hash); - expect_pending_htlcs_forwardable!(expected_paths[0].last().unwrap()); + let expected_destinations: Vec = repeat(HTLCDestination::FailedPayment { payment_hash: our_payment_hash }).take(expected_paths.len()).collect(); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!(expected_paths[0].last().unwrap(), expected_destinations); pass_failed_payment_back(origin_node, expected_paths, skip_last, our_payment_hash); } @@ -1846,7 +1906,7 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe node.node.handle_update_fail_htlc(&prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0); commitment_signed_dance!(node, prev_node, next_msgs.as_ref().unwrap().1, update_next_node); if !update_next_node { - expect_pending_htlcs_forwardable!(node); + expect_pending_htlcs_forwardable_and_htlc_handling_failed!(node, vec![HTLCDestination::NextHopChannel { node_id: Some(prev_node.node.get_our_node_id()), channel_id: next_msgs.as_ref().unwrap().0.channel_id }]); } } let events = node.node.get_and_clear_pending_msg_events(); @@ -1933,9 +1993,8 @@ pub fn create_chanmon_cfgs(node_count: usize) -> Vec { let persister = test_utils::TestPersister::new(); let seed = [i as u8; 32]; let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); - let network_graph = NetworkGraph::new(chain_source.genesis_hash); - chan_mon_cfgs.push(TestChanMonCfg{ tx_broadcaster, fee_estimator, chain_source, logger, persister, keys_manager, network_graph }); + chan_mon_cfgs.push(TestChanMonCfg{ tx_broadcaster, fee_estimator, chain_source, logger, persister, keys_manager }); } chan_mon_cfgs @@ -1956,7 +2015,7 @@ 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 = MIN_CLTV_EXPIRY_DELTA; - default_config.channel_options.announced_channel = true; - default_config.peer_channel_config_limits.force_announced_channel_preference = false; + default_config.channel_config.cltv_expiry_delta = MIN_CLTV_EXPIRY_DELTA; + default_config.channel_handshake_config.announced_channel = true; + default_config.channel_handshake_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.channel_handshake_config.our_htlc_minimum_msat = 1000; // When most of our tests were written, we didn't have the notion of a `max_dust_htlc_exposure_msat`, // It now defaults to 5_000_000 msat; to avoid interfering with tests we bump it to 50_000_000 msat. - default_config.channel_options.max_dust_htlc_exposure_msat = 50_000_000; + default_config.channel_config.max_dust_htlc_exposure_msat = 50_000_000; default_config } @@ -2002,7 +2061,7 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec