Have `get_route` take `RouteParameters`
authorElias Rohrer <dev@tnull.de>
Thu, 31 Aug 2023 10:25:38 +0000 (12:25 +0200)
committerElias Rohrer <dev@tnull.de>
Wed, 6 Sep 2023 17:35:37 +0000 (19:35 +0200)
fuzz/src/full_stack.rs
fuzz/src/router.rs
lightning-invoice/src/utils.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/onion_route_tests.rs
lightning/src/ln/outbound_payment.rs
lightning/src/ln/payment_tests.rs
lightning/src/ln/shutdown_tests.rs
lightning/src/routing/router.rs

index a11e5c81368f5757be8081fc7cdbefb6bc6549a0..d7167146cac18d90c58d31f617f5af677875bbbf 100644 (file)
@@ -527,10 +527,8 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                        4 => {
                                let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
                                let payment_params = PaymentParameters::from_node_id(get_pubkey!(), 42);
-                               let params = RouteParameters {
-                                       payment_params,
-                                       final_value_msat,
-                               };
+                               let params = RouteParameters::from_payment_params_and_value(
+                                       payment_params, final_value_msat);
                                let mut payment_hash = PaymentHash([0; 32]);
                                payment_hash.0[0..8].copy_from_slice(&be64_to_array(payments_sent));
                                let mut sha = Sha256::engine();
@@ -548,10 +546,8 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
                        15 => {
                                let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
                                let payment_params = PaymentParameters::from_node_id(get_pubkey!(), 42);
-                               let params = RouteParameters {
-                                       payment_params,
-                                       final_value_msat,
-                               };
+                               let params = RouteParameters::from_payment_params_and_value(
+                                       payment_params, final_value_msat);
                                let mut payment_hash = PaymentHash([0; 32]);
                                payment_hash.0[0..8].copy_from_slice(&be64_to_array(payments_sent));
                                let mut sha = Sha256::engine();
index 830f6f4e201cb3d91155dca468492d586133b031..b7d45bf729f4d6c488c5916de536a5cf6f02f6dc 100644 (file)
@@ -326,11 +326,10 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                let mut last_hops = Vec::new();
                                last_hops!(last_hops);
                                find_routes!(first_hops, node_pks.iter(), |final_amt, final_delta, target: &PublicKey| {
-                                       RouteParameters {
-                                               payment_params: PaymentParameters::from_node_id(*target, final_delta)
+                                       RouteParameters::from_payment_params_and_value(
+                                               PaymentParameters::from_node_id(*target, final_delta)
                                                        .with_route_hints(last_hops.clone()).unwrap(),
-                                               final_value_msat: final_amt,
-                                       }
+                                               final_amt)
                                });
                        },
                        x => {
@@ -366,11 +365,9 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                let mut features = Bolt12InvoiceFeatures::empty();
                                features.set_basic_mpp_optional();
                                find_routes!(first_hops, vec![dummy_pk].iter(), |final_amt, _, _| {
-                                       RouteParameters {
-                                               payment_params: PaymentParameters::blinded(last_hops.clone())
-                                                       .with_bolt12_features(features.clone()).unwrap(),
-                                               final_value_msat: final_amt,
-                                       }
+                                       RouteParameters::from_payment_params_and_value(PaymentParameters::blinded(last_hops.clone())
+                                               .with_bolt12_features(features.clone()).unwrap(),
+                                       final_amt)
                                });
                        }
                }
index 744c2654cd84705965999d09f602e4c17f2de3dd..a512b2de05dd74eb7125bf543d44fd0dbe5ec315 100644 (file)
@@ -869,10 +869,8 @@ mod test {
                                invoice.min_final_cltv_expiry_delta() as u32)
                        .with_bolt11_features(invoice.features().unwrap().clone()).unwrap()
                        .with_route_hints(invoice.route_hints()).unwrap();
-               let route_params = RouteParameters {
-                       payment_params,
-                       final_value_msat: invoice.amount_milli_satoshis().unwrap(),
-               };
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, invoice.amount_milli_satoshis().unwrap());
                let payment_event = {
                        let mut payment_hash = PaymentHash([0; 32]);
                        payment_hash.0.copy_from_slice(&invoice.payment_hash().as_ref()[0..32]);
@@ -1326,10 +1324,8 @@ mod test {
                                invoice.min_final_cltv_expiry_delta() as u32)
                        .with_bolt11_features(invoice.features().unwrap().clone()).unwrap()
                        .with_route_hints(invoice.route_hints()).unwrap();
-               let params = RouteParameters {
-                       payment_params,
-                       final_value_msat: invoice.amount_milli_satoshis().unwrap(),
-               };
+               let params = RouteParameters::from_payment_params_and_value(
+                       payment_params, invoice.amount_milli_satoshis().unwrap());
                let (payment_event, fwd_idx) = {
                        let mut payment_hash = PaymentHash([0; 32]);
                        payment_hash.0.copy_from_slice(&invoice.payment_hash().as_ref()[0..32]);
index 213a2882fbc3f899e5dd43ebc09a92a47f35c39a..5624204a504b82d4cb134598386d06bd9faa4c3e 100644 (file)
@@ -9653,10 +9653,9 @@ mod tests {
                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_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV, false),
-                       final_value_msat: 100_000,
-               };
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(),
+                       TEST_FINAL_CLTV, false), 100_000);
                let route = find_route(
                        &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph,
                        None, nodes[0].logger, &scorer, &(), &random_seed_bytes
@@ -9744,10 +9743,10 @@ mod tests {
                pass_along_path(&nodes[0], &path, 100_000, payment_hash, None, event, true, Some(payment_preimage));
 
                // Next, attempt a keysend payment and make sure it fails.
-               let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV, false),
-                       final_value_msat: 100_000,
-               };
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       PaymentParameters::for_keysend(expected_route.last().unwrap().node.get_our_node_id(), TEST_FINAL_CLTV, false),
+                       100_000
+               );
                let route = find_route(
                        &nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph,
                        None, nodes[0].logger, &scorer, &(), &random_seed_bytes
@@ -9793,10 +9792,8 @@ mod tests {
                let payee_pubkey = nodes[1].node.get_our_node_id();
 
                let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
-               let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, false),
-                       final_value_msat: 10_000,
-               };
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       PaymentParameters::for_keysend(payee_pubkey, 40, false), 10_000);
                let network_graph = nodes[0].network_graph.clone();
                let first_hops = nodes[0].node.list_usable_channels();
                let scorer = test_utils::TestScorer::new();
@@ -9840,10 +9837,8 @@ mod tests {
                let payee_pubkey = nodes[1].node.get_our_node_id();
 
                let _chan = create_chan_between_nodes(&nodes[0], &nodes[1]);
-               let route_params = RouteParameters {
-                       payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, false),
-                       final_value_msat: 10_000,
-               };
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       PaymentParameters::for_keysend(payee_pubkey, 40, false), 10_000);
                let network_graph = nodes[0].network_graph.clone();
                let first_hops = nodes[0].node.list_usable_channels();
                let scorer = test_utils::TestScorer::new();
@@ -10740,9 +10735,9 @@ pub mod bench {
                                let payment_secret = $node_b.create_inbound_payment_for_hash(payment_hash, None, 7200, None).unwrap();
 
                                $node_a.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
-                                       PaymentId(payment_hash.0), RouteParameters {
-                                               payment_params, final_value_msat: 10_000,
-                                       }, Retry::Attempts(0)).unwrap();
+                                       PaymentId(payment_hash.0),
+                                       RouteParameters::from_payment_params_and_value(payment_params, 10_000),
+                                       Retry::Attempts(0)).unwrap();
                                let payment_event = SendEvent::from_event($node_a.get_and_clear_pending_msg_events().pop().unwrap());
                                $node_b.handle_update_add_htlc(&$node_a.get_our_node_id(), &payment_event.msgs[0]);
                                $node_b.handle_commitment_signed(&$node_a.get_our_node_id(), &payment_event.commitment_msg);
