X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=39efab5fd2d92eccf73f82dc7a3f708ee2f98bf3;hb=f76f60ff855ff286fc5c71704ea74430cdfb7d86;hp=48656c81e02eab86e956acf7b3952c9889e75823;hpb=ac35492877637d6dbbe6ee93dc5ed0f678bfbb5f;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 48656c81..39efab5f 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -15,7 +15,7 @@ use chain::channelmonitor::ChannelMonitor; use chain::transaction::OutPoint; use ln::{PaymentPreimage, PaymentHash, PaymentSecret}; use ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, PaymentId, MIN_CLTV_EXPIRY_DELTA}; -use routing::network_graph::{P2PGossipSync, NetworkGraph}; +use routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate}; use routing::router::{PaymentParameters, Route, get_route}; use ln::features::{InitFeatures, InvoiceFeatures}; use ln::msgs; @@ -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,8 @@ use core::cell::RefCell; use alloc::rc::Rc; use sync::{Arc, Mutex}; use core::mem; +use core::iter::repeat; +use bitcoin::{PackedLockTime, TxMerkleNode}; pub const CHAN_CONFIRM_DEPTH: u32 = 10; @@ -76,11 +78,11 @@ pub fn confirm_transaction_at<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, tx: &T connect_blocks(node, conf_height - first_connect_height); } let mut block = Block { - header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: conf_height, bits: 42, nonce: 42 }, + header: BlockHeader { version: 0x20000000, prev_blockhash: node.best_block_hash(), merkle_root: TxMerkleNode::all_zeros(), time: conf_height, bits: 42, nonce: 42 }, txdata: Vec::new(), }; for _ in 0..*node.network_chan_count.borrow() { // Make sure we don't end up with channels at the same short id by offsetting by chan_count - block.txdata.push(Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() }); + block.txdata.push(Transaction { version: 0, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() }); } block.txdata.push(tx.clone()); connect_block(node, &block); @@ -147,7 +149,7 @@ pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32) -> let height = node.best_block_info().1 + 1; let mut block = Block { - header: BlockHeader { version: 0x2000000, prev_blockhash: node.best_block_hash(), merkle_root: Default::default(), time: height, bits: 42, nonce: 42 }, + header: BlockHeader { version: 0x2000000, prev_blockhash: node.best_block_hash(), merkle_root: TxMerkleNode::all_zeros(), time: height, bits: 42, nonce: 42 }, txdata: vec![], }; assert!(depth >= 1); @@ -155,7 +157,7 @@ pub fn connect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, depth: u32) -> let prev_blockhash = block.header.block_hash(); do_connect_block(node, block, skip_intermediaries); block = Block { - header: BlockHeader { version: 0x20000000, prev_blockhash, merkle_root: Default::default(), time: height + i, bits: 42, nonce: 42 }, + header: BlockHeader { version: 0x20000000, prev_blockhash, merkle_root: TxMerkleNode::all_zeros(), time: height + i, bits: 42, nonce: 42 }, txdata: vec![], }; } @@ -257,7 +259,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 +268,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 +279,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,27 +312,27 @@ 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 ); let mut chan_progress = 0; loop { - let orig_announcements = self.gossip_sync.get_next_channel_announcements(chan_progress, 255); - let deserialized_announcements = gossip_sync.get_next_channel_announcements(chan_progress, 255); + let orig_announcements = self.gossip_sync.get_next_channel_announcement(chan_progress); + let deserialized_announcements = gossip_sync.get_next_channel_announcement(chan_progress); assert!(orig_announcements == deserialized_announcements); - chan_progress = match orig_announcements.last() { + chan_progress = match orig_announcements { Some(announcement) => announcement.0.contents.short_channel_id + 1, None => break, }; } let mut node_progress = None; loop { - let orig_announcements = self.gossip_sync.get_next_node_announcements(node_progress.as_ref(), 255); - let deserialized_announcements = gossip_sync.get_next_node_announcements(node_progress.as_ref(), 255); + let orig_announcements = self.gossip_sync.get_next_node_announcement(node_progress.as_ref()); + let deserialized_announcements = gossip_sync.get_next_node_announcement(node_progress.as_ref()); assert!(orig_announcements == deserialized_announcements); - node_progress = match orig_announcements.last() { + node_progress = match orig_announcements { Some(announcement) => Some(announcement.contents.node_id), None => break, }; @@ -353,6 +354,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 +374,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(..) { @@ -621,7 +620,7 @@ pub fn create_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, expected_ assert_eq!(*channel_value_satoshis, expected_chan_value); assert_eq!(user_channel_id, expected_user_chan_id); - let tx = Transaction { version: chan_id as i32, lock_time: 0, input: Vec::new(), output: vec![TxOut { + let tx = Transaction { version: chan_id as i32, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: vec![TxOut { value: *channel_value_satoshis, script_pubkey: output_script.clone(), }]}; let funding_outpoint = OutPoint { txid: tx.txid(), index: 0 }; @@ -670,6 +669,72 @@ pub fn sign_funding_transaction<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: & tx } +// Receiver must have been initialized with manually_accept_inbound_channels set to true. +pub fn open_zero_conf_channel<'a, 'b, 'c, 'd>(initiator: &'a Node<'b, 'c, 'd>, receiver: &'a Node<'b, 'c, 'd>, initiator_config: Option) -> (bitcoin::Transaction, [u8; 32]) { + let initiator_channels = initiator.node.list_usable_channels().len(); + let receiver_channels = receiver.node.list_usable_channels().len(); + + initiator.node.create_channel(receiver.node.get_our_node_id(), 100_000, 10_001, 42, initiator_config).unwrap(); + let open_channel = get_event_msg!(initiator, MessageSendEvent::SendOpenChannel, receiver.node.get_our_node_id()); + + receiver.node.handle_open_channel(&initiator.node.get_our_node_id(), InitFeatures::known(), &open_channel); + let events = receiver.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match events[0] { + Event::OpenChannelRequest { temporary_channel_id, .. } => { + receiver.node.accept_inbound_channel_from_trusted_peer_0conf(&temporary_channel_id, &initiator.node.get_our_node_id(), 0).unwrap(); + }, + _ => panic!("Unexpected event"), + }; + + let accept_channel = get_event_msg!(receiver, MessageSendEvent::SendAcceptChannel, initiator.node.get_our_node_id()); + assert_eq!(accept_channel.minimum_depth, 0); + initiator.node.handle_accept_channel(&receiver.node.get_our_node_id(), InitFeatures::known(), &accept_channel); + + let (temporary_channel_id, tx, _) = create_funding_transaction(&initiator, &receiver.node.get_our_node_id(), 100_000, 42); + initiator.node.funding_transaction_generated(&temporary_channel_id, &receiver.node.get_our_node_id(), tx.clone()).unwrap(); + let funding_created = get_event_msg!(initiator, MessageSendEvent::SendFundingCreated, receiver.node.get_our_node_id()); + + receiver.node.handle_funding_created(&initiator.node.get_our_node_id(), &funding_created); + check_added_monitors!(receiver, 1); + let bs_signed_locked = receiver.node.get_and_clear_pending_msg_events(); + assert_eq!(bs_signed_locked.len(), 2); + let as_channel_ready; + match &bs_signed_locked[0] { + MessageSendEvent::SendFundingSigned { node_id, msg } => { + assert_eq!(*node_id, initiator.node.get_our_node_id()); + initiator.node.handle_funding_signed(&receiver.node.get_our_node_id(), &msg); + check_added_monitors!(initiator, 1); + + assert_eq!(initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1); + assert_eq!(initiator.tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0], tx); + + as_channel_ready = get_event_msg!(initiator, MessageSendEvent::SendChannelReady, receiver.node.get_our_node_id()); + } + _ => panic!("Unexpected event"), + } + match &bs_signed_locked[1] { + MessageSendEvent::SendChannelReady { node_id, msg } => { + assert_eq!(*node_id, initiator.node.get_our_node_id()); + initiator.node.handle_channel_ready(&receiver.node.get_our_node_id(), &msg); + } + _ => panic!("Unexpected event"), + } + + receiver.node.handle_channel_ready(&initiator.node.get_our_node_id(), &as_channel_ready); + + let as_channel_update = get_event_msg!(initiator, MessageSendEvent::SendChannelUpdate, receiver.node.get_our_node_id()); + let bs_channel_update = get_event_msg!(receiver, MessageSendEvent::SendChannelUpdate, initiator.node.get_our_node_id()); + + initiator.node.handle_channel_update(&receiver.node.get_our_node_id(), &bs_channel_update); + receiver.node.handle_channel_update(&initiator.node.get_our_node_id(), &as_channel_update); + + assert_eq!(initiator.node.list_usable_channels().len(), initiator_channels + 1); + assert_eq!(receiver.node.list_usable_channels().len(), receiver_channels + 1); + + (tx, as_channel_ready.channel_id) +} + pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, channel_value: u64, push_msat: u64, a_flags: InitFeatures, b_flags: InitFeatures) -> Transaction { let create_chan_id = node_a.node.create_channel(node_b.node.get_our_node_id(), channel_value, push_msat, 42, None).unwrap(); let open_channel_msg = get_event_msg!(node_a, MessageSendEvent::SendOpenChannel, node_b.node.get_our_node_id()); @@ -773,7 +838,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); @@ -895,11 +960,11 @@ macro_rules! check_spends { { $( for outp in $spends_txn.output.iter() { - assert!(outp.value >= outp.script_pubkey.dust_value().as_sat(), "Input tx output didn't meet dust limit"); + assert!(outp.value >= outp.script_pubkey.dust_value().to_sat(), "Input tx output didn't meet dust limit"); } )* for outp in $tx.output.iter() { - assert!(outp.value >= outp.script_pubkey.dust_value().as_sat(), "Spending tx output didn't meet dust limit"); + assert!(outp.value >= outp.script_pubkey.dust_value().to_sat(), "Spending tx output didn't meet dust limit"); } let get_output = |out_point: &bitcoin::blockdata::transaction::OutPoint| { $( @@ -1188,7 +1253,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 +1321,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. @@ -1467,8 +1581,10 @@ impl<'a> PaymentFailedConditions<'a> { #[cfg(test)] macro_rules! expect_payment_failed_with_update { ($node: expr, $expected_payment_hash: expr, $rejected_by_dest: expr, $scid: expr, $chan_closed: expr) => { - expect_payment_failed_conditions!($node, $expected_payment_hash, $rejected_by_dest, - $crate::ln::functional_test_utils::PaymentFailedConditions::new().blamed_scid($scid).blamed_chan_closed($chan_closed)); + $crate::ln::functional_test_utils::expect_payment_failed_conditions( + &$node, $expected_payment_hash, $rejected_by_dest, + $crate::ln::functional_test_utils::PaymentFailedConditions::new() + .blamed_scid($scid).blamed_chan_closed($chan_closed)); } } @@ -1480,68 +1596,86 @@ macro_rules! expect_payment_failed { $( conditions = conditions.expected_htlc_error_data($expected_error_code, &$expected_error_data); )* - expect_payment_failed_conditions!($node, $expected_payment_hash, $rejected_by_dest, conditions); + $crate::ln::functional_test_utils::expect_payment_failed_conditions(&$node, $expected_payment_hash, $rejected_by_dest, conditions); }; } -#[cfg(test)] -macro_rules! expect_payment_failed_conditions { - ($node: expr, $expected_payment_hash: expr, $rejected_by_dest: expr, $conditions: expr) => { - let events = $node.node.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); - let expected_payment_id = match events[0] { - Event::PaymentPathFailed { ref payment_hash, rejected_by_dest, ref error_code, ref error_data, ref path, ref retry, ref payment_id, ref network_update, .. } => { - assert_eq!(*payment_hash, $expected_payment_hash, "unexpected payment_hash"); - assert_eq!(rejected_by_dest, $rejected_by_dest, "unexpected rejected_by_dest value"); - 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"); +pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>( + node: &'a Node<'b, 'c, 'd>, payment_failed_event: Event, expected_payment_hash: PaymentHash, + expected_rejected_by_dest: bool, conditions: PaymentFailedConditions<'e> +) { + let expected_payment_id = match payment_failed_event { + Event::PaymentPathFailed { payment_hash, rejected_by_dest, path, retry, payment_id, network_update, short_channel_id, + #[cfg(test)] + error_code, + #[cfg(test)] + error_data, .. } => { + assert_eq!(payment_hash, expected_payment_hash, "unexpected payment_hash"); + assert_eq!(rejected_by_dest, expected_rejected_by_dest, "unexpected rejected_by_dest value"); + 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)] + { assert!(error_code.is_some(), "expected error_code.is_some() = true"); assert!(error_data.is_some(), "expected error_data.is_some() = true"); - if let Some((code, data)) = $conditions.expected_htlc_error_data { + if let Some((code, data)) = conditions.expected_htlc_error_data { assert_eq!(error_code.unwrap(), code, "unexpected error code"); assert_eq!(&error_data.as_ref().unwrap()[..], data, "unexpected error data"); } + } - if let Some(chan_closed) = $conditions.expected_blamed_chan_closed { - match network_update { - &Some($crate::routing::network_graph::NetworkUpdate::ChannelUpdateMessage { ref msg }) if !chan_closed => { - if let Some(scid) = $conditions.expected_blamed_scid { - assert_eq!(msg.contents.short_channel_id, scid); - } - assert_eq!(msg.contents.flags & 2, 0); - }, - &Some($crate::routing::network_graph::NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }) if chan_closed => { - if let Some(scid) = $conditions.expected_blamed_scid { - assert_eq!(short_channel_id, scid); - } - assert!(is_permanent); - }, - Some(_) => panic!("Unexpected update type"), - None => panic!("Expected update"), - } + if let Some(chan_closed) = conditions.expected_blamed_chan_closed { + match network_update { + Some(NetworkUpdate::ChannelUpdateMessage { ref msg }) if !chan_closed => { + if let Some(scid) = conditions.expected_blamed_scid { + assert_eq!(msg.contents.short_channel_id, scid); + } + const CHAN_DISABLED_FLAG: u8 = 2; + assert_eq!(msg.contents.flags & CHAN_DISABLED_FLAG, 0); + }, + Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }) if chan_closed => { + if let Some(scid) = conditions.expected_blamed_scid { + assert_eq!(short_channel_id, scid); + } + assert!(is_permanent); + }, + Some(_) => panic!("Unexpected update type"), + None => panic!("Expected update"), } + } - payment_id.unwrap() - }, - _ => panic!("Unexpected event"), - }; - if !$conditions.expected_mpp_parts_remain { - $node.node.abandon_payment(expected_payment_id); - let events = $node.node.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); - match events[0] { - Event::PaymentFailed { ref payment_hash, ref payment_id } => { - assert_eq!(*payment_hash, $expected_payment_hash, "unexpected second payment_hash"); - assert_eq!(*payment_id, expected_payment_id); - } - _ => panic!("Unexpected second event"), + payment_id.unwrap() + }, + _ => panic!("Unexpected event"), + }; + if !conditions.expected_mpp_parts_remain { + node.node.abandon_payment(expected_payment_id); + let events = node.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match events[0] { + Event::PaymentFailed { ref payment_hash, ref payment_id } => { + assert_eq!(*payment_hash, expected_payment_hash, "unexpected second payment_hash"); + assert_eq!(*payment_id, expected_payment_id); } + _ => panic!("Unexpected second event"), } } } +pub fn expect_payment_failed_conditions<'a, 'b, 'c, 'd, 'e>( + node: &'a Node<'b, 'c, 'd>, expected_payment_hash: PaymentHash, expected_rejected_by_dest: bool, + conditions: PaymentFailedConditions<'e> +) { + let mut events = node.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + expect_payment_failed_conditions_event(node, events.pop().unwrap(), expected_payment_hash, expected_rejected_by_dest, conditions); +} + pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, route: Route, expected_paths: &[&[&Node<'a, 'b, 'c>]], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret) -> PaymentId { let payment_id = origin_node.node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap(); check_added_monitors!(origin_node, expected_paths.len()); @@ -1680,7 +1814,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); @@ -1795,7 +1938,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); } @@ -1836,7 +1980,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(); @@ -1923,9 +2067,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 @@ -1946,7 +2089,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 } @@ -1992,7 +2135,7 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec(node: &Node<'a, 'b, 'c>, chan: &(msgs::Cha if tx.input.len() == 1 && tx.input[0].previous_output.txid == res[0].txid() { check_spends!(tx, res[0]); if has_htlc_tx == HTLCType::TIMEOUT { - assert!(tx.lock_time != 0); + assert!(tx.lock_time.0 != 0); } else { - assert!(tx.lock_time == 0); + assert!(tx.lock_time.0 == 0); } res.push(tx.clone()); false