Merge pull request #1600 from TheBlueMatt/2022-07-explicit-avoid-retries
[rust-lightning] / lightning / src / routing / router.rs
index 7f6b3afdebc3fe7edbd097e41ffea8fc9fa4fb58..a97e1b6ffa45db704b89505cfce7d6c58cc1f16b 100644 (file)
@@ -9,17 +9,17 @@
 
 //! The top-level routing/network map tracking logic lives here.
 //!
-//! You probably want to create a NetGraphMsgHandler and use that as your RoutingMessageHandler and then
+//! You probably want to create a P2PGossipSync and use that as your RoutingMessageHandler and then
 //! interrogate it to get routes for your own payments.
 
-use bitcoin::secp256k1::key::PublicKey;
+use bitcoin::secp256k1::PublicKey;
 
 use ln::channelmanager::ChannelDetails;
 use ln::features::{ChannelFeatures, InvoiceFeatures, NodeFeatures};
 use ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
-use routing::scoring::Score;
-use routing::network_graph::{DirectedChannelInfoWithUpdate, EffectiveCapacity, NetworkGraph, ReadOnlyNetworkGraph, NodeId, RoutingFees};
-use util::ser::{Writeable, Readable};
+use routing::gossip::{DirectedChannelInfoWithUpdate, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees};
+use routing::scoring::{ChannelUsage, Score};
+use util::ser::{Writeable, Readable, Writer};
 use util::logger::{Level, Logger};
 use util::chacha20::ChaCha20;
 
