X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=6b247b28f097d30b9576b13c6fa435343ecf4fd1;hb=17e1403856933f9649413a179325eaea25da825e;hp=ee34b590f47c23e4867b9f8f5b8256629418b1de;hpb=5bccd2eee2a5756b32fa1bc18557978b4a5a95c1;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index ee34b590..6b247b28 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,12 +40,14 @@ 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}; 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![], }; } @@ -274,9 +276,10 @@ pub struct NodeCfg<'a> { pub struct Node<'a, 'b: 'a, 'c: 'b> { pub chain_source: &'c test_utils::TestChainSource, pub tx_broadcaster: &'c test_utils::TestBroadcaster, + pub fee_estimator: &'c test_utils::TestFeeEstimator, 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], @@ -302,9 +305,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. { @@ -317,20 +329,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, }; @@ -352,6 +364,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. { @@ -362,29 +379,22 @@ 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) }, 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(..) { - 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!(); } } @@ -578,7 +588,7 @@ macro_rules! get_local_commitment_txn { macro_rules! unwrap_send_err { ($res: expr, $all_failed: expr, $type: pat, $check: expr) => { match &$res { - &Err(PaymentSendFailure::AllFailedRetrySafe(ref fails)) if $all_failed => { + &Err(PaymentSendFailure::AllFailedResendSafe(ref fails)) if $all_failed => { assert_eq!(fails.len(), 1); match fails[0] { $type => { $check }, @@ -609,7 +619,61 @@ macro_rules! check_added_monitors { } } -pub fn create_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, expected_counterparty_node_id: &PublicKey, expected_chan_value: u64, expected_user_chan_id: u64) -> ([u8; 32], Transaction, OutPoint) { +pub fn _reload_node<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, default_config: UserConfig, chanman_encoded: &[u8], monitors_encoded: &[&[u8]]) -> ChannelManager<&'b TestChainMonitor<'c>, &'c test_utils::TestBroadcaster, &'b test_utils::TestKeysInterface, &'c test_utils::TestFeeEstimator, &'c test_utils::TestLogger> { + let mut monitors_read = Vec::with_capacity(monitors_encoded.len()); + for encoded in monitors_encoded { + let mut monitor_read = &encoded[..]; + let (_, monitor) = <(BlockHash, ChannelMonitor)> + ::read(&mut monitor_read, node.keys_manager).unwrap(); + assert!(monitor_read.is_empty()); + monitors_read.push(monitor); + } + + let mut node_read = &chanman_encoded[..]; + let (_, node_deserialized) = { + let mut channel_monitors = HashMap::new(); + for monitor in monitors_read.iter_mut() { + assert!(channel_monitors.insert(monitor.get_funding_txo().0, monitor).is_none()); + } + <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut node_read, ChannelManagerReadArgs { + default_config, + keys_manager: node.keys_manager, + fee_estimator: node.fee_estimator, + chain_monitor: node.chain_monitor, + tx_broadcaster: node.tx_broadcaster, + logger: node.logger, + channel_monitors, + }).unwrap() + }; + assert!(node_read.is_empty()); + + for monitor in monitors_read.drain(..) { + assert_eq!(node.chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor), + ChannelMonitorUpdateStatus::Completed); + check_added_monitors!(node, 1); + } + + node_deserialized +} + +#[cfg(test)] +macro_rules! reload_node { + ($node: expr, $new_config: expr, $chanman_encoded: expr, $monitors_encoded: expr, $persister: ident, $new_chain_monitor: ident, $new_channelmanager: ident) => { + let chanman_encoded = $chanman_encoded; + + $persister = test_utils::TestPersister::new(); + $new_chain_monitor = test_utils::TestChainMonitor::new(Some($node.chain_source), $node.tx_broadcaster.clone(), $node.logger, $node.fee_estimator, &$persister, &$node.keys_manager); + $node.chain_monitor = &$new_chain_monitor; + + $new_channelmanager = _reload_node(&$node, $new_config, &chanman_encoded, $monitors_encoded); + $node.node = &$new_channelmanager; + }; + ($node: expr, $chanman_encoded: expr, $monitors_encoded: expr, $persister: ident, $new_chain_monitor: ident, $new_channelmanager: ident) => { + reload_node!($node, $crate::util::config::UserConfig::default(), $chanman_encoded, $monitors_encoded, $persister, $new_chain_monitor, $new_channelmanager); + }; +} + +pub fn create_funding_transaction<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, expected_counterparty_node_id: &PublicKey, expected_chan_value: u64, expected_user_chan_id: u128) -> ([u8; 32], Transaction, OutPoint) { let chan_id = *node.network_chan_count.borrow(); let events = node.node.get_and_clear_pending_events(); @@ -620,7 +684,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 }; @@ -669,14 +733,85 @@ 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()); assert_eq!(open_channel_msg.temporary_channel_id, create_chan_id); + assert_eq!(node_a.node.list_channels().iter().find(|channel| channel.channel_id == create_chan_id).unwrap().user_channel_id, 42); node_b.node.handle_open_channel(&node_a.node.get_our_node_id(), a_flags, &open_channel_msg); let accept_channel_msg = get_event_msg!(node_b, MessageSendEvent::SendAcceptChannel, node_a.node.get_our_node_id()); assert_eq!(accept_channel_msg.temporary_channel_id, create_chan_id); node_a.node.handle_accept_channel(&node_b.node.get_our_node_id(), b_flags, &accept_channel_msg); + assert_ne!(node_b.node.list_channels().iter().find(|channel| channel.channel_id == create_chan_id).unwrap().user_channel_id, 0); sign_funding_transaction(node_a, node_b, channel_value, create_chan_id) } @@ -719,6 +854,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 +893,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 +932,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 +965,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. @@ -894,11 +983,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| { $( @@ -1026,7 +1115,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 +1140,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 +1190,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 { @@ -1187,7 +1276,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(); @@ -1244,7 +1333,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) => {{ @@ -1254,55 +1343,33 @@ macro_rules! get_route_and_payment_hash { }} } -pub struct HTLCHandlingFailedConditions { - pub expected_destinations: Vec, -} - -impl HTLCHandlingFailedConditions { - pub fn new() -> Self { - Self { - expected_destinations: vec![], - } - } - - pub fn with_reason(mut self, reason: HTLCDestination) -> Self { - self.expected_destinations = vec![reason]; - self - } - - pub fn with_reasons(mut self, reasons: Vec) -> Self { - self.expected_destinations = reasons; - self - } -} - #[macro_export] macro_rules! expect_pending_htlcs_forwardable_conditions { - ($node: expr, $conditions: expr) => {{ - let conditions = $conditions; + ($node: expr, $expected_failures: expr) => {{ + let expected_failures = $expected_failures; let events = $node.node.get_and_clear_pending_events(); match events[0] { $crate::util::events::Event::PendingHTLCsForwardable { .. } => { }, _ => panic!("Unexpected event"), }; - let count = conditions.expected_destinations.len() + 1; + let count = expected_failures.len() + 1; assert_eq!(events.len(), count); - if conditions.expected_destinations.len() > 0 { - expect_htlc_handling_failed_destinations!(events, conditions.expected_destinations) + if expected_failures.len() > 0 { + expect_htlc_handling_failed_destinations!(events, expected_failures) } }} } #[macro_export] macro_rules! expect_htlc_handling_failed_destinations { - ($events: expr, $destinations: expr) => {{ + ($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!($destinations.contains(&failed_next_destination)) + assert!($expected_failures.contains(&failed_next_destination)) }, _ => panic!("Unexpected destination"), } @@ -1314,15 +1381,15 @@ macro_rules! expect_htlc_handling_failed_destinations { /// Clears (and ignores) a PendingHTLCsForwardable event macro_rules! expect_pending_htlcs_forwardable_ignore { ($node: expr) => {{ - expect_pending_htlcs_forwardable_conditions!($node, $crate::ln::functional_test_utils::HTLCHandlingFailedConditions::new()); + 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, $conditions: expr) => {{ - expect_pending_htlcs_forwardable_conditions!($node, $conditions); + ($node: expr, $expected_failures: expr) => {{ + expect_pending_htlcs_forwardable_conditions!($node, $expected_failures); }}; } @@ -1341,8 +1408,8 @@ macro_rules! expect_pending_htlcs_forwardable { #[macro_export] /// Handles a PendingHTLCsForwardable and HTLCHandlingFailed event macro_rules! expect_pending_htlcs_forwardable_and_htlc_handling_failed { - ($node: expr, $conditions: expr) => {{ - expect_pending_htlcs_forwardable_and_htlc_handling_failed_ignore!($node, $conditions); + ($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. @@ -1500,6 +1567,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, @@ -1536,9 +1616,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)); } @@ -1546,33 +1626,34 @@ 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, + 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"); + if let Some(scid) = short_channel_id { + assert!(retry.as_ref().unwrap().payment_params.previously_failed_channels.contains(&scid)); + } #[cfg(test)] { @@ -1622,8 +1703,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 @@ -1840,7 +1931,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()); @@ -1854,7 +1945,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]; @@ -1870,7 +1961,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"))); } @@ -1884,12 +1975,29 @@ 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); } 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()); @@ -1913,6 +2021,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; @@ -1925,7 +2035,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(); @@ -1961,10 +2071,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); @@ -1972,19 +2082,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"), - } - } + }); } } @@ -1993,6 +2091,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) { @@ -2033,7 +2133,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; @@ -2073,7 +2173,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)); @@ -2083,6 +2183,7 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec(node_count: usize, cfgs: &'b Vec(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 @@ -2269,15 +2369,27 @@ macro_rules! get_channel_value_stat { macro_rules! get_chan_reestablish_msgs { ($src_node: expr, $dst_node: expr) => { { + 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 } } @@ -2301,6 +2413,14 @@ macro_rules! handle_chan_reestablish_msgs { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); } + let mut had_channel_update = false; // ChannelUpdate may be now or later, but not both + 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()); + idx += 1; + assert_eq!(msg.contents.flags & 2, 0); // "disabled" flag must not be set as we just reconnected. + had_channel_update = true; + } + let mut revoke_and_ack = None; let mut commitment_update = None; let order = if let Some(ev) = msg_events.get(idx) { @@ -2345,6 +2465,7 @@ macro_rules! handle_chan_reestablish_msgs { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); idx += 1; assert_eq!(msg.contents.flags & 2, 0); // "disabled" flag must not be set as we just reconnected. + assert!(!had_channel_update); } assert_eq!(msg_events.len(), idx); @@ -2357,9 +2478,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 {