Pass Route to send_payment as a reference, not move
[rust-lightning] / lightning / src / ln / functional_tests.rs
index da6999ff847bd2714662413666dbe13058b7d7ef..8c0f05723bf521fa4904815fb80649f26a24284b 100644 (file)
@@ -6,7 +6,7 @@ use chain::transaction::OutPoint;
 use chain::keysinterface::{ChannelKeys, KeysInterface, SpendableOutputDescriptor};
 use chain::chaininterface::{ChainListener, ChainWatchInterfaceUtil, BlockNotifier};
 use ln::channel::{COMMITMENT_TX_BASE_WEIGHT, COMMITMENT_TX_WEIGHT_PER_HTLC};
-use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, BREAKDOWN_TIMEOUT};
+use ln::channelmanager::{ChannelManager,ChannelManagerReadArgs,HTLCForwardInfo,RAACommitmentOrder, PaymentPreimage, PaymentHash, PaymentSecret, PaymentSendFailure, BREAKDOWN_TIMEOUT};
 use ln::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ManyChannelMonitor, ANTI_REORG_DELAY};
 use ln::channel::{Channel, ChannelError};
 use ln::{chan_utils, onion_utils};
@@ -155,7 +155,7 @@ fn test_async_inbound_update_fee() {
 
        // ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]...
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[1].node.send_payment(nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 40000, TEST_FINAL_CLTV).unwrap(), our_payment_hash, &None).unwrap();
+       nodes[1].node.send_payment(&nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 40000, TEST_FINAL_CLTV).unwrap(), our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[1], 1);
 
        let payment_event = {
@@ -251,7 +251,7 @@ fn test_update_fee_unordered_raa() {
 
        // ...but before it's delivered, nodes[1] starts to send a payment back to nodes[0]...
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[1].node.send_payment(nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 40000, TEST_FINAL_CLTV).unwrap(), our_payment_hash, &None).unwrap();
+       nodes[1].node.send_payment(&nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 40000, TEST_FINAL_CLTV).unwrap(), our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[1], 1);
 
        let payment_event = {
@@ -642,7 +642,7 @@ fn test_update_fee_with_fundee_update_add_htlc() {
        let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[1]);
 
        // nothing happens since node[1] is in AwaitingRemoteRevoke
-       nodes[1].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[1].node.send_payment(&route, our_payment_hash, &None).unwrap();
        {
                let mut added_monitors = nodes[0].chan_monitor.added_monitors.lock().unwrap();
                assert_eq!(added_monitors.len(), 0);
@@ -861,10 +861,8 @@ fn updates_shutdown_wait() {
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
 
        let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       if let Err(APIError::ChannelUnavailable {..}) = nodes[0].node.send_payment(route_1, payment_hash, &None) {}
-       else { panic!("New sends should fail!") };
-       if let Err(APIError::ChannelUnavailable {..}) = nodes[1].node.send_payment(route_2, payment_hash, &None) {}
-       else { panic!("New sends should fail!") };
+       unwrap_send_err!(nodes[0].node.send_payment(&route_1, payment_hash, &None), true, APIError::ChannelUnavailable {..}, {});
+       unwrap_send_err!(nodes[1].node.send_payment(&route_2, payment_hash, &None), true, APIError::ChannelUnavailable {..}, {});
 
        assert!(nodes[2].node.claim_funds(our_payment_preimage, &None, 100_000));
        check_added_monitors!(nodes[2], 1);
@@ -924,7 +922,7 @@ fn htlc_fail_async_shutdown() {
 
        let route = nodes[0].router.get_route(&nodes[2].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        assert_eq!(updates.update_add_htlcs.len(), 1);
@@ -1226,7 +1224,7 @@ fn fake_network_test() {
        });
        hops[1].fee_msat = chan_4.1.contents.fee_base_msat as u64 + chan_4.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
        hops[0].fee_msat = chan_3.0.contents.fee_base_msat as u64 + chan_3.0.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
-       let payment_preimage_1 = send_along_route(&nodes[1], Route { hops }, &vec!(&nodes[2], &nodes[3], &nodes[1])[..], 1000000).0;
+       let payment_preimage_1 = send_along_route(&nodes[1], Route { paths: vec![hops] }, &vec!(&nodes[2], &nodes[3], &nodes[1])[..], 1000000).0;
 
        let mut hops = Vec::with_capacity(3);
        hops.push(RouteHop {
@@ -1255,7 +1253,7 @@ fn fake_network_test() {
        });
        hops[1].fee_msat = chan_2.1.contents.fee_base_msat as u64 + chan_2.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
        hops[0].fee_msat = chan_3.1.contents.fee_base_msat as u64 + chan_3.1.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
-       let payment_hash_2 = send_along_route(&nodes[1], Route { hops }, &vec!(&nodes[3], &nodes[2], &nodes[1])[..], 1000000).1;
+       let payment_hash_2 = send_along_route(&nodes[1], Route { paths: vec![hops] }, &vec!(&nodes[3], &nodes[2], &nodes[1])[..], 1000000).1;
 
        // Claim the rebalances...
        fail_payment(&nodes[1], &vec!(&nodes[3], &nodes[2], &nodes[1])[..], payment_hash_2);
@@ -1305,7 +1303,7 @@ fn holding_cell_htlc_counting() {
        for _ in 0..::ln::channel::OUR_MAX_HTLCS {
                let route = nodes[1].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 100000, TEST_FINAL_CLTV).unwrap();
                let (payment_preimage, payment_hash) = get_payment_preimage_hash!(nodes[0]);
-               nodes[1].node.send_payment(route, payment_hash, &None).unwrap();
+               nodes[1].node.send_payment(&route, payment_hash, &None).unwrap();
                payments.push((payment_preimage, payment_hash));
        }
        check_added_monitors!(nodes[1], 1);
@@ -1320,16 +1318,15 @@ fn holding_cell_htlc_counting() {
        // another HTLC.
        let route = nodes[1].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 100000, TEST_FINAL_CLTV).unwrap();
        let (_, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
-       if let APIError::ChannelUnavailable { err } = nodes[1].node.send_payment(route, payment_hash_1, &None).unwrap_err() {
-               assert_eq!(err, "Cannot push more than their max accepted HTLCs");
-       } else { panic!("Unexpected event"); }
+       unwrap_send_err!(nodes[1].node.send_payment(&route, payment_hash_1, &None), true, APIError::ChannelUnavailable { err },
+               assert_eq!(err, "Cannot push more than their max accepted HTLCs"));
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
        nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot push more than their max accepted HTLCs".to_string(), 1);
 
        // This should also be true if we try to forward a payment.
        let route = nodes[0].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 100000, TEST_FINAL_CLTV).unwrap();
        let (_, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, payment_hash_2, &None).unwrap();
+       nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
 
        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -1562,12 +1559,9 @@ fn do_channel_reserve_test(test_recv: bool) {
        // attempt to send amt_msat > their_max_htlc_value_in_flight_msat
        {
                let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_0 + 1);
-               assert!(route.hops.iter().rev().skip(1).all(|h| h.fee_msat == feemsat));
-               let err = nodes[0].node.send_payment(route, our_payment_hash, &None).err().unwrap();
-               match err {
-                       APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"),
-                       _ => panic!("Unknown error variants"),
-               }
+               assert!(route.paths[0].iter().rev().skip(1).all(|h| h.fee_msat == feemsat));
+               unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+                       assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
                assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
                nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over the max HTLC value in flight our peer will accept".to_string(), 1);
        }
@@ -1601,11 +1595,8 @@ fn do_channel_reserve_test(test_recv: bool) {
                let recv_value = stat01.value_to_self_msat - stat01.channel_reserve_msat - total_fee_msat;
                // attempt to get channel_reserve violation
                let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value + 1);
-               let err = nodes[0].node.send_payment(route.clone(), our_payment_hash, &None).err().unwrap();
-               match err {
-                       APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over their reserve value"),
-                       _ => panic!("Unknown error variants"),
-               }
+               unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+                       assert_eq!(err, "Cannot send value that would put us over their reserve value"));
                assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
                nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over their reserve value".to_string(), 1);
        }
@@ -1616,7 +1607,7 @@ fn do_channel_reserve_test(test_recv: bool) {
 
        let (route_1, our_payment_hash_1, our_payment_preimage_1) = get_route_and_payment_hash!(recv_value_1);
        let payment_event_1 = {
-               nodes[0].node.send_payment(route_1, our_payment_hash_1, &None).unwrap();
+               nodes[0].node.send_payment(&route_1, our_payment_hash_1, &None).unwrap();
                check_added_monitors!(nodes[0], 1);
 
                let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -1629,10 +1620,8 @@ fn do_channel_reserve_test(test_recv: bool) {
        let recv_value_2 = stat01.value_to_self_msat - amt_msat_1 - stat01.channel_reserve_msat - total_fee_msat;
        {
                let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_2 + 1);
-               match nodes[0].node.send_payment(route, our_payment_hash, &None).err().unwrap() {
-                       APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over their reserve value"),
-                       _ => panic!("Unknown error variants"),
-               }
+               unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+                       assert_eq!(err, "Cannot send value that would put us over their reserve value"));
                assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
                nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over their reserve value".to_string(), 2);
        }
@@ -1651,8 +1640,8 @@ fn do_channel_reserve_test(test_recv: bool) {
                }).expect("RNG is bad!");
 
                let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
-               let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
-               let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, cur_height).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
+               let (onion_payloads, htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], recv_value_2 + 1, &None, cur_height).unwrap();
                let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash);
                let msg = msgs::UpdateAddHTLC {
                        channel_id: chan_1.2,
@@ -1686,7 +1675,7 @@ fn do_channel_reserve_test(test_recv: bool) {
        // now see if they go through on both sides
        let (route_21, our_payment_hash_21, our_payment_preimage_21) = get_route_and_payment_hash!(recv_value_21);
        // but this will stuck in the holding cell
-       nodes[0].node.send_payment(route_21, our_payment_hash_21, &None).unwrap();
+       nodes[0].node.send_payment(&route_21, our_payment_hash_21, &None).unwrap();
        check_added_monitors!(nodes[0], 0);
        let events = nodes[0].node.get_and_clear_pending_events();
        assert_eq!(events.len(), 0);
@@ -1694,17 +1683,15 @@ fn do_channel_reserve_test(test_recv: bool) {
        // test with outbound holding cell amount > 0
        {
                let (route, our_payment_hash, _) = get_route_and_payment_hash!(recv_value_22+1);
-               match nodes[0].node.send_payment(route, our_payment_hash, &None).err().unwrap() {
-                       APIError::ChannelUnavailable{err} => assert_eq!(err, "Cannot send value that would put us over their reserve value"),
-                       _ => panic!("Unknown error variants"),
-               }
+               unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+                       assert_eq!(err, "Cannot send value that would put us over their reserve value"));
                assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
                nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over their reserve value".to_string(), 3);
        }
 
        let (route_22, our_payment_hash_22, our_payment_preimage_22) = get_route_and_payment_hash!(recv_value_22);
        // this will also stuck in the holding cell
-       nodes[0].node.send_payment(route_22, our_payment_hash_22, &None).unwrap();
+       nodes[0].node.send_payment(&route_22, our_payment_hash_22, &None).unwrap();
        check_added_monitors!(nodes[0], 0);
        assert!(nodes[0].node.get_and_clear_pending_events().is_empty());
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
@@ -1828,7 +1815,7 @@ fn channel_reserve_in_flight_removes() {
        let (payment_preimage_3, payment_hash_3) = get_payment_preimage_hash!(nodes[0]);
        let send_1 = {
                let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
-               nodes[0].node.send_payment(route, payment_hash_3, &None).unwrap();
+               nodes[0].node.send_payment(&route, payment_hash_3, &None).unwrap();
                check_added_monitors!(nodes[0], 1);
                let mut events = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(events.len(), 1);
@@ -1900,7 +1887,7 @@ fn channel_reserve_in_flight_removes() {
        let (payment_preimage_4, payment_hash_4) = get_payment_preimage_hash!(nodes[1]);
        let send_2 = {
                let route = nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &[], 10000, TEST_FINAL_CLTV).unwrap();
-               nodes[1].node.send_payment(route, payment_hash_4, &None).unwrap();
+               nodes[1].node.send_payment(&route, payment_hash_4, &None).unwrap();
                check_added_monitors!(nodes[1], 1);
                let mut events = nodes[1].node.get_and_clear_pending_msg_events();
                assert_eq!(events.len(), 1);
@@ -2858,7 +2845,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
        // on nodes[2]'s RAA.
        let route = nodes[1].router.get_route(&nodes[2].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
        let (_, fourth_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[1].node.send_payment(route, fourth_payment_hash, &None).unwrap();
+       nodes[1].node.send_payment(&route, fourth_payment_hash, &None).unwrap();
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
        assert!(nodes[1].node.get_and_clear_pending_events().is_empty());
        check_added_monitors!(nodes[1], 0);
@@ -3002,7 +2989,7 @@ fn fail_backward_pending_htlc_upon_channel_failure() {
        {
                let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
                let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 50_000, TEST_FINAL_CLTV).unwrap();
-               nodes[0].node.send_payment(route, payment_hash, &None).unwrap();
+               nodes[0].node.send_payment(&route, payment_hash, &None).unwrap();
                check_added_monitors!(nodes[0], 1);
 
                let payment_event = {
@@ -3018,7 +3005,7 @@ fn fail_backward_pending_htlc_upon_channel_failure() {
        let (_, failed_payment_hash) = get_payment_preimage_hash!(nodes[0]);
        {
                let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 50_000, TEST_FINAL_CLTV).unwrap();
-               nodes[0].node.send_payment(route, failed_payment_hash, &None).unwrap();
+               nodes[0].node.send_payment(&route, failed_payment_hash, &None).unwrap();
                check_added_monitors!(nodes[0], 0);
 
                assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
@@ -3038,8 +3025,8 @@ fn fail_backward_pending_htlc_upon_channel_failure() {
                };
 
                let current_height = nodes[1].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
-               let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route, &None, current_height).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route, &session_priv).unwrap();
+               let (onion_payloads, _amount_msat, cltv_expiry) = onion_utils::build_onion_payloads(&route.paths[0], 50_000, &None, current_height).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&secp_ctx, &route.paths[0], &session_priv).unwrap();
                let onion_routing_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
 
                // Send a 0-msat update_add_htlc to fail the channel.
@@ -3103,7 +3090,7 @@ fn test_force_close_fail_back() {
        let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
 
        let mut payment_event = {
-               nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+               nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
                check_added_monitors!(nodes[0], 1);
 
                let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -3274,7 +3261,7 @@ fn do_test_drop_messages_peer_disconnect(messages_delivered: u8) {
        let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]);
 
        let payment_event = {
-               nodes[0].node.send_payment(route.clone(), payment_hash_1, &None).unwrap();
+               nodes[0].node.send_payment(&route, payment_hash_1, &None).unwrap();
                check_added_monitors!(nodes[0], 1);
 
                let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -3566,7 +3553,7 @@ fn test_drop_messages_peer_disconnect_dual_htlc() {
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap();
        let (payment_preimage_2, payment_hash_2) = get_payment_preimage_hash!(nodes[0]);
 
-       nodes[0].node.send_payment(route.clone(), payment_hash_2, &None).unwrap();
+       nodes[0].node.send_payment(&route, payment_hash_2, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
 
        let events_1 = nodes[0].node.get_and_clear_pending_msg_events();
@@ -5131,7 +5118,7 @@ fn do_htlc_claim_current_remote_commitment_only(use_dust: bool) {
 
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), if use_dust { 50000 } else { 3000000 }, TEST_FINAL_CLTV).unwrap();
        let (_, payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
 
        let _as_update = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
@@ -5279,7 +5266,7 @@ fn run_onion_failure_test_with_fail_intercept<F1,F2,F3>(_name: &str, test_case:
        }
 
        // 0 ~~> 2 send payment
-       nodes[0].node.send_payment(route.clone(), payment_hash.clone(), &None).unwrap();
+       nodes[0].node.send_payment(&route, payment_hash.clone(), &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let update_0 = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        // temper update_add (0 => 1)
@@ -5470,8 +5457,8 @@ fn test_onion_failure() {
        run_onion_failure_test("invalid_realm", 0, &nodes, &route, &payment_hash, |msg| {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
                let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
-               let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, cur_height).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
+               let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height).unwrap();
                let mut new_payloads = Vec::new();
                for payload in onion_payloads.drain(..) {
                        new_payloads.push(BogusOnionHopData::new(payload));
@@ -5486,8 +5473,8 @@ fn test_onion_failure() {
        run_onion_failure_test("invalid_realm", 3, &nodes, &route, &payment_hash, |msg| {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
                let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
-               let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, cur_height).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
+               let (mut onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height).unwrap();
                let mut new_payloads = Vec::new();
                for payload in onion_payloads.drain(..) {
                        new_payloads.push(BogusOnionHopData::new(payload));
@@ -5507,57 +5494,57 @@ fn test_onion_failure() {
        }, |msg| {
                // and tamper returning error message
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], NODE|2, &[0;0]);
-       }, ||{}, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[0].pubkey, is_permanent: false}));
+       }, ||{}, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][0].pubkey, is_permanent: false}));
 
        // final node failure
        run_onion_failure_test_with_fail_intercept("temporary_node_failure", 200, &nodes, &route, &payment_hash, |_msg| {}, |msg| {
                // and tamper returning error message
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], NODE|2, &[0;0]);
        }, ||{
                nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
-       }, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[1].pubkey, is_permanent: false}));
+       }, true, Some(NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][1].pubkey, is_permanent: false}));
 
        // intermediate node failure
        run_onion_failure_test_with_fail_intercept("permanent_node_failure", 100, &nodes, &route, &payment_hash, |msg| {
                msg.amount_msat -= 1;
        }, |msg| {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|NODE|2, &[0;0]);
-       }, ||{}, true, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[0].pubkey, is_permanent: true}));
+       }, ||{}, true, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][0].pubkey, is_permanent: true}));
 
        // final node failure
        run_onion_failure_test_with_fail_intercept("permanent_node_failure", 200, &nodes, &route, &payment_hash, |_msg| {}, |msg| {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], PERM|NODE|2, &[0;0]);
        }, ||{
                nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
-       }, false, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[1].pubkey, is_permanent: true}));
+       }, false, Some(PERM|NODE|2), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][1].pubkey, is_permanent: true}));
 
        // intermediate node failure
        run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 100, &nodes, &route, &payment_hash, |msg| {
                msg.amount_msat -= 1;
        }, |msg| {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|NODE|3, &[0;0]);
        }, ||{
                nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
-       }, true, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[0].pubkey, is_permanent: true}));
+       }, true, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][0].pubkey, is_permanent: true}));
 
        // final node failure
        run_onion_failure_test_with_fail_intercept("required_node_feature_missing", 200, &nodes, &route, &payment_hash, |_msg| {}, |msg| {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[1].shared_secret[..], PERM|NODE|3, &[0;0]);
        }, ||{
                nodes[2].node.fail_htlc_backwards(&payment_hash, &None);
-       }, false, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.hops[1].pubkey, is_permanent: true}));
+       }, false, Some(PERM|NODE|3), Some(msgs::HTLCFailChannelUpdate::NodeFailure{node_id: route.paths[0][1].pubkey, is_permanent: true}));
 
        run_onion_failure_test("invalid_onion_version", 0, &nodes, &route, &payment_hash, |msg| { msg.onion_routing_packet.version = 1; }, ||{}, true,
                Some(BADONION|PERM|4), None);
