X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Ffunctional_test_utils.rs;h=0c21588fb717af4aee2ef93a52f9da16abaaaaa3;hb=d0b8f455fe86d3e55231d35d35dd96693abe2049;hp=7bf51df5c7a28bb553dd67fd44de672e0f98142d;hpb=41e6eba20106e66f4c28422ff8e4632e98b2fb42;p=rust-lightning diff --git a/lightning/src/ln/functional_test_utils.rs b/lightning/src/ln/functional_test_utils.rs index 7bf51df5..0c21588f 100644 --- a/lightning/src/ln/functional_test_utils.rs +++ b/lightning/src/ln/functional_test_utils.rs @@ -305,6 +305,7 @@ pub struct TestChanMonCfg { pub persister: test_utils::TestPersister, pub logger: test_utils::TestLogger, pub keys_manager: test_utils::TestKeysInterface, + pub scorer: Mutex, } pub struct NodeCfg<'a> { @@ -350,6 +351,19 @@ impl<'a, 'b, 'c> Node<'a, 'b, 'c> { } } +/// If we need an unsafe pointer to a `Node` (ie to reference it in a thread +/// pre-std::thread::scope), this provides that with `Sync`. Note that accessing some of the fields +/// in the `Node` are not safe to use (i.e. the ones behind an `Rc`), but that's left to the caller +/// to figure out. +pub struct NodePtr(pub *const Node<'static, 'static, 'static>); +impl NodePtr { + pub fn from_node<'a, 'b: 'a, 'c: 'b>(node: &Node<'a, 'b, 'c>) -> Self { + Self((node as *const Node<'a, 'b, 'c>).cast()) + } +} +unsafe impl Send for NodePtr {} +unsafe impl Sync for NodePtr {} + impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { fn drop(&mut self) { if !panicking() { @@ -427,6 +441,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { channel_monitors.insert(monitor.get_funding_txo().0, monitor); } + let scorer = Mutex::new(test_utils::TestScorer::new()); let mut w = test_utils::TestVecWriter(Vec::new()); self.node.write(&mut w).unwrap(); <(BlockHash, ChannelManager<&test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestRouter, &test_utils::TestLogger>)>::read(&mut io::Cursor::new(w.0), ChannelManagerReadArgs { @@ -435,7 +450,7 @@ impl<'a, 'b, 'c> Drop for Node<'a, 'b, 'c> { node_signer: self.keys_manager, signer_provider: self.keys_manager, fee_estimator: &test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }, - router: &test_utils::TestRouter::new(Arc::new(network_graph)), + router: &test_utils::TestRouter::new(Arc::new(network_graph), &scorer), chain_monitor: self.chain_monitor, tx_broadcaster: &broadcaster, logger: &self.logger, @@ -572,12 +587,12 @@ macro_rules! get_htlc_update_msgs { } /// Fetches the first `msg_event` to the passed `node_id` in the passed `msg_events` vec. -/// Returns the `msg_event`, along with an updated `msg_events` vec with the message removed. +/// Returns the `msg_event`. /// /// Note that even though `BroadcastChannelAnnouncement` and `BroadcastChannelUpdate` /// `msg_events` are stored under specific peers, this function does not fetch such `msg_events` as /// such messages are intended to all peers. -pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &Vec) -> (MessageSendEvent, Vec) { +pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &mut Vec) -> MessageSendEvent { let ev_index = msg_events.iter().position(|e| { match e { MessageSendEvent::SendAcceptChannel { node_id, .. } => { node_id == msg_node_id @@ -644,9 +659,7 @@ pub fn remove_first_msg_event_to_node(msg_node_id: &PublicKey, msg_events: &Vec< }, }}); if ev_index.is_some() { - let mut updated_msg_events = msg_events.to_vec(); - let ev = updated_msg_events.remove(ev_index.unwrap()); - (ev, updated_msg_events) + msg_events.remove(ev_index.unwrap()) } else { panic!("Couldn't find any MessageSendEvent to the node!") } @@ -1486,9 +1499,9 @@ pub fn do_main_commitment_signed_dance(node_a: &Node<'_, '_, '_>, node_b: &Node< check_added_monitors!(node_b, 1); node_b.node.handle_commitment_signed(&node_a.node.get_our_node_id(), &as_commitment_signed); let (bs_revoke_and_ack, extra_msg_option) = { - let events = node_b.node.get_and_clear_pending_msg_events(); + let mut events = node_b.node.get_and_clear_pending_msg_events(); assert!(events.len() <= 2); - let (node_a_event, events) = remove_first_msg_event_to_node(&node_a.node.get_our_node_id(), &events); + let node_a_event = remove_first_msg_event_to_node(&node_a.node.get_our_node_id(), &mut events); (match node_a_event { MessageSendEvent::SendRevokeAndACK { ref node_id, ref msg } => { assert_eq!(*node_id, node_a.node.get_our_node_id()); @@ -1570,7 +1583,7 @@ macro_rules! get_payment_preimage_hash { macro_rules! get_route { ($send_node: expr, $payment_params: expr, $recv_value: expr, $cltv: expr) => {{ use $crate::chain::keysinterface::EntropySource; - let scorer = $crate::util::test_utils::TestScorer::with_penalty(0); + let scorer = $crate::util::test_utils::TestScorer::new(); let keys_manager = $crate::util::test_utils::TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); $crate::routing::router::get_route( @@ -1800,17 +1813,18 @@ macro_rules! expect_payment_failed { } 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, + payment_failed_events: Vec, expected_payment_hash: PaymentHash, expected_payment_failed_permanently: bool, conditions: PaymentFailedConditions<'e> ) { - let expected_payment_id = match payment_failed_event { + if conditions.expected_mpp_parts_remain { assert_eq!(payment_failed_events.len(), 1); } else { assert_eq!(payment_failed_events.len(), 2); } + let expected_payment_id = match &payment_failed_events[0] { 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!(payment_failed_permanently, expected_payment_failed_permanently, "unexpected payment_failed_permanently value"); + assert_eq!(*payment_hash, expected_payment_hash, "unexpected payment_hash"); + 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"); @@ -1839,7 +1853,7 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>( }, Some(NetworkUpdate::ChannelFailure { short_channel_id, is_permanent }) if chan_closed => { if let Some(scid) = conditions.expected_blamed_scid { - assert_eq!(short_channel_id, scid); + assert_eq!(*short_channel_id, scid); } assert!(is_permanent); }, @@ -1853,10 +1867,7 @@ pub fn expect_payment_failed_conditions_event<'a, 'b, 'c, 'd, 'e>( _ => panic!("Unexpected event"), }; if !conditions.expected_mpp_parts_remain { - node.node.abandon_payment(expected_payment_id); - let events = node.node.get_and_clear_pending_events(); - assert_eq!(events.len(), 1); - match events[0] { + match &payment_failed_events[1] { Event::PaymentFailed { ref payment_hash, ref payment_id } => { assert_eq!(*payment_hash, expected_payment_hash, "unexpected second payment_hash"); assert_eq!(*payment_id, expected_payment_id); @@ -1870,9 +1881,8 @@ 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); + let events = node.node.get_and_clear_pending_events(); + expect_payment_failed_conditions_event(events, 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 { @@ -1943,8 +1953,7 @@ pub fn pass_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou let mut events = origin_node.node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), expected_route.len()); for (path_idx, expected_path) in expected_route.iter().enumerate() { - let (ev, updated_events) = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &events); - events = updated_events; + let ev = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events); // Once we've gotten through all the HTLCs, the last one should result in a // PaymentClaimable (but each previous one should not!), . let expect_payment = path_idx == expected_route.len() - 1; @@ -2003,9 +2012,8 @@ pub fn do_claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, } else { for expected_path in expected_paths.iter() { // For MPP payments, we always want the message to the first node in the path. - let (ev, updated_events) = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &events); + let ev = remove_first_msg_event_to_node(&expected_path[0].node.get_our_node_id(), &mut events); per_path_msgs.push(msgs_from_ev!(&ev)); - events = updated_events; } } @@ -2124,7 +2132,7 @@ pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_rou let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV) .with_features(expected_route.last().unwrap().node.invoice_features()); let network_graph = origin_node.network_graph.read_only(); - let scorer = test_utils::TestScorer::with_penalty(0); + let scorer = test_utils::TestScorer::new(); let seed = [0u8; 32]; let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); let random_seed_bytes = keys_manager.get_secure_random_bytes(); @@ -2159,22 +2167,6 @@ 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()); @@ -2198,8 +2190,6 @@ pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b 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; @@ -2247,8 +2237,9 @@ pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b assert!(origin_node.node.get_and_clear_pending_msg_events().is_empty()); 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); - expected_payment_id = Some(match events[0] { + if i == expected_paths.len() - 1 { assert_eq!(events.len(), 2); } else { assert_eq!(events.len(), 1); } + + let expected_payment_id = 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!(payment_failed_permanently); @@ -2259,7 +2250,16 @@ pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b payment_id.unwrap() }, _ => panic!("Unexpected event"), - }); + }; + if i == expected_paths.len() - 1 { + match events[1] { + 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"), + } + } } } @@ -2268,8 +2268,6 @@ pub fn pass_failed_payment_back_no_abandon<'a, 'b, 'c>(origin_node: &Node<'a, 'b 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) { @@ -2289,8 +2287,9 @@ pub fn create_chanmon_cfgs(node_count: usize) -> Vec { let persister = test_utils::TestPersister::new(); let seed = [i as u8; 32]; let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet); + let scorer = Mutex::new(test_utils::TestScorer::new()); - chan_mon_cfgs.push(TestChanMonCfg { tx_broadcaster, fee_estimator, chain_source, logger, persister, keys_manager }); + chan_mon_cfgs.push(TestChanMonCfg { tx_broadcaster, fee_estimator, chain_source, logger, persister, keys_manager, scorer }); } chan_mon_cfgs @@ -2308,7 +2307,7 @@ pub fn create_node_cfgs<'a>(node_count: usize, chanmon_cfgs: &'a Vec