@@ -65,11 +65,10 @@ impl_writeable_tlv_based!(RouteHop, {
 #[derive(Clone, Hash, PartialEq, Eq)]
 pub struct Route {
        /// The list of routes taken for a single (potentially-)multi-part payment. The pubkey of the
-       /// last RouteHop in each path must be the same.
-       /// Each entry represents a list of hops, NOT INCLUDING our own, where the last hop is the
-       /// destination. Thus, this must always be at least length one. While the maximum length of any
-       /// given path is variable, keeping the length of any path to less than 20 should currently
-       /// ensure it is viable.
+       /// last RouteHop in each path must be the same. Each entry represents a list of hops, NOT
+       /// INCLUDING our own, where the last hop is the destination. Thus, this must always be at
+       /// least length one. While the maximum length of any given path is variable, keeping the length
+       /// of any path less or equal to 19 should currently ensure it is viable.
        pub paths: Vec<Vec<RouteHop>>,
        /// The `payment_params` parameter passed to [`find_route`].
        /// This is used by `ChannelManager` to track information which may be required for retries,
@@ -152,8 +151,8 @@ impl Readable for Route {
 
 /// Parameters needed to find a [`Route`].
 ///
-/// Passed to [`find_route`] and also provided in [`Event::PaymentPathFailed`] for retrying a failed
-/// payment path.
+/// Passed to [`find_route`] and [`build_route_from_hops`], but also provided in
+/// [`Event::PaymentPathFailed`] for retrying a failed payment path.
 ///
 /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
 #[derive(Clone, Debug)]
@@ -177,9 +176,28 @@ impl_writeable_tlv_based!(RouteParameters, {
 /// Maximum total CTLV difference we allow for a full payment path.
 pub const DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA: u32 = 1008;
 
-/// The median hop CLTV expiry delta currently seen in the network.
+/// Maximum number of paths we allow an (MPP) payment to have.
+// The default limit is currently set rather arbitrary - there aren't any real fundamental path-count
+// limits, but for now more than 10 paths likely carries too much one-path failure.
+pub const DEFAULT_MAX_PATH_COUNT: u8 = 10;
+
+// The median hop CLTV expiry delta currently seen in the network.
 const MEDIAN_HOP_CLTV_EXPIRY_DELTA: u32 = 40;
 
+// During routing, we only consider paths shorter than our maximum length estimate.
+// In the legacy onion format, the maximum number of hops used to be a fixed value of 20.
+// However, in the TLV onion format, there is no fixed maximum length, but the `hop_payloads`
+// field is always 1300 bytes. As the `tlv_payload` for each hop may vary in length, we have to
+// estimate how many hops the route may have so that it actually fits the `hop_payloads` field.
+//
+// We estimate 3+32 (payload length and HMAC) + 2+8 (amt_to_forward) + 2+4 (outgoing_cltv_value) +
+// 2+8 (short_channel_id) = 61 bytes for each intermediate hop and 3+32
+// (payload length and HMAC) + 2+8 (amt_to_forward) + 2+4 (outgoing_cltv_value) + 2+32+8
+// (payment_secret and total_msat) = 93 bytes for the final hop.
+// Since the length of the potentially included `payment_metadata` is unknown to us, we round
+// down from (1300-93) / 61 = 19.78... to arrive at a conservative estimate of 19.
+const MAX_PATH_LENGTH_ESTIMATE: u8 = 19;
+
 /// The recipient of a payment.
 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
 pub struct PaymentParameters {
@@ -201,15 +219,43 @@ pub struct PaymentParameters {
        pub expiry_time: Option<u64>,
 
        /// The maximum total CLTV delta we accept for the route.
+       /// Defaults to [`DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA`].
        pub max_total_cltv_expiry_delta: u32,
+
+       /// The maximum number of paths that may be used by (MPP) payments.
+       /// Defaults to [`DEFAULT_MAX_PATH_COUNT`].
+       pub max_path_count: u8,
+
+       /// Selects the maximum share of a channel's total capacity which will be sent over a channel,
+       /// as a power of 1/2. A higher value prefers to send the payment using more MPP parts whereas
+       /// a lower value prefers to send larger MPP parts, potentially saturating channels and
+       /// increasing failure probability for those paths.
+       ///
+       /// Note that this restriction will be relaxed during pathfinding after paths which meet this
+       /// restriction have been found. While paths which meet this criteria will be searched for, it
+       /// is ultimately up to the scorer to select them over other paths.
+       ///
+       /// A value of 0 will allow payments up to and including a channel's total announced usable
+       /// capacity, a value of one will only use up to half its capacity, two 1/4, etc.
+       ///
+       /// Default value: 1
+       pub max_channel_saturation_power_of_half: u8,
+
+       /// A list of SCIDs which this payment was previously attempted over and which caused the
+       /// payment to fail. Future attempts for the same payment shouldn't be relayed through any of
+       /// these SCIDs.
+       pub previously_failed_channels: Vec<u64>,
 }
 
 impl_writeable_tlv_based!(PaymentParameters, {
        (0, payee_pubkey, required),
        (1, max_total_cltv_expiry_delta, (default_value, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA)),
        (2, features, option),
+       (3, max_path_count, (default_value, DEFAULT_MAX_PATH_COUNT)),
        (4, route_hints, vec_type),
+       (5, max_channel_saturation_power_of_half, (default_value, 1)),
        (6, expiry_time, option),
+       (7, previously_failed_channels, vec_type),
 });
 
 impl PaymentParameters {
@@ -221,6 +267,9 @@ impl PaymentParameters {
                        route_hints: vec![],
                        expiry_time: None,
                        max_total_cltv_expiry_delta: DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA,
+                       max_path_count: DEFAULT_MAX_PATH_COUNT,
+                       max_channel_saturation_power_of_half: 1,
+                       previously_failed_channels: Vec::new(),
                }
        }
 
@@ -256,6 +305,20 @@ impl PaymentParameters {
        pub fn with_max_total_cltv_expiry_delta(self, max_total_cltv_expiry_delta: u32) -> Self {
                Self { max_total_cltv_expiry_delta, ..self }
        }
+
+       /// Includes a limit for the maximum number of payment paths that may be used.
+       ///
+       /// (C-not exported) since bindings don't support move semantics
+       pub fn with_max_path_count(self, max_path_count: u8) -> Self {
+               Self { max_path_count, ..self }
+       }
+
+       /// Includes a limit for the maximum number of payment paths that may be used.
+       ///
+       /// (C-not exported) since bindings don't support move semantics
+       pub fn with_max_channel_saturation_power_of_half(self, max_channel_saturation_power_of_half: u8) -> Self {
+               Self { max_channel_saturation_power_of_half, ..self }
+       }
 }
 
 /// A list of hops along a payment path terminating with a channel to the recipient.
@@ -327,6 +390,8 @@ struct RouteGraphNode {
        /// All penalties incurred from this hop on the way to the destination, as calculated using
        /// channel scoring.
        path_penalty_msat: u64,
+       /// The number of hops walked up to this node.
+       path_length_to_node: u8,
 }
 
 impl cmp::Ord for RouteGraphNode {
@@ -354,7 +419,7 @@ enum CandidateRouteHop<'a> {
        FirstHop {
                details: &'a ChannelDetails,
        },
-       /// A hop found in the [`NetworkGraph`], where the channel capacity may or may not be known.
+       /// A hop found in the [`ReadOnlyNetworkGraph`], where the channel capacity may be unknown.
        PublicHop {
                info: DirectedChannelInfoWithUpdate<'a>,
                short_channel_id: u64,
@@ -368,7 +433,7 @@ enum CandidateRouteHop<'a> {
 impl<'a> CandidateRouteHop<'a> {
        fn short_channel_id(&self) -> u64 {
                match self {
-                       CandidateRouteHop::FirstHop { details } => details.short_channel_id.unwrap(),
+                       CandidateRouteHop::FirstHop { details } => details.get_outbound_payment_scid().unwrap(),
                        CandidateRouteHop::PublicHop { short_channel_id, .. } => *short_channel_id,
                        CandidateRouteHop::PrivateHop { hint } => hint.short_channel_id,
                }
@@ -412,7 +477,7 @@ impl<'a> CandidateRouteHop<'a> {
        fn effective_capacity(&self) -> EffectiveCapacity {
                match self {
                        CandidateRouteHop::FirstHop { details } => EffectiveCapacity::ExactLiquidity {
-                               liquidity_msat: details.outbound_capacity_msat,
+                               liquidity_msat: details.next_outbound_htlc_limit_msat,
                        },
                        CandidateRouteHop::PublicHop { info, .. } => info.effective_capacity(),
                        CandidateRouteHop::PrivateHop { .. } => EffectiveCapacity::Infinite,
@@ -420,6 +485,33 @@ impl<'a> CandidateRouteHop<'a> {
        }
 }
 
+#[inline]
+fn max_htlc_from_capacity(capacity: EffectiveCapacity, max_channel_saturation_power_of_half: u8) -> u64 {
+       let saturation_shift: u32 = max_channel_saturation_power_of_half as u32;
+       match capacity {
+               EffectiveCapacity::ExactLiquidity { liquidity_msat } => liquidity_msat,
+               EffectiveCapacity::Infinite => u64::max_value(),
+               EffectiveCapacity::Unknown => EffectiveCapacity::Unknown.as_msat(),
+               EffectiveCapacity::MaximumHTLC { amount_msat } =>
+                       amount_msat.checked_shr(saturation_shift).unwrap_or(0),
+               EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: None } =>
+                       capacity_msat.checked_shr(saturation_shift).unwrap_or(0),
+               EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat: Some(htlc_max) } =>
+                       cmp::min(capacity_msat.checked_shr(saturation_shift).unwrap_or(0), htlc_max),
+       }
+}
+
+fn iter_equal<I1: Iterator, I2: Iterator>(mut iter_a: I1, mut iter_b: I2)
+-> bool where I1::Item: PartialEq<I2::Item> {
+       loop {
+               let a = iter_a.next();
+               let b = iter_b.next();
+               if a.is_none() && b.is_none() { return true; }
+               if a.is_none() || b.is_none() { return false; }
+               if a.unwrap().ne(&b.unwrap()) { return false; }
+       }
+}
+
 /// It's useful to keep track of the hops associated with the fees required to use them,
 /// so that we can choose cheaper paths (as per Dijkstra's algorithm).
 /// Fee values should be updated only in the context of the whole path, see update_value_and_recompute_fees.
@@ -466,7 +558,8 @@ struct PathBuildingHop<'a> {
 
 impl<'a> core::fmt::Debug for PathBuildingHop<'a> {
        fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
-               f.debug_struct("PathBuildingHop")
+               let mut debug_struct = f.debug_struct("PathBuildingHop");
+               debug_struct
                        .field("node_id", &self.node_id)
                        .field("short_channel_id", &self.candidate.short_channel_id())
                        .field("total_fee_msat", &self.total_fee_msat)
@@ -475,8 +568,11 @@ impl<'a> core::fmt::Debug for PathBuildingHop<'a> {
                        .field("total_fee_msat - (next_hops_fee_msat + hop_use_fee_msat)", &(&self.total_fee_msat - (&self.next_hops_fee_msat + &self.hop_use_fee_msat)))
                        .field("path_penalty_msat", &self.path_penalty_msat)
                        .field("path_htlc_minimum_msat", &self.path_htlc_minimum_msat)
-                       .field("cltv_expiry_delta", &self.candidate.cltv_expiry_delta())
-                       .finish()
+                       .field("cltv_expiry_delta", &self.candidate.cltv_expiry_delta());
+               #[cfg(all(not(feature = "_bench_unstable"), any(test, fuzzing)))]
+               let debug_struct = debug_struct
+                       .field("value_contribution_msat", &self.value_contribution_msat);
+               debug_struct.finish()
        }
 }
 
@@ -523,10 +619,9 @@ impl<'a> PaymentPath<'a> {
        // to the fees being paid not lining up with the actual limits.
        //
        // Note that this function is not aware of the available_liquidity limit, and thus does not
-       // support increasing the value being transferred.
+       // support increasing the value being transferred beyond what was selected during the initial
+       // routing passes.
        fn update_value_and_recompute_fees(&mut self, value_msat: u64) {
-               assert!(value_msat <= self.hops.last().unwrap().0.fee_msat);
-
                let mut total_fee_paid_msat = 0 as u64;
                for i in (0..self.hops.len()).rev() {
                        let last_hop = i == self.hops.len() - 1;
@@ -602,6 +697,17 @@ fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
        }
 }
 
+/// The default `features` we assume for a node in a route, when no `features` are known about that
+/// specific node.
+///
+/// Default features are:
+/// * variable_length_onion_optional
+fn default_node_features() -> NodeFeatures {
+       let mut features = NodeFeatures::empty();
+       features.set_variable_length_onion_optional();
+       features
+}
+
 /// Finds a route from us (payer) to the given target node (payee).
 ///
 /// If the payee provided features in their invoice, they should be provided via `params.payee`.
@@ -610,8 +716,8 @@ fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
 /// Private routing paths between a public node and the target may be included in `params.payee`.
 ///
 /// If some channels aren't announced, it may be useful to fill in `first_hops` with the results
-/// from [`ChannelManager::list_usable_channels`]. If it is filled in, the view of our local
-/// channels from [`NetworkGraph`] will be ignored, and only those in `first_hops` will be used.
+/// from [`ChannelManager::list_usable_channels`]. If it is filled in, the view of these channels
+/// from `network_graph` will be ignored, and only those in `first_hops` will be used.
 ///
 /// The fees on channels from us to the next hop are ignored as they are assumed to all be equal.
 /// However, the enabled/disabled bit on such channels as well as the `htlc_minimum_msat` /
@@ -630,22 +736,19 @@ fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
 ///
 /// [`ChannelManager::list_usable_channels`]: crate::ln::channelmanager::ChannelManager::list_usable_channels
 /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
-pub fn find_route<L: Deref, S: Score>(
-       our_node_pubkey: &PublicKey, route_params: &RouteParameters, network: &NetworkGraph,
-       first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, random_seed_bytes: &[u8; 32]
+/// [`NetworkGraph`]: crate::routing::gossip::NetworkGraph
+pub fn find_route<L: Deref, GL: Deref, S: Score>(
+       our_node_pubkey: &PublicKey, route_params: &RouteParameters,
+       network_graph: &NetworkGraph<GL>, first_hops: Option<&[&ChannelDetails]>, logger: L,
+       scorer: &S, random_seed_bytes: &[u8; 32]
 ) -> Result<Route, LightningError>
-where L::Target: Logger {
-       let network_graph = network.read_only();
-       match get_route(
-               our_node_pubkey, &route_params.payment_params, &network_graph, first_hops, route_params.final_value_msat,
-               route_params.final_cltv_expiry_delta, logger, scorer, random_seed_bytes
-       ) {
-               Ok(mut route) => {
-                       add_random_cltv_offset(&mut route, &route_params.payment_params, &network_graph, random_seed_bytes);
-                       Ok(route)
-               },
-               Err(err) => Err(err),
-       }
+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, route_params.final_cltv_expiry_delta, logger, scorer,
+               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: Score>(
@@ -744,16 +847,23 @@ where L::Target: Logger {
        let network_channels = network_graph.channels();
        let network_nodes = network_graph.nodes();
 
+       if payment_params.max_path_count == 0 {
+               return Err(LightningError{err: "Can't find a route with no paths allowed.".to_owned(), action: ErrorAction::IgnoreError});
+       }
+
        // Allow MPP only if we have a features set from somewhere that indicates the payee supports
        // it. If the payee supports it they're supposed to include it in the invoice, so that should
        // work reliably.
-       let allow_mpp = if let Some(features) = &payment_params.features {
+       let allow_mpp = if payment_params.max_path_count == 1 {
+               false
+       } else if let Some(features) = &payment_params.features {
                features.supports_basic_mpp()
        } else if let Some(node) = network_nodes.get(&payee_node_id) {
                if let Some(node_info) = node.announcement_info.as_ref() {
                        node_info.features.supports_basic_mpp()
                } else { false }
        } else { false };
+
        log_trace!(logger, "Searching for a route from payer {} to payee {} {} MPP and {} first hops {}overriding the network graph", our_node_pubkey,
                payment_params.payee_pubkey, if allow_mpp { "with" } else { "without" },
                first_hops.map(|hops| hops.len()).unwrap_or(0), if first_hops.is_some() { "" } else { "not " });
@@ -766,7 +876,7 @@ where L::Target: Logger {
                HashMap::with_capacity(if first_hops.is_some() { first_hops.as_ref().unwrap().len() } else { 0 });
        if let Some(hops) = first_hops {
                for chan in hops {
-                       if chan.short_channel_id.is_none() {
+                       if chan.get_outbound_payment_scid().is_none() {
                                panic!("first_hops should be filled in with usable channels, not pending ones");
                        }
                        if chan.counterparty.node_id == *our_node_pubkey {
@@ -785,11 +895,11 @@ where L::Target: Logger {
        // The main heap containing all candidate next-hops sorted by their score (max(A* fee,
        // htlc_minimum)). Ideally this would be a heap which allowed cheap score reduction instead of
        // adding duplicate entries when we find a better path to a given node.
-       let mut targets = BinaryHeap::new();
+       let mut targets: BinaryHeap<RouteGraphNode> = BinaryHeap::new();
 
        // Map from node_id to information about the best current path to that node, including feerate
        // information.
-       let mut dist = HashMap::with_capacity(network_nodes.len());
+       let mut dist: HashMap<NodeId, PathBuildingHop> = HashMap::with_capacity(network_nodes.len());
 
        // During routing, if we ignore a path due to an htlc_minimum_msat limit, we set this,
        // indicating that we may wish to try again with a higher value, potentially paying to meet an
@@ -804,17 +914,35 @@ where L::Target: Logger {
        let recommended_value_msat = final_value_msat * ROUTE_CAPACITY_PROVISION_FACTOR as u64;
        let mut path_value_msat = final_value_msat;
 
-       // We don't want multiple paths (as per MPP) share liquidity of the same channels.
-       // This map allows paths to be aware of the channel use by other paths in the same call.
-       // This would help to make a better path finding decisions and not "overbook" channels.
-       // It is unaware of the directions (except for `outbound_capacity_msat` in `first_hops`).
-       let mut bookkept_channels_liquidity_available_msat = HashMap::with_capacity(network_nodes.len());
-
-       // Keeping track of how much value we already collected across other paths. Helps to decide:
-       // - how much a new path should be transferring (upper bound);
-       // - whether a channel should be disregarded because
-       //   it's available liquidity is too small comparing to how much more we need to collect;
-       // - when we want to stop looking for new paths.
+       // Routing Fragmentation Mitigation heuristic:
+       //
+       // Routing fragmentation across many payment paths increases the overall routing
+       // fees as you have irreducible routing fees per-link used (`fee_base_msat`).
+       // Taking too many smaller paths also increases the chance of payment failure.
+       // Thus to avoid this effect, we require from our collected links to provide
+       // at least a minimal contribution to the recommended value yet-to-be-fulfilled.
+       // This requirement is currently set to be 1/max_path_count of the payment
+       // value to ensure we only ever return routes that do not violate this limit.
+       let minimal_value_contribution_msat: u64 = if allow_mpp {
+               (final_value_msat + (payment_params.max_path_count as u64 - 1)) / payment_params.max_path_count as u64
+       } else {
+               final_value_msat
+       };
+
+       // When we start collecting routes we enforce the max_channel_saturation_power_of_half
+       // requirement strictly. After we've collected enough (or if we fail to find new routes) we
+       // drop the requirement by setting this to 0.
+       let mut channel_saturation_pow_half = payment_params.max_channel_saturation_power_of_half;
+
+       // Keep track of how much liquidity has been used in selected channels. Used to determine
+       // if the channel can be used by additional MPP paths or to inform path finding decisions. It is
+       // aware of direction *only* to ensure that the correct htlc_maximum_msat value is used. Hence,
+       // liquidity used in one direction will not offset any used in the opposite direction.
+       let mut used_channel_liquidities: HashMap<(u64, bool), u64> =
+               HashMap::with_capacity(network_nodes.len());
+
+       // Keeping track of how much value we already collected across other paths. Helps to decide
+       // when we want to stop looking for new paths.
        let mut already_collected_value_msat = 0;
 
        for (_, channels) in first_hop_targets.iter_mut() {
@@ -830,12 +958,12 @@ where L::Target: Logger {
                // sort channels above `recommended_value_msat` in ascending order, preferring channels
                // which have enough, but not too much, capacity for the payment.
                channels.sort_unstable_by(|chan_a, chan_b| {
-                       if chan_b.outbound_capacity_msat < recommended_value_msat || chan_a.outbound_capacity_msat < recommended_value_msat {
+                       if chan_b.next_outbound_htlc_limit_msat < recommended_value_msat || chan_a.next_outbound_htlc_limit_msat < recommended_value_msat {
                                // Sort in descending order
-                               chan_b.outbound_capacity_msat.cmp(&chan_a.outbound_capacity_msat)
+                               chan_b.next_outbound_htlc_limit_msat.cmp(&chan_a.next_outbound_htlc_limit_msat)
                        } else {
                                // Sort in ascending order
-                               chan_a.outbound_capacity_msat.cmp(&chan_b.outbound_capacity_msat)
+                               chan_a.next_outbound_htlc_limit_msat.cmp(&chan_b.next_outbound_htlc_limit_msat)
                        }
                });
        }
@@ -848,8 +976,8 @@ where L::Target: Logger {
                // since that value has to be transferred over this channel.
                // Returns whether this channel caused an update to `targets`.
                ( $candidate: expr, $src_node_id: expr, $dest_node_id: expr, $next_hops_fee_msat: expr,
-                  $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr,
-                  $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr ) => { {
+                       $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr,
+                       $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => { {
                        // We "return" whether we updated the path at the end, via this:
                        let mut did_add_update_path_to_src_node = false;
                        // Channels to self should not be used. This is more of belt-and-suspenders, because in
@@ -858,9 +986,8 @@ where L::Target: Logger {
                        // - for first and last hops early in get_route
                        if $src_node_id != $dest_node_id {
                                let short_channel_id = $candidate.short_channel_id();
-                               let available_liquidity_msat = bookkept_channels_liquidity_available_msat
-                                       .entry(short_channel_id)
-                                       .or_insert_with(|| $candidate.effective_capacity().as_msat());
+                               let effective_capacity = $candidate.effective_capacity();
+                               let htlc_maximum_msat = max_htlc_from_capacity(effective_capacity, channel_saturation_pow_half);
 
                                // It is tricky to subtract $next_hops_fee_msat from available liquidity here.
                                // It may be misleading because we might later choose to reduce the value transferred
@@ -869,30 +996,20 @@ where L::Target: Logger {
                                // fees caused by one expensive channel, but then this channel could have been used
                                // if the amount being transferred over this path is lower.
                                // We do this for now, but this is a subject for removal.
-                               if let Some(available_value_contribution_msat) = available_liquidity_msat.checked_sub($next_hops_fee_msat) {
-
-                                       // Routing Fragmentation Mitigation heuristic:
-                                       //
-                                       // Routing fragmentation across many payment paths increases the overall routing
-                                       // fees as you have irreducible routing fees per-link used (`fee_base_msat`).
-                                       // Taking too many smaller paths also increases the chance of payment failure.
-                                       // Thus to avoid this effect, we require from our collected links to provide
-                                       // at least a minimal contribution to the recommended value yet-to-be-fulfilled.
-                                       //
-                                       // This requirement is currently 5% of the remaining-to-be-collected value.
-                                       // This means as we successfully advance in our collection,
-                                       // the absolute liquidity contribution is lowered,
-                                       // thus increasing the number of potential channels to be selected.
-
-                                       // Derive the minimal liquidity contribution with a ratio of 20 (5%, rounded up)
-                                       // or 100% if we're not allowed to do multipath payments.
-                                       let minimal_value_contribution_msat: u64 = if allow_mpp {
-                                               (recommended_value_msat - already_collected_value_msat + 19) / 20
-                                       } else {
-                                               final_value_msat
-                                       };
+                               if let Some(mut available_value_contribution_msat) = htlc_maximum_msat.checked_sub($next_hops_fee_msat) {
+                                       let used_liquidity_msat = used_channel_liquidities
+                                               .get(&(short_channel_id, $src_node_id < $dest_node_id))
+                                               .map_or(0, |used_liquidity_msat| {
+                                                       available_value_contribution_msat = available_value_contribution_msat
+                                                               .saturating_sub(*used_liquidity_msat);
+                                                       *used_liquidity_msat
+                                               });
+
                                        // Verify the liquidity offered by this channel complies to the minimal contribution.
                                        let contributes_sufficient_value = available_value_contribution_msat >= minimal_value_contribution_msat;
+                                       // Do not consider candidate hops that would exceed the maximum path length.
+                                       let path_length_to_node = $next_hops_path_length + 1;
+                                       let exceeds_max_path_length = path_length_to_node > MAX_PATH_LENGTH_ESTIMATE;
 
                                        // Do not consider candidates that exceed the maximum total cltv expiry limit.
                                        // In order to already account for some of the privacy enhancing random CLTV
@@ -903,7 +1020,7 @@ where L::Target: Logger {
                                                .unwrap_or(payment_params.max_total_cltv_expiry_delta - final_cltv_expiry_delta);
                                        let hop_total_cltv_delta = ($next_hops_cltv_delta as u32)
                                                .saturating_add($candidate.cltv_expiry_delta());
-                                       let doesnt_exceed_cltv_delta_limit = hop_total_cltv_delta <= max_total_cltv_expiry_delta;
+                                       let exceeds_cltv_delta_limit = hop_total_cltv_delta > max_total_cltv_expiry_delta;
 
                                        let value_contribution_msat = cmp::min(available_value_contribution_msat, $next_hops_value_contribution);
                                        // Includes paying fees for the use of the following channels.
@@ -916,14 +1033,26 @@ where L::Target: Logger {
                                        let over_path_minimum_msat = amount_to_transfer_over_msat >= $candidate.htlc_minimum_msat() &&
                                                amount_to_transfer_over_msat >= $next_hops_path_htlc_minimum_msat;
 
+                                       #[allow(unused_comparisons)] // $next_hops_path_htlc_minimum_msat is 0 in some calls so rustc complains
+                                       let may_overpay_to_meet_path_minimum_msat =
+                                               ((amount_to_transfer_over_msat < $candidate.htlc_minimum_msat() &&
+                                                 recommended_value_msat > $candidate.htlc_minimum_msat()) ||
+                                                (amount_to_transfer_over_msat < $next_hops_path_htlc_minimum_msat &&
+                                                 recommended_value_msat > $next_hops_path_htlc_minimum_msat));
+
+                                       let payment_failed_on_this_channel =
+                                               payment_params.previously_failed_channels.contains(&short_channel_id);
+
                                        // If HTLC minimum is larger than the amount we're going to transfer, we shouldn't
-                                       // bother considering this channel.
-                                       // Since we're choosing amount_to_transfer_over_msat as maximum possible, it can
-                                       // be only reduced later (not increased), so this channel should just be skipped
-                                       // as not sufficient.
-                                       if !over_path_minimum_msat && doesnt_exceed_cltv_delta_limit {
+                                       // bother considering this channel. If retrying with recommended_value_msat may
+                                       // allow us to hit the HTLC minimum limit, set htlc_minimum_limit so that we go
+                                       // around again with a higher amount.
+                                       if !contributes_sufficient_value || exceeds_max_path_length ||
+                                               exceeds_cltv_delta_limit || payment_failed_on_this_channel {
+                                               // Path isn't useful, ignore it and move on.
+                                       } else if may_overpay_to_meet_path_minimum_msat {
                                                hit_minimum_limit = true;
-                                       } else if contributes_sufficient_value && doesnt_exceed_cltv_delta_limit {
+                                       } else if over_path_minimum_msat {
                                                // Note that low contribution here (limited by available_liquidity_msat)
                                                // might violate htlc_minimum_msat on the hops which are next along the
                                                // payment path (upstream to the payee). To avoid that, we recompute
@@ -1009,9 +1138,16 @@ where L::Target: Logger {
                                                                }
                                                        }
 
-                                                       let path_penalty_msat = $next_hops_path_penalty_msat.saturating_add(
-                                                               scorer.channel_penalty_msat(short_channel_id, amount_to_transfer_over_msat,
-                                                                       *available_liquidity_msat, &$src_node_id, &$dest_node_id));
+                                                       let channel_usage = ChannelUsage {
+                                                               amount_msat: amount_to_transfer_over_msat,
+                                                               inflight_htlc_msat: used_liquidity_msat,
+                                                               effective_capacity,
+                                                       };
+                                                       let channel_penalty_msat = scorer.channel_penalty_msat(
+                                                               short_channel_id, &$src_node_id, &$dest_node_id, channel_usage
+                                                       );
+                                                       let path_penalty_msat = $next_hops_path_penalty_msat
+                                                               .saturating_add(channel_penalty_msat);
                                                        let new_graph_node = RouteGraphNode {
                                                                node_id: $src_node_id,
                                                                lowest_fee_to_peer_through_node: total_fee_msat,
@@ -1020,6 +1156,7 @@ where L::Target: Logger {
                                                                value_contribution_msat: value_contribution_msat,
                                                                path_htlc_minimum_msat,
                                                                path_penalty_msat,
+                                                               path_length_to_node,
                                                        };
 
                                                        // Update the way of reaching $src_node_id with the given short_channel_id (from $dest_node_id),
@@ -1095,14 +1232,17 @@ where L::Target: Logger {
                } }
        }
 
-       let empty_node_features = NodeFeatures::empty();
+       let default_node_features = default_node_features();
+
        // Find ways (channels with destination) to reach a given node and store them
        // in the corresponding data structures (routing graph etc).
        // $fee_to_target_msat represents how much it costs to reach to this node from the payee,
        // meaning how much will be paid in fees after this node (to the best of our knowledge).
        // This data can later be helpful to optimize routing (pay lower fees).
        macro_rules! add_entries_to_cheapest_to_target_node {
-               ( $node: expr, $node_id: expr, $fee_to_target_msat: expr, $next_hops_value_contribution: expr, $next_hops_path_htlc_minimum_msat: expr, $next_hops_path_penalty_msat: expr, $next_hops_cltv_delta: expr ) => {
+               ( $node: expr, $node_id: expr, $fee_to_target_msat: expr, $next_hops_value_contribution: expr,
+                 $next_hops_path_htlc_minimum_msat: expr, $next_hops_path_penalty_msat: expr,
+                 $next_hops_cltv_delta: expr, $next_hops_path_length: expr ) => {
                        let skip_node = if let Some(elem) = dist.get_mut(&$node_id) {
                                let was_processed = elem.was_processed;
                                elem.was_processed = true;
@@ -1119,14 +1259,17 @@ where L::Target: Logger {
                                if let Some(first_channels) = first_hop_targets.get(&$node_id) {
                                        for details in first_channels {
                                                let candidate = CandidateRouteHop::FirstHop { details };
-                                               add_entry!(candidate, our_node_id, $node_id, $fee_to_target_msat, $next_hops_value_contribution, $next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat, $next_hops_cltv_delta);
+                                               add_entry!(candidate, our_node_id, $node_id, $fee_to_target_msat,
+                                                       $next_hops_value_contribution,
+                                                       $next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat,
+                                                       $next_hops_cltv_delta, $next_hops_path_length);
                                        }
                                }
 
                                let features = if let Some(node_info) = $node.announcement_info.as_ref() {
                                        &node_info.features
                                } else {
-                                       &empty_node_features
+                                       &default_node_features
                                };
 
                                if !features.requires_unknown_bits() {
@@ -1142,7 +1285,12 @@ where L::Target: Logger {
                                                                                        info: directed_channel.with_update().unwrap(),
                                                                                        short_channel_id: *chan_id,
                                                                                };
-                                                                               add_entry!(candidate, *source, $node_id, $fee_to_target_msat, $next_hops_value_contribution, $next_hops_path_htlc_minimum_msat, $next_hops_path_penalty_msat, $next_hops_cltv_delta);
+                                                                               add_entry!(candidate, *source, $node_id,
+                                                                                       $fee_to_target_msat,
+                                                                                       $next_hops_value_contribution,
+                                                                                       $next_hops_path_htlc_minimum_msat,
+                                                                                       $next_hops_path_penalty_msat,
+                                                                                       $next_hops_cltv_delta, $next_hops_path_length);
                                                                        }
                                                                }
                                                        }
@@ -1157,9 +1305,8 @@ where L::Target: Logger {
 
        // TODO: diversify by nodes (so that all paths aren't doomed if one node is offline).
        'paths_collection: loop {
-               // For every new path, start from scratch, except
-               // bookkept_channels_liquidity_available_msat, which will improve
-               // the further iterations of path finding. Also don't erase first_hop_targets.
+               // For every new path, start from scratch, except for used_channel_liquidities, which
+               // helps to avoid reusing previously selected paths in future iterations.
                targets.clear();
                dist.clear();
                hit_minimum_limit = false;
@@ -1169,8 +1316,10 @@ where L::Target: Logger {
                if let Some(first_channels) = first_hop_targets.get(&payee_node_id) {
                        for details in first_channels {
                                let candidate = CandidateRouteHop::FirstHop { details };
-                               let added = add_entry!(candidate, our_node_id, payee_node_id, 0, path_value_msat, 0, 0u64, 0);
-                               log_trace!(logger, "{} direct route to payee via SCID {}", if added { "Added" } else { "Skipped" }, candidate.short_channel_id());
+                               let added = add_entry!(candidate, our_node_id, payee_node_id, 0, path_value_msat,
+                                                                       0, 0u64, 0, 0);
+                               log_trace!(logger, "{} direct route to payee via SCID {}",
+                                               if added { "Added" } else { "Skipped" }, candidate.short_channel_id());
                        }
                }
 
@@ -1183,7 +1332,7 @@ where L::Target: Logger {
                        // If not, targets.pop() will not even let us enter the loop in step 2.
                        None => {},
                        Some(node) => {
-                               add_entries_to_cheapest_to_target_node!(node, payee_node_id, 0, path_value_msat, 0, 0u64, 0);
+                               add_entries_to_cheapest_to_target_node!(node, payee_node_id, 0, path_value_msat, 0, 0u64, 0, 0);
                        },
                }
 
@@ -1210,6 +1359,7 @@ where L::Target: Logger {
                                let mut aggregate_next_hops_path_htlc_minimum_msat: u64 = 0;
                                let mut aggregate_next_hops_path_penalty_msat: u64 = 0;
                                let mut aggregate_next_hops_cltv_delta: u32 = 0;
+                               let mut aggregate_next_hops_path_length: u8 = 0;
 
                                for (idx, (hop, prev_hop_id)) in hop_iter.zip(prev_hop_iter).enumerate() {
                                        let source = NodeId::from_pubkey(&hop.src_node_id);
@@ -1223,25 +1373,45 @@ where L::Target: Logger {
                                                        short_channel_id: hop.short_channel_id,
                                                })
                                                .unwrap_or_else(|| CandidateRouteHop::PrivateHop { hint: hop });
-                                       let capacity_msat = candidate.effective_capacity().as_msat();
+
+                                       if !add_entry!(candidate, source, target, aggregate_next_hops_fee_msat,
+                                                               path_value_msat, aggregate_next_hops_path_htlc_minimum_msat,
+                                                               aggregate_next_hops_path_penalty_msat,
+                                                               aggregate_next_hops_cltv_delta, aggregate_next_hops_path_length) {
+                                               // If this hop was not used then there is no use checking the preceding
+                                               // hops in the RouteHint. We can break by just searching for a direct
+                                               // channel between last checked hop and first_hop_targets.
+                                               hop_used = false;
+                                       }
+
+                                       let used_liquidity_msat = used_channel_liquidities
+                                               .get(&(hop.short_channel_id, source < target)).copied().unwrap_or(0);
+                                       let channel_usage = ChannelUsage {
+                                               amount_msat: final_value_msat + aggregate_next_hops_fee_msat,
+                                               inflight_htlc_msat: used_liquidity_msat,
+                                               effective_capacity: candidate.effective_capacity(),
+                                       };
+                                       let channel_penalty_msat = scorer.channel_penalty_msat(
+                                               hop.short_channel_id, &source, &target, channel_usage
+                                       );
                                        aggregate_next_hops_path_penalty_msat = aggregate_next_hops_path_penalty_msat
-                                               .saturating_add(scorer.channel_penalty_msat(hop.short_channel_id, final_value_msat, capacity_msat, &source, &target));
+                                               .saturating_add(channel_penalty_msat);
 
                                        aggregate_next_hops_cltv_delta = aggregate_next_hops_cltv_delta
                                                .saturating_add(hop.cltv_expiry_delta as u32);
 
-                                       if !add_entry!(candidate, source, target, aggregate_next_hops_fee_msat, path_value_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta) {
-                                               // If this hop was not used then there is no use checking the preceding hops
-                                               // in the RouteHint. We can break by just searching for a direct channel between
-                                               // last checked hop and first_hop_targets
-                                               hop_used = false;
-                                       }
+                                       aggregate_next_hops_path_length = aggregate_next_hops_path_length
+                                               .saturating_add(1);
 
                                        // Searching for a direct channel between last checked hop and first_hop_targets
                                        if let Some(first_channels) = first_hop_targets.get(&NodeId::from_pubkey(&prev_hop_id)) {
                                                for details in first_channels {
                                                        let candidate = CandidateRouteHop::FirstHop { details };
-                                                       add_entry!(candidate, our_node_id, NodeId::from_pubkey(&prev_hop_id), aggregate_next_hops_fee_msat, path_value_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta);
+                                                       add_entry!(candidate, our_node_id, NodeId::from_pubkey(&prev_hop_id),
+                                                               aggregate_next_hops_fee_msat, path_value_msat,
+                                                               aggregate_next_hops_path_htlc_minimum_msat,
+                                                               aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta,
+                                                               aggregate_next_hops_path_length);
                                                }
                                        }
 
@@ -1252,7 +1422,7 @@ where L::Target: Logger {
                                        // In the next values of the iterator, the aggregate fees already reflects
                                        // the sum of value sent from payer (final_value_msat) and routing fees
                                        // for the last node in the RouteHint. We need to just add the fees to
-                                       // route through the current node so that the preceeding node (next iteration)
+                                       // route through the current node so that the preceding node (next iteration)
                                        // can use it.
                                        let hops_fee = compute_fees(aggregate_next_hops_fee_msat + final_value_msat, hop.fees)
                                                .map_or(None, |inc| inc.checked_add(aggregate_next_hops_fee_msat));
@@ -1277,7 +1447,13 @@ where L::Target: Logger {
                                                if let Some(first_channels) = first_hop_targets.get(&NodeId::from_pubkey(&hop.src_node_id)) {
                                                        for details in first_channels {
                                                                let candidate = CandidateRouteHop::FirstHop { details };
-                                                               add_entry!(candidate, our_node_id, NodeId::from_pubkey(&hop.src_node_id), aggregate_next_hops_fee_msat, path_value_msat, aggregate_next_hops_path_htlc_minimum_msat, aggregate_next_hops_path_penalty_msat, aggregate_next_hops_cltv_delta);
+                                                               add_entry!(candidate, our_node_id,
+                                                                       NodeId::from_pubkey(&hop.src_node_id),
+                                                                       aggregate_next_hops_fee_msat, path_value_msat,
+                                                                       aggregate_next_hops_path_htlc_minimum_msat,
+                                                                       aggregate_next_hops_path_penalty_msat,
+                                                                       aggregate_next_hops_cltv_delta,
+                                                                       aggregate_next_hops_path_length);
                                                        }
                                                }
                                        }
@@ -1300,19 +1476,19 @@ where L::Target: Logger {
                // Both these cases (and other cases except reaching recommended_value_msat) mean that
                // paths_collection will be stopped because found_new_path==false.
                // This is not necessarily a routing failure.
-               'path_construction: while let Some(RouteGraphNode { node_id, lowest_fee_to_node, total_cltv_delta, value_contribution_msat, path_htlc_minimum_msat, path_penalty_msat, .. }) = targets.pop() {
+               'path_construction: while let Some(RouteGraphNode { node_id, lowest_fee_to_node, total_cltv_delta, value_contribution_msat, path_htlc_minimum_msat, path_penalty_msat, path_length_to_node, .. }) = targets.pop() {
 
                        // Since we're going payee-to-payer, hitting our node as a target means we should stop
                        // traversing the graph and arrange the path out of what we found.
                        if node_id == our_node_id {
                                let mut new_entry = dist.remove(&our_node_id).unwrap();
-                               let mut ordered_hops = vec!((new_entry.clone(), NodeFeatures::empty()));
+                               let mut ordered_hops: Vec<(PathBuildingHop, NodeFeatures)> = vec!((new_entry.clone(), default_node_features.clone()));
 
                                'path_walk: loop {
                                        let mut features_set = false;
                                        if let Some(first_channels) = first_hop_targets.get(&ordered_hops.last().unwrap().0.node_id) {
                                                for details in first_channels {
-                                                       if details.short_channel_id.unwrap() == ordered_hops.last().unwrap().0.candidate.short_channel_id() {
+                                                       if details.get_outbound_payment_scid().unwrap() == ordered_hops.last().unwrap().0.candidate.short_channel_id() {
                                                                ordered_hops.last_mut().unwrap().1 = details.counterparty.features.to_context();
                                                                features_set = true;
                                                                break;
@@ -1324,7 +1500,7 @@ where L::Target: Logger {
                                                        if let Some(node_info) = node.announcement_info.as_ref() {
                                                                ordered_hops.last_mut().unwrap().1 = node_info.features.clone();
                                                        } else {
-                                                               ordered_hops.last_mut().unwrap().1 = NodeFeatures::empty();
+                                                               ordered_hops.last_mut().unwrap().1 = default_node_features.clone();
                                                        }
                                                } else {
                                                        // We can fill in features for everything except hops which were
@@ -1351,7 +1527,7 @@ where L::Target: Logger {
                                        // so that fees paid for a HTLC forwarding on the current channel are
                                        // associated with the previous channel (where they will be subtracted).
                                        ordered_hops.last_mut().unwrap().0.fee_msat = new_entry.hop_use_fee_msat;
-                                       ordered_hops.push((new_entry.clone(), NodeFeatures::empty()));
+                                       ordered_hops.push((new_entry.clone(), default_node_features.clone()));
                                }
                                ordered_hops.last_mut().unwrap().0.fee_msat = value_contribution_msat;
                                ordered_hops.last_mut().unwrap().0.hop_use_fee_msat = 0;
@@ -1378,32 +1554,36 @@ where L::Target: Logger {
                                // Remember that we used these channels so that we don't rely
                                // on the same liquidity in future paths.
                                let mut prevented_redundant_path_selection = false;
-                               for (payment_hop, _) in payment_path.hops.iter() {
-                                       let channel_liquidity_available_msat = bookkept_channels_liquidity_available_msat.get_mut(&payment_hop.candidate.short_channel_id()).unwrap();
-                                       let mut spent_on_hop_msat = value_contribution_msat;
-                                       let next_hops_fee_msat = payment_hop.next_hops_fee_msat;
-                                       spent_on_hop_msat += next_hops_fee_msat;
-                                       if spent_on_hop_msat == *channel_liquidity_available_msat {
+                               let prev_hop_iter = core::iter::once(&our_node_id)
+                                       .chain(payment_path.hops.iter().map(|(hop, _)| &hop.node_id));
+                               for (prev_hop, (hop, _)) in prev_hop_iter.zip(payment_path.hops.iter()) {
+                                       let spent_on_hop_msat = value_contribution_msat + hop.next_hops_fee_msat;
+                                       let used_liquidity_msat = used_channel_liquidities
+                                               .entry((hop.candidate.short_channel_id(), *prev_hop < hop.node_id))
+                                               .and_modify(|used_liquidity_msat| *used_liquidity_msat += spent_on_hop_msat)
+                                               .or_insert(spent_on_hop_msat);
+                                       let hop_capacity = hop.candidate.effective_capacity();
+                                       let hop_max_msat = max_htlc_from_capacity(hop_capacity, channel_saturation_pow_half);
+                                       if *used_liquidity_msat == hop_max_msat {
                                                // If this path used all of this channel's available liquidity, we know
                                                // this path will not be selected again in the next loop iteration.
                                                prevented_redundant_path_selection = true;
                                        }
-                                       *channel_liquidity_available_msat -= spent_on_hop_msat;
+                                       debug_assert!(*used_liquidity_msat <= hop_max_msat);
                                }
                                if !prevented_redundant_path_selection {
                                        // If we weren't capped by hitting a liquidity limit on a channel in the path,
                                        // we'll probably end up picking the same path again on the next iteration.
                                        // Decrease the available liquidity of a hop in the middle of the path.
                                        let victim_scid = payment_path.hops[(payment_path.hops.len()) / 2].0.candidate.short_channel_id();
+                                       let exhausted = u64::max_value();
                                        log_trace!(logger, "Disabling channel {} for future path building iterations to avoid duplicates.", victim_scid);
-                                       let victim_liquidity = bookkept_channels_liquidity_available_msat.get_mut(&victim_scid).unwrap();
-                                       *victim_liquidity = 0;
+                                       *used_channel_liquidities.entry((victim_scid, false)).or_default() = exhausted;
+                                       *used_channel_liquidities.entry((victim_scid, true)).or_default() = exhausted;
                                }
 
-                               // Track the total amount all our collected paths allow to send so that we:
-                               // - know when to stop looking for more paths
-                               // - know which of the hops are useless considering how much more sats we need
-                               //   (contributes_sufficient_value)
+                               // Track the total amount all our collected paths allow to send so that we know
+                               // when to stop looking for more paths
                                already_collected_value_msat += value_contribution_msat;
 
                                payment_paths.push(payment_path);
@@ -1422,12 +1602,18 @@ where L::Target: Logger {
                        match network_nodes.get(&node_id) {
                                None => {},
                                Some(node) => {
-                                       add_entries_to_cheapest_to_target_node!(node, node_id, lowest_fee_to_node, value_contribution_msat, path_htlc_minimum_msat, path_penalty_msat, total_cltv_delta);
+                                       add_entries_to_cheapest_to_target_node!(node, node_id, lowest_fee_to_node,
+                                               value_contribution_msat, path_htlc_minimum_msat, path_penalty_msat,
+                                               total_cltv_delta, path_length_to_node);
                                },
                        }
                }
 
                if !allow_mpp {
+                       if !found_new_path && channel_saturation_pow_half != 0 {
+                               channel_saturation_pow_half = 0;
+                               continue 'paths_collection;
+                       }
                        // If we don't support MPP, no use trying to gather more value ever.
                        break 'paths_collection;
                }
@@ -1437,7 +1623,9 @@ where L::Target: Logger {
                // iteration.
                // In the latter case, making another path finding attempt won't help,
                // because we deterministically terminated the search due to low liquidity.
-               if already_collected_value_msat >= recommended_value_msat || !found_new_path {
+               if !found_new_path && channel_saturation_pow_half != 0 {
+                       channel_saturation_pow_half = 0;
+               } else if already_collected_value_msat >= recommended_value_msat || !found_new_path {
                        log_trace!(logger, "Have now collected {} msat (seeking {} msat) in paths. Last path loop {} a new path.",
                                already_collected_value_msat, recommended_value_msat, if found_new_path { "found" } else { "did not find" });
                        break 'paths_collection;
@@ -1553,8 +1741,32 @@ where L::Target: Logger {
        // Step (9).
        // Select the best route by lowest total cost.
        drawn_routes.sort_unstable_by_key(|paths| paths.iter().map(|path| path.get_cost_msat()).sum::<u64>());
+       let selected_route = drawn_routes.first_mut().unwrap();
+
+       // Sort by the path itself and combine redundant paths.
+       // Note that we sort by SCIDs alone as its simpler but when combining we have to ensure we
+       // compare both SCIDs and NodeIds as individual nodes may use random aliases causing collisions
+       // across nodes.
+       selected_route.sort_unstable_by_key(|path| {
+               let mut key = [0u64; MAX_PATH_LENGTH_ESTIMATE as usize];
+               debug_assert!(path.hops.len() <= key.len());
+               for (scid, key) in path.hops.iter().map(|h| h.0.candidate.short_channel_id()).zip(key.iter_mut()) {
+                       *key = scid;
+               }
+               key
+       });
+       for idx in 0..(selected_route.len() - 1) {
+               if idx + 1 >= selected_route.len() { break; }
+               if iter_equal(selected_route[idx    ].hops.iter().map(|h| (h.0.candidate.short_channel_id(), h.0.node_id)),
+                             selected_route[idx + 1].hops.iter().map(|h| (h.0.candidate.short_channel_id(), h.0.node_id))) {
+                       let new_value = selected_route[idx].get_value_msat() + selected_route[idx + 1].get_value_msat();
+                       selected_route[idx].update_value_and_recompute_fees(new_value);
+                       selected_route.remove(idx + 1);
+               }
+       }
+
        let mut selected_paths = Vec::<Vec<Result<RouteHop, LightningError>>>::new();
-       for payment_path in drawn_routes.first().unwrap() {
+       for payment_path in selected_route {
                let mut path = payment_path.hops.iter().map(|(payment_hop, node_features)| {
                        Ok(RouteHop {
                                pubkey: PublicKey::from_slice(payment_hop.node_id.as_slice()).map_err(|_| LightningError{err: format!("Public key {:?} is invalid", &payment_hop.node_id), action: ErrorAction::IgnoreAndLog(Level::Trace)})?,
@@ -1572,6 +1784,8 @@ where L::Target: Logger {
                });
                selected_paths.push(path);
        }
+       // Make sure we would never create a route with more paths than we allow.
+       debug_assert!(selected_paths.len() <= payment_params.max_path_count.into());
 
        if let Some(features) = &payment_params.features {
                for path in selected_paths.iter_mut() {
@@ -1593,7 +1807,9 @@ where L::Target: Logger {
 // destination, if the remaining CLTV expiry delta exactly matches a feasible path in the network
 // graph. In order to improve privacy, this method obfuscates the CLTV expiry deltas along the
 // payment path by adding a randomized 'shadow route' offset to the final hop.
-fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters, network_graph: &ReadOnlyNetworkGraph, random_seed_bytes: &[u8; 32]) {
+fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
+       network_graph: &ReadOnlyNetworkGraph, random_seed_bytes: &[u8; 32]
+) {
        let network_channels = network_graph.channels();
        let network_nodes = network_graph.nodes();
 
@@ -1675,16 +1891,96 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
        }
 }
 
+/// Construct a route from us (payer) to the target node (payee) via the given hops (which should
+/// exclude the payer, but include the payee). This may be useful, e.g., for probing the chosen path.
+///
+/// Re-uses logic from `find_route`, so the restrictions described there also apply here.
+pub fn build_route_from_hops<L: Deref, GL: Deref>(
+       our_node_pubkey: &PublicKey, hops: &[PublicKey], route_params: &RouteParameters,
+       network_graph: &NetworkGraph<GL>, logger: L, random_seed_bytes: &[u8; 32]
+) -> 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, route_params.final_cltv_expiry_delta, 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, final_cltv_expiry_delta: u32,
+       logger: L, random_seed_bytes: &[u8; 32]
+) -> Result<Route, LightningError> where L::Target: Logger {
+
+       struct HopScorer {
+               our_node_id: NodeId,
+               hop_ids: [Option<NodeId>; MAX_PATH_LENGTH_ESTIMATE as usize],
+       }
+
+       impl Score for HopScorer {
+               fn channel_penalty_msat(&self, _short_channel_id: u64, source: &NodeId, target: &NodeId,
+                       _usage: ChannelUsage) -> u64
+               {
+                       let mut cur_id = self.our_node_id;
+                       for i in 0..self.hop_ids.len() {
+                               if let Some(next_id) = self.hop_ids[i] {
+                                       if cur_id == *source && next_id == *target {
+                                               return 0;
+                                       }
+                                       cur_id = next_id;
+                               } else {
+                                       break;
+                               }
+                       }
+                       u64::max_value()
+               }
+
+               fn payment_path_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
+
+               fn payment_path_successful(&mut self, _path: &[&RouteHop]) {}
+
+               fn probe_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
+
+               fn probe_successful(&mut self, _path: &[&RouteHop]) {}
+       }
+
+       impl<'a> Writeable for HopScorer {
+               #[inline]
+               fn write<W: Writer>(&self, _w: &mut W) -> Result<(), io::Error> {
+                       unreachable!();
+               }
+       }
+
+       if hops.len() > MAX_PATH_LENGTH_ESTIMATE.into() {
+               return Err(LightningError{err: "Cannot build a route exceeding the maximum path length.".to_owned(), action: ErrorAction::IgnoreError});
+       }
+
+       let our_node_id = NodeId::from_pubkey(our_node_pubkey);
+       let mut hop_ids = [None; MAX_PATH_LENGTH_ESTIMATE as usize];
+       for i in 0..hops.len() {
+               hop_ids[i] = Some(NodeId::from_pubkey(&hops[i]));
+       }
+
+       let scorer = HopScorer { our_node_id, hop_ids };
+
+       get_route(our_node_pubkey, payment_params, network_graph, None, final_value_msat,
+               final_cltv_expiry_delta, logger, &scorer, random_seed_bytes)
+}
+
 #[cfg(test)]
 mod tests {
-       use routing::network_graph::{NetworkGraph, NetGraphMsgHandler, NodeId};
-       use routing::router::{get_route, add_random_cltv_offset, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA};
-       use routing::scoring::Score;
+       use routing::gossip::{NetworkGraph, P2PGossipSync, NodeId, EffectiveCapacity};
+       use routing::router::{get_route, build_route_from_hops_internal, add_random_cltv_offset, default_node_features,
+               PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees,
+               DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA, MAX_PATH_LENGTH_ESTIMATE};
+       use routing::scoring::{ChannelUsage, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
        use chain::transaction::OutPoint;
        use chain::keysinterface::KeysInterface;
        use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
        use ln::msgs::{ErrorAction, LightningError, OptionalField, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler,
-          NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate};
+               NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate};
        use ln::channelmanager;
        use util::test_utils;
        use util::chacha20::ChaCha20;
@@ -1702,12 +1998,14 @@ mod tests {
 
        use hex;
 
-       use bitcoin::secp256k1::key::{PublicKey,SecretKey};
+       use bitcoin::secp256k1::{PublicKey,SecretKey};
        use bitcoin::secp256k1::{Secp256k1, All};
 
        use prelude::*;
        use sync::{self, Arc};
 
+       use core::convert::TryInto;
+
        fn get_channel_details(short_channel_id: Option<u64>, node_id: PublicKey,
                        features: InitFeatures, outbound_capacity_msat: u64) -> channelmanager::ChannelDetails {
                channelmanager::ChannelDetails {
@@ -1717,27 +2015,34 @@ mod tests {
                                node_id,
                                unspendable_punishment_reserve: 0,
                                forwarding_info: None,
+                               outbound_htlc_minimum_msat: None,
+                               outbound_htlc_maximum_msat: None,
                        },
                        funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
                        channel_type: None,
                        short_channel_id,
+                       outbound_scid_alias: None,
                        inbound_scid_alias: None,
                        channel_value_satoshis: 0,
                        user_channel_id: 0,
                        balance_msat: 0,
                        outbound_capacity_msat,
+                       next_outbound_htlc_limit_msat: outbound_capacity_msat,
                        inbound_capacity_msat: 42,
                        unspendable_punishment_reserve: None,
                        confirmations_required: None,
                        force_close_spend_delay: None,
-                       is_outbound: true, is_funding_locked: true,
+                       is_outbound: true, is_channel_ready: true,
                        is_usable: true, is_public: true,
+                       inbound_htlc_minimum_msat: None,
+                       inbound_htlc_maximum_msat: None,
+                       config: None,
                }
        }
 
        // Using the same keys for LN and BTC ids
        fn add_channel(
-               net_graph_msg_handler: &NetGraphMsgHandler<Arc<NetworkGraph>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
+               gossip_sync: &P2PGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
                secp_ctx: &Secp256k1<All>, node_1_privkey: &SecretKey, node_2_privkey: &SecretKey, features: ChannelFeatures, short_channel_id: u64
        ) {
                let node_id_1 = PublicKey::from_secret_key(&secp_ctx, node_1_privkey);
@@ -1756,36 +2061,36 @@ mod tests {
 
                let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
                let valid_announcement = ChannelAnnouncement {
-                       node_signature_1: secp_ctx.sign(&msghash, node_1_privkey),
-                       node_signature_2: secp_ctx.sign(&msghash, node_2_privkey),
-                       bitcoin_signature_1: secp_ctx.sign(&msghash, node_1_privkey),
-                       bitcoin_signature_2: secp_ctx.sign(&msghash, node_2_privkey),
+                       node_signature_1: secp_ctx.sign_ecdsa(&msghash, node_1_privkey),
+                       node_signature_2: secp_ctx.sign_ecdsa(&msghash, node_2_privkey),
+                       bitcoin_signature_1: secp_ctx.sign_ecdsa(&msghash, node_1_privkey),
+                       bitcoin_signature_2: secp_ctx.sign_ecdsa(&msghash, node_2_privkey),
                        contents: unsigned_announcement.clone(),
                };
-               match net_graph_msg_handler.handle_channel_announcement(&valid_announcement) {
+               match gossip_sync.handle_channel_announcement(&valid_announcement) {
                        Ok(res) => assert!(res),
                        _ => panic!()
                };
        }
 
        fn update_channel(
-               net_graph_msg_handler: &NetGraphMsgHandler<Arc<NetworkGraph>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
+               gossip_sync: &P2PGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
                secp_ctx: &Secp256k1<All>, node_privkey: &SecretKey, update: UnsignedChannelUpdate
        ) {
                let msghash = hash_to_message!(&Sha256dHash::hash(&update.encode()[..])[..]);
                let valid_channel_update = ChannelUpdate {
-                       signature: secp_ctx.sign(&msghash, node_privkey),
+                       signature: secp_ctx.sign_ecdsa(&msghash, node_privkey),
                        contents: update.clone()
                };
 
-               match net_graph_msg_handler.handle_channel_update(&valid_channel_update) {
+               match gossip_sync.handle_channel_update(&valid_channel_update) {
                        Ok(res) => assert!(res),
                        Err(_) => panic!()
                };
        }
 
        fn add_or_update_node(
-               net_graph_msg_handler: &NetGraphMsgHandler<Arc<NetworkGraph>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
+               gossip_sync: &P2PGossipSync<Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>,
                secp_ctx: &Secp256k1<All>, node_privkey: &SecretKey, features: NodeFeatures, timestamp: u32
        ) {
                let node_id = PublicKey::from_secret_key(&secp_ctx, node_privkey);
@@ -1801,18 +2106,18 @@ mod tests {
                };
                let msghash = hash_to_message!(&Sha256dHash::hash(&unsigned_announcement.encode()[..])[..]);
                let valid_announcement = NodeAnnouncement {
-                       signature: secp_ctx.sign(&msghash, node_privkey),
+                       signature: secp_ctx.sign_ecdsa(&msghash, node_privkey),
                        contents: unsigned_announcement.clone()
                };
 
-               match net_graph_msg_handler.handle_node_announcement(&valid_announcement) {
+               match gossip_sync.handle_node_announcement(&valid_announcement) {
                        Ok(_) => (),
                        Err(_) => panic!()
                };
        }
 
        fn get_nodes(secp_ctx: &Secp256k1<All>) -> (SecretKey, PublicKey, Vec<SecretKey>, Vec<PublicKey>) {
-               let privkeys: Vec<SecretKey> = (2..10).map(|i| {
+               let privkeys: Vec<SecretKey> = (2..22).map(|i| {
                        SecretKey::from_slice(&hex::decode(format!("{:02x}", i).repeat(32)).unwrap()[..]).unwrap()
                }).collect();
 
@@ -1839,18 +2144,71 @@ mod tests {
                }
        }
 
+       fn build_line_graph() -> (
+               Secp256k1<All>, sync::Arc<NetworkGraph<Arc<test_utils::TestLogger>>>,
+               P2PGossipSync<sync::Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, sync::Arc<test_utils::TestChainSource>, sync::Arc<test_utils::TestLogger>>,
+               sync::Arc<test_utils::TestChainSource>, sync::Arc<test_utils::TestLogger>,
+       ) {
+               let secp_ctx = Secp256k1::new();
+               let logger = Arc::new(test_utils::TestLogger::new());
+               let chain_monitor = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
+               let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
+               let network_graph = Arc::new(NetworkGraph::new(genesis_hash, Arc::clone(&logger)));
+               let gossip_sync = P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger));
+
+               // Build network from our_id to node 19:
+               // our_id -1(1)2- node0 -1(2)2- node1 - ... - node19
+               let (our_privkey, _, privkeys, _) = get_nodes(&secp_ctx);
+
+               for (idx, (cur_privkey, next_privkey)) in core::iter::once(&our_privkey)
+                       .chain(privkeys.iter()).zip(privkeys.iter()).enumerate() {
+                       let cur_short_channel_id = (idx as u64) + 1;
+                       add_channel(&gossip_sync, &secp_ctx, &cur_privkey, &next_privkey,
+                               ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), cur_short_channel_id);
+                       update_channel(&gossip_sync, &secp_ctx, &cur_privkey, UnsignedChannelUpdate {
+                               chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                               short_channel_id: cur_short_channel_id,
+                               timestamp: idx as u32,
+                               flags: 0,
+                               cltv_expiry_delta: 0,
+                               htlc_minimum_msat: 0,
+                               htlc_maximum_msat: OptionalField::Absent,
+                               fee_base_msat: 0,
+                               fee_proportional_millionths: 0,
+                               excess_data: Vec::new()
+                       });
+                       update_channel(&gossip_sync, &secp_ctx, &next_privkey, UnsignedChannelUpdate {
+                               chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                               short_channel_id: cur_short_channel_id,
+                               timestamp: (idx as u32)+1,
+                               flags: 1,
+                               cltv_expiry_delta: 0,
+                               htlc_minimum_msat: 0,
+                               htlc_maximum_msat: OptionalField::Absent,
+                               fee_base_msat: 0,
+                               fee_proportional_millionths: 0,
+                               excess_data: Vec::new()
+                       });
+                       add_or_update_node(&gossip_sync, &secp_ctx, next_privkey,
+                               NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
+               }
+
+               (secp_ctx, network_graph, gossip_sync, chain_monitor, logger)
+       }
+
        fn build_graph() -> (
                Secp256k1<All>,
-               sync::Arc<NetworkGraph>,
-               NetGraphMsgHandler<sync::Arc<NetworkGraph>, sync::Arc<test_utils::TestChainSource>, sync::Arc<crate::util::test_utils::TestLogger>>,
+               sync::Arc<NetworkGraph<Arc<test_utils::TestLogger>>>,
+               P2PGossipSync<sync::Arc<NetworkGraph<Arc<test_utils::TestLogger>>>, sync::Arc<test_utils::TestChainSource>, sync::Arc<test_utils::TestLogger>>,
                sync::Arc<test_utils::TestChainSource>,
                sync::Arc<test_utils::TestLogger>,
        ) {
                let secp_ctx = Secp256k1::new();
                let logger = Arc::new(test_utils::TestLogger::new());
                let chain_monitor = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
-               let network_graph = Arc::new(NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()));
-               let net_graph_msg_handler = NetGraphMsgHandler::new(Arc::clone(&network_graph), None, Arc::clone(&logger));
+               let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
+               let network_graph = Arc::new(NetworkGraph::new(genesis_hash, Arc::clone(&logger)));
+               let gossip_sync = P2PGossipSync::new(Arc::clone(&network_graph), None, Arc::clone(&logger));
                // Build network from our_id to node6:
                //
                //        -1(1)2-  node0  -1(3)2-
@@ -1912,8 +2270,8 @@ mod tests {
 
                let (our_privkey, _, privkeys, _) = get_nodes(&secp_ctx);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, &privkeys[0], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[0], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 1,
@@ -1926,10 +2284,10 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[0], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[0], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2);
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 1,
@@ -1941,7 +2299,7 @@ mod tests {
                        fee_proportional_millionths: u32::max_value(),
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 1,
@@ -1954,10 +2312,10 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, &privkeys[7], ChannelFeatures::from_le_bytes(id_to_feature_flags(12)), 12);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[7], ChannelFeatures::from_le_bytes(id_to_feature_flags(12)), 12);
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 1,
@@ -1969,7 +2327,7 @@ mod tests {
                        fee_proportional_millionths: u32::max_value(),
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 1,
@@ -1982,10 +2340,10 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[7], NodeFeatures::from_le_bytes(id_to_feature_flags(8)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[7], NodeFeatures::from_le_bytes(id_to_feature_flags(8)), 0);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 1,
@@ -1997,7 +2355,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 1,
@@ -2010,8 +2368,8 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 1,
@@ -2023,7 +2381,7 @@ mod tests {
                        fee_proportional_millionths: 1000000,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 1,
@@ -2036,8 +2394,8 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(13)), 13);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[7], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(13)), 13);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 1,
@@ -2049,7 +2407,7 @@ mod tests {
                        fee_proportional_millionths: 2000000,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 1,
@@ -2062,10 +2420,10 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 1,
@@ -2077,7 +2435,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 1,
@@ -2090,8 +2448,8 @@ mod tests {
                        excess_data: Vec::new(),
                });
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(11)), 11);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(11)), 11);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 11,
                        timestamp: 1,
@@ -2103,7 +2461,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 11,
                        timestamp: 1,
@@ -2116,12 +2474,12 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(5)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(5)), 0);
 
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], &privkeys[5], ChannelFeatures::from_le_bytes(id_to_feature_flags(7)), 7);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[5], ChannelFeatures::from_le_bytes(id_to_feature_flags(7)), 7);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 7,
                        timestamp: 1,
@@ -2133,7 +2491,7 @@ mod tests {
                        fee_proportional_millionths: 1000000,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[5], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[5], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 7,
                        timestamp: 1,
@@ -2146,9 +2504,9 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[5], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[5], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0);
 
-               (secp_ctx, network_graph, net_graph_msg_handler, chain_monitor, logger)
+               (secp_ctx, network_graph, gossip_sync, chain_monitor, logger)
        }
 
        #[test]
@@ -2208,7 +2566,7 @@ mod tests {
 
        #[test]
        fn htlc_minimum_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let payment_params = PaymentParameters::from_node_id(nodes[2]);
                let scorer = test_utils::TestScorer::with_penalty(0);
@@ -2218,7 +2576,7 @@ mod tests {
                // Simple route to 2 via 1
 
                // Disable other paths
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -2230,7 +2588,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 2,
@@ -2242,7 +2600,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 2,
@@ -2254,7 +2612,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 2,
@@ -2266,7 +2624,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 7,
                        timestamp: 2,
@@ -2281,7 +2639,7 @@ mod tests {
 
                // Check against amount_to_transfer_over_msat.
                // Set minimal HTLC of 200_000_000 msat.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 3,
@@ -2296,7 +2654,7 @@ mod tests {
 
                // Second hop only allows to forward 199_999_999 at most, thus not allowing the first hop to
                // be used.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 3,
@@ -2315,7 +2673,7 @@ mod tests {
                } else { panic!(); }
 
                // Lift the restriction on the first hop.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 4,
@@ -2335,7 +2693,7 @@ mod tests {
 
        #[test]
        fn htlc_minimum_overpay_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known());
                let scorer = test_utils::TestScorer::with_penalty(0);
@@ -2345,7 +2703,7 @@ mod tests {
                // A route to node#2 via two paths.
                // One path allows transferring 35-40 sats, another one also allows 35-40 sats.
                // Thus, they can't send 60 without overpaying.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -2357,7 +2715,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 3,
@@ -2371,7 +2729,7 @@ mod tests {
                });
 
                // Make 0 fee.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 2,
@@ -2383,7 +2741,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 2,
@@ -2397,7 +2755,7 @@ mod tests {
                });
 
                // Disable other paths
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 3,
@@ -2418,7 +2776,7 @@ mod tests {
 
                // Now, test that if there are 2 paths, a "cheaper" by fee path wouldn't be prioritized
                // while taking even more fee to match htlc_minimum_msat.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 4,
@@ -2430,7 +2788,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 3,
@@ -2442,7 +2800,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 4,
@@ -2473,7 +2831,7 @@ mod tests {
 
        #[test]
        fn disable_channels_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let payment_params = PaymentParameters::from_node_id(nodes[2]);
                let scorer = test_utils::TestScorer::with_penalty(0);
@@ -2481,7 +2839,7 @@ mod tests {
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
                // // Disable channels 4 and 12 by flags=2
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 2,
@@ -2493,7 +2851,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -2533,7 +2891,7 @@ mod tests {
 
        #[test]
        fn disable_node_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let payment_params = PaymentParameters::from_node_id(nodes[2]);
                let scorer = test_utils::TestScorer::with_penalty(0);
@@ -2543,9 +2901,9 @@ mod tests {
                // Disable nodes 1, 2, and 8 by requiring unknown feature bits
                let mut unknown_features = NodeFeatures::known();
                unknown_features.set_unknown_feature_required();
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[0], unknown_features.clone(), 1);
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[1], unknown_features.clone(), 1);
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[7], unknown_features.clone(), 1);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[0], unknown_features.clone(), 1);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], unknown_features.clone(), 1);
+               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, 42, Arc::clone(&logger), &scorer, &random_seed_bytes) {
@@ -2779,7 +3137,7 @@ mod tests {
                assert_eq!(route.paths[0][4].short_channel_id, 8);
                assert_eq!(route.paths[0][4].fee_msat, 100);
                assert_eq!(route.paths[0][4].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][4].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][4].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -2855,7 +3213,7 @@ mod tests {
                assert_eq!(route.paths[0][4].short_channel_id, 8);
                assert_eq!(route.paths[0][4].fee_msat, 100);
                assert_eq!(route.paths[0][4].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][4].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][4].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -2888,7 +3246,7 @@ mod tests {
 
        #[test]
        fn multi_hint_last_hops_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let last_hops = multi_hop_last_hops_hint([nodes[2], nodes[3]]);
                let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops.clone());
@@ -2899,7 +3257,7 @@ mod tests {
                // Test shows that multiple hop hints are considered.
 
                // Disabling channels 6 & 7 by flags=2
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 2,
@@ -2911,7 +3269,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 7,
                        timestamp: 2,
@@ -2952,13 +3310,13 @@ mod tests {
                assert_eq!(route.paths[0][3].short_channel_id, last_hops[0].0[1].short_channel_id);
                assert_eq!(route.paths[0][3].fee_msat, 100);
                assert_eq!(route.paths[0][3].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][3].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][3].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
        #[test]
        fn private_multi_hint_last_hops_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
 
                let non_announced_privkey = SecretKey::from_slice(&hex::decode(format!("{:02x}", 0xf0).repeat(32)).unwrap()[..]).unwrap();
@@ -2971,7 +3329,7 @@ mod tests {
                // Test shows that multiple hop hints are considered.
 
                // Disabling channels 6 & 7 by flags=2
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 2,
@@ -2983,7 +3341,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 7,
                        timestamp: 2,
@@ -3017,14 +3375,14 @@ mod tests {
                assert_eq!(route.paths[0][2].short_channel_id, last_hops[0].0[0].short_channel_id);
                assert_eq!(route.paths[0][2].fee_msat, 0);
                assert_eq!(route.paths[0][2].cltv_expiry_delta, 129);
-               assert_eq!(route.paths[0][2].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][2].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][2].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
 
                assert_eq!(route.paths[0][3].pubkey, nodes[6]);
                assert_eq!(route.paths[0][3].short_channel_id, last_hops[0].0[1].short_channel_id);
                assert_eq!(route.paths[0][3].fee_msat, 100);
                assert_eq!(route.paths[0][3].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][3].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][3].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -3115,7 +3473,7 @@ mod tests {
                assert_eq!(route.paths[0][4].short_channel_id, 8);
                assert_eq!(route.paths[0][4].fee_msat, 100);
                assert_eq!(route.paths[0][4].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][4].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][4].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -3145,7 +3503,7 @@ mod tests {
                assert_eq!(route.paths[0][1].short_channel_id, 8);
                assert_eq!(route.paths[0][1].fee_msat, 100);
                assert_eq!(route.paths[0][1].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][1].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][1].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][1].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
 
                last_hops[0].0[0].fees.base_msat = 1000;
@@ -3182,7 +3540,7 @@ mod tests {
                assert_eq!(route.paths[0][3].short_channel_id, 10);
                assert_eq!(route.paths[0][3].fee_msat, 100);
                assert_eq!(route.paths[0][3].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][3].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][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
@@ -3223,7 +3581,7 @@ mod tests {
                assert_eq!(route.paths[0][4].short_channel_id, 8);
                assert_eq!(route.paths[0][4].fee_msat, 2000);
                assert_eq!(route.paths[0][4].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][4].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][4].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -3249,8 +3607,12 @@ mod tests {
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               get_route(&source_node_id, &payment_params, &NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()).read_only(),
-                               Some(&our_chans.iter().collect::<Vec<_>>()), route_val, 42, &test_utils::TestLogger::new(), &scorer, &random_seed_bytes)
+               let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
+               let logger = test_utils::TestLogger::new();
+               let network_graph = NetworkGraph::new(genesis_hash, &logger);
+               let route = get_route(&source_node_id, &payment_params, &network_graph.read_only(),
+                               Some(&our_chans.iter().collect::<Vec<_>>()), route_val, 42, &logger, &scorer, &random_seed_bytes);
+               route
        }
 
        #[test]
@@ -3275,7 +3637,7 @@ mod tests {
                assert_eq!(route.paths[0][1].short_channel_id, 8);
                assert_eq!(route.paths[0][1].fee_msat, 1000000);
                assert_eq!(route.paths[0][1].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][1].node_features.le_flags(), &[0; 0]); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][1].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][1].channel_features.le_flags(), &[0; 0]); // We can't learn any flags from invoices, sadly
        }
 
@@ -3301,7 +3663,7 @@ mod tests {
        fn available_amount_while_routing_test() {
                // Tests whether we choose the correct available channel amount while routing.
 
-               let (secp_ctx, network_graph, mut net_graph_msg_handler, chain_monitor, logger) = build_graph();
+               let (secp_ctx, network_graph, mut gossip_sync, chain_monitor, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -3312,7 +3674,7 @@ mod tests {
                // our node to node2 via node0: channels {1, 3}.
 
                // First disable all other paths.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -3324,7 +3686,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -3339,7 +3701,7 @@ mod tests {
 
                // Make the first channel (#1) very permissive,
                // and we will be testing all limits on the second channel.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 2,
@@ -3354,7 +3716,7 @@ mod tests {
 
                // First, let's see if routing works if we have absolutely no idea about the available amount.
                // In this case, it should be set to 250_000 sats.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 2,
@@ -3385,9 +3747,9 @@ mod tests {
                        assert_eq!(path.last().unwrap().fee_msat, 250_000_000);
                }
 
-               // Check that setting outbound_capacity_msat in first_hops limits the channels.
+               // Check that setting next_outbound_htlc_limit_msat in first_hops limits the channels.
                // Disable channel #1 and use another first hop.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 3,
@@ -3400,7 +3762,7 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               // Now, limit the first_hop by the outbound_capacity_msat of 200_000 sats.
+               // Now, limit the first_hop by the next_outbound_htlc_limit_msat of 200_000 sats.
                let our_chans = vec![get_channel_details(Some(42), nodes[0].clone(), InitFeatures::from_le_bytes(vec![0b11]), 200_000_000)];
 
                {
@@ -3422,7 +3784,7 @@ mod tests {
                }
 
                // Enable channel #1 back.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 4,
@@ -3437,7 +3799,7 @@ mod tests {
 
 
                // Now let's see if routing works if we know only htlc_maximum_msat.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 3,
@@ -3472,7 +3834,7 @@ mod tests {
 
                // We can't change UTXO capacity on the fly, so we'll disable
                // the existing channel and add another one with the capacity we need.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 4,
@@ -3492,10 +3854,10 @@ mod tests {
                .push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script().to_v0_p2wsh();
 
                *chain_monitor.utxo_ret.lock().unwrap() = Ok(TxOut { value: 15, script_pubkey: good_script.clone() });
-               net_graph_msg_handler.add_chain_access(Some(chain_monitor));
+               gossip_sync.add_chain_access(Some(chain_monitor));
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 333);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[0], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 333);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 333,
                        timestamp: 1,
@@ -3507,7 +3869,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 333,
                        timestamp: 1,
@@ -3539,7 +3901,7 @@ mod tests {
                }
 
                // Now let's see if routing chooses htlc_maximum_msat over UTXO capacity.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 333,
                        timestamp: 6,
@@ -3575,7 +3937,7 @@ mod tests {
        fn available_liquidity_last_hop_test() {
                // Check that available liquidity properly limits the path even when only
                // one of the latter hops is limited.
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -3587,7 +3949,7 @@ mod tests {
                // Total capacity: 50 sats.
 
                // Disable other potential paths.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -3599,7 +3961,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 7,
                        timestamp: 2,
@@ -3614,7 +3976,7 @@ mod tests {
 
                // Limit capacities
 
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -3626,7 +3988,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 2,
@@ -3639,7 +4001,7 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 2,
@@ -3651,7 +4013,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 11,
                        timestamp: 2,
@@ -3700,7 +4062,7 @@ mod tests {
 
        #[test]
        fn ignore_fee_first_hop_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -3708,7 +4070,7 @@ mod tests {
                let payment_params = PaymentParameters::from_node_id(nodes[2]);
 
                // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50).
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 2,
@@ -3720,7 +4082,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 2,
@@ -3748,12 +4110,13 @@ mod tests {
 
        #[test]
        fn simple_mpp_route_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known());
+               let payment_params = PaymentParameters::from_node_id(nodes[2])
+                       .with_features(InvoiceFeatures::known());
 
                // We need a route consisting of 3 paths:
                // From our node to node2 via node0, node7, node1 (three paths one hop each).
@@ -3764,7 +4127,7 @@ mod tests {
                // Their aggregate capacity will be 50 + 60 + 180 = 290 sats.
 
                // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50).
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 2,
@@ -3776,7 +4139,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 2,
@@ -3791,7 +4154,7 @@ mod tests {
 
                // Path via node7 is channels {12, 13}. Limit them to 60 and 60 sats
                // (total limit 60).
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -3803,7 +4166,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 2,
@@ -3818,7 +4181,7 @@ mod tests {
 
                // Path via node1 is channels {2, 4}. Limit them to 200 and 180 sats
                // (total capacity 180 sats).
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -3830,7 +4193,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 2,
@@ -3846,15 +4209,39 @@ mod tests {
                {
                        // Attempt to route more than available results in a failure.
                        if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
-                                       &our_id, &payment_params, &network_graph.read_only(), None, 300_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes) {
-                               assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                               &our_id, &payment_params, &network_graph.read_only(), None, 300_000, 42,
+                               Arc::clone(&logger), &scorer, &random_seed_bytes) {
+                                       assert_eq!(err, "Failed to find a sufficient route to the given destination");
+                       } else { panic!(); }
+               }
+
+               {
+                       // 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);
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
+                               &our_id, &zero_payment_params, &network_graph.read_only(), None, 100, 42,
+                               Arc::clone(&logger), &scorer, &random_seed_bytes) {
+                                       assert_eq!(err, "Can't find a route with no paths allowed.");
+                       } else { panic!(); }
+               }
+
+               {
+                       // Attempt to route while setting max_path_count to 3 results in a failure.
+                       // 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);
+                       if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(
+                               &our_id, &fail_payment_params, &network_graph.read_only(), None, 250_000, 42,
+                               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 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, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
+                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None,
+                               250_000, 42, 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 {
@@ -3867,7 +4254,8 @@ 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, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
+                       let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None,
+                               290_000, 42, 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 {
@@ -3881,7 +4269,7 @@ mod tests {
 
        #[test]
        fn long_mpp_route_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -3896,7 +4284,7 @@ mod tests {
                // are used twice will have 200 sats capacity.
 
                // Disable other potential paths.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -3908,7 +4296,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 7,
                        timestamp: 2,
@@ -3922,7 +4310,7 @@ mod tests {
                });
 
                // Path via {node0, node2} is channels {1, 3, 5}.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 2,
@@ -3934,7 +4322,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 2,
@@ -3948,8 +4336,8 @@ mod tests {
                });
 
                // Capacity of 200 sats because this channel will be used by 3rd path as well.
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 5,
                        timestamp: 2,
@@ -3965,7 +4353,7 @@ mod tests {
                // Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
                // Add 100 sats to the capacities of {12, 13}, because these channels
                // are also used for 3rd path. 100 sats for the rest. Total capacity: 100 sats.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -3977,7 +4365,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 2,
@@ -3990,7 +4378,7 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 2,
@@ -4002,7 +4390,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 11,
                        timestamp: 2,
@@ -4045,7 +4433,7 @@ mod tests {
 
        #[test]
        fn mpp_cheaper_route_test() {
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -4064,7 +4452,7 @@ mod tests {
                // are used twice will have 200 sats capacity.
 
                // Disable other potential paths.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -4076,7 +4464,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 7,
                        timestamp: 2,
@@ -4090,7 +4478,7 @@ mod tests {
                });
 
                // Path via {node0, node2} is channels {1, 3, 5}.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 2,
@@ -4102,7 +4490,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 2,
@@ -4116,8 +4504,8 @@ mod tests {
                });
 
                // Capacity of 200 sats because this channel will be used by 3rd path as well.
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 5,
                        timestamp: 2,
@@ -4133,7 +4521,7 @@ mod tests {
                // Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
                // Add 100 sats to the capacities of {12, 13}, because these channels
                // are also used for 3rd path. 100 sats for the rest. Total capacity: 100 sats.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -4145,7 +4533,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 2,
@@ -4158,7 +4546,7 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 2,
@@ -4170,7 +4558,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 11,
                        timestamp: 2,
@@ -4214,7 +4602,7 @@ mod tests {
                // This test makes sure that MPP algorithm properly takes into account
                // fees charged on the channels, by making the fees impactful:
                // if the fee is not properly accounted for, the behavior is different.
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -4231,7 +4619,7 @@ mod tests {
                // It's fine to ignore this concern for now.
 
                // Disable other potential paths.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -4244,7 +4632,7 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 7,
                        timestamp: 2,
@@ -4258,7 +4646,7 @@ mod tests {
                });
 
                // Path via {node0, node2} is channels {1, 3, 5}.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 2,
@@ -4270,7 +4658,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 2,
@@ -4283,8 +4671,8 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 5,
                        timestamp: 2,
@@ -4307,7 +4695,7 @@ mod tests {
                // - channel 12 capacity is 250 sats
                // - fee for channel 6 is 150 sats
                // Let's test this by enforcing these 2 conditions and removing other limits.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -4319,7 +4707,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 2,
@@ -4332,7 +4720,7 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 2,
@@ -4344,7 +4732,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 11,
                        timestamp: 2,
@@ -4395,7 +4783,7 @@ mod tests {
                // to only have the remaining to-collect amount in available liquidity.
                //
                // This bug appeared in production in some specific channel configurations.
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -4415,7 +4803,7 @@ mod tests {
                // would first use the no-fee route and then fail to find a path along the second route as
                // we think we can only send up to 1 additional sat over the last-hop but refuse to as its
                // under 5% of our payment amount.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 2,
@@ -4427,7 +4815,7 @@ mod tests {
                        fee_proportional_millionths: u32::max_value(),
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -4439,7 +4827,7 @@ mod tests {
                        fee_proportional_millionths: u32::max_value(),
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 2,
@@ -4451,7 +4839,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 2,
@@ -4466,17 +4854,18 @@ 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 route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
+               let mut route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths.len(), 2);
-               // Paths are somewhat randomly ordered, but:
-               // * the first is channel 2 (1 msat fee) -> channel 4 -> channel 42
-               // * the second is channel 1 (0 fee, but 99 sat maximum) -> channel 3 -> channel 42
-               assert_eq!(route.paths[0][0].short_channel_id, 2);
-               assert_eq!(route.paths[0][0].fee_msat, 1);
-               assert_eq!(route.paths[0][2].fee_msat, 1_000);
-               assert_eq!(route.paths[1][0].short_channel_id, 1);
-               assert_eq!(route.paths[1][0].fee_msat, 0);
-               assert_eq!(route.paths[1][2].fee_msat, 99_000);
+               route.paths.sort_by_key(|path| path[0].short_channel_id);
+               // Paths are manually ordered ordered by SCID, so:
+               // * the first is channel 1 (0 fee, but 99 sat maximum) -> channel 3 -> channel 42
+               // * the second is channel 2 (1 msat fee) -> channel 4 -> channel 42
+               assert_eq!(route.paths[0][0].short_channel_id, 1);
+               assert_eq!(route.paths[0][0].fee_msat, 0);
+               assert_eq!(route.paths[0][2].fee_msat, 99_000);
+               assert_eq!(route.paths[1][0].short_channel_id, 2);
+               assert_eq!(route.paths[1][0].fee_msat, 1);
+               assert_eq!(route.paths[1][2].fee_msat, 1_000);
                assert_eq!(route.get_total_fees(), 1);
                assert_eq!(route.get_total_amount(), 100_000);
        }
@@ -4485,12 +4874,13 @@ mod tests {
        fn drop_lowest_channel_mpp_route_test() {
                // This test checks that low-capacity channel is dropped when after
                // path finding we realize that we found more capacity than we need.
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
-               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known());
+               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known())
+                       .with_max_channel_saturation_power_of_half(0);
 
                // We need a route consisting of 3 paths:
                // From our node to node2 via node0, node7, node1 (three paths one hop each).
@@ -4502,7 +4892,7 @@ mod tests {
                // Their aggregate capacity will be 50 + 60 + 20 = 130 sats.
 
                // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 2,
@@ -4514,7 +4904,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[0], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 2,
@@ -4528,7 +4918,7 @@ mod tests {
                });
 
                // Path via node7 is channels {12, 13}. Limit them to 60 and 60 sats (total limit 60);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -4540,7 +4930,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 13,
                        timestamp: 2,
@@ -4554,7 +4944,7 @@ mod tests {
                });
 
                // Path via node1 is channels {2, 4}. Limit them to 20 and 20 sats (total capacity 20 sats).
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -4566,7 +4956,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 2,
@@ -4642,17 +5032,18 @@ mod tests {
                // payment) htlc_minimum_msat. In the original algorithm, this resulted in node4's
                // "previous hop" being set to node 3, creating a loop in the path.
                let secp_ctx = Secp256k1::new();
+               let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
                let logger = Arc::new(test_utils::TestLogger::new());
-               let network = Arc::new(NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()));
-               let net_graph_msg_handler = NetGraphMsgHandler::new(Arc::clone(&network), None, Arc::clone(&logger));
+               let network = Arc::new(NetworkGraph::new(genesis_hash, Arc::clone(&logger)));
+               let gossip_sync = P2PGossipSync::new(Arc::clone(&network), None, Arc::clone(&logger));
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let payment_params = PaymentParameters::from_node_id(nodes[6]);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &our_privkey, &privkeys[1], ChannelFeatures::from_le_bytes(id_to_feature_flags(6)), 6);
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 6,
                        timestamp: 1,
@@ -4664,10 +5055,10 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[1], NodeFeatures::from_le_bytes(id_to_feature_flags(1)), 0);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[1], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(5)), 5);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 5,
                        timestamp: 1,
@@ -4679,10 +5070,10 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[4], NodeFeatures::from_le_bytes(id_to_feature_flags(4)), 0);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[3], ChannelFeatures::from_le_bytes(id_to_feature_flags(4)), 4);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 1,
@@ -4694,10 +5085,10 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[3], NodeFeatures::from_le_bytes(id_to_feature_flags(3)), 0);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[3], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[3], &privkeys[2], ChannelFeatures::from_le_bytes(id_to_feature_flags(3)), 3);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[3], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 3,
                        timestamp: 1,
@@ -4709,10 +5100,10 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[2], NodeFeatures::from_le_bytes(id_to_feature_flags(2)), 0);
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[2], &privkeys[4], ChannelFeatures::from_le_bytes(id_to_feature_flags(2)), 2);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[2], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 1,
@@ -4725,8 +5116,8 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               add_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
+               add_channel(&gossip_sync, &secp_ctx, &privkeys[4], &privkeys[6], ChannelFeatures::from_le_bytes(id_to_feature_flags(1)), 1);
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[4], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 1,
                        timestamp: 1,
@@ -4738,7 +5129,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[6], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0);
+               add_or_update_node(&gossip_sync, &secp_ctx, &privkeys[6], NodeFeatures::from_le_bytes(id_to_feature_flags(6)), 0);
 
                {
                        // Now ensure the route flows simply over nodes 1 and 4 to 6.
@@ -4775,7 +5166,7 @@ mod tests {
                // Test that if, while walking the graph, we find a hop that has exactly enough liquidity
                // for us, including later hop fees, we take it. In the first version of our MPP algorithm
                // we calculated fees on a higher value, resulting in us ignoring such paths.
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, _, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -4784,7 +5175,7 @@ mod tests {
 
                // We modify the graph to set the htlc_maximum of channel 2 to below the value we wish to
                // send.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -4797,7 +5188,7 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 12,
                        timestamp: 2,
@@ -4839,7 +5230,7 @@ mod tests {
                // htlc_maximum_msat, we don't end up undershooting a later htlc_minimum_msat. In the
                // initial version of MPP we'd accept such routes but reject them while recalculating fees,
                // resulting in us thinking there is no possible path, even if other paths exist.
-               let (secp_ctx, network_graph, net_graph_msg_handler, _, logger) = build_graph();
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
                let (our_privkey, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
                let scorer = test_utils::TestScorer::with_penalty(0);
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -4849,7 +5240,7 @@ mod tests {
                // We modify the graph to set the htlc_minimum of channel 2 and 4 as needed - channel 2
                // gets an htlc_maximum_msat of 80_000 and channel 4 an htlc_minimum_msat of 90_000. We
                // then try to send 90_000.
-               update_channel(&net_graph_msg_handler, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &our_privkey, UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 2,
                        timestamp: 2,
@@ -4861,7 +5252,7 @@ mod tests {
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
                });
-               update_channel(&net_graph_msg_handler, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
                        chain_hash: genesis_block(Network::Testnet).header.block_hash(),
                        short_channel_id: 4,
                        timestamp: 2,
@@ -4908,8 +5299,9 @@ mod tests {
                // route over multiple channels with the same first hop.
                let secp_ctx = Secp256k1::new();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
+               let genesis_hash = genesis_block(Network::Testnet).header.block_hash();
                let logger = Arc::new(test_utils::TestLogger::new());
-               let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
+               let network_graph = NetworkGraph::new(genesis_hash, Arc::clone(&logger));
                let scorer = test_utils::TestScorer::with_penalty(0);
                let payment_params = PaymentParameters::from_node_id(nodes[0]).with_features(InvoiceFeatures::known());
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
@@ -4936,12 +5328,13 @@ mod tests {
                        assert_eq!(route.paths[0].len(), 1);
                        assert_eq!(route.paths[1].len(), 1);
 
+                       assert!((route.paths[0][0].short_channel_id == 3 && route.paths[1][0].short_channel_id == 2) ||
+                               (route.paths[0][0].short_channel_id == 2 && route.paths[1][0].short_channel_id == 3));
+
                        assert_eq!(route.paths[0][0].pubkey, nodes[0]);
-                       assert_eq!(route.paths[0][0].short_channel_id, 3);
                        assert_eq!(route.paths[0][0].fee_msat, 50_000);
 
                        assert_eq!(route.paths[1][0].pubkey, nodes[0]);
-                       assert_eq!(route.paths[1][0].short_channel_id, 2);
                        assert_eq!(route.paths[1][0].fee_msat, 50_000);
                }
 
@@ -5015,12 +5408,14 @@ mod tests {
                fn write<W: Writer>(&self, _w: &mut W) -> Result<(), ::io::Error> { unimplemented!() }
        }
        impl Score for BadChannelScorer {
-               fn channel_penalty_msat(&self, short_channel_id: u64, _send_amt: u64, _capacity_msat: u64, _source: &NodeId, _target: &NodeId) -> u64 {
+               fn channel_penalty_msat(&self, short_channel_id: u64, _: &NodeId, _: &NodeId, _: ChannelUsage) -> u64 {
                        if short_channel_id == self.short_channel_id { u64::max_value() } else { 0 }
                }
 
                fn payment_path_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
                fn payment_path_successful(&mut self, _path: &[&RouteHop]) {}
+               fn probe_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
+               fn probe_successful(&mut self, _path: &[&RouteHop]) {}
        }
 
        struct BadNodeScorer {
@@ -5033,12 +5428,14 @@ mod tests {
        }
 
        impl Score for BadNodeScorer {
-               fn channel_penalty_msat(&self, _short_channel_id: u64, _send_amt: u64, _capacity_msat: u64, _source: &NodeId, target: &NodeId) -> u64 {
+               fn channel_penalty_msat(&self, _: u64, _: &NodeId, target: &NodeId, _: ChannelUsage) -> u64 {
                        if *target == self.node_id { u64::max_value() } else { 0 }
                }
 
                fn payment_path_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
                fn payment_path_successful(&mut self, _path: &[&RouteHop]) {}
+               fn probe_failed(&mut self, _path: &[&RouteHop], _short_channel_id: u64) {}
+               fn probe_successful(&mut self, _path: &[&RouteHop]) {}
        }
 
        #[test]
@@ -5189,6 +5586,64 @@ mod tests {
                }
        }
 
+       #[test]
+       fn avoids_recently_failed_paths() {
+               // Ensure that the router always avoids all of the `previously_failed_channels` channels by
+               // randomly inserting channels into it until we can't find a route anymore.
+               let (secp_ctx, network, _, _, logger) = build_graph();
+               let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
+               let network_graph = network.read_only();
+
+               let scorer = test_utils::TestScorer::with_penalty(0);
+               let mut payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes))
+                       .with_max_path_count(1);
+               let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
+               let random_seed_bytes = keys_manager.get_secure_random_bytes();
+
+               // 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, 0, Arc::clone(&logger), &scorer, &random_seed_bytes).is_ok());
+               loop {
+                       if let Ok(route) = get_route(&our_id, &payment_params, &network_graph, None, 100, 0, Arc::clone(&logger), &scorer, &random_seed_bytes) {
+                               for chan in route.paths[0].iter() {
+                                       assert!(!payment_params.previously_failed_channels.contains(&chan.short_channel_id));
+                               }
+                               let victim = (u64::from_ne_bytes(random_seed_bytes[0..8].try_into().unwrap()) as usize)
+                                       % route.paths[0].len();
+                               payment_params.previously_failed_channels.push(route.paths[0][victim].short_channel_id);
+                       } else { break; }
+               }
+       }
+
+       #[test]
+       fn limits_path_length() {
+               let (secp_ctx, network, _, _, logger) = build_line_graph();
+               let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
+               let network_graph = network.read_only();
+
+               let scorer = test_utils::TestScorer::with_penalty(0);
+               let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
+               let random_seed_bytes = keys_manager.get_secure_random_bytes();
+
+               // First check we can actually create a long route on this graph.
+               let feasible_payment_params = PaymentParameters::from_node_id(nodes[18]);
+               let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, 0,
+                       Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
+               let path = route.paths[0].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]);
+               match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, 0,
+                       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"),
+               }
+       }
+
        #[test]
        fn adds_and_limits_cltv_offset() {
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
@@ -5289,6 +5744,70 @@ mod tests {
                assert!(path_plausibility.iter().all(|x| *x));
        }
 
+       #[test]
+       fn builds_correct_path_from_hops() {
+               let (secp_ctx, network, _, _, logger) = build_graph();
+               let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
+               let network_graph = network.read_only();
+
+               let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
+               let random_seed_bytes = keys_manager.get_secure_random_bytes();
+
+               let payment_params = PaymentParameters::from_node_id(nodes[3]);
+               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, 0, Arc::clone(&logger), &random_seed_bytes).unwrap();
+               let route_hop_pubkeys = route.paths[0].iter().map(|hop| hop.pubkey).collect::<Vec<_>>();
+               assert_eq!(hops.len(), route.paths[0].len());
+               for (idx, hop_pubkey) in hops.iter().enumerate() {
+                       assert!(*hop_pubkey == route_hop_pubkeys[idx]);
+               }
+       }
+
+       #[test]
+       fn avoids_saturating_channels() {
+               let (secp_ctx, network_graph, gossip_sync, _, logger) = build_graph();
+               let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
+
+               let scorer = ProbabilisticScorer::new(Default::default(), &*network_graph, Arc::clone(&logger));
+
+               // Set the fee on channel 13 to 100% to match channel 4 giving us two equivalent paths (us
+               // -> node 7 -> node2 and us -> node 1 -> node 2) which we should balance over.
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[1], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 4,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: (4 << 4) | 1,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(200_000_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+               update_channel(&gossip_sync, &secp_ctx, &privkeys[7], UnsignedChannelUpdate {
+                       chain_hash: genesis_block(Network::Testnet).header.block_hash(),
+                       short_channel_id: 13,
+                       timestamp: 2,
+                       flags: 0,
+                       cltv_expiry_delta: (13 << 4) | 1,
+                       htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Present(200_000_000),
+                       fee_base_msat: 0,
+                       fee_proportional_millionths: 0,
+                       excess_data: Vec::new()
+               });
+
+               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known());
+               let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
+               let random_seed_bytes = keys_manager.get_secure_random_bytes();
+               // 150,000 sat is less than the available liquidity on each channel, set above.
+               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 150_000_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
+               assert_eq!(route.paths.len(), 2);
+               assert!((route.paths[0][1].short_channel_id == 4 && route.paths[1][1].short_channel_id == 13) ||
+                       (route.paths[1][1].short_channel_id == 4 && route.paths[0][1].short_channel_id == 13));
+       }
+
        #[cfg(not(feature = "no-std"))]
        pub(super) fn random_init_seed() -> u64 {
                // Because the default HashMap in std pulls OS randomness, we can use it as a (bad) RNG.
@@ -5298,7 +5817,7 @@ mod tests {
                seed
        }
        #[cfg(not(feature = "no-std"))]
-       use util::ser::Readable;
+       use util::ser::ReadableArgs;
 
        #[test]
        #[cfg(not(feature = "no-std"))]
@@ -5312,7 +5831,8 @@ mod tests {
                                return;
                        },
                };
-               let graph = NetworkGraph::read(&mut d).unwrap();
+               let logger = test_utils::TestLogger::new();
+               let graph = NetworkGraph::read(&mut d, &logger).unwrap();
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -5328,8 +5848,8 @@ mod tests {
                                let payment_params = PaymentParameters::from_node_id(dst);
                                let amt = seed as u64 % 200_000_000;
                                let params = ProbabilisticScoringParameters::default();
-                               let scorer = ProbabilisticScorer::new(params, &graph);
-                               if get_route(src, &payment_params, &graph.read_only(), None, amt, 42, &test_utils::TestLogger::new(), &scorer, &random_seed_bytes).is_ok() {
+                               let scorer = ProbabilisticScorer::new(params, &graph, &logger);
+                               if get_route(src, &payment_params, &graph.read_only(), None, amt, 42, &logger, &scorer, &random_seed_bytes).is_ok() {
                                        continue 'load_endpoints;
                                }
                        }
@@ -5348,7 +5868,8 @@ mod tests {
                                return;
                        },
                };
-               let graph = NetworkGraph::read(&mut d).unwrap();
+               let logger = test_utils::TestLogger::new();
+               let graph = NetworkGraph::read(&mut d, &logger).unwrap();
                let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
@@ -5364,13 +5885,50 @@ mod tests {
                                let payment_params = PaymentParameters::from_node_id(dst).with_features(InvoiceFeatures::known());
                                let amt = seed as u64 % 200_000_000;
                                let params = ProbabilisticScoringParameters::default();
-                               let scorer = ProbabilisticScorer::new(params, &graph);
-                               if get_route(src, &payment_params, &graph.read_only(), None, amt, 42, &test_utils::TestLogger::new(), &scorer, &random_seed_bytes).is_ok() {
+                               let scorer = ProbabilisticScorer::new(params, &graph, &logger);
+                               if get_route(src, &payment_params, &graph.read_only(), None, amt, 42, &logger, &scorer, &random_seed_bytes).is_ok() {
                                        continue 'load_endpoints;
                                }
                        }
                }
        }
+
+       #[test]
+       fn honors_manual_penalties() {
+               let (secp_ctx, network_graph, _, _, logger) = build_line_graph();
+               let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
+
+               let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
+               let random_seed_bytes = keys_manager.get_secure_random_bytes();
+
+               let scorer_params = ProbabilisticScoringParameters::default();
+               let mut scorer = ProbabilisticScorer::new(scorer_params, Arc::clone(&network_graph), Arc::clone(&logger));
+
+               // First check set manual penalties are returned by the scorer.
+               let usage = ChannelUsage {
+                       amount_msat: 0,
+                       inflight_htlc_msat: 0,
+                       effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: Some(1_000) },
+               };
+               scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123);
+               scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456);
+               assert_eq!(scorer.channel_penalty_msat(42, &NodeId::from_pubkey(&nodes[3]), &NodeId::from_pubkey(&nodes[4]), usage), 456);
+
+               // Then check we can get a normal route
+               let payment_params = PaymentParameters::from_node_id(nodes[10]);
+               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes);
+               assert!(route.is_ok());
+
+               // Then check that we can't get a route if we ban an intermediate node.
+               scorer.add_banned(&NodeId::from_pubkey(&nodes[3]));
+               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes);
+               assert!(route.is_err());
+
+               // Finally make sure we can route again, when we remove the ban.
+               scorer.remove_banned(&NodeId::from_pubkey(&nodes[3]));
+               let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes);
+               assert!(route.is_ok());
+       }
 }
 
 #[cfg(all(test, not(feature = "no-std")))]
@@ -5409,8 +5967,10 @@ mod benches {
        use chain::keysinterface::{KeysManager,KeysInterface};
        use ln::channelmanager::{ChannelCounterparty, ChannelDetails};
        use ln::features::{InitFeatures, InvoiceFeatures};
-       use routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringParameters, Scorer};
+       use routing::gossip::NetworkGraph;
+       use routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringParameters};
        use util::logger::{Logger, Record};
+       use util::ser::ReadableArgs;
 
        use test::Bencher;
 
@@ -5419,9 +5979,9 @@ mod benches {
                fn log(&self, _record: &Record) {}
        }
 
-       fn read_network_graph() -> NetworkGraph {
+       fn read_network_graph(logger: &DummyLogger) -> NetworkGraph<&DummyLogger> {
                let mut d = test_utils::get_route_file().unwrap();
-               NetworkGraph::read(&mut d).unwrap()
+               NetworkGraph::read(&mut d, logger).unwrap()
        }
 
        fn payer_pubkey() -> PublicKey {
@@ -5438,6 +5998,8 @@ mod benches {
                                node_id,
                                unspendable_punishment_reserve: 0,
                                forwarding_info: None,
+                               outbound_htlc_minimum_msat: None,
+                               outbound_htlc_maximum_msat: None,
                        },
                        funding_txo: Some(OutPoint {
                                txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0
@@ -5445,67 +6007,63 @@ mod benches {
                        channel_type: None,
                        short_channel_id: Some(1),
                        inbound_scid_alias: None,
+                       outbound_scid_alias: None,
                        channel_value_satoshis: 10_000_000,
                        user_channel_id: 0,
                        balance_msat: 10_000_000,
                        outbound_capacity_msat: 10_000_000,
+                       next_outbound_htlc_limit_msat: 10_000_000,
                        inbound_capacity_msat: 0,
                        unspendable_punishment_reserve: None,
                        confirmations_required: None,
                        force_close_spend_delay: None,
                        is_outbound: true,
-                       is_funding_locked: true,
+                       is_channel_ready: true,
                        is_usable: true,
                        is_public: true,
+                       inbound_htlc_minimum_msat: None,
+                       inbound_htlc_maximum_msat: None,
+                       config: None,
                }
        }
 
        #[bench]
        fn generate_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
-               let network_graph = read_network_graph();
+               let logger = DummyLogger {};
+               let network_graph = read_network_graph(&logger);
                let scorer = FixedPenaltyScorer::with_penalty(0);
                generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty());
        }
 
        #[bench]
        fn generate_mpp_routes_with_zero_penalty_scorer(bench: &mut Bencher) {
-               let network_graph = read_network_graph();
+               let logger = DummyLogger {};
+               let network_graph = read_network_graph(&logger);
                let scorer = FixedPenaltyScorer::with_penalty(0);
                generate_routes(bench, &network_graph, scorer, InvoiceFeatures::known());
        }
 
-       #[bench]
-       fn generate_routes_with_default_scorer(bench: &mut Bencher) {
-               let network_graph = read_network_graph();
-               let scorer = Scorer::default();
-               generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty());
-       }
-
-       #[bench]
-       fn generate_mpp_routes_with_default_scorer(bench: &mut Bencher) {
-               let network_graph = read_network_graph();
-               let scorer = Scorer::default();
-               generate_routes(bench, &network_graph, scorer, InvoiceFeatures::known());
-       }
-
        #[bench]
        fn generate_routes_with_probabilistic_scorer(bench: &mut Bencher) {
-               let network_graph = read_network_graph();
+               let logger = DummyLogger {};
+               let network_graph = read_network_graph(&logger);
                let params = ProbabilisticScoringParameters::default();
-               let scorer = ProbabilisticScorer::new(params, &network_graph);
+               let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
                generate_routes(bench, &network_graph, scorer, InvoiceFeatures::empty());
        }
 
        #[bench]
        fn generate_mpp_routes_with_probabilistic_scorer(bench: &mut Bencher) {
-               let network_graph = read_network_graph();
+               let logger = DummyLogger {};
+               let network_graph = read_network_graph(&logger);
                let params = ProbabilisticScoringParameters::default();
-               let scorer = ProbabilisticScorer::new(params, &network_graph);
+               let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
                generate_routes(bench, &network_graph, scorer, InvoiceFeatures::known());
        }
 
        fn generate_routes<S: Score>(
-               bench: &mut Bencher, graph: &NetworkGraph, mut scorer: S, features: InvoiceFeatures
+               bench: &mut Bencher, graph: &NetworkGraph<&DummyLogger>, mut scorer: S,
+               features: InvoiceFeatures
        ) {
                let nodes = graph.read_only().nodes().clone();
                let payer = payer_pubkey();