@@ -5572,7 +5559,7 @@ fn test_onion_failure() {
                msg.amount_msat -= 1;
        }, |msg| {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], UPDATE|7, &ChannelUpdate::dummy().encode_with_len()[..]);
        }, ||{}, true, Some(UPDATE|7), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
 
@@ -5580,7 +5567,7 @@ fn test_onion_failure() {
                msg.amount_msat -= 1;
        }, |msg| {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|8, &[0;0]);
                // short_channel_id from the processing node
        }, ||{}, true, Some(PERM|8), Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: true}));
@@ -5589,20 +5576,20 @@ fn test_onion_failure() {
                msg.amount_msat -= 1;
        }, |msg| {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
                msg.reason = onion_utils::build_first_hop_failure_packet(&onion_keys[0].shared_secret[..], PERM|9, &[0;0]);
                // short_channel_id from the processing node
        }, ||{}, true, Some(PERM|9), Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: channels[1].0.contents.short_channel_id, is_permanent: true}));
 
        let mut bogus_route = route.clone();
-       bogus_route.hops[1].short_channel_id -= 1;
+       bogus_route.paths[0][1].short_channel_id -= 1;
        run_onion_failure_test("unknown_next_peer", 0, &nodes, &bogus_route, &payment_hash, |_| {}, ||{}, true, Some(PERM|10),
-         Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: bogus_route.hops[1].short_channel_id, is_permanent:true}));
+         Some(msgs::HTLCFailChannelUpdate::ChannelClosed{short_channel_id: bogus_route.paths[0][1].short_channel_id, is_permanent:true}));
 
        let amt_to_forward = nodes[1].node.channel_state.lock().unwrap().by_id.get(&channels[1].2).unwrap().get_their_htlc_minimum_msat() - 1;
        let mut bogus_route = route.clone();
