Fix RoutingFees::base_msat docs
[rust-lightning] / lightning / src / routing / router.rs
index 9e31d9ea5e734a3746486b07d5a27415bfccd7b0..1e2ca10c0bf4a0795bc4089d0145b69ad8914de5 100644 (file)
 //! interrogate it to get routes for your own payments.
 
 use bitcoin::secp256k1::PublicKey;
+use bitcoin::hashes::Hash;
+use bitcoin::hashes::sha256::Hash as Sha256;
 
-use crate::ln::channelmanager::ChannelDetails;
+use crate::ln::PaymentHash;
+use crate::ln::channelmanager::{ChannelDetails, PaymentId};
 use crate::ln::features::{ChannelFeatures, InvoiceFeatures, NodeFeatures};
 use crate::ln::msgs::{DecodeError, ErrorAction, LightningError, MAX_VALUE_MSAT};
 use crate::routing::gossip::{DirectedChannelInfo, EffectiveCapacity, ReadOnlyNetworkGraph, NetworkGraph, NodeId, RoutingFees};
-use crate::routing::scoring::{ChannelUsage, Score};
+use crate::routing::scoring::{ChannelUsage, LockableScore, Score};
 use crate::util::ser::{Writeable, Readable, Writer};
 use crate::util::logger::{Level, Logger};
 use crate::util::chacha20::ChaCha20;
 
 use crate::io;
 use crate::prelude::*;
+use crate::sync::Mutex;
 use alloc::collections::BinaryHeap;
 use core::cmp;
 use core::ops::Deref;
 