index b8c2e085999c0dbdb978bbf2b85093580b464a37..a43cfae9e68f759280a5e0a05bb8a04514c0ca7e 100644 (file)
@@ -19,7 +19,7 @@ use crate::events::bump_transaction::{BumpTransactionEventHandler, Wallet, Walle
 use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
 use crate::ln::channelmanager::{self, AChannelManager, ChainParameters, ChannelManager, ChannelManagerReadArgs, RAACommitmentOrder, PaymentSendFailure, RecipientOnionFields, PaymentId, MIN_CLTV_EXPIRY_DELTA};
 use crate::routing::gossip::{P2PGossipSync, NetworkGraph, NetworkUpdate};
-use crate::routing::router::{self, PaymentParameters, Route};
+use crate::routing::router::{self, PaymentParameters, Route, RouteParameters};
 use crate::ln::features::InitFeatures;
 use crate::ln::msgs;
 use crate::ln::msgs::{ChannelMessageHandler,RoutingMessageHandler};
@@ -1838,14 +1838,14 @@ macro_rules! get_payment_preimage_hash {
 }
 
 /// Gets a route from the given sender to the node described in `payment_params`.
-pub fn get_route(send_node: &Node, payment_params: &PaymentParameters, recv_value: u64) -> Result<Route, msgs::LightningError> {
+pub fn get_route(send_node: &Node, route_params: &RouteParameters) -> Result<Route, msgs::LightningError> {
        let scorer = TestScorer::new();
        let keys_manager = TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet);
        let random_seed_bytes = keys_manager.get_secure_random_bytes();
        router::get_route(
-               &send_node.node.get_our_node_id(), payment_params, &send_node.network_graph.read_only(),
+               &send_node.node.get_our_node_id(), route_params, &send_node.network_graph.read_only(),
                Some(&send_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
-               recv_value, send_node.logger, &scorer, &(), &random_seed_bytes
+               send_node.logger, &scorer, &(), &random_seed_bytes
        )
 }
 
@@ -1854,9 +1854,10 @@ pub fn get_route(send_node: &Node, payment_params: &PaymentParameters, recv_valu
 /// Don't use this, use the identically-named function instead.
 #[macro_export]
 macro_rules! get_route {
-       ($send_node: expr, $payment_params: expr, $recv_value: expr) => {
-               $crate::ln::functional_test_utils::get_route(&$send_node, &$payment_params, $recv_value)
-       }
+       ($send_node: expr, $payment_params: expr, $recv_value: expr) => {{
+               let route_params = $crate::routing::router::RouteParameters::from_payment_params_and_value($payment_params, $recv_value);
+               $crate::ln::functional_test_utils::get_route(&$send_node, &route_params)
+       }}
 }
 
 #[cfg(test)]
@@ -1868,9 +1869,10 @@ macro_rules! get_route_and_payment_hash {
                $crate::get_route_and_payment_hash!($send_node, $recv_node, payment_params, $recv_value)
        }};
        ($send_node: expr, $recv_node: expr, $payment_params: expr, $recv_value: expr) => {{
+               let route_params = $crate::routing::router::RouteParameters::from_payment_params_and_value($payment_params, $recv_value);
                let (payment_preimage, payment_hash, payment_secret) =
                        $crate::ln::functional_test_utils::get_payment_preimage_hash(&$recv_node, Some($recv_value), None);
-               let route = $crate::ln::functional_test_utils::get_route(&$send_node, &$payment_params, $recv_value);
+               let route = $crate::ln::functional_test_utils::get_route(&$send_node, &route_params);
                (route.unwrap(), payment_hash, payment_preimage, payment_secret)
        }}
 }
@@ -2464,7 +2466,8 @@ 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(), TEST_FINAL_CLTV)
                .with_bolt11_features(expected_route.last().unwrap().node.invoice_features()).unwrap();
-       let route = get_route(origin_node, &payment_params, recv_value).unwrap();
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value);
+       let route = get_route(origin_node, &route_params).unwrap();
        assert_eq!(route.paths.len(), 1);
        assert_eq!(route.paths[0].hops.len(), expected_route.len());
        for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) {
@@ -2478,14 +2481,14 @@ 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(), TEST_FINAL_CLTV)
                .with_bolt11_features(expected_route.last().unwrap().node.invoice_features()).unwrap();
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, recv_value);
        let network_graph = origin_node.network_graph.read_only();
        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();
-       let route = router::get_route(
-               &origin_node.node.get_our_node_id(), &payment_params, &network_graph,
-               None, recv_value, origin_node.logger, &scorer, &(), &random_seed_bytes).unwrap();
+       let route = router::get_route(&origin_node.node.get_our_node_id(), &route_params, &network_graph,
+               None, origin_node.logger, &scorer, &(), &random_seed_bytes).unwrap();
        assert_eq!(route.paths.len(), 1);
        assert_eq!(route.paths[0].hops.len(), expected_route.len());
        for (node, hop) in expected_route.iter().zip(route.paths[0].hops.iter()) {
index d3401e5f0681a73c77157f9756169fe4c9229158..8c71e5bd93c5851534505c6480d4084cb6d5f0c8 100644 (file)
@@ -26,7 +26,7 @@ use crate::ln::channel::{DISCONNECT_PEER_AWAITING_RESPONSE_TICKS, ChannelError};
 use crate::ln::{chan_utils, onion_utils};
 use crate::ln::chan_utils::{OFFERED_HTLC_SCRIPT_WEIGHT, htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment};
 use crate::routing::gossip::{NetworkGraph, NetworkUpdate};
-use crate::routing::router::{Path, PaymentParameters, Route, RouteHop, get_route};
+use crate::routing::router::{Path, PaymentParameters, Route, RouteHop, get_route, RouteParameters};
 use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, NodeFeatures};
 use crate::ln::msgs;
 use crate::ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction};
@@ -7137,8 +7137,11 @@ fn test_check_htlc_underpaying() {
 
        let scorer = test_utils::TestScorer::new();
        let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
-       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV).with_bolt11_features(nodes[1].node.invoice_features()).unwrap();
-       let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None, 10_000, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(),
+               TEST_FINAL_CLTV).with_bolt11_features(nodes[1].node.invoice_features()).unwrap();
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, 10_000);
+       let route = get_route(&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(),
+               None, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
        let (_, our_payment_hash, _) = get_payment_preimage_hash!(nodes[0]);
        let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200, None).unwrap();
        nodes[0].node.send_payment_with_route(&route, our_payment_hash,
@@ -7394,12 +7397,14 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), 50).with_bolt11_features(nodes[1].node.invoice_features()).unwrap();
        let scorer = test_utils::TestScorer::new();
        let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
-       let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None,
-               3_000_000, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, 3_000_000);
+       let route = get_route(&nodes[0].node.get_our_node_id(), &route_params, &nodes[0].network_graph.read_only(), None,
+               nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
        let payment_preimage = send_along_route(&nodes[0], route, &[&nodes[1]], 3_000_000).0;
        let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), 50).with_bolt11_features(nodes[0].node.invoice_features()).unwrap();
-       let route = get_route(&nodes[1].node.get_our_node_id(), &payment_params, &nodes[1].network_graph.read_only(), None,
-               3_000_000, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, 3_000_000);
+       let route = get_route(&nodes[1].node.get_our_node_id(), &route_params, &nodes[1].network_graph.read_only(), None,
+               nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
        send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000);
 
        let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan.2);
index d326c1aab74441f1203f532ea48a333b85f8c375..469517b02ba3e32589ffc5d428a15bb8b455a81f 100644 (file)
@@ -19,7 +19,7 @@ use crate::ln::channel::EXPIRE_PREV_CONFIG_TICKS;
 use crate::ln::channelmanager::{HTLCForwardInfo, FailureCode, CLTV_FAR_FAR_AWAY, DISABLE_GOSSIP_TICKS, MIN_CLTV_EXPIRY_DELTA, PendingAddHTLCInfo, PendingHTLCInfo, PendingHTLCRouting, PaymentId, RecipientOnionFields};
 use crate::ln::onion_utils;
 use crate::routing::gossip::{NetworkUpdate, RoutingFees};
-use crate::routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop};
+use crate::routing::router::{get_route, PaymentParameters, Route, RouteParameters, RouteHint, RouteHintHop};
 use crate::ln::features::{InitFeatures, Bolt11InvoiceFeatures};
 use crate::ln::msgs;
 use crate::ln::msgs::{ChannelMessageHandler, ChannelUpdate};
@@ -1048,10 +1048,11 @@ macro_rules! get_phantom_route {
                ])]).unwrap();
                let scorer = test_utils::TestScorer::new();
                let network_graph = $nodes[0].network_graph.read_only();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, $amt);
                (get_route(
-                       &$nodes[0].node.get_our_node_id(), &payment_params, &network_graph,
+                       &$nodes[0].node.get_our_node_id(), &route_params, &network_graph,
                        Some(&$nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
-                       $amt, $nodes[0].logger, &scorer, &(), &[0u8; 32]
+                       $nodes[0].logger, &scorer, &(), &[0u8; 32]
                ).unwrap(), phantom_route_hint.phantom_scid)
        }
 }}
index f60bf565efa35ddadac28416f2a7da22233d4892..38ae89aec6b02187c7181c0bad1bf939e0cb2beb 100644 (file)
@@ -1565,10 +1565,7 @@ mod tests {
                                PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()),
                                0
                        ).with_expiry_time(past_expiry_time);