-       let route_len = bogus_route.hops.len();
-       bogus_route.hops[route_len-1].fee_msat = amt_to_forward;
+       let route_len = bogus_route.paths[0].len();
+       bogus_route.paths[0][route_len-1].fee_msat = amt_to_forward;
        run_onion_failure_test("amount_below_minimum", 0, &nodes, &bogus_route, &payment_hash, |_| {}, ||{}, true, Some(UPDATE|11), Some(msgs::HTLCFailChannelUpdate::ChannelUpdateMessage{msg: ChannelUpdate::dummy()}));
 
        //TODO: with new config API, we will be able to generate both valid and
@@ -5670,9 +5657,9 @@ fn test_onion_failure() {
                let session_priv = SecretKey::from_slice(&[3; 32]).unwrap();
                let mut route = route.clone();
                let height = 1;
-               route.hops[1].cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route.hops[0].cltv_expiry_delta + 1;
-               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route, &session_priv).unwrap();
-               let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, height).unwrap();
+               route.paths[0][1].cltv_expiry_delta += CLTV_FAR_FAR_AWAY + route.paths[0][0].cltv_expiry_delta + 1;
+               let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::new(), &route.paths[0], &session_priv).unwrap();
+               let (onion_payloads, _, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, height).unwrap();
                let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &payment_hash);
                msg.cltv_expiry = htlc_cltv;
                msg.onion_routing_packet = onion_packet;