+/// A [`Router`] implemented using [`find_route`].
+pub struct DefaultRouter<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> where
+       L::Target: Logger,
+       S::Target: for <'a> LockableScore<'a>,
+{
+       network_graph: G,
+       logger: L,
+       random_seed_bytes: Mutex<[u8; 32]>,
+       scorer: S
+}
+
+impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> DefaultRouter<G, L, S> where
+       L::Target: Logger,
+       S::Target: for <'a> LockableScore<'a>,
+{
+       /// Creates a new router.
+       pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32], scorer: S) -> Self {
+               let random_seed_bytes = Mutex::new(random_seed_bytes);
+               Self { network_graph, logger, random_seed_bytes, scorer }
+       }
+}
+
+impl<G: Deref<Target = NetworkGraph<L>>, L: Deref, S: Deref> Router for DefaultRouter<G, L, S> where
+       L::Target: Logger,
+       S::Target: for <'a> LockableScore<'a>,
+{
+       fn find_route(
+               &self, payer: &PublicKey, params: &RouteParameters, first_hops: Option<&[&ChannelDetails]>,
+               inflight_htlcs: &InFlightHtlcs
+       ) -> Result<Route, LightningError> {
+               let random_seed_bytes = {
+                       let mut locked_random_seed_bytes = self.random_seed_bytes.lock().unwrap();
+                       *locked_random_seed_bytes = Sha256::hash(&*locked_random_seed_bytes).into_inner();
+                       *locked_random_seed_bytes
+               };
+
+               find_route(
+                       payer, params, &self.network_graph, first_hops, &*self.logger,
+                       &ScorerAccountingForInFlightHtlcs::new(self.scorer.lock(), inflight_htlcs),
+                       &random_seed_bytes
+               )
+       }
+
+       fn notify_payment_path_failed(&self, path: &[&RouteHop], short_channel_id: u64) {
+               self.scorer.lock().payment_path_failed(path, short_channel_id);
+       }
+
+       fn notify_payment_path_successful(&self, path: &[&RouteHop]) {
+               self.scorer.lock().payment_path_successful(path);
+       }
+
+       fn notify_payment_probe_successful(&self, path: &[&RouteHop]) {
+               self.scorer.lock().probe_successful(path);
+       }
+
+       fn notify_payment_probe_failed(&self, path: &[&RouteHop], short_channel_id: u64) {
+               self.scorer.lock().probe_failed(path, short_channel_id);
+       }
+}
+
+/// A trait defining behavior for routing a payment.
+pub trait Router {
+       /// Finds a [`Route`] between `payer` and `payee` for a payment with the given values.
+       fn find_route(
+               &self, payer: &PublicKey, route_params: &RouteParameters,
+               first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: &InFlightHtlcs
+       ) -> Result<Route, LightningError>;
+       /// Finds a [`Route`] between `payer` and `payee` for a payment with the given values. Includes
+       /// `PaymentHash` and `PaymentId` to be able to correlate the request with a specific payment.
+       fn find_route_with_id(
+               &self, payer: &PublicKey, route_params: &RouteParameters,
+               first_hops: Option<&[&ChannelDetails]>, inflight_htlcs: &InFlightHtlcs,
+               _payment_hash: PaymentHash, _payment_id: PaymentId
+       ) -> Result<Route, LightningError> {
+               self.find_route(payer, route_params, first_hops, inflight_htlcs)
+       }
+       /// Lets the router know that payment through a specific path has failed.
+       fn notify_payment_path_failed(&self, path: &[&RouteHop], short_channel_id: u64);
+       /// Lets the router know that payment through a specific path was successful.
+       fn notify_payment_path_successful(&self, path: &[&RouteHop]);
+       /// Lets the router know that a payment probe was successful.
+       fn notify_payment_probe_successful(&self, path: &[&RouteHop]);
+       /// Lets the router know that a payment probe failed.
+       fn notify_payment_probe_failed(&self, path: &[&RouteHop], short_channel_id: u64);
+}
+
+/// [`Score`] implementation that factors in in-flight HTLC liquidity.
+///
+/// Useful for custom [`Router`] implementations to wrap their [`Score`] on-the-fly when calling
+/// [`find_route`].
+///
+/// [`Score`]: crate::routing::scoring::Score
+pub struct ScorerAccountingForInFlightHtlcs<'a, S: Score> {
+       scorer: S,
+       // Maps a channel's short channel id and its direction to the liquidity used up.
+       inflight_htlcs: &'a InFlightHtlcs,
+}
+
+impl<'a, S: Score> ScorerAccountingForInFlightHtlcs<'a, S> {
+       /// Initialize a new `ScorerAccountingForInFlightHtlcs`.
+       pub fn new(scorer: S, inflight_htlcs: &'a InFlightHtlcs) -> Self {
+               ScorerAccountingForInFlightHtlcs {
+                       scorer,
+                       inflight_htlcs
+               }
+       }
+}
+
+#[cfg(c_bindings)]
+impl<'a, S: Score> Writeable for ScorerAccountingForInFlightHtlcs<'a, S> {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> { self.scorer.write(writer) }
+}
+
+impl<'a, S: Score> Score for ScorerAccountingForInFlightHtlcs<'a, S> {
+       fn channel_penalty_msat(&self, short_channel_id: u64, source: &NodeId, target: &NodeId, usage: ChannelUsage) -> u64 {
+               if let Some(used_liquidity) = self.inflight_htlcs.used_liquidity_msat(
+                       source, target, short_channel_id
+               ) {
+                       let usage = ChannelUsage {
+                               inflight_htlc_msat: usage.inflight_htlc_msat + used_liquidity,
+                               ..usage
+                       };
+
+                       self.scorer.channel_penalty_msat(short_channel_id, source, target, usage)
+               } else {
+                       self.scorer.channel_penalty_msat(short_channel_id, source, target, usage)
+               }
+       }
+
+       fn payment_path_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) {
+               self.scorer.payment_path_failed(path, short_channel_id)
+       }
+
+       fn payment_path_successful(&mut self, path: &[&RouteHop]) {
+               self.scorer.payment_path_successful(path)
+       }
+
+       fn probe_failed(&mut self, path: &[&RouteHop], short_channel_id: u64) {
+               self.scorer.probe_failed(path, short_channel_id)
+       }
+
+       fn probe_successful(&mut self, path: &[&RouteHop]) {
+               self.scorer.probe_successful(path)
+       }
+}
+
+/// A data structure for tracking in-flight HTLCs. May be used during pathfinding to account for
+/// in-use channel liquidity.
+#[derive(Clone)]
+pub struct InFlightHtlcs(
+       // A map with liquidity value (in msat) keyed by a short channel id and the direction the HTLC
+       // is traveling in. The direction boolean is determined by checking if the HTLC source's public
+       // key is less than its destination. See `InFlightHtlcs::used_liquidity_msat` for more
+       // details.
+       HashMap<(u64, bool), u64>
+);
+
+impl InFlightHtlcs {
+       /// Constructs an empty `InFlightHtlcs`.
+       pub fn new() -> Self { InFlightHtlcs(HashMap::new()) }
+
+       /// Takes in a path with payer's node id and adds the path's details to `InFlightHtlcs`.
+       pub fn process_path(&mut self, path: &[RouteHop], payer_node_id: PublicKey) {
+               if path.is_empty() { return };
+               // total_inflight_map needs to be direction-sensitive when keeping track of the HTLC value
+               // that is held up. However, the `hops` array, which is a path returned by `find_route` in
+               // the router excludes the payer node. In the following lines, the payer's information is
+               // hardcoded with an inflight value of 0 so that we can correctly represent the first hop
+               // in our sliding window of two.
+               let reversed_hops_with_payer = path.iter().rev().skip(1)
+                       .map(|hop| hop.pubkey)
+                       .chain(core::iter::once(payer_node_id));
+               let mut cumulative_msat = 0;
+
+               // Taking the reversed vector from above, we zip it with just the reversed hops list to
+               // work "backwards" of the given path, since the last hop's `fee_msat` actually represents
+               // the total amount sent.
+               for (next_hop, prev_hop) in path.iter().rev().zip(reversed_hops_with_payer) {
+                       cumulative_msat += next_hop.fee_msat;
+                       self.0
+                               .entry((next_hop.short_channel_id, NodeId::from_pubkey(&prev_hop) < NodeId::from_pubkey(&next_hop.pubkey)))
+                               .and_modify(|used_liquidity_msat| *used_liquidity_msat += cumulative_msat)
+                               .or_insert(cumulative_msat);
+               }
+       }
+
+       /// Returns liquidity in msat given the public key of the HTLC source, target, and short channel
+       /// id.
+       pub fn used_liquidity_msat(&self, source: &NodeId, target: &NodeId, channel_scid: u64) -> Option<u64> {
+               self.0.get(&(channel_scid, source < target)).map(|v| *v)
+       }
+}
+
+impl Writeable for InFlightHtlcs {
+       fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> { self.0.write(writer) }
+}
+
+impl Readable for InFlightHtlcs {
+       fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+               let infight_map: HashMap<(u64, bool), u64> = Readable::read(reader)?;
+               Ok(Self(infight_map))
+       }
+}
+
 /// A hop in a route
 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
 pub struct RouteHop {
@@ -155,7 +363,7 @@ impl Readable for Route {
 /// [`Event::PaymentPathFailed`] for retrying a failed payment path.
 ///
 /// [`Event::PaymentPathFailed`]: crate::util::events::Event::PaymentPathFailed
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct RouteParameters {
        /// The parameters of the failed payment path.
        pub payment_params: PaymentParameters,
@@ -185,8 +393,7 @@ pub const DEFAULT_MAX_PATH_COUNT: u8 = 10;
 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`
+// 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.
 //
@@ -375,7 +582,6 @@ impl_writeable_tlv_based!(RouteHintHop, {
 #[derive(Eq, PartialEq)]
 struct RouteGraphNode {
        node_id: NodeId,
-       lowest_fee_to_peer_through_node: u64,
        lowest_fee_to_node: u64,
        total_cltv_delta: u32,
        // The maximum value a yet-to-be-constructed payment path might flow through this node.
@@ -396,9 +602,9 @@ struct RouteGraphNode {
 
 impl cmp::Ord for RouteGraphNode {
        fn cmp(&self, other: &RouteGraphNode) -> cmp::Ordering {
-               let other_score = cmp::max(other.lowest_fee_to_peer_through_node, other.path_htlc_minimum_msat)
+               let other_score = cmp::max(other.lowest_fee_to_node, other.path_htlc_minimum_msat)
                        .saturating_add(other.path_penalty_msat);
-               let self_score = cmp::max(self.lowest_fee_to_peer_through_node, self.path_htlc_minimum_msat)
+               let self_score = cmp::max(self.lowest_fee_to_node, self.path_htlc_minimum_msat)
                        .saturating_add(self.path_penalty_msat);
                other_score.cmp(&self_score).then_with(|| other.node_id.cmp(&self.node_id))
        }
@@ -494,10 +700,8 @@ fn max_htlc_from_capacity(capacity: EffectiveCapacity, max_channel_saturation_po
                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),
+               EffectiveCapacity::Total { capacity_msat, htlc_maximum_msat } =>
+                       cmp::min(capacity_msat.checked_shr(saturation_shift).unwrap_or(0), htlc_maximum_msat),
        }
 }
 
@@ -524,8 +728,6 @@ struct PathBuildingHop<'a> {
        candidate: CandidateRouteHop<'a>,
        fee_msat: u64,
 
-       /// Minimal fees required to route to the source node of the current hop via any of its inbound channels.
-       src_lowest_inbound_fees: RoutingFees,
        /// All the fees paid *after* this channel on the way to the destination
        next_hops_fee_msat: u64,
        /// Fee paid for the use of the current channel (see candidate.fees()).
@@ -683,18 +885,20 @@ impl<'a> PaymentPath<'a> {
        }
 }
 
+#[inline(always)]
+/// Calculate the fees required to route the given amount over a channel with the given fees.
 fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
-       let proportional_fee_millions =
-               amount_msat.checked_mul(channel_fees.proportional_millionths as u64);
-       if let Some(new_fee) = proportional_fee_millions.and_then(|part| {
-                       (channel_fees.base_msat as u64).checked_add(part / 1_000_000) }) {
+       amount_msat.checked_mul(channel_fees.proportional_millionths as u64)
+               .and_then(|part| (channel_fees.base_msat as u64).checked_add(part / 1_000_000))
+}
 
-               Some(new_fee)
-       } else {
-               // This function may be (indirectly) called without any verification,
-               // with channel_fees provided by a caller. We should handle it gracefully.
-               None
-       }
+#[inline(always)]
+/// Calculate the fees required to route the given amount over a channel with the given fees,
+/// saturating to [`u64::max_value`].
+fn compute_fees_saturating(amount_msat: u64, channel_fees: RoutingFees) -> u64 {
+       amount_msat.checked_mul(channel_fees.proportional_millionths as u64)
+               .map(|prop| prop / 1_000_000).unwrap_or(u64::max_value())
+               .saturating_add(channel_fees.base_msat as u64)
 }
 
 /// The default `features` we assume for a node in a route, when no `features` are known about that
@@ -802,9 +1006,8 @@ where L::Target: Logger {
        // 8. If our maximum channel saturation limit caused us to pick two identical paths, combine
        //    them so that we're not sending two HTLCs along the same path.
 
-       // As for the actual search algorithm,
-       // we do a payee-to-payer pseudo-Dijkstra's sorting by each node's distance from the payee
-       // plus the minimum per-HTLC fee to get from it to another node (aka "shitty pseudo-A*").
+       // As for the actual search algorithm, we do a payee-to-payer Dijkstra's sorting by each node's
+       // distance from the payee
        //
        // We are not a faithful Dijkstra's implementation because we can change values which impact
        // earlier nodes while processing later nodes. Specifically, if we reach a channel with a lower
@@ -839,10 +1042,6 @@ where L::Target: Logger {
        // runtime for little gain. Specifically, the current algorithm rather efficiently explores the
        // graph for candidate paths, calculating the maximum value which can realistically be sent at
        // the same time, remaining generic across different payment values.
-       //
-       // TODO: There are a few tweaks we could do, including possibly pre-calculating more stuff
-       // to use as the A* heuristic beyond just the cost to get one node further than the current
-       // one.
 
        let network_channels = network_graph.channels();
        let network_nodes = network_graph.nodes();
@@ -892,7 +1091,7 @@ where L::Target: Logger {
                }
        }
 
-       // The main heap containing all candidate next-hops sorted by their score (max(A* fee,
+       // The main heap containing all candidate next-hops sorted by their score (max(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<RouteGraphNode> = BinaryHeap::new();
@@ -1057,10 +1256,10 @@ where L::Target: Logger {
                                                // might violate htlc_minimum_msat on the hops which are next along the
                                                // payment path (upstream to the payee). To avoid that, we recompute
                                                // path fees knowing the final path contribution after constructing it.
-                                               let path_htlc_minimum_msat = compute_fees($next_hops_path_htlc_minimum_msat, $candidate.fees())
-                                                       .and_then(|fee_msat| fee_msat.checked_add($next_hops_path_htlc_minimum_msat))
-                                                       .map(|fee_msat| cmp::max(fee_msat, $candidate.htlc_minimum_msat()))
-                                                       .unwrap_or_else(|| u64::max_value());
+                                               let path_htlc_minimum_msat = cmp::max(
+                                                       compute_fees_saturating($next_hops_path_htlc_minimum_msat, $candidate.fees())
+                                                               .saturating_add($next_hops_path_htlc_minimum_msat),
+                                                       $candidate.htlc_minimum_msat());
                                                let hm_entry = dist.entry($src_node_id);
                                                let old_entry = hm_entry.or_insert_with(|| {
                                                        // If there was previously no known way to access the source node
@@ -1068,20 +1267,10 @@ where L::Target: Logger {
                                                        // semi-dummy record just to compute the fees to reach the source node.
                                                        // This will affect our decision on selecting short_channel_id
                                                        // as a way to reach the $dest_node_id.
-                                                       let mut fee_base_msat = 0;
-                                                       let mut fee_proportional_millionths = 0;
-                                                       if let Some(Some(fees)) = network_nodes.get(&$src_node_id).map(|node| node.lowest_inbound_channel_fees) {
-                                                               fee_base_msat = fees.base_msat;
-                                                               fee_proportional_millionths = fees.proportional_millionths;
-                                                       }
                                                        PathBuildingHop {
                                                                node_id: $dest_node_id.clone(),
                                                                candidate: $candidate.clone(),
                                                                fee_msat: 0,
-                                                               src_lowest_inbound_fees: RoutingFees {
-                                                                       base_msat: fee_base_msat,
-                                                                       proportional_millionths: fee_proportional_millionths,
-                                                               },
                                                                next_hops_fee_msat: u64::max_value(),
                                                                hop_use_fee_msat: u64::max_value(),
                                                                total_fee_msat: u64::max_value(),
@@ -1104,38 +1293,15 @@ where L::Target: Logger {
 
                                                if should_process {
                                                        let mut hop_use_fee_msat = 0;
-                                                       let mut total_fee_msat = $next_hops_fee_msat;
+                                                       let mut total_fee_msat: u64 = $next_hops_fee_msat;
 
                                                        // Ignore hop_use_fee_msat for channel-from-us as we assume all channels-from-us
                                                        // will have the same effective-fee
                                                        if $src_node_id != our_node_id {
-                                                               match compute_fees(amount_to_transfer_over_msat, $candidate.fees()) {
-                                                                       // max_value means we'll always fail
-                                                                       // the old_entry.total_fee_msat > total_fee_msat check
-                                                                       None => total_fee_msat = u64::max_value(),
-                                                                       Some(fee_msat) => {
-                                                                               hop_use_fee_msat = fee_msat;
-                                                                               total_fee_msat += hop_use_fee_msat;
-                                                                               // When calculating the lowest inbound fees to a node, we
-                                                                               // calculate fees here not based on the actual value we think
-                                                                               // will flow over this channel, but on the minimum value that
-                                                                               // we'll accept flowing over it. The minimum accepted value
-                                                                               // is a constant through each path collection run, ensuring
-                                                                               // consistent basis. Otherwise we may later find a
-                                                                               // different path to the source node that is more expensive,
-                                                                               // but which we consider to be cheaper because we are capacity
-                                                                               // constrained and the relative fee becomes lower.
-                                                                               match compute_fees(minimal_value_contribution_msat, old_entry.src_lowest_inbound_fees)
-                                                                                               .map(|a| a.checked_add(total_fee_msat)) {
-                                                                                       Some(Some(v)) => {
-                                                                                               total_fee_msat = v;
-                                                                                       },
-                                                                                       _ => {
-                                                                                               total_fee_msat = u64::max_value();
-                                                                                       }
-                                                                               };
-                                                                       }
-                                                               }
+                                                               // Note that `u64::max_value` means we'll always fail the
+                                                               // `old_entry.total_fee_msat > total_fee_msat` check below
+                                                               hop_use_fee_msat = compute_fees_saturating(amount_to_transfer_over_msat, $candidate.fees());
+                                                               total_fee_msat = total_fee_msat.saturating_add(hop_use_fee_msat);
                                                        }
 
                                                        let channel_usage = ChannelUsage {
@@ -1150,8 +1316,7 @@ where L::Target: Logger {
                                                                .saturating_add(channel_penalty_msat);
                                                        let new_graph_node = RouteGraphNode {
                                                                node_id: $src_node_id,
-                                                               lowest_fee_to_peer_through_node: total_fee_msat,
-                                                               lowest_fee_to_node: $next_hops_fee_msat as u64 + hop_use_fee_msat,
+                                                               lowest_fee_to_node: total_fee_msat,
                                                                total_cltv_delta: hop_total_cltv_delta,
                                                                value_contribution_msat,
                                                                path_htlc_minimum_msat,
@@ -1934,10 +2099,11 @@ mod tests {
        use crate::routing::scoring::{ChannelUsage, Score, ProbabilisticScorer, ProbabilisticScoringParameters};
        use crate::routing::test_utils::{add_channel, add_or_update_node, build_graph, build_line_graph, id_to_feature_flags, get_nodes, update_channel};
        use crate::chain::transaction::OutPoint;
-       use crate::chain::keysinterface::KeysInterface;
+       use crate::chain::keysinterface::EntropySource;
        use crate::ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
        use crate::ln::msgs::{ErrorAction, LightningError, UnsignedChannelUpdate, MAX_VALUE_MSAT};
        use crate::ln::channelmanager;
+       use crate::util::config::UserConfig;
        use crate::util::test_utils as ln_test_utils;
        use crate::util::chacha20::ChaCha20;
        #[cfg(c_bindings)]
@@ -1985,6 +2151,7 @@ mod tests {
                        inbound_capacity_msat: 42,
                        unspendable_punishment_reserve: None,
                        confirmations_required: None,
+                       confirmations: None,
                        force_close_spend_delay: None,
                        is_outbound: true, is_channel_ready: true,
                        is_usable: true, is_public: true,
@@ -2180,7 +2347,8 @@ mod tests {
        fn htlc_minimum_overpay_test() {
                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(channelmanager::provided_invoice_features());
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config));
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
@@ -3153,7 +3321,8 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_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(channelmanager::provided_invoice_features());
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config));
 
                // We will use a simple single-path route from
                // our node to node2 via node0: channels {1, 3}.
@@ -3427,7 +3596,8 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_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]).with_features(channelmanager::provided_invoice_features());
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features(&config));
 
                // Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
                // {12, 13, 11} have the capacities of 100, {6} has a capacity of 50.
@@ -3600,8 +3770,9 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
+               let config = UserConfig::default();
                let payment_params = PaymentParameters::from_node_id(nodes[2])
-                       .with_features(channelmanager::provided_invoice_features());
+                       .with_features(channelmanager::provided_invoice_features(&config));
 
                // We need a route consisting of 3 paths:
                // From our node to node2 via node0, node7, node1 (three paths one hop each).
@@ -3759,7 +3930,8 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_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]).with_features(channelmanager::provided_invoice_features());
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features(&config));
 
                // We need a route consisting of 3 paths:
                // From our node to node3 via {node0, node2}, {node7, node2, node4} and {node7, node2}.
@@ -3923,7 +4095,8 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_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]).with_features(channelmanager::provided_invoice_features());
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features(&config));
 
                // This test checks that if we have two cheaper paths and one more expensive path,
                // so that liquidity-wise any 2 of 3 combination is sufficient,
@@ -4092,7 +4265,8 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_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]).with_features(channelmanager::provided_invoice_features());
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[3]).with_features(channelmanager::provided_invoice_features(&config));
 
                // We need a route consisting of 2 paths:
                // From our node to node3 via {node0, node2} and {node7, node2, node4}.
@@ -4273,7 +4447,8 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_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(PublicKey::from_slice(&[02; 33]).unwrap()).with_features(channelmanager::provided_invoice_features())
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(PublicKey::from_slice(&[02; 33]).unwrap()).with_features(channelmanager::provided_invoice_features(&config))
                        .with_route_hints(vec![RouteHint(vec![RouteHintHop {
                                src_node_id: nodes[2],
                                short_channel_id: 42,
@@ -4364,7 +4539,8 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_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(channelmanager::provided_invoice_features())
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config))
                        .with_max_channel_saturation_power_of_half(0);
 
                // We need a route consisting of 3 paths:
@@ -4720,7 +4896,8 @@ mod tests {
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
                let keys_manager = ln_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(channelmanager::provided_invoice_features());
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config));
 
                // 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
@@ -4769,7 +4946,7 @@ mod tests {
                        assert_eq!(route.paths[0][1].short_channel_id, 13);
                        assert_eq!(route.paths[0][1].fee_msat, 90_000);
                        assert_eq!(route.paths[0][1].cltv_expiry_delta, 42);
-                       assert_eq!(route.paths[0][1].node_features.le_flags(), channelmanager::provided_invoice_features().le_flags());
+                       assert_eq!(route.paths[0][1].node_features.le_flags(), channelmanager::provided_invoice_features(&config).le_flags());
                        assert_eq!(route.paths[0][1].channel_features.le_flags(), &id_to_feature_flags(13));
                }
        }
@@ -4788,14 +4965,15 @@ mod tests {
                let logger = Arc::new(ln_test_utils::TestLogger::new());
                let network_graph = NetworkGraph::new(genesis_hash, Arc::clone(&logger));
                let scorer = ln_test_utils::TestScorer::with_penalty(0);
-               let payment_params = PaymentParameters::from_node_id(nodes[0]).with_features(channelmanager::provided_invoice_features());
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[0]).with_features(channelmanager::provided_invoice_features(&config));
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
 
                {
                        let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
-                               &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(), 200_000),
-                               &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(), 10_000),
+                               &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 200_000),
+                               &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 10_000),
                        ]), 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].len(), 1);
@@ -4806,8 +4984,8 @@ mod tests {
                }
                {
                        let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
-                               &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(), 50_000),
-                               &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(), 50_000),
+                               &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000),
+                               &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000),
                        ]), 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 2);
                        assert_eq!(route.paths[0].len(), 1);
@@ -4832,14 +5010,14 @@ mod tests {
                        // smallest of them, avoiding further fragmenting our available outbound balance to
                        // this node.
                        let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
-                               &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(), 50_000),
-                               &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(), 50_000),
-                               &get_channel_details(Some(5), nodes[0], channelmanager::provided_init_features(), 50_000),
-                               &get_channel_details(Some(6), nodes[0], channelmanager::provided_init_features(), 300_000),
-                               &get_channel_details(Some(7), nodes[0], channelmanager::provided_init_features(), 50_000),
-                               &get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(), 50_000),
-                               &get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(), 50_000),
-                               &get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(), 1_000_000),
+                               &get_channel_details(Some(2), nodes[0], channelmanager::provided_init_features(&config), 50_000),
+                               &get_channel_details(Some(3), nodes[0], channelmanager::provided_init_features(&config), 50_000),
+                               &get_channel_details(Some(5), nodes[0], channelmanager::provided_init_features(&config), 50_000),
+                               &get_channel_details(Some(6), nodes[0], channelmanager::provided_init_features(&config), 300_000),
+                               &get_channel_details(Some(7), nodes[0], channelmanager::provided_init_features(&config), 50_000),
+                               &get_channel_details(Some(8), nodes[0], channelmanager::provided_init_features(&config), 50_000),
+                               &get_channel_details(Some(9), nodes[0], channelmanager::provided_init_features(&config), 50_000),
+                               &get_channel_details(Some(4), nodes[0], channelmanager::provided_init_features(&config), 1_000_000),
                        ]), 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].len(), 1);
@@ -5281,7 +5459,8 @@ mod tests {
                        excess_data: Vec::new()
                });
 
-               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features());
+               let config = UserConfig::default();
+               let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(channelmanager::provided_invoice_features(&config));
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
                // 100,000 sats is less than the available liquidity on each channel, set above.
@@ -5325,9 +5504,9 @@ mod tests {
                'load_endpoints: for _ in 0..10 {
                        loop {
                                seed = seed.overflowing_mul(0xdeadbeef).0;
-                               let src = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let src = &PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                seed = seed.overflowing_mul(0xdeadbeef).0;
-                               let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                let payment_params = PaymentParameters::from_node_id(dst);
                                let amt = seed as u64 % 200_000_000;
                                let params = ProbabilisticScoringParameters::default();
@@ -5355,6 +5534,7 @@ mod tests {
                let graph = NetworkGraph::read(&mut d, &logger).unwrap();
                let keys_manager = ln_test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
                let random_seed_bytes = keys_manager.get_secure_random_bytes();
+               let config = UserConfig::default();
 
                // First, get 100 (source, destination) pairs for which route-getting actually succeeds...
                let mut seed = random_init_seed() as usize;
@@ -5362,10 +5542,10 @@ mod tests {
                'load_endpoints: for _ in 0..10 {
                        loop {
                                seed = seed.overflowing_mul(0xdeadbeef).0;
-                               let src = &PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let src = &PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                seed = seed.overflowing_mul(0xdeadbeef).0;
-                               let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
-                               let payment_params = PaymentParameters::from_node_id(dst).with_features(channelmanager::provided_invoice_features());
+                               let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let payment_params = PaymentParameters::from_node_id(dst).with_features(channelmanager::provided_invoice_features(&config));
                                let amt = seed as u64 % 200_000_000;
                                let params = ProbabilisticScoringParameters::default();
                                let scorer = ProbabilisticScorer::new(params, &graph, &logger);
@@ -5391,7 +5571,7 @@ mod tests {
                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) },
+                       effective_capacity: EffectiveCapacity::Total { capacity_msat: 1_024_000, htlc_maximum_msat: 1_000 },
                };
                scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[3]), 123);
                scorer.set_manual_penalty(&NodeId::from_pubkey(&nodes[4]), 456);
@@ -5419,8 +5599,8 @@ pub(crate) mod bench_utils {
        use std::fs::File;
        /// Tries to open a network graph file, or panics with a URL to fetch it.
        pub(crate) fn get_route_file() -> Result<std::fs::File, &'static str> {
-               let res = File::open("net_graph-2021-05-31.bin") // By default we're run in RL/lightning
-                       .or_else(|_| File::open("lightning/net_graph-2021-05-31.bin")) // We may be run manually in RL/
+               let res = File::open("net_graph-2023-01-18.bin") // By default we're run in RL/lightning
+                       .or_else(|_| File::open("lightning/net_graph-2023-01-18.bin")) // We may be run manually in RL/
                        .or_else(|_| { // Fall back to guessing based on the binary location
                                // path is likely something like .../rust-lightning/target/debug/deps/lightning-...
                                let mut path = std::env::current_exe().unwrap();
@@ -5429,11 +5609,11 @@ pub(crate) mod bench_utils {
                                path.pop(); // debug
                                path.pop(); // target
                                path.push("lightning");
-                               path.push("net_graph-2021-05-31.bin");
+                               path.push("net_graph-2023-01-18.bin");
                                eprintln!("{}", path.to_str().unwrap());
                                File::open(path)
                        })
-               .map_err(|_| "Please fetch https://bitcoin.ninja/ldk-net_graph-v0.0.15-2021-05-31.bin and place it at lightning/net_graph-2021-05-31.bin");
+               .map_err(|_| "Please fetch https://bitcoin.ninja/ldk-net_graph-v0.0.113-2023-01-18.bin and place it at lightning/net_graph-2023-01-18.bin");
                #[cfg(require_route_graph_test)]
                return Ok(res.unwrap());
                #[cfg(not(require_route_graph_test))]
@@ -5447,11 +5627,12 @@ mod benches {
        use bitcoin::hashes::Hash;
        use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
        use crate::chain::transaction::OutPoint;
-       use crate::chain::keysinterface::{KeysManager,KeysInterface};
+       use crate::chain::keysinterface::{EntropySource, KeysManager};
        use crate::ln::channelmanager::{self, ChannelCounterparty, ChannelDetails};
        use crate::ln::features::InvoiceFeatures;
        use crate::routing::gossip::NetworkGraph;
        use crate::routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringParameters};
+       use crate::util::config::UserConfig;
        use crate::util::logger::{Logger, Record};
        use crate::util::ser::ReadableArgs;
 
@@ -5477,7 +5658,7 @@ mod benches {
                ChannelDetails {
                        channel_id: [0; 32],
                        counterparty: ChannelCounterparty {
-                               features: channelmanager::provided_init_features(),
+                               features: channelmanager::provided_init_features(&UserConfig::default()),
                                node_id,
                                unspendable_punishment_reserve: 0,
                                forwarding_info: None,
@@ -5499,6 +5680,7 @@ mod benches {
                        inbound_capacity_msat: 0,
                        unspendable_punishment_reserve: None,
                        confirmations_required: None,
+                       confirmations: None,
                        force_close_spend_delay: None,
                        is_outbound: true,
                        is_channel_ready: true,
@@ -5523,7 +5705,7 @@ mod benches {
                let logger = DummyLogger {};
                let network_graph = read_network_graph(&logger);
                let scorer = FixedPenaltyScorer::with_penalty(0);
-               generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features());
+               generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()));
        }
 
        #[bench]
@@ -5541,7 +5723,7 @@ mod benches {
                let network_graph = read_network_graph(&logger);
                let params = ProbabilisticScoringParameters::default();
                let scorer = ProbabilisticScorer::new(params, &network_graph, &logger);
-               generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features());
+               generate_routes(bench, &network_graph, scorer, channelmanager::provided_invoice_features(&UserConfig::default()));
        }
 
        fn generate_routes<S: Score>(
@@ -5560,9 +5742,9 @@ mod benches {
                'load_endpoints: for _ in 0..150 {
                        loop {
                                seed *= 0xdeadbeef;
-                               let src = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let src = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                seed *= 0xdeadbeef;
-                               let dst = PublicKey::from_slice(nodes.keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
+                               let dst = PublicKey::from_slice(nodes.unordered_keys().skip(seed % nodes.len()).next().unwrap().as_slice()).unwrap();
                                let params = PaymentParameters::from_node_id(dst).with_features(features.clone());
                                let first_hop = first_hop(src);
                                let amt = seed as u64 % 1_000_000;