X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=17a287c74c0859180292dfd21c9a85c6d5b10fda;hb=094ddb264bbb2d71d84822033f2a5e83a5f7f60b;hp=9e4708dcfd6a6dbeb4e676a5e7f495d09cac7c97;hpb=0a31c12f85b55dd2b3a85e929a5c92086bc8842b;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 9e4708dc..17a287c7 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -45,7 +45,7 @@ use chain::transaction::{OutPoint, TransactionData}; use ln::{PaymentHash, PaymentPreimage, PaymentSecret}; use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch}; use ln::features::{InitFeatures, NodeFeatures}; -use routing::router::{Route, RouteHop}; +use routing::router::{Payee, Route, RouteHop, RoutePath, RouteParameters}; use ln::msgs; use ln::msgs::NetAddress; use ln::onion_utils; @@ -173,6 +173,7 @@ struct ClaimableHTLC { } /// A payment identifier used to uniquely identify a payment to LDK. +/// (C-not exported) as we just use [u8; 32] directly #[derive(Hash, Copy, Clone, PartialEq, Eq, Debug)] pub struct PaymentId(pub [u8; 32]); @@ -201,6 +202,7 @@ pub(crate) enum HTLCSource { first_hop_htlc_msat: u64, payment_id: PaymentId, payment_secret: Option, + payee: Option, }, } #[allow(clippy::derive_hash_xor_eq)] // Our Hash is faithful to the data, we just don't have SecretKey::hash @@ -211,13 +213,14 @@ impl core::hash::Hash for HTLCSource { 0u8.hash(hasher); prev_hop_data.hash(hasher); }, - HTLCSource::OutboundRoute { path, session_priv, payment_id, payment_secret, first_hop_htlc_msat } => { + HTLCSource::OutboundRoute { path, session_priv, payment_id, payment_secret, first_hop_htlc_msat, payee } => { 1u8.hash(hasher); path.hash(hasher); session_priv[..].hash(hasher); payment_id.hash(hasher); payment_secret.hash(hasher); first_hop_htlc_msat.hash(hasher); + payee.hash(hasher); }, } } @@ -231,6 +234,7 @@ impl HTLCSource { first_hop_htlc_msat: 0, payment_id: PaymentId([2; 32]), payment_secret: None, + payee: None, } } } @@ -433,6 +437,8 @@ pub(crate) enum PendingOutboundPayment { payment_hash: PaymentHash, payment_secret: Option, pending_amt_msat: u64, + /// Used to track the fee paid. Only present if the payment was serialized on 0.0.103+. + pending_fee_msat: Option, /// The total payment amount across all paths, used to verify that a retry is not overpaying. total_msat: u64, /// Our best known block height at the time this payment was initiated. @@ -459,6 +465,12 @@ impl PendingOutboundPayment { _ => false, } } + fn get_pending_fee_msat(&self) -> Option { + match self { + PendingOutboundPayment::Retryable { pending_fee_msat, .. } => pending_fee_msat.clone(), + _ => None, + } + } fn mark_fulfilled(&mut self) { let mut session_privs = HashSet::new(); @@ -471,8 +483,8 @@ impl PendingOutboundPayment { *self = PendingOutboundPayment::Fulfilled { session_privs }; } - /// panics if part_amt_msat is None and !self.is_fulfilled - fn remove(&mut self, session_priv: &[u8; 32], part_amt_msat: Option) -> bool { + /// panics if path is None and !self.is_fulfilled + fn remove(&mut self, session_priv: &[u8; 32], path: Option<&Vec>) -> bool { let remove_res = match self { PendingOutboundPayment::Legacy { session_privs } | PendingOutboundPayment::Retryable { session_privs, .. } | @@ -481,14 +493,19 @@ impl PendingOutboundPayment { } }; if remove_res { - if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, .. } = self { - *pending_amt_msat -= part_amt_msat.expect("We must only not provide an amount if the payment was already fulfilled"); + if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self { + let path = path.expect("Fulfilling a payment should always come with a path"); + let path_last_hop = path.last().expect("Outbound payments must have had a valid path"); + *pending_amt_msat -= path_last_hop.fee_msat; + if let Some(fee_msat) = pending_fee_msat.as_mut() { + *fee_msat -= path.get_path_fees(); + } } } remove_res } - fn insert(&mut self, session_priv: [u8; 32], part_amt_msat: u64) -> bool { + fn insert(&mut self, session_priv: [u8; 32], path: &Vec) -> bool { let insert_res = match self { PendingOutboundPayment::Legacy { session_privs } | PendingOutboundPayment::Retryable { session_privs, .. } => { @@ -497,8 +514,12 @@ impl PendingOutboundPayment { PendingOutboundPayment::Fulfilled { .. } => false }; if insert_res { - if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, .. } = self { - *pending_amt_msat += part_amt_msat; + if let PendingOutboundPayment::Retryable { ref mut pending_amt_msat, ref mut pending_fee_msat, .. } = self { + let path_last_hop = path.last().expect("Outbound payments must have had a valid path"); + *pending_amt_msat += path_last_hop.fee_msat; + if let Some(fee_msat) = pending_fee_msat.as_mut() { + *fee_msat += path.get_path_fees(); + } } } insert_res @@ -925,7 +946,16 @@ pub enum PaymentSendFailure { /// as they will result in over-/re-payment. These HTLCs all either successfully sent (in the /// case of Ok(())) or will send once channel_monitor_updated is called on the next-hop channel /// with the latest update_id. - PartialFailure(Vec>), + PartialFailure { + /// The errors themselves, in the same order as the route hops. + results: Vec>, + /// If some paths failed without irrevocably committing to the new HTLC(s), this will + /// contain a [`RouteParameters`] object which can be used to calculate a new route that + /// will pay all remaining unpaid balance. + failed_paths_retry: Option, + /// The payment id for the payment, which is now at least partially pending. + payment_id: PaymentId, + }, } macro_rules! handle_error { @@ -2021,7 +2051,7 @@ impl ChannelMana } // Only public for testing, this should otherwise never be called direcly - pub(crate) fn send_payment_along_path(&self, path: &Vec, payment_hash: &PaymentHash, payment_secret: &Option, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option) -> Result<(), APIError> { + pub(crate) fn send_payment_along_path(&self, path: &Vec, payee: &Option, payment_hash: &PaymentHash, payment_secret: &Option, total_value: u64, cur_height: u32, payment_id: PaymentId, keysend_preimage: &Option) -> Result<(), APIError> { log_trace!(self.logger, "Attempting to send payment for path with next hop {}", path.first().unwrap().short_channel_id); let prng_seed = self.keys_manager.get_secure_random_bytes(); let session_priv_bytes = self.keys_manager.get_secure_random_bytes(); @@ -2071,18 +2101,20 @@ impl ChannelMana first_hop_htlc_msat: htlc_msat, payment_id, payment_secret: payment_secret.clone(), + payee: payee.clone(), }, onion_packet, &self.logger), channel_state, chan); let payment = payment_entry.or_insert_with(|| PendingOutboundPayment::Retryable { session_privs: HashSet::new(), pending_amt_msat: 0, + pending_fee_msat: Some(0), payment_hash: *payment_hash, payment_secret: *payment_secret, starting_block_height: self.best_block.read().unwrap().height(), total_msat: total_value, }); - assert!(payment.insert(session_priv_bytes, path.last().unwrap().fee_msat)); + assert!(payment.insert(session_priv_bytes, path)); send_res } { @@ -2209,11 +2241,13 @@ impl ChannelMana let cur_height = self.best_block.read().unwrap().height() + 1; let mut results = Vec::new(); for path in route.paths.iter() { - results.push(self.send_payment_along_path(&path, &payment_hash, payment_secret, total_value, cur_height, payment_id, &keysend_preimage)); + results.push(self.send_payment_along_path(&path, &route.payee, &payment_hash, payment_secret, total_value, cur_height, payment_id, &keysend_preimage)); } let mut has_ok = false; let mut has_err = false; - for res in results.iter() { + let mut pending_amt_unsent = 0; + let mut max_unsent_cltv_delta = 0; + for (res, path) in results.iter().zip(route.paths.iter()) { if res.is_ok() { has_ok = true; } if res.is_err() { has_err = true; } if let &Err(APIError::MonitorUpdateFailed) = res { @@ -2221,11 +2255,25 @@ impl ChannelMana // PartialFailure. has_err = true; has_ok = true; - break; + } else if res.is_err() { + pending_amt_unsent += path.last().unwrap().fee_msat; + max_unsent_cltv_delta = cmp::max(max_unsent_cltv_delta, path.last().unwrap().cltv_expiry_delta); } } if has_err && has_ok { - Err(PaymentSendFailure::PartialFailure(results)) + Err(PaymentSendFailure::PartialFailure { + results, + payment_id, + failed_paths_retry: if pending_amt_unsent != 0 { + if let Some(payee) = &route.payee { + Some(RouteParameters { + payee: payee.clone(), + final_value_msat: pending_amt_unsent, + final_cltv_expiry_delta: max_unsent_cltv_delta, + }) + } else { None } + } else { None }, + }) } else if has_err { Err(PaymentSendFailure::AllFailedRetrySafe(results.drain(..).map(|r| r.unwrap_err()).collect())) } else { @@ -3098,22 +3146,30 @@ impl ChannelMana self.fail_htlc_backwards_internal(channel_state, htlc_src, &payment_hash, HTLCFailReason::Reason { failure_code, data: onion_failure_data}); }, - HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => { + HTLCSource::OutboundRoute { session_priv, payment_id, path, payee, .. } => { let mut session_priv_bytes = [0; 32]; session_priv_bytes.copy_from_slice(&session_priv[..]); let mut outbounds = self.pending_outbound_payments.lock().unwrap(); if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) { - if payment.get_mut().remove(&session_priv_bytes, Some(path.last().unwrap().fee_msat)) && - !payment.get().is_fulfilled() - { + if payment.get_mut().remove(&session_priv_bytes, Some(&path)) && !payment.get().is_fulfilled() { + let retry = if let Some(payee_data) = payee { + let path_last_hop = path.last().expect("Outbound payments must have had a valid path"); + Some(RouteParameters { + payee: payee_data, + final_value_msat: path_last_hop.fee_msat, + final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta, + }) + } else { None }; self.pending_events.lock().unwrap().push( events::Event::PaymentPathFailed { + payment_id: Some(payment_id), payment_hash, rejected_by_dest: false, network_update: None, all_paths_failed: payment.get().remaining_parts() == 0, path: path.clone(), short_channel_id: None, + retry, #[cfg(test)] error_code: None, #[cfg(test)] @@ -3145,13 +3201,13 @@ impl ChannelMana // from block_connected which may run during initialization prior to the chain_monitor // being fully configured. See the docs for `ChannelManagerReadArgs` for more. match source { - HTLCSource::OutboundRoute { ref path, session_priv, payment_id, .. } => { + HTLCSource::OutboundRoute { ref path, session_priv, payment_id, ref payee, .. } => { let mut session_priv_bytes = [0; 32]; session_priv_bytes.copy_from_slice(&session_priv[..]); let mut outbounds = self.pending_outbound_payments.lock().unwrap(); let mut all_paths_failed = false; if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) { - if !payment.get_mut().remove(&session_priv_bytes, Some(path.last().unwrap().fee_msat)) { + if !payment.get_mut().remove(&session_priv_bytes, Some(&path)) { log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0)); return; } @@ -3166,8 +3222,16 @@ impl ChannelMana log_trace!(self.logger, "Received duplicative fail for HTLC with payment_hash {}", log_bytes!(payment_hash.0)); return; } - log_trace!(self.logger, "Failing outbound payment HTLC with payment_hash {}", log_bytes!(payment_hash.0)); mem::drop(channel_state_lock); + let retry = if let Some(payee_data) = payee { + let path_last_hop = path.last().expect("Outbound payments must have had a valid path"); + Some(RouteParameters { + payee: payee_data.clone(), + final_value_msat: path_last_hop.fee_msat, + final_cltv_expiry_delta: path_last_hop.cltv_expiry_delta, + }) + } else { None }; + log_trace!(self.logger, "Failing outbound payment HTLC with payment_hash {}", log_bytes!(payment_hash.0)); match &onion_error { &HTLCFailReason::LightningError { ref err } => { #[cfg(test)] @@ -3179,12 +3243,14 @@ impl ChannelMana // next-hop is needlessly blaming us! self.pending_events.lock().unwrap().push( events::Event::PaymentPathFailed { + payment_id: Some(payment_id), payment_hash: payment_hash.clone(), rejected_by_dest: !payment_retryable, network_update, all_paths_failed, path: path.clone(), short_channel_id, + retry, #[cfg(test)] error_code: onion_error_code, #[cfg(test)] @@ -3207,12 +3273,14 @@ impl ChannelMana // channel here as we apparently can't relay through them anyway. self.pending_events.lock().unwrap().push( events::Event::PaymentPathFailed { + payment_id: Some(payment_id), payment_hash: payment_hash.clone(), rejected_by_dest: path.len() == 1, network_update: None, all_paths_failed, path: path.clone(), short_channel_id: Some(path.first().unwrap().short_channel_id), + retry, #[cfg(test)] error_code: Some(*failure_code), #[cfg(test)] @@ -3431,8 +3499,9 @@ impl ChannelMana let mut session_priv_bytes = [0; 32]; session_priv_bytes.copy_from_slice(&session_priv[..]); let mut outbounds = self.pending_outbound_payments.lock().unwrap(); - let found_payment = if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) { + if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) { let found_payment = !payment.get().is_fulfilled(); + let fee_paid_msat = payment.get().get_pending_fee_msat(); payment.get_mut().mark_fulfilled(); if from_onchain { // We currently immediately remove HTLCs which were fulfilled on-chain. @@ -3441,21 +3510,22 @@ impl ChannelMana // restart. // TODO: We should have a second monitor event that informs us of payments // irrevocably fulfilled. - payment.get_mut().remove(&session_priv_bytes, Some(path.last().unwrap().fee_msat)); + payment.get_mut().remove(&session_priv_bytes, Some(&path)); if payment.get().remaining_parts() == 0 { payment.remove(); } } - found_payment - } else { false }; - if found_payment { - let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner()); - self.pending_events.lock().unwrap().push( - events::Event::PaymentSent { - payment_preimage, - payment_hash: payment_hash - } - ); + if found_payment { + let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0).into_inner()); + self.pending_events.lock().unwrap().push( + events::Event::PaymentSent { + payment_id: Some(payment_id), + payment_preimage, + payment_hash: payment_hash, + fee_paid_msat, + } + ); + } } else { log_trace!(self.logger, "Received duplicative fulfill for HTLC with payment_preimage {}", log_bytes!(payment_preimage.0)); } @@ -5375,12 +5445,14 @@ impl Readable for HTLCSource { let mut path = Some(Vec::new()); let mut payment_id = None; let mut payment_secret = None; + let mut payee = None; read_tlv_fields!(reader, { (0, session_priv, required), (1, payment_id, option), (2, first_hop_htlc_msat, required), (3, payment_secret, option), (4, path, vec_type), + (5, payee, option), }); if payment_id.is_none() { // For backwards compat, if there was no payment_id written, use the session_priv bytes @@ -5393,6 +5465,7 @@ impl Readable for HTLCSource { path: path.unwrap(), payment_id: payment_id.unwrap(), payment_secret, + payee, }) } 1 => Ok(HTLCSource::PreviousHopData(Readable::read(reader)?)), @@ -5404,7 +5477,7 @@ impl Readable for HTLCSource { impl Writeable for HTLCSource { fn write(&self, writer: &mut W) -> Result<(), ::io::Error> { match self { - HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id, payment_secret } => { + HTLCSource::OutboundRoute { ref session_priv, ref first_hop_htlc_msat, ref path, payment_id, payment_secret, payee } => { 0u8.write(writer)?; let payment_id_opt = Some(payment_id); write_tlv_fields!(writer, { @@ -5413,6 +5486,7 @@ impl Writeable for HTLCSource { (2, first_hop_htlc_msat, required), (3, payment_secret, option), (4, path, vec_type), + (5, payee, option), }); } HTLCSource::PreviousHopData(ref field) => { @@ -5464,6 +5538,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment, }, (2, Retryable) => { (0, session_privs, required), + (1, pending_fee_msat, option), (2, payment_hash, required), (4, payment_secret, option), (6, total_msat, required), @@ -5920,16 +5995,18 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> session_priv_bytes[..].copy_from_slice(&session_priv[..]); match pending_outbound_payments.as_mut().unwrap().entry(payment_id) { hash_map::Entry::Occupied(mut entry) => { - let newly_added = entry.get_mut().insert(session_priv_bytes, path_amt); + let newly_added = entry.get_mut().insert(session_priv_bytes, &path); log_info!(args.logger, "{} a pending payment path for {} msat for session priv {} on an existing pending payment with payment hash {}", if newly_added { "Added" } else { "Had" }, path_amt, log_bytes!(session_priv_bytes), log_bytes!(htlc.payment_hash.0)); }, hash_map::Entry::Vacant(entry) => { + let path_fee = path.get_path_fees(); entry.insert(PendingOutboundPayment::Retryable { session_privs: [session_priv_bytes].iter().map(|a| *a).collect(), payment_hash: htlc.payment_hash, payment_secret, pending_amt_msat: path_amt, + pending_fee_msat: Some(path_fee), total_msat: path_amt, starting_block_height: best_block_height, }); @@ -6005,12 +6082,11 @@ mod tests { use core::time::Duration; use ln::{PaymentPreimage, PaymentHash, PaymentSecret}; use ln::channelmanager::{PaymentId, PaymentSendFailure}; - use ln::features::{InitFeatures, InvoiceFeatures}; + use ln::features::InitFeatures; use ln::functional_test_utils::*; use ln::msgs; use ln::msgs::ChannelMessageHandler; - use routing::router::{get_keysend_route, get_route}; - use routing::scorer::Scorer; + use routing::router::{Payee, RouteParameters, find_route}; use util::errors::APIError; use util::events::{Event, MessageSendEvent, MessageSendEventsProvider}; use util::test_utils; @@ -6157,7 +6233,7 @@ mod tests { // Use the utility function send_payment_along_path to send the payment with MPP data which // indicates there are more HTLCs coming. let cur_height = CHAN_CONFIRM_DEPTH + 1; // route_payment calls send_payment, which adds 1 to the current height. So we do the same here to match. - nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap(); + nodes[0].node.send_payment_along_path(&route.paths[0], &route.payee, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -6187,7 +6263,7 @@ mod tests { expect_payment_failed!(nodes[0], our_payment_hash, true); // Send the second half of the original MPP payment. - nodes[0].node.send_payment_along_path(&route.paths[0], &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap(); + nodes[0].node.send_payment_along_path(&route.paths[0], &route.payee, &our_payment_hash, &Some(payment_secret), 200_000, cur_height, payment_id, &None).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events.len(), 1); @@ -6229,7 +6305,8 @@ mod tests { // further events will be generated for subsequence path successes. let events = nodes[0].node.get_and_clear_pending_events(); match events[0] { - Event::PaymentSent { payment_preimage: ref preimage, payment_hash: ref hash } => { + Event::PaymentSent { payment_id: ref id, payment_preimage: ref preimage, payment_hash: ref hash, .. } => { + assert_eq!(Some(payment_id), *id); assert_eq!(payment_preimage, *preimage); assert_eq!(our_payment_hash, *hash); }, @@ -6248,15 +6325,22 @@ mod tests { let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let nodes = create_network(2, &node_cfgs, &node_chanmgrs); create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); - let logger = test_utils::TestLogger::new(); - let scorer = Scorer::new(0); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); // To start (1), send a regular payment but don't claim it. let expected_route = [&nodes[1]]; let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &expected_route, 100_000); // Next, attempt a keysend payment and make sure it fails. - let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); + let params = RouteParameters { + payee: Payee::for_keysend(expected_route.last().unwrap().node.get_our_node_id()), + final_value_msat: 100_000, + final_cltv_expiry_delta: TEST_FINAL_CLTV, + }; + let route = find_route( + &nodes[0].node.get_our_node_id(), ¶ms, nodes[0].network_graph, None, + nodes[0].logger, &scorer + ).unwrap(); nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -6284,7 +6368,10 @@ mod tests { // To start (2), send a keysend payment but don't claim it. let payment_preimage = PaymentPreimage([42; 32]); - let route = get_route(&nodes[0].node.get_our_node_id(), &nodes[0].net_graph_msg_handler.network_graph, &expected_route.last().unwrap().node.get_our_node_id(), Some(InvoiceFeatures::known()), None, &Vec::new(), 100_000, TEST_FINAL_CLTV, &logger, &scorer).unwrap(); + let route = find_route( + &nodes[0].node.get_our_node_id(), ¶ms, nodes[0].network_graph, None, + nodes[0].logger, &scorer + ).unwrap(); let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap(); check_added_monitors!(nodes[0], 1); let mut events = nodes[0].node.get_and_clear_pending_msg_events(); @@ -6336,12 +6423,18 @@ mod tests { nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() }); let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known()); - let network_graph = &nodes[0].net_graph_msg_handler.network_graph; + let params = RouteParameters { + payee: Payee::for_keysend(payee_pubkey), + final_value_msat: 10000, + final_cltv_expiry_delta: 40, + }; + let network_graph = nodes[0].network_graph; let first_hops = nodes[0].node.list_usable_channels(); - let scorer = Scorer::new(0); - let route = get_keysend_route(&payer_pubkey, network_graph, &payee_pubkey, - Some(&first_hops.iter().collect::>()), &vec![], 10000, 40, - nodes[0].logger, &scorer).unwrap(); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); + let route = find_route( + &payer_pubkey, ¶ms, network_graph, Some(&first_hops.iter().collect::>()), + nodes[0].logger, &scorer + ).unwrap(); let test_preimage = PaymentPreimage([42; 32]); let mismatch_payment_hash = PaymentHash([43; 32]); @@ -6373,12 +6466,18 @@ mod tests { nodes[1].node.peer_connected(&payer_pubkey, &msgs::Init { features: InitFeatures::known() }); let _chan = create_chan_between_nodes(&nodes[0], &nodes[1], InitFeatures::known(), InitFeatures::known()); - let network_graph = &nodes[0].net_graph_msg_handler.network_graph; + let params = RouteParameters { + payee: Payee::for_keysend(payee_pubkey), + final_value_msat: 10000, + final_cltv_expiry_delta: 40, + }; + let network_graph = nodes[0].network_graph; let first_hops = nodes[0].node.list_usable_channels(); - let scorer = Scorer::new(0); - let route = get_keysend_route(&payer_pubkey, network_graph, &payee_pubkey, - Some(&first_hops.iter().collect::>()), &vec![], 10000, 40, - nodes[0].logger, &scorer).unwrap(); + let scorer = test_utils::TestScorer::with_fixed_penalty(0); + let route = find_route( + &payer_pubkey, ¶ms, network_graph, Some(&first_hops.iter().collect::>()), + nodes[0].logger, &scorer + ).unwrap(); let test_preimage = PaymentPreimage([42; 32]); let test_secret = PaymentSecret([43; 32]); @@ -6438,7 +6537,7 @@ pub mod bench { use ln::functional_test_utils::*; use ln::msgs::{ChannelMessageHandler, Init}; use routing::network_graph::NetworkGraph; - use routing::router::get_route; + use routing::router::{Payee, get_route}; use routing::scorer::Scorer; use util::test_utils; use util::config::UserConfig; @@ -6547,9 +6646,11 @@ pub mod bench { macro_rules! send_payment { ($node_a: expr, $node_b: expr) => { let usable_channels = $node_a.list_usable_channels(); - let scorer = Scorer::new(0); - let route = get_route(&$node_a.get_our_node_id(), &dummy_graph, &$node_b.get_our_node_id(), Some(InvoiceFeatures::known()), - Some(&usable_channels.iter().map(|r| r).collect::>()), &[], 10_000, TEST_FINAL_CLTV, &logger_a, &scorer).unwrap(); + let payee = Payee::new($node_b.get_our_node_id()) + .with_features(InvoiceFeatures::known()); + let scorer = Scorer::with_fixed_penalty(0); + let route = get_route(&$node_a.get_our_node_id(), &payee, &dummy_graph, + Some(&usable_channels.iter().map(|r| r).collect::>()), 10_000, TEST_FINAL_CLTV, &logger_a, &scorer).unwrap(); let mut payment_preimage = PaymentPreimage([0; 32]); payment_preimage.0[0..8].copy_from_slice(&payment_count.to_le_bytes());