@@ -5762,15 +5749,10 @@ fn test_update_add_htlc_bolt2_sender_value_below_minimum_msat() {
        let mut route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
 
-       route.hops[0].fee_msat = 100;
+       route.paths[0][0].fee_msat = 100;
 
-       let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
-
-       if let Err(APIError::ChannelUnavailable{err}) = err {
-               assert_eq!(err, "Cannot send less than their minimum HTLC value");
-       } else {
-               assert!(false);
-       }
+       unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+               assert_eq!(err, "Cannot send less than their minimum HTLC value"));
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
        nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send less than their minimum HTLC value".to_string(), 1);
 }
@@ -5786,15 +5768,10 @@ fn test_update_add_htlc_bolt2_sender_zero_value_msat() {
        let mut route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
 
-       route.hops[0].fee_msat = 0;
-
-       let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
+       route.paths[0][0].fee_msat = 0;
 
-       if let Err(APIError::ChannelUnavailable{err}) = err {
-               assert_eq!(err, "Cannot send 0-msat HTLC");
-       } else {
-               assert!(false);
-       }
+       unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+               assert_eq!(err, "Cannot send 0-msat HTLC"));
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
        nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send 0-msat HTLC".to_string(), 1);
 }
@@ -5810,7 +5787,7 @@ fn test_update_add_htlc_bolt2_receiver_zero_value_msat() {
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
 
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        updates.update_add_htlcs[0].amount_msat = 0;
@@ -5833,13 +5810,8 @@ fn test_update_add_htlc_bolt2_sender_cltv_expiry_too_high() {
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000000, 500000001).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
 
-       let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
-
-       if let Err(APIError::RouteError{err}) = err {
-               assert_eq!(err, "Channel CLTV overflowed?!");
-       } else {
-               assert!(false);
-       }
+       unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::RouteError { err },
+               assert_eq!(err, "Channel CLTV overflowed?!"));
 }
 
 #[test]