-               let expired_route_params = RouteParameters {
-                       payment_params,
-                       final_value_msat: 0,
-               };
+               let expired_route_params = RouteParameters::from_payment_params_and_value(payment_params, 0);
                let pending_events = Mutex::new(VecDeque::new());
                if on_retry {
                        outbound_payments.add_new_pending_payment(PaymentHash([0; 32]), RecipientOnionFields::spontaneous_empty(),
@@ -1609,10 +1606,7 @@ mod tests {
 
                let payment_params = PaymentParameters::from_node_id(
                        PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0);
-               let route_params = RouteParameters {
-                       payment_params,
-                       final_value_msat: 0,
-               };
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 0);
                router.expect_find_route(route_params.clone(),
                        Err(LightningError { err: String::new(), action: ErrorAction::IgnoreError }));
 
@@ -1652,10 +1646,7 @@ mod tests {
                let sender_pk = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
                let receiver_pk = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[43; 32]).unwrap());
                let payment_params = PaymentParameters::from_node_id(sender_pk, 0);
-               let route_params = RouteParameters {
-                       payment_params: payment_params.clone(),
-                       final_value_msat: 0,
-               };
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params.clone(), 0);
                let failed_scid = 42;
                let route = Route {
                        paths: vec![Path { hops: vec![RouteHop {
index f0c3fa92d37c4b07f3c40d641e011e70d8b87c2e..f8000423b565748e96794e6e3aedfb8a102916a8 100644 (file)
@@ -94,10 +94,7 @@ fn mpp_retry() {
 
        // Initiate the MPP payment.
        let payment_id = PaymentId(payment_hash.0);
-       let mut route_params = RouteParameters {
-               payment_params: route.payment_params.clone().unwrap(),
-               final_value_msat: amt_msat,
-       };
+       let mut route_params = RouteParameters::from_payment_params_and_value(route.payment_params.clone().unwrap(), amt_msat);
 
        nodes[0].router.expect_find_route(route_params.clone(), Ok(route.clone()));
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
@@ -257,10 +254,8 @@ fn do_test_keysend_payments(public_node: bool, with_retry: bool) {
        }
        let payer_pubkey = nodes[0].node.get_our_node_id();
        let payee_pubkey = nodes[1].node.get_our_node_id();
-       let route_params = RouteParameters {
-               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, false),
-               final_value_msat: 10000,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(
+               PaymentParameters::for_keysend(payee_pubkey, 40, false), 10000);
 
        let network_graph = nodes[0].network_graph.clone();
        let channels = nodes[0].node.list_usable_channels();
@@ -319,10 +314,8 @@ fn test_mpp_keysend() {
        let payer_pubkey = nodes[0].node.get_our_node_id();
        let payee_pubkey = nodes[3].node.get_our_node_id();
        let recv_value = 15_000_000;
-       let route_params = RouteParameters {
-               payment_params: PaymentParameters::for_keysend(payee_pubkey, 40, true),
-               final_value_msat: recv_value,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(
+               PaymentParameters::for_keysend(payee_pubkey, 40, true), recv_value);
        let scorer = test_utils::TestScorer::new();
        let random_seed_bytes = chanmon_cfgs[0].keys_manager.get_secure_random_bytes();
        let route = find_route(&payer_pubkey, &route_params, &network_graph, None, nodes[0].logger,
@@ -531,10 +524,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
        let amt_msat = 1_000_000;
        let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat);
        let (payment_preimage_1, payment_hash_1, _, payment_id_1) = send_along_route(&nodes[0], route.clone(), &[&nodes[1], &nodes[2]], 1_000_000);
-       let route_params = RouteParameters {
-               payment_params: route.payment_params.clone().unwrap(),
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(route.payment_params.clone().unwrap(), amt_msat);
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
                PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
        check_added_monitors!(nodes[0], 1);
@@ -1111,10 +1101,11 @@ fn get_ldk_payment_preimage() {
        let scorer = test_utils::TestScorer::new();
        let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
        let random_seed_bytes = keys_manager.get_secure_random_bytes();
-       let route = get_route(
-               &nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(),
-               Some(&nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
-               amt_msat, nodes[0].logger, &scorer, &(), &random_seed_bytes).unwrap();
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
+       let route = get_route( &nodes[0].node.get_our_node_id(), &route_params,
+               &nodes[0].network_graph.read_only(),
+               Some(&nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()), nodes[0].logger,
+               &scorer, &(), &random_seed_bytes).unwrap();
        nodes[0].node.send_payment_with_route(&route, payment_hash,
                RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)).unwrap();
        check_added_monitors!(nodes[0], 1);
@@ -1224,7 +1215,7 @@ fn failed_probe_yields_event() {
 
        let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42);
 
-       let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], &payment_params, 9_998_000);
+       let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], payment_params, 9_998_000);
 
        let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap();
 
@@ -1273,7 +1264,7 @@ fn onchain_failed_probe_yields_event() {
        let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), 42);
 
        // Send a dust HTLC, which will be treated as if it timed out once the channel hits the chain.
-       let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], &payment_params, 1_000);
+       let (route, _, _, _) = get_route_and_payment_hash!(&nodes[0], nodes[2], payment_params, 1_000);
        let (payment_hash, payment_id) = nodes[0].node.send_probe(route.paths[0].clone()).unwrap();
 
        // node[0] -- update_add_htlcs -> node[1]
@@ -1661,15 +1652,10 @@ fn do_test_intercepted_payment(test: InterceptTest) {
                        }])
                ]).unwrap()
                .with_bolt11_features(nodes[2].node.invoice_features()).unwrap();
