X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=3b0a8452b7b16ec713f90c5640c8059469d94d59;hb=2e5e40e0b21fbac862478dce4d81cf037f37060d;hp=49db3b1158a361260bbe408f01b363f44f177f1f;hpb=fd0ebcf8ecc62f4b414248f2e53d548d6f5e1354;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 49db3b11..3b0a8452 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -10,10 +10,11 @@ //! A bunch of useful utilities for building networks of nodes and exchanging messages between //! nodes for functional tests. -use chain::{Confirm, Listen, Watch}; +use chain::{BestBlock, Confirm, Listen, Watch}; use chain::channelmonitor::ChannelMonitor; use chain::transaction::OutPoint; -use ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure}; +use ln::{PaymentPreimage, PaymentHash, PaymentSecret}; +use ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure}; use routing::router::{Route, get_route}; use routing::network_graph::{NetGraphMsgHandler, NetworkGraph}; use ln::features::{InitFeatures, InvoiceFeatures}; @@ -22,7 +23,7 @@ use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler}; use util::enforcing_trait_impls::EnforcingSigner; use util::test_utils; use util::test_utils::TestChainMonitor; -use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider}; +use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose}; use util::errors::APIError; use util::config::UserConfig; use util::ser::{ReadableArgs, Writeable, Readable}; @@ -38,11 +39,12 @@ use bitcoin::hash_types::BlockHash; use bitcoin::secp256k1::key::PublicKey; -use std::cell::RefCell; +use io; +use prelude::*; +use core::cell::RefCell; use std::rc::Rc; -use std::sync::Mutex; -use std::mem; -use std::collections::HashMap; +use sync::{Arc, Mutex}; +use core::mem; pub const CHAN_CONFIRM_DEPTH: u32 = 10; @@ -147,14 +149,14 @@ fn do_connect_block<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, block: &Block, s } } node.node.test_process_background_events(); - node.blocks.borrow_mut().push((block.header, height)); + node.blocks.lock().unwrap().push((block.header, height)); } pub fn disconnect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, count: u32) { for i in 0..count { - let orig_header = node.blocks.borrow_mut().pop().unwrap(); + let orig_header = node.blocks.lock().unwrap().pop().unwrap(); assert!(orig_header.1 > 0); // Cannot disconnect genesis - let prev_header = node.blocks.borrow().last().unwrap().clone(); + let prev_header = node.blocks.lock().unwrap().last().unwrap().clone(); match *node.connect_style.borrow() { ConnectStyle::FullBlockViaListen => { @@ -176,7 +178,7 @@ pub fn disconnect_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>, count: u32) } pub fn disconnect_all_blocks<'a, 'b, 'c, 'd>(node: &'a Node<'b, 'c, 'd>) { - let count = node.blocks.borrow_mut().len() as u32 - 1; + let count = node.blocks.lock().unwrap().len() as u32 - 1; disconnect_blocks(node, count); } @@ -197,6 +199,7 @@ pub struct NodeCfg<'a> { pub keys_manager: &'a test_utils::TestKeysInterface, pub logger: &'a test_utils::TestLogger, pub node_seed: [u8; 32], + pub features: InitFeatures, } pub struct Node<'a, 'b: 'a, 'c: 'b> { @@ -210,15 +213,18 @@ pub struct Node<'a, 'b: 'a, 'c: 'b> { pub network_payment_count: Rc>, pub network_chan_count: Rc>, pub logger: &'c test_utils::TestLogger, - pub blocks: RefCell>, + pub blocks: Arc>>, pub connect_style: Rc>, } impl<'a, 'b, 'c> Node<'a, 'b, 'c> { pub fn best_block_hash(&self) -> BlockHash { - self.blocks.borrow_mut().last().unwrap().0.block_hash() + self.blocks.lock().unwrap().last().unwrap().0.block_hash() } pub fn best_block_info(&self) -> (BlockHash, u32) { - self.blocks.borrow_mut().last().map(|(a, b)| (a.block_hash(), *b)).unwrap() + self.blocks.lock().unwrap().last().map(|(a, b)| (a.block_hash(), *b)).unwrap() + } + pub fn get_block_header(&self, height: u32) -> BlockHeader { + self.blocks.lock().unwrap()[height as usize].0 } } @@ -235,7 +241,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { let mut w = test_utils::TestVecWriter(Vec::new()); let network_graph_ser = self.net_graph_msg_handler.network_graph.read().unwrap(); network_graph_ser.write(&mut w).unwrap(); - let network_graph_deser = ::read(&mut ::std::io::Cursor::new(&w.0)).unwrap(); + let network_graph_deser = ::read(&mut io::Cursor::new(&w.0)).unwrap(); assert!(network_graph_deser == *self.net_graph_msg_handler.network_graph.read().unwrap()); let net_graph_msg_handler = NetGraphMsgHandler::from_net_graph( Some(self.chain_source), self.logger, network_graph_deser @@ -265,7 +271,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { // Check that if we serialize and then deserialize all our channel monitors we get the // same set of outputs to watch for on chain as we have now. Note that if we write // tests that fully close channels and remove the monitors at some point this may break. - let feeest = test_utils::TestFeeEstimator { sat_per_kw: 253 }; + let feeest = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }; let mut deserialized_monitors = Vec::new(); { let old_monitors = self.chain_monitor.chain_monitor.monitors.read().unwrap(); @@ -273,7 +279,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { let mut w = test_utils::TestVecWriter(Vec::new()); old_monitor.write(&mut w).unwrap(); let (_, deserialized_monitor) = <(BlockHash, ChannelMonitor)>::read( - &mut ::std::io::Cursor::new(&w.0), self.keys_manager).unwrap(); + &mut io::Cursor::new(&w.0), self.keys_manager).unwrap(); deserialized_monitors.push(deserialized_monitor); } } @@ -288,13 +294,14 @@ 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 ::std::io::Cursor::new(w.0), ChannelManagerReadArgs { + <(BlockHash, ChannelManager)>::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: 253 }, + fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }, chain_monitor: self.chain_monitor, tx_broadcaster: &test_utils::TestBroadcaster { - txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()) + txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()), + blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())), }, logger: &test_utils::TestLogger::new(), channel_monitors, @@ -303,7 +310,8 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { let persister = test_utils::TestPersister::new(); let broadcaster = test_utils::TestBroadcaster { - txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()) + txn_broadcasted: Mutex::new(self.tx_broadcaster.txn_broadcasted.lock().unwrap().clone()), + blocks: Arc::new(Mutex::new(self.tx_broadcaster.blocks.lock().unwrap().clone())), }; let chain_source = test_utils::TestChainSource::new(Network::Testnet); let chain_monitor = test_utils::TestChainMonitor::new(Some(&chain_source), &broadcaster, &self.logger, &feeest, &persister, &self.keys_manager); @@ -408,12 +416,22 @@ macro_rules! get_htlc_update_msgs { } } +#[cfg(test)] +macro_rules! get_channel_ref { + ($node: expr, $lock: ident, $channel_id: expr) => { + { + $lock = $node.node.channel_state.lock().unwrap(); + $lock.by_id.get_mut(&$channel_id).unwrap() + } + } +} + #[cfg(test)] macro_rules! get_feerate { ($node: expr, $channel_id: expr) => { { - let chan_lock = $node.node.channel_state.lock().unwrap(); - let chan = chan_lock.by_id.get(&$channel_id).unwrap(); + let mut lock; + let chan = get_channel_ref!($node, lock, $channel_id); chan.get_feerate() } } @@ -556,7 +574,7 @@ pub fn create_chan_between_nodes_with_value_confirm_second<'a, 'b, 'c>(node_recv } pub fn create_chan_between_nodes_with_value_confirm<'a, 'b, 'c, 'd>(node_a: &'a Node<'b, 'c, 'd>, node_b: &'a Node<'b, 'c, 'd>, tx: &Transaction) -> ((msgs::FundingLocked, msgs::AnnouncementSignatures), [u8; 32]) { - let conf_height = std::cmp::max(node_a.best_block_info().1 + 1, node_b.best_block_info().1 + 1); + let conf_height = core::cmp::max(node_a.best_block_info().1 + 1, node_b.best_block_info().1 + 1); create_chan_between_nodes_with_value_confirm_first(node_a, node_b, tx, conf_height); confirm_transaction_at(node_a, tx, conf_height); connect_blocks(node_a, CHAN_CONFIRM_DEPTH - 1); @@ -614,8 +632,22 @@ pub fn create_announced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec>, a: usize, b: usize, ann: &msgs::ChannelAnnouncement, upd_1: &msgs::ChannelUpdate, upd_2: &msgs::ChannelUpdate) { nodes[a].node.broadcast_node_announcement([0, 0, 0], [0; 32], Vec::new()); let a_events = nodes[a].node.get_and_clear_pending_msg_events(); - assert_eq!(a_events.len(), 1); - let a_node_announcement = match a_events[0] { + assert!(a_events.len() >= 2); + + // ann should be re-generated by broadcast_node_announcement - check that we have it. + let mut found_ann_1 = false; + for event in a_events.iter() { + match event { + MessageSendEvent::BroadcastChannelAnnouncement { ref msg, .. } => { + if msg == ann { found_ann_1 = true; } + }, + MessageSendEvent::BroadcastNodeAnnouncement { .. } => {}, + _ => panic!("Unexpected event {:?}", event), + } + } + assert!(found_ann_1); + + let a_node_announcement = match a_events.last().unwrap() { MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => { (*msg).clone() }, @@ -624,8 +656,22 @@ pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec= 2); + + // ann should be re-generated by broadcast_node_announcement - check that we have it. + let mut found_ann_2 = false; + for event in b_events.iter() { + match event { + MessageSendEvent::BroadcastChannelAnnouncement { ref msg, .. } => { + if msg == ann { found_ann_2 = true; } + }, + MessageSendEvent::BroadcastNodeAnnouncement { .. } => {}, + _ => panic!("Unexpected event"), + } + } + assert!(found_ann_2); + + let b_node_announcement = match b_events.last().unwrap() { MessageSendEvent::BroadcastNodeAnnouncement { ref msg } => { (*msg).clone() }, @@ -719,7 +765,7 @@ macro_rules! check_closed_broadcast { pub fn close_channel<'a, 'b, 'c>(outbound_node: &Node<'a, 'b, 'c>, inbound_node: &Node<'a, 'b, 'c>, channel_id: &[u8; 32], funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate, Transaction) { let (node_a, broadcaster_a, struct_a) = if close_inbound_first { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) } else { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) }; - let (node_b, broadcaster_b) = if close_inbound_first { (&outbound_node.node, &outbound_node.tx_broadcaster) } else { (&inbound_node.node, &inbound_node.tx_broadcaster) }; + let (node_b, broadcaster_b, struct_b) = if close_inbound_first { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) } else { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) }; let (tx_a, tx_b); node_a.close_channel(channel_id).unwrap(); @@ -752,29 +798,33 @@ pub fn close_channel<'a, 'b, 'c>(outbound_node: &Node<'a, 'b, 'c>, inbound_node: 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()); - assert_eq!(broadcaster_a.txn_broadcasted.lock().unwrap().len(), 1); - tx_a = broadcaster_a.txn_broadcasted.lock().unwrap().remove(0); - let (as_update, closing_signed_a) = get_closing_signed_broadcast!(node_a, node_b.get_our_node_id()); - node_b.handle_closing_signed(&node_a.get_our_node_id(), &closing_signed_a.unwrap()); - let (bs_update, none_b) = get_closing_signed_broadcast!(node_b, node_a.get_our_node_id()); - assert!(none_b.is_none()); + node_b.handle_closing_signed(&node_a.get_our_node_id(), &get_event_msg!(struct_a, MessageSendEvent::SendClosingSigned, node_b.get_our_node_id())); assert_eq!(broadcaster_b.txn_broadcasted.lock().unwrap().len(), 1); tx_b = broadcaster_b.txn_broadcasted.lock().unwrap().remove(0); + let (bs_update, closing_signed_b) = get_closing_signed_broadcast!(node_b, node_a.get_our_node_id()); + + node_a.handle_closing_signed(&node_b.get_our_node_id(), &closing_signed_b.unwrap()); + let (as_update, none_a) = get_closing_signed_broadcast!(node_a, node_b.get_our_node_id()); + assert!(none_a.is_none()); + assert_eq!(broadcaster_a.txn_broadcasted.lock().unwrap().len(), 1); + tx_a = broadcaster_a.txn_broadcasted.lock().unwrap().remove(0); (as_update, bs_update) } else { let closing_signed_a = get_event_msg!(struct_a, MessageSendEvent::SendClosingSigned, node_b.get_our_node_id()); node_b.handle_closing_signed(&node_a.get_our_node_id(), &closing_signed_a); - assert_eq!(broadcaster_b.txn_broadcasted.lock().unwrap().len(), 1); - tx_b = broadcaster_b.txn_broadcasted.lock().unwrap().remove(0); - let (bs_update, closing_signed_b) = get_closing_signed_broadcast!(node_b, node_a.get_our_node_id()); + node_a.handle_closing_signed(&node_b.get_our_node_id(), &get_event_msg!(struct_b, MessageSendEvent::SendClosingSigned, node_a.get_our_node_id())); - node_a.handle_closing_signed(&node_b.get_our_node_id(), &closing_signed_b.unwrap()); - let (as_update, none_a) = get_closing_signed_broadcast!(node_a, node_b.get_our_node_id()); - assert!(none_a.is_none()); assert_eq!(broadcaster_a.txn_broadcasted.lock().unwrap().len(), 1); tx_a = broadcaster_a.txn_broadcasted.lock().unwrap().remove(0); + let (as_update, closing_signed_a) = get_closing_signed_broadcast!(node_a, node_b.get_our_node_id()); + + node_b.handle_closing_signed(&node_a.get_our_node_id(), &closing_signed_a.unwrap()); + let (bs_update, none_b) = get_closing_signed_broadcast!(node_b, node_a.get_our_node_id()); + assert!(none_b.is_none()); + assert_eq!(broadcaster_b.txn_broadcasted.lock().unwrap().len(), 1); + tx_b = broadcaster_b.txn_broadcasted.lock().unwrap().remove(0); (as_update, bs_update) }; assert_eq!(tx_a, tx_b); @@ -942,11 +992,16 @@ macro_rules! expect_payment_received { let events = $node.node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { - Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt, user_payment_id: _ } => { + Event::PaymentReceived { ref payment_hash, ref purpose, amt } => { assert_eq!($expected_payment_hash, *payment_hash); - assert!(payment_preimage.is_none()); - assert_eq!($expected_payment_secret, *payment_secret); assert_eq!($expected_recv_value, amt); + match purpose { + PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => { + assert!(payment_preimage.is_none()); + assert_eq!($expected_payment_secret, *payment_secret); + }, + _ => {}, + } }, _ => panic!("Unexpected event"), } @@ -966,6 +1021,44 @@ macro_rules! expect_payment_sent { } } +macro_rules! expect_payment_forwarded { + ($node: expr, $expected_fee: expr, $upstream_force_closed: expr) => { + let events = $node.node.get_and_clear_pending_events(); + assert_eq!(events.len(), 1); + match events[0] { + Event::PaymentForwarded { fee_earned_msat, claim_from_onchain_tx } => { + assert_eq!(fee_earned_msat, $expected_fee); + assert_eq!(claim_from_onchain_tx, $upstream_force_closed); + }, + _ => panic!("Unexpected event"), + } + } +} + +#[cfg(test)] +macro_rules! expect_payment_failure_chan_update { + ($node: expr, $scid: expr, $chan_closed: expr) => { + let events = $node.node.get_and_clear_pending_msg_events(); + assert_eq!(events.len(), 1); + match events[0] { + MessageSendEvent::PaymentFailureNetworkUpdate { ref update } => { + match update { + &HTLCFailChannelUpdate::ChannelUpdateMessage { ref msg } if !$chan_closed => { + assert_eq!(msg.contents.short_channel_id, $scid); + assert_eq!(msg.contents.flags & 2, 0); + }, + &HTLCFailChannelUpdate::ChannelClosed { short_channel_id, is_permanent } if $chan_closed => { + assert_eq!(short_channel_id, $scid); + assert!(is_permanent); + }, + _ => panic!("Unexpected update type"), + } + }, + _ => panic!("Unexpected event"), + } + } +} + #[cfg(test)] macro_rules! expect_payment_failed { ($node: expr, $expected_payment_hash: expr, $rejected_by_dest: expr $(, $expected_error_code: expr, $expected_error_data: expr)*) => { @@ -993,7 +1086,7 @@ pub fn send_along_route_with_secret<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, pass_along_route(origin_node, expected_paths, recv_value, our_payment_hash, our_payment_secret); } -pub fn pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: PaymentSecret, ev: MessageSendEvent, payment_received_expected: bool) { +pub fn pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path: &[&Node<'a, 'b, 'c>], recv_value: u64, our_payment_hash: PaymentHash, our_payment_secret: Option, ev: MessageSendEvent, payment_received_expected: bool, expected_preimage: Option) { let mut payment_event = SendEvent::from_event(ev); let mut prev_node = origin_node; @@ -1011,10 +1104,18 @@ pub fn pass_along_path<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_path if payment_received_expected { assert_eq!(events_2.len(), 1); match events_2[0] { - Event::PaymentReceived { ref payment_hash, ref payment_preimage, ref payment_secret, amt, user_payment_id: _ } => { + Event::PaymentReceived { ref payment_hash, ref purpose, amt} => { assert_eq!(our_payment_hash, *payment_hash); - assert!(payment_preimage.is_none()); - assert_eq!(our_payment_secret, *payment_secret); + match &purpose { + PaymentPurpose::InvoicePayment { payment_preimage, payment_secret, .. } => { + assert_eq!(expected_preimage, *payment_preimage); + assert_eq!(our_payment_secret.unwrap(), *payment_secret); + }, + PaymentPurpose::SpontaneousPayment(payment_preimage) => { + assert_eq!(expected_preimage.unwrap(), *payment_preimage); + assert!(our_payment_secret.is_none()); + }, + } assert_eq!(amt, recv_value); }, _ => panic!("Unexpected event"), @@ -1041,7 +1142,7 @@ pub fn pass_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou // Once we've gotten through all the HTLCs, the last one should result in a // PaymentReceived (but each previous one should not!), . let expect_payment = path_idx == expected_route.len() - 1; - pass_along_path(origin_node, expected_path, recv_value, our_payment_hash.clone(), our_payment_secret, ev, expect_payment); + pass_along_path(origin_node, expected_path, recv_value, our_payment_hash.clone(), Some(our_payment_secret), ev, expect_payment, None); } } @@ -1098,6 +1199,8 @@ pub fn claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, exp ($node: expr, $prev_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; + expect_payment_forwarded!($node, Some(fee as u64), false); check_added_monitors!($node, 1); let new_next_msgs = if $new_msgs { let events = $node.node.get_and_clear_pending_msg_events(); @@ -1143,12 +1246,15 @@ pub fn claim_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: claim_payment_along_route(origin_node, &[expected_route], false, our_payment_preimage); } -pub const TEST_FINAL_CLTV: u32 = 50; +pub const TEST_FINAL_CLTV: u32 = 70; pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) { let net_graph_msg_handler = &origin_node.net_graph_msg_handler; let logger = test_utils::TestLogger::new(); - let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), recv_value, TEST_FINAL_CLTV, &logger).unwrap(); + let route = get_route(&origin_node.node.get_our_node_id(), &net_graph_msg_handler.network_graph.read().unwrap(), + &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), + Some(&origin_node.node.list_usable_channels().iter().collect::>()), &[], + recv_value, TEST_FINAL_CLTV, &logger).unwrap(); assert_eq!(route.paths.len(), 1); assert_eq!(route.paths[0].len(), expected_route.len()); for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) { @@ -1254,8 +1360,11 @@ pub fn fail_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: pub fn create_chanmon_cfgs(node_count: usize) -> Vec { let mut chan_mon_cfgs = Vec::new(); for i in 0..node_count { - let tx_broadcaster = test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())}; - let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: 253 }; + let tx_broadcaster = test_utils::TestBroadcaster { + txn_broadcasted: Mutex::new(Vec::new()), + blocks: Arc::new(Mutex::new(vec![(genesis_block(Network::Testnet).header, 0)])), + }; + let fee_estimator = test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }; let chain_source = test_utils::TestChainSource::new(Network::Testnet); let logger = test_utils::TestLogger::with_id(format!("node {}", i)); let persister = test_utils::TestPersister::new(); @@ -1274,28 +1383,47 @@ pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec UserConfig { + let mut default_config = UserConfig::default(); + // Set cltv_expiry_delta slightly lower to keep the final CLTV values inside one byte in our + // tests so that our script-length checks don't fail (see ACCEPTED_HTLC_SCRIPT_WEIGHT). + default_config.channel_options.cltv_expiry_delta = 6*6; + default_config.channel_options.announced_channel = true; + default_config.peer_channel_config_limits.force_announced_channel_preference = false; + // When most of our tests were written, the default HTLC minimum was fixed at 1000. + // It now defaults to 1, so we simply set it to the expected value here. + default_config.own_channel_config.our_htlc_minimum_msat = 1000; + // 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 +} + pub fn create_node_chanmgrs<'a, 'b>(node_count: usize, cfgs: &'a Vec>, node_config: &[Option]) -> Vec, &'b test_utils::TestBroadcaster, &'a test_utils::TestKeysInterface, &'b test_utils::TestFeeEstimator, &'b test_utils::TestLogger>> { let mut chanmgrs = Vec::new(); for i in 0..node_count { - let mut default_config = UserConfig::default(); - // Set cltv_expiry_delta slightly lower to keep the final CLTV values inside one byte in our - // tests so that our script-length checks don't fail (see ACCEPTED_HTLC_SCRIPT_WEIGHT). - default_config.channel_options.cltv_expiry_delta = 6*6; - default_config.channel_options.announced_channel = true; - default_config.peer_channel_config_limits.force_announced_channel_preference = false; - default_config.own_channel_config.our_htlc_minimum_msat = 1000; // sanitization being done by the sender, to exerce receiver logic we need to lift of limit let network = Network::Testnet; let params = ChainParameters { network, best_block: BestBlock::from_genesis(network), }; - let node = ChannelManager::new(cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, cfgs[i].logger, cfgs[i].keys_manager, if node_config[i].is_some() { node_config[i].clone().unwrap() } else { default_config }, params); + let node = ChannelManager::new(cfgs[i].fee_estimator, &cfgs[i].chain_monitor, cfgs[i].tx_broadcaster, cfgs[i].logger, cfgs[i].keys_manager, + if node_config[i].is_some() { node_config[i].clone().unwrap() } else { test_default_channel_config() }, params); chanmgrs.push(node); } @@ -1315,11 +1443,18 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); revoke_and_ack = Some(msg.clone()); + idx += 1; RAACommitmentOrder::RevokeAndACKFirst }, &MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); commitment_update = Some(updates.clone()); + idx += 1; RAACommitmentOrder::CommitmentFirst }, + &MessageSendEvent::SendChannelUpdate { .. } => RAACommitmentOrder::CommitmentFirst, _ => panic!("Unexpected event"), } } else { @@ -1541,16 +1683,24 @@ macro_rules! handle_chan_reestablish_msgs { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); assert!(revoke_and_ack.is_none()); revoke_and_ack = Some(msg.clone()); + idx += 1; }, &MessageSendEvent::UpdateHTLCs { ref node_id, ref updates } => { assert_eq!(*node_id, $dst_node.node.get_our_node_id()); assert!(commitment_update.is_none()); commitment_update = Some(updates.clone()); + idx += 1; }, + &MessageSendEvent::SendChannelUpdate { .. } => {}, _ => panic!("Unexpected event"), } } + if let Some(&MessageSendEvent::SendChannelUpdate { ref node_id, ref msg }) = msg_events.get(idx) { + assert_eq!(*node_id, $dst_node.node.get_our_node_id()); + assert_eq!(msg.contents.flags & 2, 0); // "disabled" flag must not be set as we just reconnected. + } + (funding_locked, revoke_and_ack, commitment_update, order) } } @@ -1558,7 +1708,7 @@ 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_funding_locked: (bool, bool), pending_htlc_adds: (i64, i64), pending_htlc_claims: (usize, usize), pending_cell_htlc_claims: (usize, usize), pending_cell_htlc_fails: (usize, usize), pending_raa: (bool, bool)) { +pub fn reconnect_nodes<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>, send_funding_locked: (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() }); 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() }); @@ -1612,8 +1762,10 @@ pub fn reconnect_nodes<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, } // We don't yet support both needing updates, as that would require a different commitment dance: - assert!((pending_htlc_adds.0 == 0 && pending_htlc_claims.0 == 0 && pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0) || - (pending_htlc_adds.1 == 0 && pending_htlc_claims.1 == 0 && pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0)); + assert!((pending_htlc_adds.0 == 0 && pending_htlc_claims.0 == 0 && pending_htlc_fails.0 == 0 && + pending_cell_htlc_claims.0 == 0 && pending_cell_htlc_fails.0 == 0) || + (pending_htlc_adds.1 == 0 && pending_htlc_claims.1 == 0 && pending_htlc_fails.1 == 0 && + pending_cell_htlc_claims.1 == 0 && pending_cell_htlc_fails.1 == 0)); for chan_msgs in resp_1.drain(..) { if send_funding_locked.0 { @@ -1636,7 +1788,7 @@ pub fn reconnect_nodes<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, } else { assert!(chan_msgs.1.is_none()); } - if pending_htlc_adds.0 != 0 || pending_htlc_claims.0 != 0 || pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 { + if pending_htlc_adds.0 != 0 || pending_htlc_claims.0 != 0 || pending_htlc_fails.0 != 0 || pending_cell_htlc_claims.0 != 0 || pending_cell_htlc_fails.0 != 0 { let commitment_update = chan_msgs.2.unwrap(); if pending_htlc_adds.0 != -1 { // We use -1 to denote a response commitment_signed assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.0 as usize); @@ -1644,7 +1796,7 @@ pub fn reconnect_nodes<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, assert!(commitment_update.update_add_htlcs.is_empty()); } assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0 + pending_cell_htlc_claims.0); - assert_eq!(commitment_update.update_fail_htlcs.len(), pending_cell_htlc_fails.0); + assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.0 + pending_cell_htlc_fails.0); assert!(commitment_update.update_fail_malformed_htlcs.is_empty()); for update_add in commitment_update.update_add_htlcs { node_a.node.handle_update_add_htlc(&node_b.node.get_our_node_id(), &update_add); @@ -1693,13 +1845,13 @@ pub fn reconnect_nodes<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, } else { assert!(chan_msgs.1.is_none()); } - if pending_htlc_adds.1 != 0 || pending_htlc_claims.1 != 0 || pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 { + if pending_htlc_adds.1 != 0 || pending_htlc_claims.1 != 0 || pending_htlc_fails.1 != 0 || pending_cell_htlc_claims.1 != 0 || pending_cell_htlc_fails.1 != 0 { let commitment_update = chan_msgs.2.unwrap(); if pending_htlc_adds.1 != -1 { // We use -1 to denote a response commitment_signed assert_eq!(commitment_update.update_add_htlcs.len(), pending_htlc_adds.1 as usize); } - assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.0 + pending_cell_htlc_claims.0); - assert_eq!(commitment_update.update_fail_htlcs.len(), pending_cell_htlc_fails.0); + assert_eq!(commitment_update.update_fulfill_htlcs.len(), pending_htlc_claims.1 + pending_cell_htlc_claims.1); + assert_eq!(commitment_update.update_fail_htlcs.len(), pending_htlc_fails.1 + pending_cell_htlc_fails.1); assert!(commitment_update.update_fail_malformed_htlcs.is_empty()); for update_add in commitment_update.update_add_htlcs { node_b.node.handle_update_add_htlc(&node_a.node.get_our_node_id(), &update_add);