@@ -5858,7 +5830,7 @@ fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increment()
                let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
                let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
                let payment_event = {
-                       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+                       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
                        check_added_monitors!(nodes[0], 1);
 
                        let mut events = nodes[0].node.get_and_clear_pending_msg_events();
@@ -5879,13 +5851,9 @@ fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_num_and_htlc_id_increment()
        }
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
+       unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+               assert_eq!(err, "Cannot push more than their max accepted HTLCs"));
 
-       if let Err(APIError::ChannelUnavailable{err}) = err {
-               assert_eq!(err, "Cannot push more than their max accepted HTLCs");
-       } else {
-               assert!(false);
-       }
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
        nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot push more than their max accepted HTLCs".to_string(), 1);
 }
@@ -5905,13 +5873,9 @@ fn test_update_add_htlc_bolt2_sender_exceed_max_htlc_value_in_flight() {
 
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], max_in_flight+1, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       let err = nodes[0].node.send_payment(route, our_payment_hash, &None);
+       unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &None), true, APIError::ChannelUnavailable { err },
+               assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept"));
 
-       if let Err(APIError::ChannelUnavailable{err}) = err {
-               assert_eq!(err, "Cannot send value that would put us over the max HTLC value in flight our peer will accept");
-       } else {
-               assert!(false);
-       }
        assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
        nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Cannot send value that would put us over the max HTLC value in flight our peer will accept".to_string(), 1);
 