-       let route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
-       let route = get_route(
-               &nodes[0].node.get_our_node_id(), &route_params.payment_params,
-               &nodes[0].network_graph.read_only(), None, route_params.final_value_msat,
-               nodes[0].logger, &scorer, &(), &random_seed_bytes,
-       ).unwrap();
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat,);
+       let route = get_route( &nodes[0].node.get_our_node_id(), &route_params,
+               &nodes[0].network_graph.read_only(), None, nodes[0].logger, &scorer, &(),
+               &random_seed_bytes,).unwrap();
 
        let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap();
        nodes[0].node.send_payment_with_route(&route, payment_hash,
@@ -1850,10 +1836,7 @@ fn do_accept_underpaying_htlcs_config(num_mpp_parts: usize) {
        let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_route_hints(route_hints).unwrap()
                .with_bolt11_features(nodes[2].node.invoice_features()).unwrap();
-       let route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
        let (payment_hash, payment_secret) = nodes[2].node.create_inbound_payment(Some(amt_msat), 60 * 60, None).unwrap();
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
                PaymentId(payment_hash.0), route_params, Retry::Attempts(0)).unwrap();
@@ -1980,10 +1963,7 @@ fn do_automatic_retries(test: AutoRetry) {
        let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_bolt11_features(invoice_features).unwrap();
-       let route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
        let (_, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], amt_msat);
 
        macro_rules! pass_failed_attempt_with_retry_along_path {
@@ -2199,10 +2179,7 @@ fn auto_retry_partial_failure() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_bolt11_features(invoice_features).unwrap();
-       let route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
 
        // Ensure the first monitor update (for the initial send path1 over chan_1) succeeds, but the
        // second (for the initial send path2 over chan_2) fails.
@@ -2273,14 +2250,14 @@ fn auto_retry_partial_failure() {
        nodes[0].router.expect_find_route(route_params.clone(), Ok(send_route));
        let mut payment_params = route_params.payment_params.clone();
        payment_params.previously_failed_channels.push(chan_2_id);
-       nodes[0].router.expect_find_route(RouteParameters {
-                       payment_params, final_value_msat: amt_msat / 2,
-               }, Ok(retry_1_route));
+       nodes[0].router.expect_find_route(
+               RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 2),
+               Ok(retry_1_route));
        let mut payment_params = route_params.payment_params.clone();
        payment_params.previously_failed_channels.push(chan_3_id);
-       nodes[0].router.expect_find_route(RouteParameters {
-                       payment_params, final_value_msat: amt_msat / 4,
-               }, Ok(retry_2_route));
+       nodes[0].router.expect_find_route(
+               RouteParameters::from_payment_params_and_value(payment_params, amt_msat / 4),
+               Ok(retry_2_route));
 
        // Send a payment that will partially fail on send, then partially fail on retry, then succeed.
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
@@ -2416,10 +2393,7 @@ fn auto_retry_zero_attempts_send_error() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_bolt11_features(invoice_features).unwrap();
-       let route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
 
        chanmon_cfgs[0].persister.set_update_ret(ChannelMonitorUpdateStatus::PermanentFailure);
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
@@ -2456,10 +2430,7 @@ fn fails_paying_after_rejected_by_payee() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_bolt11_features(invoice_features).unwrap();
-       let route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
 
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
                PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
@@ -2503,10 +2474,8 @@ fn retry_multi_path_single_failed_payment() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_bolt11_features(invoice_features).unwrap();
-       let route_params = RouteParameters {
-               payment_params: payment_params.clone(),
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(
+               payment_params.clone(), amt_msat);
 
        let chans = nodes[0].node.list_usable_channels();
        let mut route = Route {
@@ -2536,12 +2505,11 @@ fn retry_multi_path_single_failed_payment() {
        route.paths[1].hops[0].fee_msat = 50_000_000;
        let mut pay_params = route.payment_params.clone().unwrap();
        pay_params.previously_failed_channels.push(chans[1].short_channel_id.unwrap());
-       nodes[0].router.expect_find_route(RouteParameters {
-                       payment_params: pay_params,
-                       // Note that the second request here requests the amount we originally failed to send,
-                       // not the amount remaining on the full payment, which should be changed.
-                       final_value_msat: 100_000_001,
-               }, Ok(route.clone()));
+       nodes[0].router.expect_find_route(
+               // Note that the second request here requests the amount we originally failed to send,
+               // not the amount remaining on the full payment, which should be changed.
+               RouteParameters::from_payment_params_and_value(pay_params, 100_000_001),
+               Ok(route.clone()));
 
        {
                let scorer = chanmon_cfgs[0].scorer.read().unwrap();
@@ -2596,10 +2564,7 @@ fn immediate_retry_on_failure() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_bolt11_features(invoice_features).unwrap();
-       let route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
 
        let chans = nodes[0].node.list_usable_channels();
        let mut route = Route {
@@ -2623,9 +2588,9 @@ fn immediate_retry_on_failure() {
        route.paths[1].hops[0].fee_msat = 50_000_001;
        let mut pay_params = route_params.payment_params.clone();
        pay_params.previously_failed_channels.push(chans[0].short_channel_id.unwrap());
-       nodes[0].router.expect_find_route(RouteParameters {
-                       payment_params: pay_params, final_value_msat: amt_msat,
-               }, Ok(route.clone()));
+       nodes[0].router.expect_find_route(
+               RouteParameters::from_payment_params_and_value(pay_params, amt_msat),
+               Ok(route.clone()));
 
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
                PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
@@ -2684,10 +2649,7 @@ fn no_extra_retries_on_back_to_back_fail() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_bolt11_features(invoice_features).unwrap();
-       let route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
 
        let mut route = Route {
                paths: vec![
@@ -2730,10 +2692,9 @@ fn no_extra_retries_on_back_to_back_fail() {
        // On retry, we'll only return one path
        route.paths.remove(1);
        route.paths[0].hops[1].fee_msat = amt_msat;
-       nodes[0].router.expect_find_route(RouteParameters {
-                       payment_params: second_payment_params,
-                       final_value_msat: amt_msat,
-               }, Ok(route.clone()));
+       nodes[0].router.expect_find_route(
+               RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat),
+               Ok(route.clone()));
 
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
                PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
@@ -2886,10 +2847,7 @@ fn test_simple_partial_retry() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_bolt11_features(invoice_features).unwrap();
-       let route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
 
        let mut route = Route {
                paths: vec![
@@ -2931,10 +2889,9 @@ fn test_simple_partial_retry() {
        second_payment_params.previously_failed_channels = vec![chan_2_scid];
        // On retry, we'll only be asked for one path (or 100k sats)
        route.paths.remove(0);
-       nodes[0].router.expect_find_route(RouteParameters {
-                       payment_params: second_payment_params,
-                       final_value_msat: amt_msat / 2,
-               }, Ok(route.clone()));
+       nodes[0].router.expect_find_route(
+               RouteParameters::from_payment_params_and_value(second_payment_params, amt_msat / 2),
+               Ok(route.clone()));
 
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields::secret_only(payment_secret),
                PaymentId(payment_hash.0), route_params, Retry::Attempts(1)).unwrap();
@@ -3052,10 +3009,7 @@ fn test_threaded_payment_retries() {
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_expiry_time(payment_expiry_secs as u64)
                .with_bolt11_features(invoice_features).unwrap();
-       let mut route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
 
        let mut route = Route {
                paths: vec![
@@ -3303,11 +3257,10 @@ fn do_claim_from_closed_chan(fail_payment: bool) {
        create_announced_chan_between_nodes(&nodes, 2, 3);
 
        let (payment_preimage, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[3]);
-       let mut route_params = RouteParameters {
-               payment_params: PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
+       let mut route_params = RouteParameters::from_payment_params_and_value(
+               PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
                        .with_bolt11_features(nodes[1].node.invoice_features()).unwrap(),
-               final_value_msat: 10_000_000,
-       };
+               10_000_000);
        let mut route = nodes[0].router.find_route(&nodes[0].node.get_our_node_id(), &route_params,
                None, nodes[0].node.compute_inflight_htlcs()).unwrap();
        // Make sure the route is ordered as the B->D path before C->D
@@ -3517,10 +3470,7 @@ fn test_retry_custom_tlvs() {
 
        // Initiate the payment
        let payment_id = PaymentId(payment_hash.0);
-       let mut route_params = RouteParameters {
-               payment_params: route.payment_params.clone().unwrap(),
-               final_value_msat: amt_msat,
-       };
+       let mut route_params = RouteParameters::from_payment_params_and_value(route.payment_params.clone().unwrap(), amt_msat);
 
        let custom_tlvs = vec![((1 << 16) + 1, vec![0x42u8; 16])];
        let onion_fields = RecipientOnionFields::secret_only(payment_secret);
@@ -3772,10 +3722,7 @@ fn do_test_payment_metadata_consistency(do_reload: bool, do_modify: bool) {
 
        let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id(), TEST_FINAL_CLTV)
                .with_bolt11_features(nodes[1].node.invoice_features()).unwrap();
-       let mut route_params = RouteParameters {
-               payment_params,
-               final_value_msat: amt_msat,
-       };
+       let mut route_params = RouteParameters::from_payment_params_and_value(payment_params, amt_msat);
 
        // Send the MPP payment, delivering the updated commitment state to nodes[1].
        nodes[0].node.send_payment(payment_hash, RecipientOnionFields {
index f975e18412967bc07a6058572091cf0377eead1f..38db58c5549bb3381c1808e97d91c368e0f77a73 100644 (file)
@@ -13,7 +13,7 @@ use crate::sign::{EntropySource, SignerProvider};
 use crate::chain::transaction::OutPoint;
 use crate::events::{Event, MessageSendEvent, MessageSendEventsProvider, ClosureReason};
 use crate::ln::channelmanager::{self, PaymentSendFailure, PaymentId, RecipientOnionFields, ChannelShutdownState, ChannelDetails};
-use crate::routing::router::{PaymentParameters, get_route};
+use crate::routing::router::{PaymentParameters, get_route, RouteParameters};
 use crate::ln::msgs;
 use crate::ln::msgs::{ChannelMessageHandler, ErrorAction};
 use crate::ln::script::ShutdownScript;
@@ -313,9 +313,14 @@ fn updates_shutdown_wait() {
        let (_, payment_hash, payment_secret) = get_payment_preimage_hash!(nodes[0]);
 
        let payment_params_1 = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id(), TEST_FINAL_CLTV).with_bolt11_features(nodes[1].node.invoice_features()).unwrap();
-       let route_1 = get_route(&nodes[0].node.get_our_node_id(), &payment_params_1, &nodes[0].network_graph.read_only(), None, 100000, &logger, &scorer, &(), &random_seed_bytes).unwrap();
-       let payment_params_2 = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(), TEST_FINAL_CLTV).with_bolt11_features(nodes[0].node.invoice_features()).unwrap();
-       let route_2 = get_route(&nodes[1].node.get_our_node_id(), &payment_params_2, &nodes[1].network_graph.read_only(), None, 100000, &logger, &scorer, &(), &random_seed_bytes).unwrap();
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params_1, 100_000);
+       let route_1 = get_route(&nodes[0].node.get_our_node_id(), &route_params,
+               &nodes[0].network_graph.read_only(), None, &logger, &scorer, &(), &random_seed_bytes).unwrap();
+       let payment_params_2 = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id(),
+               TEST_FINAL_CLTV).with_bolt11_features(nodes[0].node.invoice_features()).unwrap();
+       let route_params = RouteParameters::from_payment_params_and_value(payment_params_2, 100_000);
+       let route_2 = get_route(&nodes[1].node.get_our_node_id(), &route_params,
+               &nodes[1].network_graph.read_only(), None, &logger, &scorer, &(), &random_seed_bytes).unwrap();
        unwrap_send_err!(nodes[0].node.send_payment_with_route(&route_1, payment_hash,
                        RecipientOnionFields::secret_only(payment_secret), PaymentId(payment_hash.0)
                ), true, APIError::ChannelUnavailable {..}, {});
index a279568cda8d77b38bafe478ff450e498283d641..799b6407981341b0bc4fbfae0f387bdbe23186ad 100644 (file)
@@ -1407,19 +1407,21 @@ pub fn find_route<L: Deref, GL: Deref, S: ScoreLookUp>(
 ) -> Result<Route, LightningError>
 where L::Target: Logger, GL::Target: Logger {
        let graph_lock = network_graph.read_only();
-       let mut route = get_route(our_node_pubkey, &route_params.payment_params, &graph_lock, first_hops,
-               route_params.final_value_msat, logger, scorer, score_params,
-               random_seed_bytes)?;
+       let mut route = get_route(our_node_pubkey, &route_params, &graph_lock, first_hops, logger,
+               scorer, score_params, random_seed_bytes)?;
        add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
        Ok(route)
 }
 
 pub(crate) fn get_route<L: Deref, S: ScoreLookUp>(
-       our_node_pubkey: &PublicKey, payment_params: &PaymentParameters, network_graph: &ReadOnlyNetworkGraph,
-       first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, logger: L, scorer: &S, score_params: &S::ScoreParams,
+       our_node_pubkey: &PublicKey, route_params: &RouteParameters, network_graph: &ReadOnlyNetworkGraph,
+       first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, score_params: &S::ScoreParams,
        _random_seed_bytes: &[u8; 32]
 ) -> Result<Route, LightningError>
 where L::Target: Logger {
+
+       let payment_params = &route_params.payment_params;
+       let final_value_msat = route_params.final_value_msat;
        // If we're routing to a blinded recipient, we won't have their node id. Therefore, keep the
        // unblinded payee id as an option. We also need a non-optional "payee id" for path construction,
        // so use a dummy id for this in the blinded case.
@@ -2592,17 +2594,15 @@ pub fn build_route_from_hops<L: Deref, GL: Deref>(
 ) -> Result<Route, LightningError>
 where L::Target: Logger, GL::Target: Logger {
        let graph_lock = network_graph.read_only();
-       let mut route = build_route_from_hops_internal(
-               our_node_pubkey, hops, &route_params.payment_params, &graph_lock,
-               route_params.final_value_msat, logger, random_seed_bytes)?;
+       let mut route = build_route_from_hops_internal(our_node_pubkey, hops, &route_params,
+               &graph_lock, logger, random_seed_bytes)?;
        add_random_cltv_offset(&mut route, &route_params.payment_params, &graph_lock, random_seed_bytes);
        Ok(route)
 }
 
 fn build_route_from_hops_internal<L: Deref>(
-       our_node_pubkey: &PublicKey, hops: &[PublicKey], payment_params: &PaymentParameters,
-       network_graph: &ReadOnlyNetworkGraph, final_value_msat: u64, logger: L,
-       random_seed_bytes: &[u8; 32]
+       our_node_pubkey: &PublicKey, hops: &[PublicKey], route_params: &RouteParameters,
+       network_graph: &ReadOnlyNetworkGraph, logger: L, random_seed_bytes: &[u8; 32],
 ) -> Result<Route, LightningError> where L::Target: Logger {
 
        struct HopScorer {
@@ -2649,8 +2649,7 @@ fn build_route_from_hops_internal<L: Deref>(
 
        let scorer = HopScorer { our_node_id, hop_ids };
 
-       get_route(our_node_pubkey, payment_params, network_graph, None, final_value_msat,
-               logger, &scorer, &(), random_seed_bytes)
+       get_route(our_node_pubkey, route_params, network_graph, None, logger, &scorer, &(), random_seed_bytes)
 }
 
 #[cfg(test)]
@@ -2660,7 +2659,7 @@ mod tests {
        use crate::routing::utxo::UtxoResult;
        use crate::routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features,
                BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees,
-               DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE};
+               DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE, RouteParameters};
        use crate::routing::scoring::{ChannelUsage, FixedPenaltyScorer, ScoreLookUp, ProbabilisticScorer, ProbabilisticScoringFeeParameters, ProbabilisticScoringDecayParameters};
        use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
        use crate::chain::transaction::OutPoint;
@@ -2743,11 +2742,17 @@ mod tests {
 
                // Simple route to 2 via 1
 
-               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 0, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                       assert_eq!(err, "Cannot send a payment of 0 msat");
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params.clone(), 0);
+               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id,
+                       &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes) {
+                               assert_eq!(err, "Cannot send a payment of 0 msat");
                } else { panic!(); }
 
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 2);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@@ -2778,12 +2783,15 @@ mod tests {
 
                let our_chans = vec![get_channel_details(Some(2), our_id, InitFeatures::from_le_bytes(vec![0b11]), 100000)];
 
-               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) =
-                       get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                       assert_eq!(err, "First hop cannot have our_node_pubkey as a destination.");
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id,
+                       &route_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()),
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
+                               assert_eq!(err, "First hop cannot have our_node_pubkey as a destination.");
                } else { panic!(); }
-
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 2);
        }
 
@@ -2891,8 +2899,12 @@ mod tests {
                });
 
                // Not possible to send 199_999_999, because the minimum on channel=2 is 200_000_000.
-               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                       assert_eq!(err, "Failed to find a path to the given destination");
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, 199_999_999);
+               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id,
+                       &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes) {
+                               assert_eq!(err, "Failed to find a path to the given destination");
                } else { panic!(); }
 
                // Lift the restriction on the first hop.
@@ -2910,7 +2922,8 @@ mod tests {
                });
 
                // A payment above the minimum should pass
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 2);
        }
 
@@ -2992,7 +3005,10 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params.clone(), 60_000);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                // Overpay fees to hit htlc_minimum_msat.
                let overpaid_fees = route.paths[0].hops[0].fee_msat + route.paths[1].hops[0].fee_msat;
                // TODO: this could be better balanced to overpay 10k and not 15k.
@@ -3037,14 +3053,17 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                // Fine to overpay for htlc_minimum_msat if it allows us to save fee.
                assert_eq!(route.paths.len(), 1);
                assert_eq!(route.paths[0].hops[0].short_channel_id, 12);
                let fees = route.paths[0].hops[0].fee_msat;
                assert_eq!(fees, 5_000);
 
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 50_000);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                // Not fine to overpay for htlc_minimum_msat if it requires paying more than fee on
                // the other channel.
                assert_eq!(route.paths.len(), 1);
@@ -3089,13 +3108,19 @@ mod tests {
                });
 
                // If all the channels require some features we don't understand, route should fail
-               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                       assert_eq!(err, "Failed to find a path to the given destination");
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id,
+                       &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes) {
+                               assert_eq!(err, "Failed to find a path to the given destination");
                } else { panic!(); }
 
                // If we specify a channel to node7, that overrides our local channel view and that gets used
-               let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(),
+                       InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(),
+                       Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 2);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
@@ -3130,13 +3155,19 @@ mod tests {
                add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[7], unknown_features.clone(), 1);
 
                // If all nodes require some features we don't understand, route should fail
-               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                       assert_eq!(err, "Failed to find a path to the given destination");
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id,
+                       &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes) {
+                               assert_eq!(err, "Failed to find a path to the given destination");
                } else { panic!(); }
 
                // If we specify a channel to node7, that overrides our local channel view and that gets used
