X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=39a457c8b4a975e04a77e8a0e75b6a1f8a131b2e;hb=384c4dc7753e4b7ac53ea380e52809babd8f0f9b;hp=4c91d4f7b1cd9f81208afb5f9367156c18d47b06;hpb=7e05623befc111422d1d4230f4e51629566a2ae6;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 4c91d4f7..39a457c8 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -10,24 +10,24 @@ //! A bunch of useful utilities for building networks of nodes and exchanging messages between //! nodes for functional tests. -use chain::{BestBlock, Confirm, Listen, Watch, keysinterface::KeysInterface}; -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::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate}; -use routing::router::{PaymentParameters, Route, get_route}; -use ln::features::{InitFeatures, InvoiceFeatures}; -use ln::msgs; -use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler}; -use util::enforcing_trait_impls::EnforcingSigner; -use util::scid_utils; -use util::test_utils; -use util::test_utils::{panicking, TestChainMonitor}; -use util::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose}; -use util::errors::APIError; -use util::config::UserConfig; -use util::ser::{ReadableArgs, Writeable}; +use crate::chain::{BestBlock, ChannelMonitorUpdateStatus, Confirm, Listen, Watch, keysinterface::KeysInterface}; +use crate::chain::channelmonitor::ChannelMonitor; +use crate::chain::transaction::OutPoint; +use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret}; +use crate::ln::channelmanager::{self, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, PaymentId, MIN_CLTV_EXPIRY_DELTA}; +use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate}; +use crate::routing::router::{PaymentParameters, Route, get_route}; +use crate::ln::features::InitFeatures; +use crate::ln::msgs; +use crate::ln::msgs::{ChannelMessageHandler,RoutingMessageHandler}; +use crate::util::enforcing_trait_impls::EnforcingSigner; +use crate::util::scid_utils; +use crate::util::test_utils; +use crate::util::test_utils::{panicking, TestChainMonitor}; +use crate::util::events::{Event, HTLCDestination, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose}; +use crate::util::errors::APIError; +use crate::util::config::UserConfig; +use crate::util::ser::{ReadableArgs, Writeable}; use bitcoin::blockdata::block::{Block, BlockHeader}; use bitcoin::blockdata::constants::genesis_block; @@ -40,11 +40,11 @@ use bitcoin::hashes::Hash as _; use bitcoin::secp256k1::PublicKey; -use io; -use prelude::*; +use crate::io; +use crate::prelude::*; use core::cell::RefCell; use alloc::rc::Rc; -use sync::{Arc, Mutex}; +use crate::sync::{Arc, Mutex}; use core::mem; use core::iter::repeat; use bitcoin::{PackedLockTime, TxMerkleNode}; @@ -278,7 +278,7 @@ pub struct Node<'a, 'b: 'a, 'c: 'b> { pub tx_broadcaster: &'c test_utils::TestBroadcaster, 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 node: &'a ChannelManager<&'b TestChainMonitor<'c>, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'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], @@ -304,9 +304,18 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { fn drop(&mut self) { if !panicking() { // Check that we processed all pending events - assert!(self.node.get_and_clear_pending_msg_events().is_empty()); - assert!(self.node.get_and_clear_pending_events().is_empty()); - assert!(self.chain_monitor.added_monitors.lock().unwrap().is_empty()); + let msg_events = self.node.get_and_clear_pending_msg_events(); + if !msg_events.is_empty() { + panic!("Had excess message events on node {}: {:?}", self.logger.id, msg_events); + } + let events = self.node.get_and_clear_pending_events(); + if !events.is_empty() { + panic!("Had excess events on node {}: {:?}", self.logger.id, events); + } + let added_monitors = self.chain_monitor.added_monitors.lock().unwrap().split_off(0); + if !added_monitors.is_empty() { + panic!("Had {} excess added monitors on node {}", added_monitors.len(), self.logger.id); + } // Check that if we serialize the Router, we can deserialize it again. { @@ -319,20 +328,20 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { ); 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, }; @@ -369,7 +378,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { let mut w = test_utils::TestVecWriter(Vec::new()); self.node.write(&mut w).unwrap(); - <(BlockHash, ChannelManager)>::read(&mut io::Cursor::new(w.0), ChannelManagerReadArgs { + <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut 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: Mutex::new(253) }, @@ -384,7 +393,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { 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(..) { - if let Err(_) = chain_monitor.watch_channel(deserialized_monitor.get_funding_txo().0, deserialized_monitor) { + if chain_monitor.watch_channel(deserialized_monitor.get_funding_txo().0, deserialized_monitor) != ChannelMonitorUpdateStatus::Completed { panic!(); } } @@ -669,6 +678,75 @@ 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(), channelmanager::provided_init_features(), &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(), channelmanager::provided_init_features(), &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); + + expect_channel_ready_event(&initiator, &receiver.node.get_our_node_id()); + expect_channel_ready_event(&receiver, &initiator.node.get_our_node_id()); + + (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()); @@ -719,6 +797,7 @@ pub fn create_chan_between_nodes_with_value_confirm<'a, 'b, 'c, 'd>(node_a: &'a 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); + expect_channel_ready_event(&node_a, &node_b.node.get_our_node_id()); create_chan_between_nodes_with_value_confirm_second(node_b, node_a) } @@ -757,6 +836,7 @@ pub fn create_chan_between_nodes_with_value_b<'a, 'b, 'c>(node_a: &Node<'a, 'b, *node_a.network_chan_count.borrow_mut() += 1; + expect_channel_ready_event(&node_b, &node_a.node.get_our_node_id()); ((*announcement).clone(), (*as_update).clone(), (*bs_update).clone()) } @@ -795,8 +875,10 @@ pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: & connect_blocks(&nodes[b], CHAN_CONFIRM_DEPTH - 1); let as_channel_ready = get_event_msg!(nodes[a], MessageSendEvent::SendChannelReady, nodes[b].node.get_our_node_id()); nodes[a].node.handle_channel_ready(&nodes[b].node.get_our_node_id(), &get_event_msg!(nodes[b], MessageSendEvent::SendChannelReady, nodes[a].node.get_our_node_id())); + expect_channel_ready_event(&nodes[a], &nodes[b].node.get_our_node_id()); let as_update = get_event_msg!(nodes[a], MessageSendEvent::SendChannelUpdate, nodes[b].node.get_our_node_id()); nodes[b].node.handle_channel_ready(&nodes[a].node.get_our_node_id(), &as_channel_ready); + expect_channel_ready_event(&nodes[b], &nodes[a].node.get_our_node_id()); let bs_update = get_event_msg!(nodes[b], MessageSendEvent::SendChannelUpdate, nodes[a].node.get_our_node_id()); nodes[a].node.handle_channel_update(&nodes[b].node.get_our_node_id(), &bs_update); @@ -826,60 +908,10 @@ pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: & } 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!(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() - }, - _ => panic!("Unexpected event"), - }; - - nodes[b].node.broadcast_node_announcement([1, 1, 1], [1; 32], Vec::new()); - let b_events = nodes[b].node.get_and_clear_pending_msg_events(); - assert!(b_events.len() >= 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() - }, - _ => panic!("Unexpected event"), - }; - for node in nodes { assert!(node.gossip_sync.handle_channel_announcement(ann).unwrap()); node.gossip_sync.handle_channel_update(upd_1).unwrap(); node.gossip_sync.handle_channel_update(upd_2).unwrap(); - node.gossip_sync.handle_node_announcement(&a_node_announcement).unwrap(); - node.gossip_sync.handle_node_announcement(&b_node_announcement).unwrap(); // Note that channel_updates are also delivered to ChannelManagers to ensure we have // forwarding info for local channels even if its not accepted in the network graph. @@ -1026,7 +1058,7 @@ pub fn close_channel<'a, 'b, 'c>(outbound_node: &Node<'a, 'b, 'c>, inbound_node: let (tx_a, tx_b); node_a.close_channel(channel_id, &node_b.get_our_node_id()).unwrap(); - node_b.handle_shutdown(&node_a.get_our_node_id(), &InitFeatures::known(), &get_event_msg!(struct_a, MessageSendEvent::SendShutdown, node_b.get_our_node_id())); + node_b.handle_shutdown(&node_a.get_our_node_id(), &channelmanager::provided_init_features(), &get_event_msg!(struct_a, MessageSendEvent::SendShutdown, node_b.get_our_node_id())); let events_1 = node_b.get_and_clear_pending_msg_events(); assert!(events_1.len() >= 1); @@ -1051,7 +1083,7 @@ pub fn close_channel<'a, 'b, 'c>(outbound_node: &Node<'a, 'b, 'c>, inbound_node: }) }; - node_a.handle_shutdown(&node_b.get_our_node_id(), &InitFeatures::known(), &shutdown_b); + node_a.handle_shutdown(&node_b.get_our_node_id(), &channelmanager::provided_init_features(), &shutdown_b); let (as_update, bs_update) = if close_inbound_first { assert!(node_a.get_and_clear_pending_msg_events().is_empty()); node_a.handle_closing_signed(&node_b.get_our_node_id(), &closing_signed_b.unwrap()); @@ -1101,7 +1133,7 @@ impl SendEvent { assert!(updates.update_fail_htlcs.is_empty()); assert!(updates.update_fail_malformed_htlcs.is_empty()); assert!(updates.update_fee.is_none()); - SendEvent { node_id: node_id, msgs: updates.update_add_htlcs, commitment_msg: updates.commitment_signed } + SendEvent { node_id, msgs: updates.update_add_htlcs, commitment_msg: updates.commitment_signed } } pub fn from_event(event: MessageSendEvent) -> SendEvent { @@ -1244,7 +1276,7 @@ macro_rules! get_route { macro_rules! get_route_and_payment_hash { ($send_node: expr, $recv_node: expr, $recv_value: expr) => {{ let payment_params = $crate::routing::router::PaymentParameters::from_node_id($recv_node.node.get_our_node_id()) - .with_features($crate::ln::features::InvoiceFeatures::known()); + .with_features($crate::ln::channelmanager::provided_invoice_features()); $crate::get_route_and_payment_hash!($send_node, $recv_node, payment_params, $recv_value, TEST_FINAL_CLTV) }}; ($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr, $cltv: expr) => {{ @@ -1478,6 +1510,19 @@ macro_rules! expect_payment_forwarded { } } +#[cfg(any(test, feature = "_bench_unstable", feature = "_test_utils"))] +pub fn expect_channel_ready_event<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, expected_counterparty_node_id: &PublicKey) { + let events = node.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match events[0] { + crate::util::events::Event::ChannelReady{ ref counterparty_node_id, .. } => { + assert_eq!(*expected_counterparty_node_id, *counterparty_node_id); + }, + _ => panic!("Unexpected event"), + } +} + + pub struct PaymentFailedConditions<'a> { pub(crate) expected_htlc_error_data: Option<(u16, &'a [u8])>, pub(crate) expected_blamed_scid: Option, @@ -1514,9 +1559,9 @@ 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) => { + ($node: expr, $expected_payment_hash: expr, $payment_failed_permanently: expr, $scid: expr, $chan_closed: expr) => { $crate::ln::functional_test_utils::expect_payment_failed_conditions( - &$node, $expected_payment_hash, $rejected_by_dest, + &$node, $expected_payment_hash, $payment_failed_permanently, $crate::ln::functional_test_utils::PaymentFailedConditions::new() .blamed_scid($scid).blamed_chan_closed($chan_closed)); } @@ -1524,30 +1569,28 @@ macro_rules! expect_payment_failed_with_update { #[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)*) => { + ($node: expr, $expected_payment_hash: expr, $payment_failed_permanently: expr $(, $expected_error_code: expr, $expected_error_data: expr)*) => { #[allow(unused_mut)] let mut conditions = $crate::ln::functional_test_utils::PaymentFailedConditions::new(); $( conditions = conditions.expected_htlc_error_data($expected_error_code, &$expected_error_data); )* - $crate::ln::functional_test_utils::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, $payment_failed_permanently, conditions); }; } -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> +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_payment_failed_permanently: bool, conditions: PaymentFailedConditions<'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, short_channel_id, + let expected_payment_id = match payment_failed_event { + Event::PaymentPathFailed { payment_hash, payment_failed_permanently, 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_eq!(payment_failed_permanently, expected_payment_failed_permanently, "unexpected payment_failed_permanently 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"); @@ -1603,8 +1646,18 @@ pub fn expect_payment_failed_conditions<'a, 'b, 'c, 'd, 'e>( } } +pub fn expect_payment_failed_conditions<'a, 'b, 'c, 'd, 'e>( + node: &'a Node<'b, 'c, 'd>, expected_payment_hash: PaymentHash, expected_payment_failed_permanently: 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_payment_failed_permanently, 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(); + let payment_id = PaymentId(origin_node.keys_manager.backing.get_secure_random_bytes()); + origin_node.node.send_payment(&route, our_payment_hash, &Some(our_payment_secret), payment_id).unwrap(); check_added_monitors!(origin_node, expected_paths.len()); pass_along_route(origin_node, expected_paths, recv_value, our_payment_hash, our_payment_secret); payment_id @@ -1821,7 +1874,7 @@ 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 payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id()) - .with_features(InvoiceFeatures::known()); + .with_features(channelmanager::provided_invoice_features()); let route = get_route!(origin_node, payment_params, recv_value, TEST_FINAL_CLTV).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), expected_route.len()); @@ -1835,7 +1888,7 @@ pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) { let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id()) - .with_features(InvoiceFeatures::known()); + .with_features(channelmanager::provided_invoice_features()); let network_graph = origin_node.network_graph.read_only(); let scorer = test_utils::TestScorer::with_penalty(0); let seed = [0u8; 32]; @@ -1851,7 +1904,7 @@ pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou } let (_, our_payment_hash, our_payment_preimage) = get_payment_preimage_hash!(expected_route.last().unwrap()); - unwrap_send_err!(origin_node.node.send_payment(&route, our_payment_hash, &Some(our_payment_preimage)), true, APIError::ChannelUnavailable { ref err }, + unwrap_send_err!(origin_node.node.send_payment(&route, our_payment_hash, &Some(our_payment_preimage), PaymentId(our_payment_hash.0)), true, APIError::ChannelUnavailable { ref err }, assert!(err.contains("Cannot send value that would put us over the max HTLC value in flight our peer will accept"))); } @@ -1872,6 +1925,22 @@ pub fn fail_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe } pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths_slice: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_hash: PaymentHash) { + let expected_payment_id = pass_failed_payment_back_no_abandon(origin_node, expected_paths_slice, skip_last, our_payment_hash); + if !skip_last { + origin_node.node.abandon_payment(expected_payment_id.unwrap()); + let events = origin_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, our_payment_hash, "unexpected second payment_hash"); + assert_eq!(*payment_id, expected_payment_id.unwrap()); + } + _ => panic!("Unexpected second event"), + } + } +} + +pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_paths_slice: &[&[&Node<'a, 'b, 'c>]], skip_last: bool, our_payment_hash: PaymentHash) -> Option { let mut expected_paths: Vec<_> = expected_paths_slice.iter().collect(); check_added_monitors!(expected_paths[0].last().unwrap(), expected_paths.len()); @@ -1895,6 +1964,8 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe per_path_msgs.sort_unstable_by(|(_, node_id_a), (_, node_id_b)| node_id_a.cmp(node_id_b)); expected_paths.sort_unstable_by(|path_a, path_b| path_a[path_a.len() - 2].node.get_our_node_id().cmp(&path_b[path_b.len() - 2].node.get_our_node_id())); + let mut expected_payment_id = None; + for (i, (expected_route, (path_msgs, next_hop))) in expected_paths.iter().zip(per_path_msgs.drain(..)).enumerate() { let mut next_msgs = Some(path_msgs); let mut expected_next_node = next_hop; @@ -1943,10 +2014,10 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe commitment_signed_dance!(origin_node, prev_node, next_msgs.as_ref().unwrap().1, false); let events = origin_node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); - let expected_payment_id = match events[0] { - Event::PaymentPathFailed { payment_hash, rejected_by_dest, all_paths_failed, ref path, ref payment_id, .. } => { + expected_payment_id = Some(match events[0] { + Event::PaymentPathFailed { payment_hash, payment_failed_permanently, all_paths_failed, ref path, ref payment_id, .. } => { assert_eq!(payment_hash, our_payment_hash); - assert!(rejected_by_dest); + assert!(payment_failed_permanently); assert_eq!(all_paths_failed, i == expected_paths.len() - 1); for (idx, hop) in expected_route.iter().enumerate() { assert_eq!(hop.node.get_our_node_id(), path[idx].pubkey); @@ -1954,19 +2025,7 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe payment_id.unwrap() }, _ => panic!("Unexpected event"), - }; - if i == expected_paths.len() - 1 { - origin_node.node.abandon_payment(expected_payment_id); - let events = origin_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, our_payment_hash, "unexpected second payment_hash"); - assert_eq!(*payment_id, expected_payment_id); - } - _ => panic!("Unexpected second event"), - } - } + }); } } @@ -1975,6 +2034,8 @@ pub fn pass_failed_payment_back<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expe assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_events().is_empty()); assert!(expected_paths[0].last().unwrap().node.get_and_clear_pending_msg_events().is_empty()); check_added_monitors!(expected_paths[0].last().unwrap(), 0); + + expected_payment_id } pub fn fail_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], our_payment_hash: PaymentHash) { @@ -2015,7 +2076,7 @@ pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec UserConfig { 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>> { +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 network = Network::Testnet; @@ -2055,7 +2116,7 @@ pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec chanmgrs } -pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec>, chan_mgrs: &'a Vec, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'c test_utils::TestLogger>>) -> Vec> { +pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec>, chan_mgrs: &'a Vec, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'c test_utils::TestLogger>>) -> Vec> { let mut nodes = Vec::new(); let chan_count = Rc::new(RefCell::new(0)); let payment_count = Rc::new(RefCell::new(0)); @@ -2076,8 +2137,8 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec(node_count: usize, cfgs: &'b Vec { { + let mut announcements = $crate::prelude::HashSet::new(); let mut res = Vec::with_capacity(1); for msg in $src_node.node.get_and_clear_pending_msg_events() { if let MessageSendEvent::SendChannelReestablish { ref node_id, ref msg } = msg { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); res.push(msg.clone()); + } else if let MessageSendEvent::SendChannelAnnouncement { ref node_id, ref msg, .. } = msg { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + announcements.insert(msg.contents.short_channel_id); } else { panic!("Unexpected event") } } + for chan in $src_node.node.list_channels() { + if chan.is_public && chan.counterparty.node_id != $dst_node.node.get_our_node_id() { + if let Some(scid) = chan.short_channel_id { + assert!(announcements.remove(&scid)); + } + } + } + assert!(announcements.is_empty()); res } } @@ -2339,9 +2411,9 @@ macro_rules! handle_chan_reestablish_msgs { /// pending_htlc_adds includes both the holding cell and in-flight update_add_htlcs, whereas /// for claims/fails they are separated out. pub fn reconnect_nodes<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, send_channel_ready: (bool, bool), pending_htlc_adds: (i64, i64), pending_htlc_claims: (usize, usize), pending_htlc_fails: (usize, usize), pending_cell_htlc_claims: (usize, usize), pending_cell_htlc_fails: (usize, usize), pending_raa: (bool, bool)) { - node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None }); + node_a.node.peer_connected(&node_b.node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap(); let reestablish_1 = get_chan_reestablish_msgs!(node_a, node_b); - node_b.node.peer_connected(&node_a.node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty(), remote_network_address: None }); + node_b.node.peer_connected(&node_a.node.get_our_node_id(), &msgs::Init { features: channelmanager::provided_init_features(), remote_network_address: None }).unwrap(); let reestablish_2 = get_chan_reestablish_msgs!(node_b, node_a); if send_channel_ready.0 {