@@ -5935,7 +5899,7 @@ fn test_update_add_htlc_bolt2_receiver_check_amount_received_more_than_min() {
        }
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], htlc_minimum_msat, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        updates.update_add_htlcs[0].amount_msat = htlc_minimum_msat-1;
@@ -5959,7 +5923,7 @@ fn test_update_add_htlc_bolt2_receiver_sender_can_afford_amount_sent() {
 
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 5000000-their_channel_reserve, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
 
@@ -5992,8 +5956,8 @@ fn test_update_add_htlc_bolt2_receiver_check_max_htlc_limit() {
        }).expect("RNG is bad!");
 
        let cur_height = nodes[0].node.latest_block_height.load(Ordering::Acquire) as u32 + 1;
-       let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route, &session_priv).unwrap();
-       let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route, &None, cur_height).unwrap();
+       let onion_keys = onion_utils::construct_onion_keys(&Secp256k1::signing_only(), &route.paths[0], &session_priv).unwrap();
+       let (onion_payloads, _htlc_msat, htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 3999999, &None, cur_height).unwrap();
        let onion_packet = onion_utils::construct_onion_packet(onion_payloads, onion_keys, [0; 32], &our_payment_hash);
 
        let mut msg = msgs::UpdateAddHTLC {
@@ -6028,7 +5992,7 @@ fn test_update_add_htlc_bolt2_receiver_check_max_in_flight_msat() {
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::supported(), InitFeatures::supported());
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        updates.update_add_htlcs[0].amount_msat = get_channel_value_stat!(nodes[1], chan.2).their_max_htlc_value_in_flight_msat + 1;
@@ -6050,7 +6014,7 @@ fn test_update_add_htlc_bolt2_receiver_check_cltv_expiry() {
        create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 95000000, InitFeatures::supported(), InitFeatures::supported());
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 3999999, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        updates.update_add_htlcs[0].cltv_expiry = 500000000;
@@ -6074,7 +6038,7 @@ fn test_update_add_htlc_bolt2_receiver_check_repeated_id_ignore() {
        create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported());
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
@@ -6120,7 +6084,7 @@ fn test_update_fulfill_htlc_bolt2_update_fulfill_htlc_before_commitment() {
 
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
        let (our_payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
@@ -6151,7 +6115,7 @@ fn test_update_fulfill_htlc_bolt2_update_fail_htlc_before_commitment() {
 
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
@@ -6182,7 +6146,7 @@ fn test_update_fulfill_htlc_bolt2_update_fail_malformed_htlc_before_commitment()
 
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
        let updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
        nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &updates.update_add_htlcs[0]);
@@ -6295,7 +6259,7 @@ fn test_update_fulfill_htlc_bolt2_missing_badonion_bit_for_malformed_htlc_messag
        create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 1000000, InitFeatures::supported(), InitFeatures::supported());
        let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &[], 1000000, TEST_FINAL_CLTV).unwrap();
        let (_, our_payment_hash) = get_payment_preimage_hash!(nodes[0]);
-       nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+       nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
        check_added_monitors!(nodes[0], 1);
 
        let mut updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id());