-               let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(),
+                       InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(),
+                       Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 2);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
@@ -3168,7 +3199,9 @@ mod tests {
 
                // Route to 1 via 2 and 3 because our channel to 1 is disabled
                let payment_params = PaymentParameters::from_node_id(nodes[0], 42);
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 3);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@@ -3194,8 +3227,12 @@ mod tests {
 
                // If we specify a channel to node7, that overrides our local channel view and that gets used
                let payment_params = PaymentParameters::from_node_id(nodes[2], 42);
-               let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(),
+                       InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(),
+                       Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 2);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[7]);
@@ -3317,14 +3354,21 @@ mod tests {
                let mut invalid_last_hops = last_hops_multi_private_channels(&nodes);
                invalid_last_hops.push(invalid_last_hop);
                {
-                       let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(invalid_last_hops).unwrap();
-                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Route hint cannot have the payee as the source.");
+                       let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
+                               .with_route_hints(invalid_last_hops).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id,
+                               &route_params, &network_graph.read_only(), None, Arc::clone(&logger), &scorer, &(),
+                               &random_seed_bytes) {
+                                       assert_eq!(err, "Route hint cannot have the payee as the source.");
                        } else { panic!(); }
                }
 
-               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap();
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
+                       .with_route_hints(last_hops_multi_private_channels(&nodes)).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 5);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@@ -3399,8 +3443,9 @@ mod tests {
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
                // Test handling of an empty RouteHint passed in Invoice.
-
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 5);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@@ -3506,7 +3551,9 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 4);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@@ -3578,7 +3625,9 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &[42u8; 32]).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &[42u8; 32]).unwrap();
                assert_eq!(route.paths[0].hops.len(), 4);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@@ -3660,7 +3709,9 @@ mod tests {
                // This test shows that public routes can be present in the invoice
                // which would be handled in the same manner.
 
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 5);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@@ -3712,8 +3763,12 @@ mod tests {
                // Simple test with outbound channel to 4 to test that last_hops and first_hops connect
                let our_chans = vec![get_channel_details(Some(42), nodes[3].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
                let mut last_hops = last_hops(&nodes);
-               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops.clone()).unwrap();
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
+                       .with_route_hints(last_hops.clone()).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(),
+                       Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 2);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[3]);
@@ -3733,8 +3788,12 @@ mod tests {
                last_hops[0].0[0].fees.base_msat = 1000;
 
                // Revert to via 6 as the fee on 8 goes up
-               let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops).unwrap();
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let payment_params = PaymentParameters::from_node_id(nodes[6], 42)
+                       .with_route_hints(last_hops).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params.clone(), 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 4);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@@ -3768,7 +3827,9 @@ mod tests {
                assert_eq!(route.paths[0].hops[3].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
 
                // ...but still use 8 for larger payments as 6 has a variable feerate
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 2000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 2000);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].hops.len(), 5);
 
                assert_eq!(route.paths[0].hops[0].pubkey, nodes[1]);
@@ -3833,8 +3894,10 @@ mod tests {
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let logger = ln_test_utils::TestLogger::new();
                let network_graph = NetworkGraph::new(Network::Testnet, &logger);
-               let route = get_route(&source_node_id, &payment_params, &network_graph.read_only(),
-                               Some(&our_chans.iter().collect::<Vec<_>>()), route_val, &logger, &scorer, &(), &random_seed_bytes);
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, route_val);
+               let route = get_route(&source_node_id, &route_params, &network_graph.read_only(),
+                               Some(&our_chans.iter().collect::<Vec<_>>()), &logger, &scorer, &(),
+                               &random_seed_bytes);
                route
        }
 
@@ -3955,15 +4018,21 @@ mod tests {
 
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 250_000_001);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), None, 250_000_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                                       &our_id, &route_params, &network_graph.read_only(), None,
+                                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
+                                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
                }
 
                {
                        // Now, attempt to route an exact amount we have should be fine.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 250_000_000, Arc::clone(&logger), &scorer, &(),&random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 250_000_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(),&random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.hops.len(), 2);
@@ -3991,15 +4060,23 @@ mod tests {
 
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 200_000_001);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                                       &our_id, &route_params, &network_graph.read_only(),
+                                       Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer,
+                                       &(), &random_seed_bytes) {
+                                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
                }
 
                {
                        // Now, attempt to route an exact amount we have should be fine.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 200_000_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(),
+                               Some(&our_chans.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
+                               &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.hops.len(), 2);
@@ -4038,15 +4115,21 @@ mod tests {
 
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 15_001);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                                       &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
+                                       &scorer, &(), &random_seed_bytes) {
+                                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
                }
 
                {
                        // Now, attempt to route an exact amount we have should be fine.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 15_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.hops.len(), 2);
@@ -4109,15 +4192,21 @@ mod tests {
 
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 15_001);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), None, 15_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                                       &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
+                                       &scorer, &(), &random_seed_bytes) {
+                                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
                }
 
                {
                        // Now, attempt to route an exact amount we have should be fine.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 15_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.hops.len(), 2);
@@ -4141,15 +4230,21 @@ mod tests {
 
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 10_001);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), None, 10_001, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                                       &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
+                                       &scorer, &(), &random_seed_bytes) {
+                                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
                }
 
                {
                        // Now, attempt to route an exact amount we have should be fine.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 10_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.hops.len(), 2);
@@ -4253,15 +4348,21 @@ mod tests {
                });
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 60_000);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), None, 60_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                                       &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
+                                       &scorer, &(), &random_seed_bytes) {
+                                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
                }
 
                {
                        // Now, attempt to route 49 sats (just a bit below the capacity).
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 49_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 49_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
@@ -4274,7 +4375,10 @@ mod tests {
 
                {
                        // Attempt to route an exact amount is also fine
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params, 50_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
@@ -4322,7 +4426,10 @@ mod tests {
                });
 
                {
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params, 50_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
@@ -4487,8 +4594,10 @@ mod tests {
 
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 300_000);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                               &our_id, &payment_params, &network_graph.read_only(), None, 300_000,
+                               &our_id, &route_params, &network_graph.read_only(), None,
                                Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
                                        assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
@@ -4497,8 +4606,10 @@ mod tests {
                {
                        // Attempt to route while setting max_path_count to 0 results in a failure.
                        let zero_payment_params = payment_params.clone().with_max_path_count(0);
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               zero_payment_params, 100);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                               &our_id, &zero_payment_params, &network_graph.read_only(), None, 100,
+                               &our_id, &route_params, &network_graph.read_only(), None,
                                Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
                                        assert_eq!(err, "Can't find a route with no paths allowed.");
                        } else { panic!(); }
@@ -4509,8 +4620,10 @@ mod tests {
                        // This is the case because the minimal_value_contribution_msat would require each path
                        // to account for 1/3 of the total value, which is violated by 2 out of 3 paths.
                        let fail_payment_params = payment_params.clone().with_max_path_count(3);
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               fail_payment_params, 250_000);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                               &our_id, &fail_payment_params, &network_graph.read_only(), None, 250_000,
+                               &our_id, &route_params, &network_graph.read_only(), None,
                                Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
                                        assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
@@ -4519,8 +4632,10 @@ mod tests {
                {
                        // Now, attempt to route 250 sats (just a bit below the capacity).
                        // Our algorithm should provide us with these 3 paths.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None,
-                               250_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 250_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 3);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
@@ -4537,8 +4652,10 @@ mod tests {
 
                {
                        // Attempt to route an exact amount is also fine
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None,
-                               290_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 290_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 3);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
@@ -4572,7 +4689,8 @@ mod tests {
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let config = UserConfig::default();
-               let payment_params = PaymentParameters::from_node_id(nodes[3], 42).with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap();
+               let payment_params = PaymentParameters::from_node_id(nodes[3], 42)
+                       .with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap();
 
                // We need a route consisting of 3 paths:
                // From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}.
@@ -4707,16 +4825,22 @@ mod tests {
 
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 350_000);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), None, 350_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                                       &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
+                                       &scorer, &(), &random_seed_bytes) {
+                                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
                }
 
                {
                        // Now, attempt to route 300 sats (exact amount we can route).
                        // Our algorithm should provide us with these 3 paths, 100 sats each.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 300_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params, 300_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 3);
 
                        let mut total_amount_paid_msat = 0;
@@ -4877,7 +5001,10 @@ mod tests {
                {
                        // Now, attempt to route 180 sats.
                        // Our algorithm should provide us with these 2 paths.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 180_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params, 180_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 2);
 
                        let mut total_value_transferred_msat = 0;
@@ -5047,15 +5174,20 @@ mod tests {
 
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 210_000);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), None, 210_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                                       &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
+                                       &scorer, &(), &random_seed_bytes) {
+                                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
                }
 
                {
                        // Now, attempt to route 200 sats (exact amount we can route).
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 200_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(payment_params, 200_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 2);
 
                        let mut total_amount_paid_msat = 0;
@@ -5155,7 +5287,10 @@ mod tests {
 
                // Get a route for 100 sats and check that we found the MPP route no problem and didn't
                // overpay at all.
-               let mut route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, 100_000);
+               let mut route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 2);
                route.paths.sort_by_key(|path| path.hops[0].short_channel_id);
                // Paths are manually ordered ordered by SCID, so:
@@ -5273,16 +5408,22 @@ mod tests {
 
                {
                        // Attempt to route more than available results in a failure.
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 150_000);
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), None, 150_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                                       &our_id, &route_params, &network_graph.read_only(), None, Arc::clone(&logger),
+                                       &scorer, &(), &random_seed_bytes) {
+                                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
                        } else { panic!(); }
                }
 
                {
                        // Now, attempt to route 125 sats (just a bit below the capacity of 3 channels).
                        // Our algorithm should provide us with these 3 paths.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 125_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 125_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 3);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
@@ -5295,7 +5436,10 @@ mod tests {
 
                {
                        // Attempt to route without the last small cheap channel
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params, 90_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 2);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
@@ -5434,7 +5578,10 @@ mod tests {
 
                {
                        // Now ensure the route flows simply over nodes 1 and 4 to 6.
-                       let route = get_route(&our_id, &payment_params, &network.read_only(), None, 10_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params, 10_000);
+                       let route = get_route(&our_id, &route_params, &network.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].hops.len(), 3);
 
@@ -5505,7 +5652,10 @@ mod tests {
                {
                        // Now, attempt to route 90 sats, which is exactly 90 sats at the last hop, plus the
                        // 200% fee charged channel 13 in the 1-to-2 direction.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params, 90_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].hops.len(), 2);
 
@@ -5571,7 +5721,10 @@ mod tests {
                        // Now, attempt to route 90 sats, hitting the htlc_minimum on channel 4, but
                        // overshooting the htlc_maximum on channel 2. Thus, we should pick the (absurdly
                        // expensive) channels 12-13 path.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params, 90_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].hops.len(), 2);
 
@@ -5610,10 +5763,12 @@ mod tests {
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
                {
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 100_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[
                                &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 200_000),
                                &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 10_000),
-                       ]), 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       ]), Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].hops.len(), 1);
 
@@ -5622,10 +5777,12 @@ mod tests {
                        assert_eq!(route.paths[0].hops[0].fee_msat, 100_000);
                }
                {
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 100_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[
                                &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000),
                                &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000),
-                       ]), 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       ]), Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 2);
                        assert_eq!(route.paths[0].hops.len(), 1);
                        assert_eq!(route.paths[1].hops.len(), 1);
@@ -5648,7 +5805,9 @@ mod tests {
                        // If we have several options above the 3xpayment value threshold, we should pick the
                        // smallest of them, avoiding further fragmenting our available outbound balance to
                        // this node.
-                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params, 100_000);
+                       let route = get_route(&our_id, &route_params, &network_graph.read_only(), Some(&[
                                &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000),
                                &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000),
                                &get_channel_details(Some(5), nodes[0], channelmanager::provided_init_features(&config), 50_000),
@@ -5657,7 +5816,7 @@ mod tests {
                                &get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(&config), 50_000),
                                &get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(&config), 50_000),
                                &get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(&config), 1_000_000),
-                       ]), 100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+                       ]), Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].hops.len(), 1);
 
@@ -5677,10 +5836,10 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let route = get_route(
-                       &our_id, &payment_params, &network_graph.read_only(), None, 100,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes
-               ).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params.clone(), 100);
+               let route = get_route( &our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
 
                assert_eq!(route.get_total_fees(), 100);
@@ -5690,10 +5849,10 @@ mod tests {
                // Applying a 100 msat penalty to each hop results in taking channels 7 and 10 to nodes[6]
                // from nodes[2] rather than channel 6, 11, and 8, even though the longer path is cheaper.
                let scorer = FixedPenaltyScorer::with_penalty(100);
-               let route = get_route(
-                       &our_id, &payment_params, &network_graph.read_only(), None, 100,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes
-               ).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, 100);
+               let route = get_route( &our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
 
                assert_eq!(route.get_total_fees(), 300);
@@ -5743,10 +5902,10 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::new();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let route = get_route(
-                       &our_id, &payment_params, &network_graph, None, 100,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes
-               ).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, 100);
+               let route = get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger),
+                       &scorer, &(), &random_seed_bytes).unwrap();
                let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
 
                assert_eq!(route.get_total_fees(), 100);