@@ -6346,7 +6310,7 @@ fn test_update_fulfill_htlc_bolt2_after_malformed_htlc_message_must_forward_upda
 
        //First hop
        let mut payment_event = {
-               nodes[0].node.send_payment(route, our_payment_hash, &None).unwrap();
+               nodes[0].node.send_payment(&route, our_payment_hash, &None).unwrap();
                check_added_monitors!(nodes[0], 1);
                let mut events = nodes[0].node.get_and_clear_pending_msg_events();
                assert_eq!(events.len(), 1);
@@ -7605,10 +7569,42 @@ fn test_simple_payment_secret() {
        let (payment_preimage, payment_hash) = get_payment_preimage_hash!(&nodes[0]);
        let payment_secret = PaymentSecret([0xdb; 32]);
        let route = nodes[0].router.get_route(&nodes[2].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
-       send_along_route_with_secret(&nodes[0], route, &[&nodes[1], &nodes[2]], 100000, payment_hash, Some(payment_secret.clone()));
+       send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2]]], 100000, payment_hash, Some(payment_secret.clone()));
        // Claiming with all the correct values but the wrong secret should result in nothing...
        assert_eq!(nodes[2].node.claim_funds(payment_preimage, &None, 100_000), false);
        assert_eq!(nodes[2].node.claim_funds(payment_preimage, &Some(PaymentSecret([42; 32])), 100_000), false);
        // ...but with the right secret we should be able to claim all the way back
-       claim_payment_along_route_with_secret(&nodes[0], &[&nodes[1], &nodes[2]], false, payment_preimage, Some(payment_secret.clone()), 100_000);
+       claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[2]]], false, payment_preimage, Some(payment_secret.clone()), 100_000);
+}
+
+#[test]
+fn test_simple_mpp() {
+       // Simple test of sending a multi-path payment.
+       let chanmon_cfgs = create_chanmon_cfgs(4);
+       let node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
+       let nodes = create_network(4, &node_cfgs, &node_chanmgrs);
+
+       let chan_1_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
+       let chan_2_id = create_announced_chan_between_nodes(&nodes, 0, 2, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
+       let chan_3_id = create_announced_chan_between_nodes(&nodes, 1, 3, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
+       let chan_4_id = create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::supported(), InitFeatures::supported()).0.contents.short_channel_id;
+
+       let (payment_preimage, payment_hash) = get_payment_preimage_hash!(&nodes[0]);
+       let payment_secret = PaymentSecret([0xdb; 32]);
+       let mut route = nodes[0].router.get_route(&nodes[3].node.get_our_node_id(), None, &[], 100000, TEST_FINAL_CLTV).unwrap();
+       let path = route.paths[0].clone();
+       route.paths.push(path);
+       route.paths[0][0].pubkey = nodes[1].node.get_our_node_id();
+       route.paths[0][0].short_channel_id = chan_1_id;
+       route.paths[0][1].short_channel_id = chan_3_id;
+       route.paths[1][0].pubkey = nodes[2].node.get_our_node_id();
+       route.paths[1][0].short_channel_id = chan_2_id;
+       route.paths[1][1].short_channel_id = chan_4_id;
+       send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], 200_000, payment_hash, Some(payment_secret.clone()));
+       // Claiming with all the correct values but the wrong secret should result in nothing...
+       assert_eq!(nodes[3].node.claim_funds(payment_preimage, &None, 200_000), false);
+       assert_eq!(nodes[3].node.claim_funds(payment_preimage, &Some(PaymentSecret([42; 32])), 200_000), false);
+       // ...but with the right secret we should be able to claim all the way back
+       claim_payment_along_route_with_secret(&nodes[0], &[&[&nodes[1], &nodes[3]], &[&nodes[2], &nodes[3]]], false, payment_preimage, Some(payment_secret), 200_000);
 }