@@ -5755,10 +5914,8 @@ mod tests {
 
                // A different path to nodes[6] exists if channel 6 cannot be routed over.
                let scorer = BadChannelScorer { short_channel_id: 6 };
-               let route = get_route(
-                       &our_id, &payment_params, &network_graph, None, 100,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes
-               ).unwrap();
+               let route = get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger),
+                       &scorer, &(), &random_seed_bytes).unwrap();
                let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
 
                assert_eq!(route.get_total_fees(), 300);
@@ -5767,14 +5924,12 @@ mod tests {
 
                // A path to nodes[6] does not exist if nodes[2] cannot be routed through.
                let scorer = BadNodeScorer { node_id: NodeId::from_pubkey(&nodes[2]) };
-               match get_route(
-                       &our_id, &payment_params, &network_graph, None, 100,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes
-               ) {
-                       Err(LightningError { err, .. } ) => {
-                               assert_eq!(err, "Failed to find a path to the given destination");
-                       },
-                       Ok(_) => panic!("Expected error"),
+               match get_route( &our_id, &route_params, &network_graph, None, Arc::clone(&logger),
+                       &scorer, &(), &random_seed_bytes) {
+                               Err(LightningError { err, .. } ) => {
+                                       assert_eq!(err, "Failed to find a path to the given destination");
+                               },
+                               Ok(_) => panic!("Expected error"),
                }
        }
 
@@ -5863,7 +6018,10 @@ mod tests {
                        .with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta);
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       feasible_payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
+                       &scorer, &(), &random_seed_bytes).unwrap();
                let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
                assert_ne!(path.len(), 0);
 
@@ -5871,7 +6029,10 @@ mod tests {
                let fail_max_total_cltv_delta = 23;
                let fail_payment_params = PaymentParameters::from_node_id(nodes[6], 0).with_route_hints(last_hops(&nodes)).unwrap()
                        .with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta);
-               match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes)
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       fail_payment_params, 100);
+               match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
+                       &(), &random_seed_bytes)
                {
                        Err(LightningError { err, .. } ) => {
                                assert_eq!(err, "Failed to find a path to the given destination");
@@ -5896,9 +6057,16 @@ mod tests {
 
                // We should be able to find a route initially, and then after we fail a few random
                // channels eventually we won't be able to any longer.
-               assert!(get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).is_ok());
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params.clone(), 100);
+               assert!(get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
+                       &scorer, &(), &random_seed_bytes).is_ok());
                loop {
-                       if let Ok(route) = get_route(&our_id, &payment_params, &network_graph, None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes) {
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               payment_params.clone(), 100);
+                       if let Ok(route) = get_route(&our_id, &route_params, &network_graph, None,
+                               Arc::clone(&logger), &scorer, &(), &random_seed_bytes)
+                       {
                                for chan in route.paths[0].hops.iter() {
                                        assert!(!payment_params.previously_failed_channels.contains(&chan.short_channel_id));
                                }
@@ -5921,15 +6089,19 @@ mod tests {
 
                // First check we can actually create a long route on this graph.
                let feasible_payment_params = PaymentParameters::from_node_id(nodes[18], 0);
-               let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       feasible_payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
+                       &scorer, &(), &random_seed_bytes).unwrap();
                let path = route.paths[0].hops.iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
                assert!(path.len() == MAX_PATH_LENGTH_ESTIMATE.into());
 
                // But we can't create a path surpassing the MAX_PATH_LENGTH_ESTIMATE limit.
                let fail_payment_params = PaymentParameters::from_node_id(nodes[19], 0);
-               match get_route(&our_id, &fail_payment_params, &network_graph, None, 100,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes)
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       fail_payment_params, 100);
+               match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
+                       &(), &random_seed_bytes)
                {
                        Err(LightningError { err, .. } ) => {
                                assert_eq!(err, "Failed to find a path to the given destination");
@@ -5948,7 +6120,10 @@ mod tests {
                let payment_params = PaymentParameters::from_node_id(nodes[6], 42).with_route_hints(last_hops(&nodes)).unwrap();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params.clone(), 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 1);
 
                let cltv_expiry_deltas_before = route.paths[0].hops.iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
@@ -5982,8 +6157,10 @@ mod tests {
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[4u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
-               let mut route = get_route(&our_id, &payment_params, &network_graph, None, 100,
-                                                                 Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params.clone(), 100);
+               let mut route = get_route(&our_id, &route_params, &network_graph, None,
+                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
                add_random_cltv_offset(&mut route, &payment_params, &network_graph, &random_seed_bytes);
 
                let mut path_plausibility = vec![];
@@ -6047,8 +6224,9 @@ mod tests {
 
                let payment_params = PaymentParameters::from_node_id(nodes[3], 0);
                let hops = [nodes[1], nodes[2], nodes[4], nodes[3]];
-               let route = build_route_from_hops_internal(&our_id, &hops, &payment_params,
-                        &network_graph, 100, Arc::clone(&logger), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100);
+               let route = build_route_from_hops_internal(&our_id, &hops, &route_params, &network_graph,
+                       Arc::clone(&logger), &random_seed_bytes).unwrap();
                let route_hop_pubkeys = route.paths[0].hops.iter().map(|hop| hop.pubkey).collect::<Vec<_>>();
                assert_eq!(hops.len(), route.paths[0].hops.len());
                for (idx, hop_pubkey) in hops.iter().enumerate() {
@@ -6095,7 +6273,10 @@ mod tests {
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                // 100,000 sats is less than the available liquidity on each channel, set above.
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000_000, Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, 100_000_000);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &ProbabilisticScoringFeeParameters::default(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 2);
                assert!((route.paths[0].hops[1].short_channel_id == 4 && route.paths[1].hops[1].short_channel_id == 13) ||
                        (route.paths[1].hops[1].short_channel_id == 4 && route.paths[0].hops[1].short_channel_id == 13));
@@ -6196,17 +6377,22 @@ mod tests {
 
                // Then check we can get a normal route
                let payment_params = PaymentParameters::from_node_id(nodes[10], 42);
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, 100);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes);
                assert!(route.is_ok());
 
                // Then check that we can't get a route if we ban an intermediate node.
                scorer_params.add_banned(&NodeId::from_pubkey(&nodes[3]));
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes);
                assert!(route.is_err());
 
                // Finally make sure we can route again, when we remove the ban.
                scorer_params.remove_banned(&NodeId::from_pubkey(&nodes[3]));
-               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, Arc::clone(&logger), &scorer, &scorer_params,&random_seed_bytes);
+               let route = get_route(&our_id, &route_params, &network_graph.read_only(), None,
+                       Arc::clone(&logger), &scorer, &scorer_params, &random_seed_bytes);
                assert!(route.is_ok());
        }
 
@@ -6241,8 +6427,10 @@ mod tests {
 
                // Make sure we'll error if our route hints don't have enough liquidity according to their
                // htlc_maximum_msat.
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, max_htlc_msat + 1);
                if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id,
-                       &payment_params, &netgraph, None, max_htlc_msat + 1, Arc::clone(&logger), &scorer, &(),
+                       &route_params, &netgraph, None, Arc::clone(&logger), &scorer, &(),
                        &random_seed_bytes)
                {
                        assert_eq!(err, "Failed to find a sufficient route to the given destination");
@@ -6254,8 +6442,10 @@ mod tests {
                let payment_params = PaymentParameters::from_node_id(dest_node_id, 42)
                        .with_route_hints(vec![route_hint_1, route_hint_2]).unwrap()
                        .with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap();
-               let route = get_route(&our_id, &payment_params, &netgraph, None, max_htlc_msat + 1,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, max_htlc_msat + 1);
+               let route = get_route(&our_id, &route_params, &netgraph, None, Arc::clone(&logger),
+                       &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 2);
                assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
                assert!(route.paths[1].hops.last().unwrap().fee_msat <= max_htlc_msat);
@@ -6308,8 +6498,10 @@ mod tests {
                        .with_route_hints(vec![route_hint_1, route_hint_2]).unwrap()
                        .with_bolt11_features(channelmanager::provided_invoice_features(&config)).unwrap();
 
-               let route = get_route(&our_node_id, &payment_params, &network_graph.read_only(),
-                       Some(&first_hop.iter().collect::<Vec<_>>()), amt_msat, Arc::clone(&logger), &scorer, &(),
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, amt_msat);
+               let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
+                       Some(&first_hop.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
                        &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 2);
                assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
@@ -6322,8 +6514,8 @@ mod tests {
                        get_channel_details(Some(42), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), amt_msat - 10),
                        get_channel_details(Some(43), intermed_node_id, InitFeatures::from_le_bytes(vec![0b11]), amt_msat - 10),
                ];
-               let route = get_route(&our_node_id, &payment_params, &network_graph.read_only(),
-                       Some(&first_hops.iter().collect::<Vec<_>>()), amt_msat, Arc::clone(&logger), &scorer, &(),
+               let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
+                       Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
                        &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 2);
                assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
@@ -6352,8 +6544,10 @@ mod tests {
                        (blinded_payinfo.clone(), blinded_path.clone()),
                        (blinded_payinfo.clone(), blinded_path.clone())])
                        .with_bolt12_features(bolt12_features).unwrap();
-               let route = get_route(&our_node_id, &payment_params, &network_graph.read_only(),
-                       Some(&first_hops.iter().collect::<Vec<_>>()), amt_msat, Arc::clone(&logger), &scorer, &(),
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, amt_msat);
+               let route = get_route(&our_node_id, &route_params, &network_graph.read_only(),
+                       Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
                        &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 2);
                assert!(route.paths[0].hops.last().unwrap().fee_msat <= max_htlc_msat);
@@ -6542,9 +6736,10 @@ mod tests {
                        features: BlindedHopFeatures::empty(),
                };
 
-               let final_amt_msat = 1001;
                let payment_params = PaymentParameters::blinded(vec![(blinded_payinfo.clone(), blinded_path.clone())]);
-               let route = get_route(&our_id, &payment_params, &network_graph, None, final_amt_msat , Arc::clone(&logger),
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, 1001);
+               let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
                        &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 1);
                assert_eq!(route.paths[0].hops.len(), 2);
@@ -6598,7 +6793,8 @@ mod tests {
                let payment_params = PaymentParameters::blinded(vec![
                        (blinded_payinfo.clone(), invalid_blinded_path.clone()),
                        (blinded_payinfo.clone(), invalid_blinded_path_2)]);
-               match get_route(&our_id, &payment_params, &network_graph, None, 1001, Arc::clone(&logger),
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
+               match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
                        &scorer, &(), &random_seed_bytes)
                {
                        Err(LightningError { err, .. }) => {
@@ -6609,8 +6805,9 @@ mod tests {
 
                invalid_blinded_path.introduction_node_id = our_id;
                let payment_params = PaymentParameters::blinded(vec![(blinded_payinfo.clone(), invalid_blinded_path.clone())]);
-               match get_route(&our_id, &payment_params, &network_graph, None, 1001, Arc::clone(&logger),
-                       &scorer, &(), &random_seed_bytes)
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
+               match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
+                       &(), &random_seed_bytes)
                {
                        Err(LightningError { err, .. }) => {
                                assert_eq!(err, "Cannot generate a route to blinded paths if we are the introduction node to all of them");
@@ -6621,8 +6818,9 @@ mod tests {
                invalid_blinded_path.introduction_node_id = ln_test_utils::pubkey(46);
                invalid_blinded_path.blinded_hops.clear();
                let payment_params = PaymentParameters::blinded(vec![(blinded_payinfo, invalid_blinded_path)]);
-               match get_route(&our_id, &payment_params, &network_graph, None, 1001, Arc::clone(&logger),
-                       &scorer, &(), &random_seed_bytes)
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 1001);
+               match get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger), &scorer,
+                       &(), &random_seed_bytes)
                {
                        Err(LightningError { err, .. }) => {
                                assert_eq!(err, "0-hop blinded path provided");
@@ -6674,8 +6872,9 @@ mod tests {
                let payment_params = PaymentParameters::blinded(blinded_hints.clone())
                        .with_bolt12_features(bolt12_features.clone()).unwrap();
 
-               let route = get_route(&our_id, &payment_params, &network_graph, None,
-                       100_000, Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(payment_params, 100_000);
+               let route = get_route(&our_id, &route_params, &network_graph, None, Arc::clone(&logger),
+                       &scorer, &(), &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 2);
                let mut total_amount_paid_msat = 0;
                for path in route.paths.into_iter() {
@@ -6761,17 +6960,21 @@ mod tests {
                let payment_params = PaymentParameters::blinded(blinded_hints.clone());
 
                let netgraph = network_graph.read_only();
-               if let Err(LightningError { err, .. }) = get_route(&nodes[0], &payment_params, &netgraph,
-                       Some(&first_hops.iter().collect::<Vec<_>>()), amt_msat, Arc::clone(&logger), &scorer, &(),
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params.clone(), amt_msat);
+               if let Err(LightningError { err, .. }) = get_route(&nodes[0], &route_params, &netgraph,
+                       Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
                        &random_seed_bytes) {
-                       assert_eq!(err, "Failed to find a path to the given destination");
+                               assert_eq!(err, "Failed to find a path to the given destination");
                } else { panic!("Expected error") }
 
                // Sending an exact amount accounting for the blinded path fee works.
                let amt_minus_blinded_path_fee = amt_msat - blinded_payinfo.fee_base_msat as u64;
-               let route = get_route(&nodes[0], &payment_params, &netgraph,
-                       Some(&first_hops.iter().collect::<Vec<_>>()), amt_minus_blinded_path_fee,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, amt_minus_blinded_path_fee);
+               let route = get_route(&nodes[0], &route_params, &netgraph,
+                       Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes).unwrap();
                assert_eq!(route.get_total_fees(), blinded_payinfo.fee_base_msat as u64);
                assert_eq!(route.get_total_amount(), amt_minus_blinded_path_fee);
        }
@@ -6836,9 +7039,11 @@ mod tests {
                        .with_bolt12_features(bolt12_features.clone()).unwrap();
 
                let netgraph = network_graph.read_only();
-               let route = get_route(&nodes[0], &payment_params, &netgraph,
-                       Some(&first_hops.iter().collect::<Vec<_>>()), amt_msat,
-                       Arc::clone(&logger), &scorer, &(), &random_seed_bytes).unwrap();
+               let route_params = RouteParameters::from_payment_params_and_value(
+                       payment_params, amt_msat);
+               let route = get_route(&nodes[0], &route_params, &netgraph,
+                       Some(&first_hops.iter().collect::<Vec<_>>()), Arc::clone(&logger), &scorer, &(),
+                       &random_seed_bytes).unwrap();
                assert_eq!(route.get_total_fees(), blinded_payinfo.fee_base_msat as u64);
                assert_eq!(route.get_total_amount(), amt_msat);
        }
@@ -6970,10 +7175,12 @@ pub(crate) mod bench_utils {
                                let params = PaymentParameters::from_node_id(dst, 42)
                                        .with_bolt11_features(features.clone()).unwrap();
                                let first_hop = first_hop(src);
-                               let amt = starting_amount + seed % 1_000_000;
+                               let amt_msat = starting_amount + seed % 1_000_000;
+                               let route_params = RouteParameters::from_payment_params_and_value(
+                                       params.clone(), amt_msat);
                                let path_exists =
-                                       get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]),
-                                               amt, &TestLogger::new(), scorer, score_params, &random_seed_bytes).is_ok();
+                                       get_route(&payer, &route_params, &graph.read_only(), Some(&[&first_hop]),
+                                               &TestLogger::new(), scorer, score_params, &random_seed_bytes).is_ok();
                                if path_exists {
                                        // ...and seed the scorer with success and failure data...
                                        seed = seed.overflowing_mul(6364136223846793005).0.overflowing_add(1).0;
@@ -6985,10 +7192,11 @@ pub(crate) mod bench_utils {
                                                let mpp_features = channelmanager::provided_invoice_features(&UserConfig::default());
                                                let params = PaymentParameters::from_node_id(dst, 42)
                                                        .with_bolt11_features(mpp_features).unwrap();
-
-                                               let route_res = get_route(&payer, &params, &graph.read_only(),
-                                                       Some(&[&first_hop]), score_amt, &TestLogger::new(), scorer,
-                                                       score_params, &random_seed_bytes);
+                                               let route_params = RouteParameters::from_payment_params_and_value(
+                                                       params.clone(), score_amt);
+                                               let route_res = get_route(&payer, &route_params, &graph.read_only(),
+                                                       Some(&[&first_hop]), &TestLogger::new(), scorer, score_params,
+                                                       &random_seed_bytes);
                                                if let Ok(route) = route_res {
                                                        for path in route.paths {
                                                                if seed & 0x80 == 0 {
@@ -7005,7 +7213,7 @@ pub(crate) mod bench_utils {
                                                score_amt /= 100;
                                        }
 
-                                       route_endpoints.push((first_hop, params, amt));
+                                       route_endpoints.push((first_hop, params, amt_msat));
                                        break;
                                }
                        }
@@ -7014,8 +7222,10 @@ pub(crate) mod bench_utils {
                // Because we've changed channel scores, it's possible we'll take different routes to the
                // selected destinations, possibly causing us to fail because, eg, the newly-selected path
                // requires a too-high CLTV delta.
-               route_endpoints.retain(|(first_hop, params, amt)| {
-                       get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt,
+               route_endpoints.retain(|(first_hop, params, amt_msat)| {
+                       let route_params = RouteParameters::from_payment_params_and_value(
+                               params.clone(), *amt_msat);
+                       get_route(&payer, &route_params, &graph.read_only(), Some(&[first_hop]),
                                &TestLogger::new(), scorer, score_params, &random_seed_bytes).is_ok()
                });
                route_endpoints.truncate(route_count);
@@ -7106,7 +7316,8 @@ pub mod benches {
                let mut idx = 0;
                bench.bench_function(bench_name, |b| b.iter(|| {
                        let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()];
-                       assert!(get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt,
+                       let route_params = RouteParameters::from_payment_params_and_value(params.clone(), *amt);
+                       assert!(get_route(&payer, &route_params, &graph.read_only(), Some(&[first_hop]),
                                &DummyLogger{}, &scorer, score_params, &random_seed_bytes).is_ok());
                        idx += 1;
                }));