Merge pull request #1311 from TheBlueMatt/2022-02-0conf-part-1
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Thu, 10 Mar 2022 00:47:23 +0000 (00:47 +0000)
committerGitHub <noreply@github.com>
Thu, 10 Mar 2022 00:47:23 +0000 (00:47 +0000)
Support for SCID Aliases

1  2 
fuzz/src/router.rs
lightning-invoice/src/utils.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/onion_route_tests.rs
lightning/src/routing/router.rs

diff --combined fuzz/src/router.rs
index bb33918b44bb1f1e91da9f3b2c6c44dcb6f95344,20ca399449c85c6d5233d1010c9ff13964de36bc..5494b26c7a300e5cb99d1056cd9054a9d626a8ac
@@@ -216,6 -216,7 +216,7 @@@ pub fn do_test<Out: test_logger::Output
                                                                },
                                                                funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
                                                                short_channel_id: Some(scid),
+                                                               inbound_scid_alias: None,
                                                                channel_value_satoshis: slice_to_be64(get_slice!(8)),
                                                                user_channel_id: 0, inbound_capacity_msat: 0,
                                                                unspendable_punishment_reserve: None,
                                        }
                                }
                                let scorer = FixedPenaltyScorer::with_penalty(0);
 +                              let random_seed_bytes: [u8; 32] = [get_slice!(1)[0]; 32];
                                for target in node_pks.iter() {
                                        let route_params = RouteParameters {
                                                payment_params: PaymentParameters::from_node_id(*target).with_route_hints(last_hops.clone()),
                                        };
                                        let _ = find_route(&our_pubkey, &route_params, &net_graph,
                                                first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
 -                                              Arc::clone(&logger), &scorer);
 +                                              Arc::clone(&logger), &scorer, &random_seed_bytes);
                                }
                        },
                }
index c2bd4b49c6b2091e3c381a8a63017c3741fc9774,73f0138824d446c5defca01a0880853822e08ff8..630411f03af6243115cc69357eeecc264e9bb018
@@@ -4,15 -4,13 +4,15 @@@ use {CreationError, Currency, DEFAULT_E
  use payment::{Payer, Router};
  
  use bech32::ToBase32;
 -use bitcoin_hashes::Hash;
 +use bitcoin_hashes::{Hash, sha256};
  use crate::prelude::*;
  use lightning::chain;
  use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
  use lightning::chain::keysinterface::{Recipient, KeysInterface, Sign};
  use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 -use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, PaymentId, PaymentSendFailure, PhantomRouteHints, MIN_FINAL_CLTV_EXPIRY, MIN_CLTV_EXPIRY_DELTA};
 +use lightning::ln::channelmanager::{ChannelDetails, ChannelManager, PaymentId, PaymentSendFailure, MIN_FINAL_CLTV_EXPIRY};
 +#[cfg(feature = "std")]
 +use lightning::ln::channelmanager::{PhantomRouteHints, MIN_CLTV_EXPIRY_DELTA};
  use lightning::ln::msgs::LightningError;
  use lightning::routing::scoring::Score;
  use lightning::routing::network_graph::{NetworkGraph, RoutingFees};
@@@ -22,7 -20,6 +22,7 @@@ use secp256k1::key::PublicKey
  use core::convert::TryInto;
  use core::ops::Deref;
  use core::time::Duration;
 +use sync::Mutex;
  
  #[cfg(feature = "std")]
  /// Utility to create an invoice that can be paid to one of multiple nodes, or a "phantom invoice."
@@@ -68,7 -65,7 +68,7 @@@ pub fn create_phantom_invoice<Signer: S
  
        for hint in phantom_route_hints {
                for channel in &hint.channels {
-                       let short_channel_id = match channel.short_channel_id {
+                       let short_channel_id = match channel.get_inbound_payment_scid() {
                                Some(id) => id,
                                None => continue,
                        };
@@@ -165,7 -162,7 +165,7 @@@ wher
        let our_channels = channelmanager.list_usable_channels();
        let mut route_hints = vec![];
        for channel in our_channels {
-               let short_channel_id = match channel.short_channel_id {
+               let short_channel_id = match channel.get_inbound_payment_scid() {
                        Some(id) => id,
                        None => continue,
                };
  pub struct DefaultRouter<G: Deref<Target = NetworkGraph>, L: Deref> where L::Target: Logger {
        network_graph: G,
        logger: L,
 +      random_seed_bytes: Mutex<[u8; 32]>,
  }
  
  impl<G: Deref<Target = NetworkGraph>, L: Deref> DefaultRouter<G, L> where L::Target: Logger {
 -      /// Creates a new router using the given [`NetworkGraph`] and  [`Logger`].
 -      pub fn new(network_graph: G, logger: L) -> Self {
 -              Self { network_graph, logger }
 +      /// Creates a new router using the given [`NetworkGraph`], a [`Logger`], and a randomness source
 +      /// `random_seed_bytes`.
 +      pub fn new(network_graph: G, logger: L, random_seed_bytes: [u8; 32]) -> Self {
 +              let random_seed_bytes = Mutex::new(random_seed_bytes);
 +              Self { network_graph, logger, random_seed_bytes }
        }
  }
  
@@@ -243,12 -237,7 +243,12 @@@ where L::Target: Logger 
                &self, payer: &PublicKey, params: &RouteParameters, _payment_hash: &PaymentHash,
                first_hops: Option<&[&ChannelDetails]>, scorer: &S
        ) -> Result<Route, LightningError> {
 -              find_route(payer, params, &*self.network_graph, first_hops, &*self.logger, scorer)
 +              let random_seed_bytes = {
 +                      let mut locked_random_seed_bytes = self.random_seed_bytes.lock().unwrap();
 +                      *locked_random_seed_bytes = sha256::Hash::hash(&*locked_random_seed_bytes).into_inner();
 +                      *locked_random_seed_bytes
 +              };
 +              find_route(payer, params, &*self.network_graph, first_hops, &*self.logger, scorer, &random_seed_bytes)
        }
  }
  
@@@ -308,7 -297,6 +308,7 @@@ mod test 
        use lightning::util::enforcing_trait_impls::EnforcingSigner;
        use lightning::util::events::{MessageSendEvent, MessageSendEventsProvider, Event};
        use lightning::util::test_utils;
 +      use lightning::chain::keysinterface::KeysInterface;
        use utils::create_invoice_from_channelmanager_and_duration_since_epoch;
  
        #[test]
                assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
                assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
  
+               // Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is
+               // available.
+               assert_eq!(invoice.route_hints().len(), 1);
+               assert_eq!(invoice.route_hints()[0].0.len(), 1);
+               assert_eq!(invoice.route_hints()[0].0[0].short_channel_id,
+                       nodes[1].node.list_usable_channels()[0].inbound_scid_alias.unwrap());
                let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
                        .with_features(invoice.features().unwrap().clone())
                        .with_route_hints(invoice.route_hints());
                let network_graph = node_cfgs[0].network_graph;
                let logger = test_utils::TestLogger::new();
                let scorer = test_utils::TestScorer::with_penalty(0);
 +              let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
                let route = find_route(
                        &nodes[0].node.get_our_node_id(), &route_params, network_graph,
 -                      Some(&first_hops.iter().collect::<Vec<_>>()), &logger, &scorer,
 +                      Some(&first_hops.iter().collect::<Vec<_>>()), &logger, &scorer, &random_seed_bytes
                ).unwrap();
  
                let payment_event = {
                let network_graph = node_cfgs[0].network_graph;
                let logger = test_utils::TestLogger::new();
                let scorer = test_utils::TestScorer::with_penalty(0);
 +              let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
                let route = find_route(
                        &nodes[0].node.get_our_node_id(), &params, network_graph,
 -                      Some(&first_hops.iter().collect::<Vec<_>>()), &logger, &scorer,
 +                      Some(&first_hops.iter().collect::<Vec<_>>()), &logger, &scorer, &random_seed_bytes
                ).unwrap();
                let (payment_event, fwd_idx) = {
                        let mut payment_hash = PaymentHash([0; 32]);
index 9de7fd02fd8928fb2f5b30ef9b0d60784761da9f,699941586e653927d15201e44e1499c9d7b2786e..f3913c5167c8ebc70d0b1cfadb20568908555133
@@@ -660,8 -660,16 +660,16 @@@ pub(super) enum RAACommitmentOrder 
  // Note this is only exposed in cfg(test):
  pub(super) struct ChannelHolder<Signer: Sign> {
        pub(super) by_id: HashMap<[u8; 32], Channel<Signer>>,
+       /// SCIDs (and outbound SCID aliases) to the real channel id. Outbound SCID aliases are added
+       /// here once the channel is available for normal use, with SCIDs being added once the funding
+       /// transaction is confirmed at the channel's required confirmation depth.
        pub(super) short_to_id: HashMap<u64, [u8; 32]>,
-       /// short channel id -> forward infos. Key of 0 means payments received
+       /// SCID/SCID Alias -> forward infos. Key of 0 means payments received.
+       ///
+       /// Note that because we may have an SCID Alias as the key we can have two entries per channel,
+       /// though in practice we probably won't be receiving HTLCs for a channel both via the alias
+       /// and via the classic SCID.
+       ///
        /// Note that while this is held in the same mutex as the channels themselves, no consistency
        /// guarantees are made about the existence of a channel with the short id here, nor the short
        /// ids in the PendingHTLCInfo!
@@@ -971,6 -979,12 +979,12 @@@ pub struct ChannelManager<Signer: Sign
        /// Locked *after* channel_state.
        pending_outbound_payments: Mutex<HashMap<PaymentId, PendingOutboundPayment>>,
  
+       /// The set of outbound SCID aliases across all our channels, including unconfirmed channels
+       /// and some closed channels which reached a usable state prior to being closed. This is used
+       /// only to avoid duplicates, and is not persisted explicitly to disk, but rebuilt from the
+       /// active channel list on load.
+       outbound_scid_aliases: Mutex<HashSet<u64>>,
        our_network_key: SecretKey,
        our_network_pubkey: PublicKey,
  
@@@ -1188,7 -1202,20 +1202,20 @@@ pub struct ChannelDetails 
        pub funding_txo: Option<OutPoint>,
        /// The position of the funding transaction in the chain. None if the funding transaction has
        /// not yet been confirmed and the channel fully opened.
+       ///
+       /// Note that if [`inbound_scid_alias`] is set, it must be used for invoices and inbound
+       /// payments instead of this. See [`get_inbound_payment_scid`].
+       ///
+       /// [`inbound_scid_alias`]: Self::inbound_scid_alias
+       /// [`get_inbound_payment_scid`]: Self::get_inbound_payment_scid
        pub short_channel_id: Option<u64>,
+       /// An optional [`short_channel_id`] alias for this channel, randomly generated by our
+       /// counterparty and usable in place of [`short_channel_id`] in invoice route hints. Our
+       /// counterparty will recognize the alias provided here in place of the [`short_channel_id`]
+       /// when they see a payment to be routed to us.
+       ///
+       /// [`short_channel_id`]: Self::short_channel_id
+       pub inbound_scid_alias: Option<u64>,
        /// The value, in satoshis, of this channel as appears in the funding output
        pub channel_value_satoshis: u64,
        /// The value, in satoshis, that must always be held in the channel for us. This value ensures
        pub is_public: bool,
  }
  
+ impl ChannelDetails {
+       /// Gets the SCID which should be used to identify this channel for inbound payments. This
+       /// should be used for providing invoice hints or in any other context where our counterparty
+       /// will forward a payment to us.
+       pub fn get_inbound_payment_scid(&self) -> Option<u64> {
+               self.inbound_scid_alias.or(self.short_channel_id)
+       }
+ }
  /// If a payment fails to send, it can be in one of several states. This enum is returned as the
  /// Err() type describing which state the payment is in, see the description of individual enum
  /// states for more.
@@@ -1383,6 -1419,24 +1419,24 @@@ macro_rules! handle_error 
        }
  }
  
+ macro_rules! update_maps_on_chan_removal {
+       ($self: expr, $short_to_id: expr, $channel: expr) => {
+               if let Some(short_id) = $channel.get_short_channel_id() {
+                       $short_to_id.remove(&short_id);
+               } else {
+                       // If the channel was never confirmed on-chain prior to its closure, remove the
+                       // outbound SCID alias we used for it from the collision-prevention set. While we
+                       // generally want to avoid ever re-using an outbound SCID alias across all channels, we
+                       // also don't want a counterparty to be able to trivially cause a memory leak by simply
+                       // opening a million channels with us which are closed before we ever reach the funding
+                       // stage.
+                       let alias_removed = $self.outbound_scid_aliases.lock().unwrap().remove(&$channel.outbound_scid_alias());
+                       debug_assert!(alias_removed);
+               }
+               $short_to_id.remove(&$channel.outbound_scid_alias());
+       }
+ }
  /// Returns (boolean indicating if we should remove the Channel object from memory, a mapped error)
  macro_rules! convert_chan_err {
        ($self: ident, $err: expr, $short_to_id: expr, $channel: expr, $channel_id: expr) => {
                        },
                        ChannelError::Close(msg) => {
                                log_error!($self.logger, "Closing channel {} due to close-required error: {}", log_bytes!($channel_id[..]), msg);
-                               if let Some(short_id) = $channel.get_short_channel_id() {
-                                       $short_to_id.remove(&short_id);
-                               }
+                               update_maps_on_chan_removal!($self, $short_to_id, $channel);
                                let shutdown_res = $channel.force_shutdown(true);
                                (true, MsgHandleErrInternal::from_finish_shutdown(msg, *$channel_id, $channel.get_user_id(),
                                        shutdown_res, $self.get_channel_update_for_broadcast(&$channel).ok()))
                        },
                        ChannelError::CloseDelayBroadcast(msg) => {
                                log_error!($self.logger, "Channel {} need to be shutdown but closing transactions not broadcast due to {}", log_bytes!($channel_id[..]), msg);
-                               if let Some(short_id) = $channel.get_short_channel_id() {
-                                       $short_to_id.remove(&short_id);
-                               }
+                               update_maps_on_chan_removal!($self, $short_to_id, $channel);
                                let shutdown_res = $channel.force_shutdown(false);
                                (true, MsgHandleErrInternal::from_finish_shutdown(msg, *$channel_id, $channel.get_user_id(),
                                        shutdown_res, $self.get_channel_update_for_broadcast(&$channel).ok()))
@@@ -1446,28 -1496,21 +1496,21 @@@ macro_rules! try_chan_entry 
  }
  
  macro_rules! remove_channel {
-       ($channel_state: expr, $entry: expr) => {
+       ($self: expr, $channel_state: expr, $entry: expr) => {
                {
                        let channel = $entry.remove_entry().1;
-                       if let Some(short_id) = channel.get_short_channel_id() {
-                               $channel_state.short_to_id.remove(&short_id);
-                       }
+                       update_maps_on_chan_removal!($self, $channel_state.short_to_id, channel);
                        channel
                }
        }
  }
  
  macro_rules! handle_monitor_err {
-       ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr) => {
-               handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, Vec::new(), Vec::new())
-       };
        ($self: ident, $err: expr, $short_to_id: expr, $chan: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr, $failed_finalized_fulfills: expr, $chan_id: expr) => {
                match $err {
                        ChannelMonitorUpdateErr::PermanentFailure => {
                                log_error!($self.logger, "Closing channel {} due to monitor update ChannelMonitorUpdateErr::PermanentFailure", log_bytes!($chan_id[..]));
-                               if let Some(short_id) = $chan.get_short_channel_id() {
-                                       $short_to_id.remove(&short_id);
-                               }
+                               update_maps_on_chan_removal!($self, $short_to_id, $chan);
                                // TODO: $failed_fails is dropped here, which will cause other channels to hit the
                                // chain in a confused state! We need to move them into the ChannelMonitor which
                                // will be responsible for failing backwards once things confirm on-chain.
                }
                res
        } };
+       ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $chan_id: expr, COMMITMENT_UPDATE_ONLY) => { {
+               debug_assert!($action_type == RAACommitmentOrder::CommitmentFirst);
+               handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, true, Vec::new(), Vec::new(), Vec::new(), $chan_id)
+       } };
+       ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $chan_id: expr, NO_UPDATE) => {
+               handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, false, false, Vec::new(), Vec::new(), Vec::new(), $chan_id)
+       };
+       ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr) => {
+               handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, Vec::new(), Vec::new(), Vec::new())
+       };
        ($self: ident, $err: expr, $channel_state: expr, $entry: expr, $action_type: path, $resend_raa: expr, $resend_commitment: expr, $failed_forwards: expr, $failed_fails: expr) => {
                handle_monitor_err!($self, $err, $channel_state, $entry, $action_type, $resend_raa, $resend_commitment, $failed_forwards, $failed_fails, Vec::new())
-       }
+       };
  }
  
  macro_rules! return_monitor_err {
@@@ -1539,15 -1592,34 +1592,34 @@@ macro_rules! maybe_break_monitor_err 
        }
  }
  
+ macro_rules! send_funding_locked {
+       ($short_to_id: expr, $pending_msg_events: expr, $channel: expr, $funding_locked_msg: expr) => {
+               $pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
+                       node_id: $channel.get_counterparty_node_id(),
+                       msg: $funding_locked_msg,
+               });
+               // Note that we may send a funding locked multiple times for a channel if we reconnect, so
+               // we allow collisions, but we shouldn't ever be updating the channel ID pointed to.
+               let outbound_alias_insert = $short_to_id.insert($channel.outbound_scid_alias(), $channel.channel_id());
+               assert!(outbound_alias_insert.is_none() || outbound_alias_insert.unwrap() == $channel.channel_id(),
+                       "SCIDs should never collide - ensure you weren't behind the chain tip by a full month when creating channels");
+               if let Some(real_scid) = $channel.get_short_channel_id() {
+                       let scid_insert = $short_to_id.insert(real_scid, $channel.channel_id());
+                       assert!(scid_insert.is_none() || scid_insert.unwrap() == $channel.channel_id(),
+                               "SCIDs should never collide - ensure you weren't behind the chain tip by a full month when creating channels");
+               }
+       }
+ }
  macro_rules! handle_chan_restoration_locked {
        ($self: ident, $channel_lock: expr, $channel_state: expr, $channel_entry: expr,
         $raa: expr, $commitment_update: expr, $order: expr, $chanmon_update: expr,
         $pending_forwards: expr, $funding_broadcastable: expr, $funding_locked: expr, $announcement_sigs: expr) => { {
                let mut htlc_forwards = None;
-               let counterparty_node_id = $channel_entry.get().get_counterparty_node_id();
  
                let chanmon_update: Option<ChannelMonitorUpdate> = $chanmon_update; // Force type-checking to resolve
                let chanmon_update_is_none = chanmon_update.is_none();
+               let counterparty_node_id = $channel_entry.get().get_counterparty_node_id();
                let res = loop {
                        let forwards: Vec<(PendingHTLCInfo, u64)> = $pending_forwards; // Force type-checking to resolve
                        if !forwards.is_empty() {
                                // Similar to the above, this implies that we're letting the funding_locked fly
                                // before it should be allowed to.
                                assert!(chanmon_update.is_none());
-                               $channel_state.pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
-                                       node_id: counterparty_node_id,
-                                       msg,
-                               });
-                               $channel_state.short_to_id.insert($channel_entry.get().get_short_channel_id().unwrap(), $channel_entry.get().channel_id());
+                               send_funding_locked!($channel_state.short_to_id, $channel_state.pending_msg_events, $channel_entry.get(), msg);
                        }
                        if let Some(msg) = $announcement_sigs {
                                $channel_state.pending_msg_events.push(events::MessageSendEvent::SendAnnouncementSignatures {
@@@ -1706,6 -1774,7 +1774,7 @@@ impl<Signer: Sign, M: Deref, T: Deref, 
                                claimable_htlcs: HashMap::new(),
                                pending_msg_events: Vec::new(),
                        }),
+                       outbound_scid_aliases: Mutex::new(HashSet::new()),
                        pending_inbound_payments: Mutex::new(HashMap::new()),
                        pending_outbound_payments: Mutex::new(HashMap::new()),
  
                &self.default_configuration
        }
  
+       fn create_and_insert_outbound_scid_alias(&self) -> u64 {
+               let height = self.best_block.read().unwrap().height();
+               let mut outbound_scid_alias = 0;
+               let mut i = 0;
+               loop {
+                       if cfg!(fuzzing) { // fuzzing chacha20 doesn't use the key at all so we always get the same alias
+                               outbound_scid_alias += 1;
+                       } else {
+                               outbound_scid_alias = fake_scid::Namespace::OutboundAlias.get_fake_scid(height, &self.genesis_hash, &self.fake_scid_rand_bytes, &self.keys_manager);
+                       }
+                       if outbound_scid_alias != 0 && self.outbound_scid_aliases.lock().unwrap().insert(outbound_scid_alias) {
+                               break;
+                       }
+                       i += 1;
+                       if i > 1_000_000 { panic!("Your RNG is busted or we ran out of possible outbound SCID aliases (which should never happen before we run out of memory to store channels"); }
+               }
+               outbound_scid_alias
+       }
        /// Creates a new outbound channel to the given remote node and with the given value.
        ///
        /// `user_channel_id` will be provided back as in
                        let per_peer_state = self.per_peer_state.read().unwrap();
                        match per_peer_state.get(&their_network_key) {
                                Some(peer_state) => {
+                                       let outbound_scid_alias = self.create_and_insert_outbound_scid_alias();
                                        let peer_state = peer_state.lock().unwrap();
                                        let their_features = &peer_state.latest_features;
                                        let config = if override_config.is_some() { override_config.as_ref().unwrap() } else { &self.default_configuration };
-                                       Channel::new_outbound(&self.fee_estimator, &self.keys_manager, their_network_key, their_features,
-                                               channel_value_satoshis, push_msat, user_channel_id, config, self.best_block.read().unwrap().height())?
+                                       match Channel::new_outbound(&self.fee_estimator, &self.keys_manager, their_network_key,
+                                               their_features, channel_value_satoshis, push_msat, user_channel_id, config,
+                                               self.best_block.read().unwrap().height(), outbound_scid_alias)
+                                       {
+                                               Ok(res) => res,
+                                               Err(e) => {
+                                                       self.outbound_scid_aliases.lock().unwrap().remove(&outbound_scid_alias);
+                                                       return Err(e);
+                                               },
+                                       }
                                },
                                None => return Err(APIError::ChannelUnavailable { err: format!("Not connected to node: {}", their_network_key) }),
                        }
                                        },
                                        funding_txo: channel.get_funding_txo(),
                                        short_channel_id: channel.get_short_channel_id(),
+                                       inbound_scid_alias: channel.latest_inbound_scid_alias(),
                                        channel_value_satoshis: channel.get_value_satoshis(),
                                        unspendable_punishment_reserve: to_self_reserve_satoshis,
                                        balance_msat,
                                        if let Some(monitor_update) = monitor_update {
                                                if let Err(e) = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), monitor_update) {
                                                        let (result, is_permanent) =
-                                                               handle_monitor_err!(self, e, channel_state.short_to_id, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, false, false, Vec::new(), Vec::new(), Vec::new(), chan_entry.key());
+                                                               handle_monitor_err!(self, e, channel_state.short_to_id, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, chan_entry.key(), NO_UPDATE);
                                                        if is_permanent {
-                                                               remove_channel!(channel_state, chan_entry);
+                                                               remove_channel!(self, channel_state, chan_entry);
                                                                break result;
                                                        }
                                                }
                                        });
  
                                        if chan_entry.get().is_shutdown() {
-                                               let channel = remove_channel!(channel_state, chan_entry);
+                                               let channel = remove_channel!(self, channel_state, chan_entry);
                                                if let Ok(channel_update) = self.get_channel_update_for_broadcast(&channel) {
                                                        channel_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
                                                                msg: channel_update
                                                return Err(APIError::ChannelUnavailable{err: "No such channel".to_owned()});
                                        }
                                }
-                               if let Some(short_id) = chan.get().get_short_channel_id() {
-                                       channel_state.short_to_id.remove(&short_id);
-                               }
                                if peer_node_id.is_some() {
                                        if let Some(peer_msg) = peer_msg {
                                                self.issue_channel_close_events(chan.get(),ClosureReason::CounterpartyForceClosed { peer_msg: peer_msg.to_string() });
                                } else {
                                        self.issue_channel_close_events(chan.get(),ClosureReason::HolderForceClosed);
                                }
-                               chan.remove_entry().1
+                               remove_channel!(self, channel_state, chan)
                        } else {
                                return Err(APIError::ChannelUnavailable{err: "No such channel".to_owned()});
                        }
                                                                                }
                                                                                ChannelError::Close(msg) => {
                                                                                        log_trace!(self.logger, "Closing channel {} due to Close-required error: {}", log_bytes!(chan.key()[..]), msg);
-                                                                                       let (channel_id, mut channel) = chan.remove_entry();
-                                                                                       if let Some(short_id) = channel.get_short_channel_id() {
-                                                                                               channel_state.short_to_id.remove(&short_id);
-                                                                                       }
+                                                                                       let mut channel = remove_channel!(self, channel_state, chan);
                                                                                        // ChannelClosed event is generated by handle_error for us.
-                                                                                       Err(MsgHandleErrInternal::from_finish_shutdown(msg, channel_id, channel.get_user_id(), channel.force_shutdown(true), self.get_channel_update_for_broadcast(&channel).ok()))
+                                                                                       Err(MsgHandleErrInternal::from_finish_shutdown(msg, channel.channel_id(), channel.get_user_id(), channel.force_shutdown(true), self.get_channel_update_for_broadcast(&channel).ok()))
                                                                                },
                                                                                ChannelError::CloseDelayBroadcast(_) => { panic!("Wait is only generated on receipt of channel_reestablish, which is handled by try_chan_entry, we don't bother to support it here"); }
                                                                        };
                let ret_err = match res {
                        Ok(Some((update_fee, commitment_signed, monitor_update))) => {
                                if let Err(e) = self.chain_monitor.update_channel(chan.get_funding_txo().unwrap(), monitor_update) {
-                                       let (res, drop) = handle_monitor_err!(self, e, short_to_id, chan, RAACommitmentOrder::CommitmentFirst, false, true, Vec::new(), Vec::new(), Vec::new(), chan_id);
+                                       let (res, drop) = handle_monitor_err!(self, e, short_to_id, chan, RAACommitmentOrder::CommitmentFirst, chan_id, COMMITMENT_UPDATE_ONLY);
                                        if drop { retain_channel = false; }
                                        res
                                } else {
                        return Err(MsgHandleErrInternal::send_err_msg_no_close("No inbound channels accepted".to_owned(), msg.temporary_channel_id.clone()));
                }
  
-               let mut channel = Channel::new_from_req(&self.fee_estimator, &self.keys_manager, counterparty_node_id.clone(),
-                               &their_features, msg, 0, &self.default_configuration, self.best_block.read().unwrap().height(), &self.logger)
-                       .map_err(|e| MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id))?;
+               let outbound_scid_alias = self.create_and_insert_outbound_scid_alias();
+               let mut channel = match Channel::new_from_req(&self.fee_estimator, &self.keys_manager,
+                       counterparty_node_id.clone(), &their_features, msg, 0, &self.default_configuration,
+                       self.best_block.read().unwrap().height(), &self.logger, outbound_scid_alias)
+               {
+                       Err(e) => {
+                               self.outbound_scid_aliases.lock().unwrap().remove(&outbound_scid_alias);
+                               return Err(MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id));
+                       },
+                       Ok(res) => res
+               };
                let mut channel_state_lock = self.channel_state.lock().unwrap();
                let channel_state = &mut *channel_state_lock;
                match channel_state.by_id.entry(channel.channel_id()) {
-                       hash_map::Entry::Occupied(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("temporary_channel_id collision!".to_owned(), msg.temporary_channel_id.clone())),
+                       hash_map::Entry::Occupied(_) => {
+                               self.outbound_scid_aliases.lock().unwrap().remove(&outbound_scid_alias);
+                               return Err(MsgHandleErrInternal::send_err_msg_no_close("temporary_channel_id collision!".to_owned(), msg.temporary_channel_id.clone()))
+                       },
                        hash_map::Entry::Vacant(entry) => {
                                if !self.default_configuration.manually_accept_inbound_channels {
                                        channel_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel {
                                        if let Some(monitor_update) = monitor_update {
                                                if let Err(e) = self.chain_monitor.update_channel(chan_entry.get().get_funding_txo().unwrap(), monitor_update) {
                                                        let (result, is_permanent) =
-                                                               handle_monitor_err!(self, e, channel_state.short_to_id, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, false, false, Vec::new(), Vec::new(), Vec::new(), chan_entry.key());
+                                                               handle_monitor_err!(self, e, channel_state.short_to_id, chan_entry.get_mut(), RAACommitmentOrder::CommitmentFirst, chan_entry.key(), NO_UPDATE);
                                                        if is_permanent {
-                                                               remove_channel!(channel_state, chan_entry);
+                                                               remove_channel!(self, channel_state, chan_entry);
                                                                break result;
                                                        }
                                                }
                                                // also implies there are no pending HTLCs left on the channel, so we can
                                                // fully delete it from tracking (the channel monitor is still around to
                                                // watch for old state broadcasts)!
-                                               if let Some(short_id) = chan_entry.get().get_short_channel_id() {
-                                                       channel_state.short_to_id.remove(&short_id);
-                                               }
-                                               (tx, Some(chan_entry.remove_entry().1))
+                                               (tx, Some(remove_channel!(self, channel_state, chan_entry)))
                                        } else { (tx, None) }
                                },
                                hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
                                        let mut channel_lock = self.channel_state.lock().unwrap();
                                        let channel_state = &mut *channel_lock;
                                        let by_id = &mut channel_state.by_id;
-                                       let short_to_id = &mut channel_state.short_to_id;
                                        let pending_msg_events = &mut channel_state.pending_msg_events;
-                                       if let Some(mut chan) = by_id.remove(&funding_outpoint.to_channel_id()) {
-                                               if let Some(short_id) = chan.get_short_channel_id() {
-                                                       short_to_id.remove(&short_id);
-                                               }
+                                       if let hash_map::Entry::Occupied(chan_entry) = by_id.entry(funding_outpoint.to_channel_id()) {
+                                               let mut chan = remove_channel!(self, channel_state, chan_entry);
                                                failed_channels.push(chan.force_shutdown(false));
                                                if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
                                                        pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
                                                if let Some((commitment_update, monitor_update)) = commitment_opt {
                                                        if let Err(e) = self.chain_monitor.update_channel(chan.get_funding_txo().unwrap(), monitor_update) {
                                                                has_monitor_update = true;
-                                                               let (res, close_channel) = handle_monitor_err!(self, e, short_to_id, chan, RAACommitmentOrder::CommitmentFirst, false, true, Vec::new(), Vec::new(), Vec::new(), channel_id);
+                                                               let (res, close_channel) = handle_monitor_err!(self, e, short_to_id, chan, RAACommitmentOrder::CommitmentFirst, channel_id, COMMITMENT_UPDATE_ONLY);
                                                                handle_errors.push((chan.get_counterparty_node_id(), res));
                                                                if close_channel { return false; }
                                                        } else {
                                                if let Some(tx) = tx_opt {
                                                        // We're done with this channel. We got a closing_signed and sent back
                                                        // a closing_signed with a closing transaction to broadcast.
-                                                       if let Some(short_id) = chan.get_short_channel_id() {
-                                                               short_to_id.remove(&short_id);
-                                                       }
                                                        if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
                                                                pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
                                                                        msg: update
  
                                                        log_info!(self.logger, "Broadcasting {}", log_tx!(tx));
                                                        self.tx_broadcaster.broadcast_transaction(&tx);
+                                                       update_maps_on_chan_removal!(self, short_to_id, chan);
                                                        false
                                                } else { true }
                                        },
        /// Legacy version of [`create_inbound_payment`]. Use this method if you wish to share
        /// serialized state with LDK node(s) running 0.0.103 and earlier.
        ///
 +      /// May panic if `invoice_expiry_delta_secs` is greater than one year.
 +      ///
        /// # Note
        /// This method is deprecated and will be removed soon.
        ///
        /// If you need exact expiry semantics, you should enforce them upon receipt of
        /// [`PaymentReceived`].
        ///
 -      /// May panic if `invoice_expiry_delta_secs` is greater than one year.
 -      ///
        /// Note that invoices generated for inbound payments should have their `min_final_cltv_expiry`
        /// set to at least [`MIN_FINAL_CLTV_EXPIRY`].
        ///
        /// Legacy version of [`create_inbound_payment_for_hash`]. Use this method if you wish to share
        /// serialized state with LDK node(s) running 0.0.103 and earlier.
        ///
 +      /// May panic if `invoice_expiry_delta_secs` is greater than one year.
 +      ///
        /// # Note
        /// This method is deprecated and will be removed soon.
        ///
                let mut channel_state = self.channel_state.lock().unwrap();
                let best_block = self.best_block.read().unwrap();
                loop {
-                       let scid_candidate = fake_scid::get_phantom_scid(&self.fake_scid_rand_bytes, best_block.height(), &self.genesis_hash, &self.keys_manager);
+                       let scid_candidate = fake_scid::Namespace::Phantom.get_fake_scid(best_block.height(), &self.genesis_hash, &self.fake_scid_rand_bytes, &self.keys_manager);
                        // Ensure the generated scid doesn't conflict with a real channel.
                        match channel_state.short_to_id.entry(scid_candidate) {
                                hash_map::Entry::Occupied(_) => continue,
@@@ -5524,10 -5616,7 +5618,7 @@@ wher
                                                }));
                                        }
                                        if let Some(funding_locked) = funding_locked_opt {
-                                               pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
-                                                       node_id: channel.get_counterparty_node_id(),
-                                                       msg: funding_locked,
-                                               });
+                                               send_funding_locked!(short_to_id, pending_msg_events, channel, funding_locked);
                                                if channel.is_usable() {
                                                        log_trace!(self.logger, "Sending funding_locked with private initial channel_update for our counterparty on channel {}", log_bytes!(channel.channel_id()));
                                                        pending_msg_events.push(events::MessageSendEvent::SendChannelUpdate {
                                                } else {
                                                        log_trace!(self.logger, "Sending funding_locked WITHOUT channel_update for {}", log_bytes!(channel.channel_id()));
                                                }
-                                               short_to_id.insert(channel.get_short_channel_id().unwrap(), channel.channel_id());
                                        }
                                        if let Some(announcement_sigs) = announcement_sigs {
                                                log_trace!(self.logger, "Sending announcement_signatures for channel {}", log_bytes!(channel.channel_id()));
                                                }
                                        }
                                } else if let Err(reason) = res {
-                                       if let Some(short_id) = channel.get_short_channel_id() {
-                                               short_to_id.remove(&short_id);
-                                       }
+                                       update_maps_on_chan_removal!(self, short_to_id, channel);
                                        // It looks like our counterparty went on-chain or funding transaction was
                                        // reorged out of the main chain. Close the channel.
                                        failed_channels.push(channel.force_shutdown(true));
@@@ -5749,15 -5835,13 +5837,13 @@@ impl<Signer: Sign, M: Deref , T: Deref 
                {
                        let mut channel_state_lock = self.channel_state.lock().unwrap();
                        let channel_state = &mut *channel_state_lock;
-                       let short_to_id = &mut channel_state.short_to_id;
                        let pending_msg_events = &mut channel_state.pending_msg_events;
+                       let short_to_id = &mut channel_state.short_to_id;
                        if no_connection_possible {
                                log_debug!(self.logger, "Failing all channels with {} due to no_connection_possible", log_pubkey!(counterparty_node_id));
                                channel_state.by_id.retain(|_, chan| {
                                        if chan.get_counterparty_node_id() == *counterparty_node_id {
-                                               if let Some(short_id) = chan.get_short_channel_id() {
-                                                       short_to_id.remove(&short_id);
-                                               }
+                                               update_maps_on_chan_removal!(self, short_to_id, chan);
                                                failed_channels.push(chan.force_shutdown(true));
                                                if let Ok(update) = self.get_channel_update_for_broadcast(&chan) {
                                                        pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate {
                                        if chan.get_counterparty_node_id() == *counterparty_node_id {
                                                chan.remove_uncommitted_htlcs_and_mark_paused(&self.logger);
                                                if chan.is_shutdown() {
-                                                       if let Some(short_id) = chan.get_short_channel_id() {
-                                                               short_to_id.remove(&short_id);
-                                                       }
+                                                       update_maps_on_chan_removal!(self, short_to_id, chan);
                                                        self.issue_channel_close_events(chan, ClosureReason::DisconnectedPeer);
                                                        return false;
                                                } else {
@@@ -5968,6 -6050,7 +6052,7 @@@ impl_writeable_tlv_based!(ChannelCounte
  });
  
  impl_writeable_tlv_based!(ChannelDetails, {
+       (1, inbound_scid_alias, option),
        (2, channel_id, required),
        (4, counterparty, required),
        (6, funding_txo, option),
@@@ -6777,6 -6860,32 +6862,32 @@@ impl<'a, Signer: Sign, M: Deref, T: Der
                        }
                }
  
+               let mut outbound_scid_aliases = HashSet::new();
+               for (chan_id, chan) in by_id.iter_mut() {
+                       if chan.outbound_scid_alias() == 0 {
+                               let mut outbound_scid_alias;
+                               loop {
+                                       outbound_scid_alias = fake_scid::Namespace::OutboundAlias
+                                               .get_fake_scid(best_block_height, &genesis_hash, fake_scid_rand_bytes.as_ref().unwrap(), &args.keys_manager);
+                                       if outbound_scid_aliases.insert(outbound_scid_alias) { break; }
+                               }
+                               chan.set_outbound_scid_alias(outbound_scid_alias);
+                       } else if !outbound_scid_aliases.insert(chan.outbound_scid_alias()) {
+                               // Note that in rare cases its possible to hit this while reading an older
+                               // channel if we just happened to pick a colliding outbound alias above.
+                               log_error!(args.logger, "Got duplicate outbound SCID alias; {}", chan.outbound_scid_alias());
+                               return Err(DecodeError::InvalidValue);
+                       }
+                       if chan.is_usable() {
+                               if short_to_id.insert(chan.outbound_scid_alias(), *chan_id).is_some() {
+                                       // Note that in rare cases its possible to hit this while reading an older
+                                       // channel if we just happened to pick a colliding outbound alias above.
+                                       log_error!(args.logger, "Got duplicate outbound SCID alias; {}", chan.outbound_scid_alias());
+                                       return Err(DecodeError::InvalidValue);
+                               }
+                       }
+               }
                let inbound_pmt_key_material = args.keys_manager.get_inbound_payment_key_material();
                let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material);
                let channel_manager = ChannelManager {
                        inbound_payment_key: expanded_inbound_key,
                        pending_inbound_payments: Mutex::new(pending_inbound_payments),
                        pending_outbound_payments: Mutex::new(pending_outbound_payments.unwrap()),
+                       outbound_scid_aliases: Mutex::new(outbound_scid_aliases),
                        fake_scid_rand_bytes: fake_scid_rand_bytes.unwrap(),
  
                        our_network_key,
@@@ -6846,7 -6957,6 +6959,7 @@@ mod tests 
        use util::errors::APIError;
        use util::events::{Event, MessageSendEvent, MessageSendEventsProvider};
        use util::test_utils;
 +      use chain::keysinterface::KeysInterface;
  
        #[cfg(feature = "std")]
        #[test]
                let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
                create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
                let scorer = test_utils::TestScorer::with_penalty(0);
 +              let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
  
                // To start (1), send a regular payment but don't claim it.
                let expected_route = [&nodes[1]];
                };
                let route = find_route(
                        &nodes[0].node.get_our_node_id(), &route_params, nodes[0].network_graph, None,
 -                      nodes[0].logger, &scorer
 +                      nodes[0].logger, &scorer, &random_seed_bytes
                ).unwrap();
                nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap();
                check_added_monitors!(nodes[0], 1);
                let payment_preimage = PaymentPreimage([42; 32]);
                let route = find_route(
                        &nodes[0].node.get_our_node_id(), &route_params, nodes[0].network_graph, None,
 -                      nodes[0].logger, &scorer
 +                      nodes[0].logger, &scorer, &random_seed_bytes
                ).unwrap();
                let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(payment_preimage)).unwrap();
                check_added_monitors!(nodes[0], 1);
                let network_graph = nodes[0].network_graph;
                let first_hops = nodes[0].node.list_usable_channels();
                let scorer = test_utils::TestScorer::with_penalty(0);
 +              let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
                let route = find_route(
                        &payer_pubkey, &route_params, network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
 -                      nodes[0].logger, &scorer
 +                      nodes[0].logger, &scorer, &random_seed_bytes
                ).unwrap();
  
                let test_preimage = PaymentPreimage([42; 32]);
                let network_graph = nodes[0].network_graph;
                let first_hops = nodes[0].node.list_usable_channels();
                let scorer = test_utils::TestScorer::with_penalty(0);
 +              let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
                let route = find_route(
                        &payer_pubkey, &route_params, network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
 -                      nodes[0].logger, &scorer
 +                      nodes[0].logger, &scorer, &random_seed_bytes
                ).unwrap();
  
                let test_preimage = PaymentPreimage([42; 32]);
  pub mod bench {
        use chain::Listen;
        use chain::chainmonitor::{ChainMonitor, Persist};
 -      use chain::keysinterface::{KeysManager, InMemorySigner};
 +      use chain::keysinterface::{KeysManager, KeysInterface, InMemorySigner};
        use ln::channelmanager::{BestBlock, ChainParameters, ChannelManager, PaymentHash, PaymentPreimage};
        use ln::features::{InitFeatures, InvoiceFeatures};
        use ln::functional_test_utils::*;
        use routing::router::{PaymentParameters, get_route};
        use util::test_utils;
        use util::config::UserConfig;
 -      use util::events::{Event, MessageSendEvent, MessageSendEventsProvider, PaymentPurpose};
 +      use util::events::{Event, MessageSendEvent, MessageSendEventsProvider};
  
        use bitcoin::hashes::Hash;
        use bitcoin::hashes::sha256::Hash as Sha256;
                                let payment_params = PaymentParameters::from_node_id($node_b.get_our_node_id())
                                        .with_features(InvoiceFeatures::known());
                                let scorer = test_utils::TestScorer::with_penalty(0);
 -                              let route = get_route(&$node_a.get_our_node_id(), &payment_params, &dummy_graph,
 -                                      Some(&usable_channels.iter().map(|r| r).collect::<Vec<_>>()), 10_000, TEST_FINAL_CLTV, &logger_a, &scorer).unwrap();
 +                              let seed = [3u8; 32];
 +                              let keys_manager = KeysManager::new(&seed, 42, 42);
 +                              let random_seed_bytes = keys_manager.get_secure_random_bytes();
 +                              let route = get_route(&$node_a.get_our_node_id(), &payment_params, &dummy_graph.read_only(),
 +                                      Some(&usable_channels.iter().map(|r| r).collect::<Vec<_>>()), 10_000, TEST_FINAL_CLTV, &logger_a, &scorer, &random_seed_bytes).unwrap();
  
                                let mut payment_preimage = PaymentPreimage([0; 32]);
                                payment_preimage.0[0..8].copy_from_slice(&payment_count.to_le_bytes());
index 6efd175c3a99a4defc7e6b0cc8050216eeffc312,7a3a269316e020d54b4481990ffcdbceddd0f10a..5901efbf95cf47fbceabb97d77dcd94abfcd543f
@@@ -10,7 -10,7 +10,7 @@@
  //! A bunch of useful utilities for building networks of nodes and exchanging messages between
  //! nodes for functional tests.
  
 -use chain::{BestBlock, Confirm, Listen, Watch};
 +use chain::{BestBlock, Confirm, Listen, Watch, keysinterface::KeysInterface};
  use chain::channelmonitor::ChannelMonitor;
  use chain::transaction::OutPoint;
  use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
@@@ -693,6 -693,61 +693,61 @@@ pub fn create_announced_chan_between_no
        (chan_announcement.1, chan_announcement.2, chan_announcement.3, chan_announcement.4)
  }
  
+ pub fn create_unannounced_chan_between_nodes_with_value<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'b, 'c, 'd>>, a: usize, b: usize, channel_value: u64, push_msat: u64, a_flags: InitFeatures, b_flags: InitFeatures) -> (msgs::FundingLocked, Transaction) {
+       let mut no_announce_cfg = test_default_channel_config();
+       no_announce_cfg.channel_options.announced_channel = false;
+       nodes[a].node.create_channel(nodes[b].node.get_our_node_id(), channel_value, push_msat, 42, Some(no_announce_cfg)).unwrap();
+       let open_channel = get_event_msg!(nodes[a], MessageSendEvent::SendOpenChannel, nodes[b].node.get_our_node_id());
+       nodes[b].node.handle_open_channel(&nodes[a].node.get_our_node_id(), a_flags, &open_channel);
+       let accept_channel = get_event_msg!(nodes[b], MessageSendEvent::SendAcceptChannel, nodes[a].node.get_our_node_id());
+       nodes[a].node.handle_accept_channel(&nodes[b].node.get_our_node_id(), b_flags, &accept_channel);
+       let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[a], channel_value, 42);
+       nodes[a].node.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
+       nodes[b].node.handle_funding_created(&nodes[a].node.get_our_node_id(), &get_event_msg!(nodes[a], MessageSendEvent::SendFundingCreated, nodes[b].node.get_our_node_id()));
+       check_added_monitors!(nodes[b], 1);
+       let cs_funding_signed = get_event_msg!(nodes[b], MessageSendEvent::SendFundingSigned, nodes[a].node.get_our_node_id());
+       nodes[a].node.handle_funding_signed(&nodes[b].node.get_our_node_id(), &cs_funding_signed);
+       check_added_monitors!(nodes[a], 1);
+       let conf_height = core::cmp::max(nodes[a].best_block_info().1 + 1, nodes[b].best_block_info().1 + 1);
+       confirm_transaction_at(&nodes[a], &tx, conf_height);
+       connect_blocks(&nodes[a], CHAN_CONFIRM_DEPTH - 1);
+       confirm_transaction_at(&nodes[b], &tx, conf_height);
+       connect_blocks(&nodes[b], CHAN_CONFIRM_DEPTH - 1);
+       let as_funding_locked = get_event_msg!(nodes[a], MessageSendEvent::SendFundingLocked, nodes[b].node.get_our_node_id());
+       nodes[a].node.handle_funding_locked(&nodes[b].node.get_our_node_id(), &get_event_msg!(nodes[b], MessageSendEvent::SendFundingLocked, nodes[a].node.get_our_node_id()));
+       let as_update = get_event_msg!(nodes[a], MessageSendEvent::SendChannelUpdate, nodes[b].node.get_our_node_id());
+       nodes[b].node.handle_funding_locked(&nodes[a].node.get_our_node_id(), &as_funding_locked);
+       let bs_update = get_event_msg!(nodes[b], MessageSendEvent::SendChannelUpdate, nodes[a].node.get_our_node_id());
+       nodes[a].node.handle_channel_update(&nodes[b].node.get_our_node_id(), &bs_update);
+       nodes[b].node.handle_channel_update(&nodes[a].node.get_our_node_id(), &as_update);
+       let mut found_a = false;
+       for chan in nodes[a].node.list_usable_channels() {
+               if chan.channel_id == as_funding_locked.channel_id {
+                       assert!(!found_a);
+                       found_a = true;
+                       assert!(!chan.is_public);
+               }
+       }
+       assert!(found_a);
+       let mut found_b = false;
+       for chan in nodes[b].node.list_usable_channels() {
+               if chan.channel_id == as_funding_locked.channel_id {
+                       assert!(!found_b);
+                       found_b = true;
+                       assert!(!chan.is_public);
+               }
+       }
+       assert!(found_b);
+       (as_funding_locked, tx)
+ }
  pub fn update_nodes_with_chan_announce<'a, 'b, 'c, 'd>(nodes: &'a Vec<Node<'b, 'c, 'd>>, a: usize, b: usize, ann: &msgs::ChannelAnnouncement, upd_1: &msgs::ChannelUpdate, upd_2: &msgs::ChannelUpdate) {
        nodes[a].node.broadcast_node_announcement([0, 0, 0], [0; 32], Vec::new());
        let a_events = nodes[a].node.get_and_clear_pending_msg_events();
                node.net_graph_msg_handler.handle_channel_update(upd_2).unwrap();
                node.net_graph_msg_handler.handle_node_announcement(&a_node_announcement).unwrap();
                node.net_graph_msg_handler.handle_node_announcement(&b_node_announcement).unwrap();
+               // Note that channel_updates are also delivered to ChannelManagers to ensure we have
+               // forwarding info for local channels even if its not accepted in the network graph.
+               node.node.handle_channel_update(&nodes[a].node.get_our_node_id(), &upd_1);
+               node.node.handle_channel_update(&nodes[b].node.get_our_node_id(), &upd_2);
        }
  }
  
@@@ -1094,18 -1154,15 +1154,18 @@@ macro_rules! get_route_and_payment_has
                $crate::get_route_and_payment_hash!($send_node, $recv_node, vec![], $recv_value, TEST_FINAL_CLTV)
        }};
        ($send_node: expr, $recv_node: expr, $last_hops: expr, $recv_value: expr, $cltv: expr) => {{
 +              use $crate::chain::keysinterface::KeysInterface;
                let (payment_preimage, payment_hash, payment_secret) = $crate::get_payment_preimage_hash!($recv_node, Some($recv_value));
                let payment_params = $crate::routing::router::PaymentParameters::from_node_id($recv_node.node.get_our_node_id())
                        .with_features($crate::ln::features::InvoiceFeatures::known())
                        .with_route_hints($last_hops);
                let scorer = $crate::util::test_utils::TestScorer::with_penalty(0);
 +              let keys_manager = $crate::util::test_utils::TestKeysInterface::new(&[0u8; 32], bitcoin::network::constants::Network::Testnet);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let route = $crate::routing::router::get_route(
 -                      &$send_node.node.get_our_node_id(), &payment_params, $send_node.network_graph,
 +                      &$send_node.node.get_our_node_id(), &payment_params, &$send_node.network_graph.read_only(),
                        Some(&$send_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
 -                      $recv_value, $cltv, $send_node.logger, &scorer
 +                      $recv_value, $cltv, $send_node.logger, &scorer, &random_seed_bytes
                ).unwrap();
                (route, payment_hash, payment_preimage, payment_secret)
        }}
@@@ -1560,15 -1617,11 +1620,15 @@@ pub const TEST_FINAL_CLTV: u32 = 70
  pub fn route_payment<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64) -> (PaymentPreimage, PaymentHash, PaymentSecret) {
        let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id())
                .with_features(InvoiceFeatures::known());
 +      let network_graph = origin_node.network_graph.read_only();
        let scorer = test_utils::TestScorer::with_penalty(0);
 +      let seed = [0u8; 32];
 +      let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
 +      let random_seed_bytes = keys_manager.get_secure_random_bytes();
        let route = get_route(
 -              &origin_node.node.get_our_node_id(), &payment_params, &origin_node.network_graph,
 +              &origin_node.node.get_our_node_id(), &payment_params, &network_graph,
                Some(&origin_node.node.list_usable_channels().iter().collect::<Vec<_>>()),
 -              recv_value, TEST_FINAL_CLTV, origin_node.logger, &scorer).unwrap();
 +              recv_value, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap();
        assert_eq!(route.paths.len(), 1);
        assert_eq!(route.paths[0].len(), expected_route.len());
        for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) {
  pub fn route_over_limit<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>, expected_route: &[&Node<'a, 'b, 'c>], recv_value: u64)  {
        let payment_params = PaymentParameters::from_node_id(expected_route.last().unwrap().node.get_our_node_id())
                .with_features(InvoiceFeatures::known());
 +      let network_graph = origin_node.network_graph.read_only();
        let scorer = test_utils::TestScorer::with_penalty(0);
 +      let seed = [0u8; 32];
 +      let keys_manager = test_utils::TestKeysInterface::new(&seed, Network::Testnet);
 +      let random_seed_bytes = keys_manager.get_secure_random_bytes();
        let route = get_route(
 -              &origin_node.node.get_our_node_id(), &payment_params, origin_node.network_graph,
 -              None, recv_value, TEST_FINAL_CLTV, origin_node.logger, &scorer).unwrap();
 +              &origin_node.node.get_our_node_id(), &payment_params, &network_graph,
 +              None, recv_value, TEST_FINAL_CLTV, origin_node.logger, &scorer, &random_seed_bytes).unwrap();
        assert_eq!(route.paths.len(), 1);
        assert_eq!(route.paths[0].len(), expected_route.len());
        for (node, hop) in expected_route.iter().zip(route.paths[0].iter()) {
index ead2a8e2f4eccba54d09e9d849b256d40193a20f,598a51b0be6fa0fbad109383574a89041b6a1dfc..1f64ef0a920efc27a644fb69ee5aacb7e87e45fe
@@@ -16,15 -16,14 +16,14 @@@ use chain::{Confirm, Listen, Watch}
  use chain::channelmonitor;
  use chain::channelmonitor::{ChannelMonitor, CLTV_CLAIM_BUFFER, LATENCY_GRACE_PERIOD_BLOCKS, ANTI_REORG_DELAY};
  use chain::transaction::OutPoint;
 -use chain::keysinterface::BaseSign;
 +use chain::keysinterface::{BaseSign, KeysInterface};
  use ln::{PaymentPreimage, PaymentSecret, PaymentHash};
  use ln::channel::{commitment_tx_base_weight, COMMITMENT_TX_WEIGHT_PER_HTLC, CONCURRENT_INBOUND_HTLC_FEE_BUFFER, FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE, MIN_AFFORDABLE_HTLC_COUNT};
  use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, PaymentId, RAACommitmentOrder, PaymentSendFailure, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, PAYMENT_EXPIRY_BLOCKS };
  use ln::channel::{Channel, ChannelError};
  use ln::{chan_utils, onion_utils};
  use ln::chan_utils::{htlc_success_tx_weight, htlc_timeout_tx_weight, HTLCOutputInCommitment};
- use routing::network_graph::RoutingFees;
- use routing::router::{PaymentParameters, Route, RouteHop, RouteHint, RouteHintHop, RouteParameters, find_route, get_route};
+ use routing::router::{PaymentParameters, Route, RouteHop, RouteParameters, find_route, get_route};
  use ln::features::{ChannelFeatures, InitFeatures, InvoiceFeatures, NodeFeatures};
  use ln::msgs;
  use ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, ErrorAction};
@@@ -463,88 -462,6 +462,6 @@@ fn test_multi_flight_update_fee() 
        check_added_monitors!(nodes[1], 1);
  }
  
- fn do_test_1_conf_open(connect_style: ConnectStyle) {
-       // Previously, if the minium_depth config was set to 1, we'd never send a funding_locked. This
-       // tests that we properly send one in that case.
-       let mut alice_config = UserConfig::default();
-       alice_config.own_channel_config.minimum_depth = 1;
-       alice_config.channel_options.announced_channel = true;
-       alice_config.peer_channel_config_limits.force_announced_channel_preference = false;
-       let mut bob_config = UserConfig::default();
-       bob_config.own_channel_config.minimum_depth = 1;
-       bob_config.channel_options.announced_channel = true;
-       bob_config.peer_channel_config_limits.force_announced_channel_preference = false;
-       let chanmon_cfgs = create_chanmon_cfgs(2);
-       let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
-       let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[Some(alice_config), Some(bob_config)]);
-       let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
-       *nodes[0].connect_style.borrow_mut() = connect_style;
-       let tx = create_chan_between_nodes_with_value_init(&nodes[0], &nodes[1], 100000, 10001, InitFeatures::known(), InitFeatures::known());
-       mine_transaction(&nodes[1], &tx);
-       nodes[0].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingLocked, nodes[0].node.get_our_node_id()));
-       assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
-       mine_transaction(&nodes[0], &tx);
-       let as_msg_events = nodes[0].node.get_and_clear_pending_msg_events();
-       assert_eq!(as_msg_events.len(), 2);
-       let as_funding_locked = if let MessageSendEvent::SendFundingLocked { ref node_id, ref msg } = as_msg_events[0] {
-               assert_eq!(*node_id, nodes[1].node.get_our_node_id());
-               msg.clone()
-       } else { panic!("Unexpected event"); };
-       if let MessageSendEvent::SendChannelUpdate { ref node_id, msg: _ } = as_msg_events[1] {
-               assert_eq!(*node_id, nodes[1].node.get_our_node_id());
-       } else { panic!("Unexpected event"); }
-       nodes[1].node.handle_funding_locked(&nodes[0].node.get_our_node_id(), &as_funding_locked);
-       let bs_msg_events = nodes[1].node.get_and_clear_pending_msg_events();
-       assert_eq!(bs_msg_events.len(), 1);
-       if let MessageSendEvent::SendChannelUpdate { ref node_id, msg: _ } = bs_msg_events[0] {
-               assert_eq!(*node_id, nodes[0].node.get_our_node_id());
-       } else { panic!("Unexpected event"); }
-       send_payment(&nodes[0], &[&nodes[1]], 100_000);
-       // After 6 confirmations, as required by the spec, we'll send announcement_signatures and
-       // broadcast the channel_announcement (but not before exactly 6 confirmations).
-       connect_blocks(&nodes[0], 4);
-       assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty());
-       connect_blocks(&nodes[0], 1);
-       nodes[1].node.handle_announcement_signatures(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendAnnouncementSignatures, nodes[1].node.get_our_node_id()));
-       assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
-       connect_blocks(&nodes[1], 5);
-       let bs_announce_events = nodes[1].node.get_and_clear_pending_msg_events();
-       assert_eq!(bs_announce_events.len(), 2);
-       let bs_announcement_sigs = if let MessageSendEvent::SendAnnouncementSignatures { ref node_id, ref msg } = bs_announce_events[0] {
-               assert_eq!(*node_id, nodes[0].node.get_our_node_id());
-               msg.clone()
-       } else { panic!("Unexpected event"); };
-       let (bs_announcement, bs_update) = if let MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } = bs_announce_events[1] {
-               (msg.clone(), update_msg.clone())
-       } else { panic!("Unexpected event"); };
-       nodes[0].node.handle_announcement_signatures(&nodes[1].node.get_our_node_id(), &bs_announcement_sigs);
-       let as_announce_events = nodes[0].node.get_and_clear_pending_msg_events();
-       assert_eq!(as_announce_events.len(), 1);
-       let (announcement, as_update) = if let MessageSendEvent::BroadcastChannelAnnouncement { ref msg, ref update_msg } = as_announce_events[0] {
-               (msg.clone(), update_msg.clone())
-       } else { panic!("Unexpected event"); };
-       assert_eq!(announcement, bs_announcement);
-       for node in nodes {
-               assert!(node.net_graph_msg_handler.handle_channel_announcement(&announcement).unwrap());
-               node.net_graph_msg_handler.handle_channel_update(&as_update).unwrap();
-               node.net_graph_msg_handler.handle_channel_update(&bs_update).unwrap();
-       }
- }
- #[test]
- fn test_1_conf_open() {
-       do_test_1_conf_open(ConnectStyle::BestBlockFirst);
-       do_test_1_conf_open(ConnectStyle::TransactionsFirst);
-       do_test_1_conf_open(ConnectStyle::FullBlockViaListen);
- }
  fn do_test_sanity_on_in_flight_opens(steps: u8) {
        // Previously, we had issues deserializing channels when we hadn't connected the first block
        // after creation. To catch that and similar issues, we lean on the Node::drop impl to test
@@@ -5999,7 -5916,7 +5916,7 @@@ fn bolt2_open_channel_sending_node_chec
        let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
        let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
-       //Force duplicate channel ids
+       // Force duplicate randomness for every get-random call
        for node in nodes.iter() {
                *node.keys_manager.override_random_bytes.lock().unwrap() = Some([0; 32]);
        }
        nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), InitFeatures::known(), &node0_to_1_send_open_channel);
        get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id());
  
-       //Create a second channel with a channel_id collision
+       // Create a second channel with the same random values. This used to panic due to a colliding
+       // channel_id, but now panics due to a colliding outbound SCID alias.
        assert!(nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), channel_value_satoshis, push_msat, 42, None).is_err());
  }
  
@@@ -7262,7 -7180,10 +7180,10 @@@ fn test_user_configurable_csv_delay() 
        let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
  
        // We test config.our_to_self > BREAKDOWN_TIMEOUT is enforced in Channel::new_outbound()
-       if let Err(error) = Channel::new_outbound(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), 1000000, 1000000, 0, &low_our_to_self_config, 0) {
+       if let Err(error) = Channel::new_outbound(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
+               &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), 1000000, 1000000, 0,
+               &low_our_to_self_config, 0, 42)
+       {
                match error {
                        APIError::APIMisuseError { err } => { assert!(regex::Regex::new(r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks").unwrap().is_match(err.as_str())); },
                        _ => panic!("Unexpected event"),
        nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None).unwrap();
        let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
        open_channel.to_self_delay = 200;
-       if let Err(error) = Channel::new_from_req(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), &open_channel, 0, &low_our_to_self_config, 0, &nodes[0].logger) {
+       if let Err(error) = Channel::new_from_req(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
+               &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), &open_channel, 0,
+               &low_our_to_self_config, 0, &nodes[0].logger, 42)
+       {
                match error {
                        ChannelError::Close(err) => { assert!(regex::Regex::new(r"Configured with an unreasonable our_to_self_delay \(\d+\) putting user funds at risks").unwrap().is_match(err.as_str()));  },
                        _ => panic!("Unexpected event"),
        nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 1000000, 1000000, 42, None).unwrap();
        let mut open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[0].node.get_our_node_id());
        open_channel.to_self_delay = 200;
-       if let Err(error) = Channel::new_from_req(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) }, &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), &open_channel, 0, &high_their_to_self_config, 0, &nodes[0].logger) {
+       if let Err(error) = Channel::new_from_req(&&test_utils::TestFeeEstimator { sat_per_kw: Mutex::new(253) },
+               &nodes[0].keys_manager, nodes[1].node.get_our_node_id(), &InitFeatures::known(), &open_channel, 0,
+               &high_their_to_self_config, 0, &nodes[0].logger, 42)
+       {
                match error {
                        ChannelError::Close(err) => { assert!(regex::Regex::new(r"They wanted our payments to be delayed by a needlessly long period\. Upper limit: \d+\. Actual: \d+").unwrap().is_match(err.as_str())); },
                        _ => panic!("Unexpected event"),
@@@ -7441,9 -7368,8 +7368,9 @@@ fn test_check_htlc_underpaying() 
        create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
  
        let scorer = test_utils::TestScorer::with_penalty(0);
 +      let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(InvoiceFeatures::known());
 -      let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, nodes[0].network_graph, None, 10_000, TEST_FINAL_CLTV, nodes[0].logger, &scorer).unwrap();
 +      let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None, 10_000, TEST_FINAL_CLTV, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
        let (_, our_payment_hash, _) = get_payment_preimage_hash!(nodes[0]);
        let our_payment_secret = nodes[1].node.create_inbound_payment_for_hash(our_payment_hash, Some(100_000), 7200).unwrap();
        nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
@@@ -7570,162 -7496,6 +7497,6 @@@ fn test_announce_disable_channels() 
        assert!(chans_disabled.is_empty());
  }
  
- #[test]
- fn test_priv_forwarding_rejection() {
-       // If we have a private channel with outbound liquidity, and
-       // UserConfig::accept_forwards_to_priv_channels is set to false, we should reject any attempts
-       // to forward through that channel.
-       let chanmon_cfgs = create_chanmon_cfgs(3);
-       let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
-       let mut no_announce_cfg = test_default_channel_config();
-       no_announce_cfg.channel_options.announced_channel = false;
-       no_announce_cfg.accept_forwards_to_priv_channels = false;
-       let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, Some(no_announce_cfg), None]);
-       let persister: test_utils::TestPersister;
-       let new_chain_monitor: test_utils::TestChainMonitor;
-       let nodes_1_deserialized: ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>;
-       let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
-       let chan_id_1 = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 500_000_000, InitFeatures::known(), InitFeatures::known()).2;
-       // Note that the create_*_chan functions in utils requires announcement_signatures, which we do
-       // not send for private channels.
-       nodes[1].node.create_channel(nodes[2].node.get_our_node_id(), 1_000_000, 500_000_000, 42, None).unwrap();
-       let open_channel = get_event_msg!(nodes[1], MessageSendEvent::SendOpenChannel, nodes[2].node.get_our_node_id());
-       nodes[2].node.handle_open_channel(&nodes[1].node.get_our_node_id(), InitFeatures::known(), &open_channel);
-       let accept_channel = get_event_msg!(nodes[2], MessageSendEvent::SendAcceptChannel, nodes[1].node.get_our_node_id());
-       nodes[1].node.handle_accept_channel(&nodes[2].node.get_our_node_id(), InitFeatures::known(), &accept_channel);
-       let (temporary_channel_id, tx, _) = create_funding_transaction(&nodes[1], 1_000_000, 42);
-       nodes[1].node.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
-       nodes[2].node.handle_funding_created(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingCreated, nodes[2].node.get_our_node_id()));
-       check_added_monitors!(nodes[2], 1);
-       let cs_funding_signed = get_event_msg!(nodes[2], MessageSendEvent::SendFundingSigned, nodes[1].node.get_our_node_id());
-       nodes[1].node.handle_funding_signed(&nodes[2].node.get_our_node_id(), &cs_funding_signed);
-       check_added_monitors!(nodes[1], 1);
-       let conf_height = core::cmp::max(nodes[1].best_block_info().1 + 1, nodes[2].best_block_info().1 + 1);
-       confirm_transaction_at(&nodes[1], &tx, conf_height);
-       connect_blocks(&nodes[1], CHAN_CONFIRM_DEPTH - 1);
-       confirm_transaction_at(&nodes[2], &tx, conf_height);
-       connect_blocks(&nodes[2], CHAN_CONFIRM_DEPTH - 1);
-       let as_funding_locked = get_event_msg!(nodes[1], MessageSendEvent::SendFundingLocked, nodes[2].node.get_our_node_id());
-       nodes[1].node.handle_funding_locked(&nodes[2].node.get_our_node_id(), &get_event_msg!(nodes[2], MessageSendEvent::SendFundingLocked, nodes[1].node.get_our_node_id()));
-       get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[2].node.get_our_node_id());
-       nodes[2].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &as_funding_locked);
-       get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
-       assert!(nodes[0].node.list_usable_channels()[0].is_public);
-       assert_eq!(nodes[1].node.list_usable_channels().len(), 2);
-       assert!(!nodes[2].node.list_usable_channels()[0].is_public);
-       // We should always be able to forward through nodes[1] as long as its out through a public
-       // channel:
-       send_payment(&nodes[2], &[&nodes[1], &nodes[0]], 10_000);
-       // ... however, if we send to nodes[2], we will have to pass the private channel from nodes[1]
-       // to nodes[2], which should be rejected:
-       let route_hint = RouteHint(vec![RouteHintHop {
-               src_node_id: nodes[1].node.get_our_node_id(),
-               short_channel_id: nodes[2].node.list_channels()[0].short_channel_id.unwrap(),
-               fees: RoutingFees { base_msat: 1000, proportional_millionths: 0 },
-               cltv_expiry_delta: MIN_CLTV_EXPIRY_DELTA,
-               htlc_minimum_msat: None,
-               htlc_maximum_msat: None,
-       }]);
-       let last_hops = vec![route_hint];
-       let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], last_hops, 10_000, TEST_FINAL_CLTV);
-       nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
-       check_added_monitors!(nodes[0], 1);
-       let payment_event = SendEvent::from_event(nodes[0].node.get_and_clear_pending_msg_events().remove(0));
-       nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]);
-       commitment_signed_dance!(nodes[1], nodes[0], payment_event.commitment_msg, false, true);
-       let htlc_fail_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
-       assert!(htlc_fail_updates.update_add_htlcs.is_empty());
-       assert_eq!(htlc_fail_updates.update_fail_htlcs.len(), 1);
-       assert!(htlc_fail_updates.update_fail_malformed_htlcs.is_empty());
-       assert!(htlc_fail_updates.update_fee.is_none());
-       nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &htlc_fail_updates.update_fail_htlcs[0]);
-       commitment_signed_dance!(nodes[0], nodes[1], htlc_fail_updates.commitment_signed, true, true);
-       expect_payment_failed_with_update!(nodes[0], our_payment_hash, false, nodes[2].node.list_channels()[0].short_channel_id.unwrap(), true);
-       // Now disconnect nodes[1] from its peers and restart with accept_forwards_to_priv_channels set
-       // to true. Sadly there is currently no way to change it at runtime.
-       nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       nodes[2].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false);
-       let nodes_1_serialized = nodes[1].node.encode();
-       let mut monitor_a_serialized = test_utils::TestVecWriter(Vec::new());
-       let mut monitor_b_serialized = test_utils::TestVecWriter(Vec::new());
-       get_monitor!(nodes[1], chan_id_1).write(&mut monitor_a_serialized).unwrap();
-       get_monitor!(nodes[1], cs_funding_signed.channel_id).write(&mut monitor_b_serialized).unwrap();
-       persister = test_utils::TestPersister::new();
-       let keys_manager = &chanmon_cfgs[1].keys_manager;
-       new_chain_monitor = test_utils::TestChainMonitor::new(Some(nodes[1].chain_source), nodes[1].tx_broadcaster.clone(), nodes[1].logger, node_cfgs[1].fee_estimator, &persister, keys_manager);
-       nodes[1].chain_monitor = &new_chain_monitor;
-       let mut monitor_a_read = &monitor_a_serialized.0[..];
-       let mut monitor_b_read = &monitor_b_serialized.0[..];
-       let (_, mut monitor_a) = <(BlockHash, ChannelMonitor<EnforcingSigner>)>::read(&mut monitor_a_read, keys_manager).unwrap();
-       let (_, mut monitor_b) = <(BlockHash, ChannelMonitor<EnforcingSigner>)>::read(&mut monitor_b_read, keys_manager).unwrap();
-       assert!(monitor_a_read.is_empty());
-       assert!(monitor_b_read.is_empty());
-       no_announce_cfg.accept_forwards_to_priv_channels = true;
-       let mut nodes_1_read = &nodes_1_serialized[..];
-       let (_, nodes_1_deserialized_tmp) = {
-               let mut channel_monitors = HashMap::new();
-               channel_monitors.insert(monitor_a.get_funding_txo().0, &mut monitor_a);
-               channel_monitors.insert(monitor_b.get_funding_txo().0, &mut monitor_b);
-               <(BlockHash, ChannelManager<EnforcingSigner, &test_utils::TestChainMonitor, &test_utils::TestBroadcaster, &test_utils::TestKeysInterface, &test_utils::TestFeeEstimator, &test_utils::TestLogger>)>::read(&mut nodes_1_read, ChannelManagerReadArgs {
-                       default_config: no_announce_cfg,
-                       keys_manager,
-                       fee_estimator: node_cfgs[1].fee_estimator,
-                       chain_monitor: nodes[1].chain_monitor,
-                       tx_broadcaster: nodes[1].tx_broadcaster.clone(),
-                       logger: nodes[1].logger,
-                       channel_monitors,
-               }).unwrap()
-       };
-       assert!(nodes_1_read.is_empty());
-       nodes_1_deserialized = nodes_1_deserialized_tmp;
-       assert!(nodes[1].chain_monitor.watch_channel(monitor_a.get_funding_txo().0, monitor_a).is_ok());
-       assert!(nodes[1].chain_monitor.watch_channel(monitor_b.get_funding_txo().0, monitor_b).is_ok());
-       check_added_monitors!(nodes[1], 2);
-       nodes[1].node = &nodes_1_deserialized;
-       nodes[0].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known() });
-       nodes[1].node.peer_connected(&nodes[0].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
-       let as_reestablish = get_event_msg!(nodes[0], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
-       let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[0].node.get_our_node_id());
-       nodes[1].node.handle_channel_reestablish(&nodes[0].node.get_our_node_id(), &as_reestablish);
-       nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
-       get_event_msg!(nodes[0], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
-       get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[0].node.get_our_node_id());
-       nodes[1].node.peer_connected(&nodes[2].node.get_our_node_id(), &msgs::Init { features: InitFeatures::known() });
-       nodes[2].node.peer_connected(&nodes[1].node.get_our_node_id(), &msgs::Init { features: InitFeatures::empty() });
-       let bs_reestablish = get_event_msg!(nodes[1], MessageSendEvent::SendChannelReestablish, nodes[2].node.get_our_node_id());
-       let cs_reestablish = get_event_msg!(nodes[2], MessageSendEvent::SendChannelReestablish, nodes[1].node.get_our_node_id());
-       nodes[2].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reestablish);
-       nodes[1].node.handle_channel_reestablish(&nodes[2].node.get_our_node_id(), &cs_reestablish);
-       get_event_msg!(nodes[1], MessageSendEvent::SendChannelUpdate, nodes[2].node.get_our_node_id());
-       get_event_msg!(nodes[2], MessageSendEvent::SendChannelUpdate, nodes[1].node.get_our_node_id());
-       nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)).unwrap();
-       check_added_monitors!(nodes[0], 1);
-       pass_along_route(&nodes[0], &[&[&nodes[1], &nodes[2]]], 10_000, our_payment_hash, our_payment_secret);
-       claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], our_payment_preimage);
- }
  #[test]
  fn test_bump_penalty_txn_on_revoked_commitment() {
        // In case of penalty txn with too low feerates for getting into mempools, RBF-bump them to be sure
@@@ -7845,13 -7615,12 +7616,13 @@@ fn test_bump_penalty_txn_on_revoked_htl
        // Lock HTLC in both directions (using a slightly lower CLTV delay to provide timely RBF bumps)
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id()).with_features(InvoiceFeatures::known());
        let scorer = test_utils::TestScorer::with_penalty(0);
 -      let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph, None,
 -              3_000_000, 50, nodes[0].logger, &scorer).unwrap();
 +      let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
 +      let route = get_route(&nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(), None,
 +              3_000_000, 50, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
        let payment_preimage = send_along_route(&nodes[0], route, &[&nodes[1]], 3_000_000).0;
        let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id()).with_features(InvoiceFeatures::known());
 -      let route = get_route(&nodes[1].node.get_our_node_id(), &payment_params, nodes[1].network_graph, None,
 -              3_000_000, 50, nodes[0].logger, &scorer).unwrap();
 +      let route = get_route(&nodes[1].node.get_our_node_id(), &payment_params, &nodes[1].network_graph.read_only(), None,
 +              3_000_000, 50, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
        send_along_route(&nodes[1], route, &[&nodes[0]], 3_000_000);
  
        let revoked_local_txn = get_local_commitment_txn!(nodes[1], chan.2);
@@@ -9620,11 -9389,10 +9391,11 @@@ fn test_dup_htlc_second_fail_panic() 
        let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
                .with_features(InvoiceFeatures::known());
        let scorer = test_utils::TestScorer::with_penalty(0);
 +      let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
        let route = get_route(
 -              &nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph,
 +              &nodes[0].node.get_our_node_id(), &payment_params, &nodes[0].network_graph.read_only(),
                Some(&nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
 -              10_000, TEST_FINAL_CLTV, nodes[0].logger, &scorer).unwrap();
 +              10_000, TEST_FINAL_CLTV, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
  
        let (_, our_payment_hash, our_payment_secret) = get_payment_preimage_hash!(&nodes[1]);
  
@@@ -9693,8 -9461,7 +9464,8 @@@ fn test_keysend_payments_to_public_node
                final_cltv_expiry_delta: 40,
        };
        let scorer = test_utils::TestScorer::with_penalty(0);
 -      let route = find_route(&payer_pubkey, &route_params, network_graph, None, nodes[0].logger, &scorer).unwrap();
 +      let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
 +      let route = find_route(&payer_pubkey, &route_params, network_graph, None, nodes[0].logger, &scorer, &random_seed_bytes).unwrap();
  
        let test_preimage = PaymentPreimage([42; 32]);
        let (payment_hash, _) = nodes[0].node.send_spontaneous_payment(&route, Some(test_preimage)).unwrap();
@@@ -9728,10 -9495,9 +9499,10 @@@ fn test_keysend_payments_to_private_nod
        let network_graph = nodes[0].network_graph;
        let first_hops = nodes[0].node.list_usable_channels();
        let scorer = test_utils::TestScorer::with_penalty(0);
 +      let random_seed_bytes = chanmon_cfgs[1].keys_manager.get_secure_random_bytes();
        let route = find_route(
                &payer_pubkey, &route_params, network_graph, Some(&first_hops.iter().collect::<Vec<_>>()),
 -              nodes[0].logger, &scorer
 +              nodes[0].logger, &scorer, &random_seed_bytes
        ).unwrap();
  
        let test_preimage = PaymentPreimage([42; 32]);
index dbdb760924eb8d16c2ce142f649230f7711251ce,af82a275d9a889eabe3276d74d49d68e3f2a8e0b..070d88dda9a3432f9eb4672a369ff2fcc774c652
@@@ -319,10 -319,10 +319,10 @@@ fn test_onion_failure() 
        let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
        let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[Some(config), Some(config), Some(node_2_cfg)]);
        let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+       let channels = [create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()), create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known())];
        for node in nodes.iter() {
                *node.keys_manager.override_random_bytes.lock().unwrap() = Some([3; 32]);
        }
-       let channels = [create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()), create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known())];
        let (route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], 40000);
        // positive case
        send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 40000);
@@@ -610,11 -610,10 +610,11 @@@ macro_rules! get_phantom_route 
                                        }
                ])]);
                let scorer = test_utils::TestScorer::with_penalty(0);
 +              let network_graph = $nodes[0].network_graph.read_only();
                (get_route(
 -                      &$nodes[0].node.get_our_node_id(), &payment_params, $nodes[0].network_graph,
 +                      &$nodes[0].node.get_our_node_id(), &payment_params, &network_graph,
                        Some(&$nodes[0].node.list_usable_channels().iter().collect::<Vec<_>>()),
 -                      $amt, TEST_FINAL_CLTV, $nodes[0].logger, &scorer
 +                      $amt, TEST_FINAL_CLTV, $nodes[0].logger, &scorer, &[0u8; 32]
                ).unwrap(), phantom_route_hint.phantom_scid)
        }
  }}
index d6aef902f0c1f28bddd8ad23279324410cd988d6,870b1e1261fd93a47467fe85e3e098934e388c11..96eabf89bbf570d5d0bae7d9299c064648487880
@@@ -18,10 -18,9 +18,10 @@@ 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, NodeId, RoutingFees};
 +use routing::network_graph::{DirectedChannelInfoWithUpdate, EffectiveCapacity, NetworkGraph, ReadOnlyNetworkGraph, NodeId, RoutingFees};
  use util::ser::{Writeable, Readable};
  use util::logger::{Level, Logger};
 +use util::chacha20::ChaCha20;
  
  use io;
  use prelude::*;
@@@ -177,9 -176,6 +177,9 @@@ impl_writeable_tlv_based!(RouteParamete
  /// 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.
 +const MEDIAN_HOP_CLTV_EXPIRY_DELTA: u32 = 40;
 +
  /// The recipient of a payment.
  #[derive(Clone, Debug, Hash, PartialEq, Eq)]
  pub struct PaymentParameters {
@@@ -262,6 -258,7 +262,6 @@@ impl PaymentParameters 
  #[derive(Clone, Debug, Hash, Eq, PartialEq)]
  pub struct RouteHint(pub Vec<RouteHintHop>);
  
 -
  impl Writeable for RouteHint {
        fn write<W: ::util::ser::Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                (self.0.len() as u64).write(writer)?;
@@@ -626,26 -623,19 +626,26 @@@ fn compute_fees(amount_msat: u64, chann
  /// [`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
 +      first_hops: Option<&[&ChannelDetails]>, logger: L, scorer: &S, random_seed_bytes: &[u8; 32]
  ) -> Result<Route, LightningError>
  where L::Target: Logger {
 -      get_route(
 -              our_node_pubkey, &route_params.payment_params, network, first_hops, route_params.final_value_msat,
 -              route_params.final_cltv_expiry_delta, logger, scorer
 -      )
 +      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),
 +      }
  }
  
  pub(crate) fn get_route<L: Deref, S: Score>(
 -      our_node_pubkey: &PublicKey, payment_params: &PaymentParameters, network: &NetworkGraph,
 -      first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, final_cltv_expiry_delta: u32, 
 -      logger: L, scorer: &S
 +      our_node_pubkey: &PublicKey, payment_params: &PaymentParameters, network_graph: &ReadOnlyNetworkGraph,
 +      first_hops: Option<&[&ChannelDetails]>, final_value_msat: u64, final_cltv_expiry_delta: u32,
 +      logger: L, scorer: &S, _random_seed_bytes: &[u8; 32]
  ) -> Result<Route, LightningError>
  where L::Target: Logger {
        let payee_node_id = NodeId::from_pubkey(&payment_params.payee_pubkey);
        //    - OR if we could not construct a new path. Any next attempt will fail too.
        //    Otherwise, repeat step 2.
        // 4. See if we managed to collect paths which aggregately are able to transfer target value
 -      //    (not recommended value). If yes, proceed. If not, fail routing.
 -      // 5. Randomly combine paths into routes having enough to fulfill the payment. (TODO: knapsack)
 -      // 6. Of all the found paths, select only those with the lowest total fee.
 -      // 7. The last path in every selected route is likely to be more than we need.
 +      //    (not recommended value).
 +      // 5. If yes, proceed. If not, fail routing.
 +      // 6. Randomly combine paths into routes having enough to fulfill the payment. (TODO: knapsack)
 +      // 7. Of all the found paths, select only those with the lowest total fee.
 +      // 8. The last path in every selected route is likely to be more than we need.
        //    Reduce its value-to-transfer and recompute fees.
 -      // 8. Choose the best route by the lowest total fee.
 +      // 9. Choose the best route by the lowest total fee.
  
        // As for the actual search algorithm,
        // we do a payee-to-payer pseudo-Dijkstra's sorting by each node's distance from the payee
        // to use as the A* heuristic beyond just the cost to get one node further than the current
        // one.
  
 -      let network_graph = network.read_only();
        let network_channels = network_graph.channels();
        let network_nodes = network_graph.nodes();
  
                                        let contributes_sufficient_value = available_value_contribution_msat >= minimal_value_contribution_msat;
  
                                        // Do not consider candidates that exceed the maximum total cltv expiry limit.
 -                                      let max_total_cltv_expiry_delta = payment_params.max_total_cltv_expiry_delta;
 +                                      // In order to already account for some of the privacy enhancing random CLTV
 +                                      // expiry delta offset we add on top later, we subtract a rough estimate
 +                                      // (2*MEDIAN_HOP_CLTV_EXPIRY_DELTA) here.
 +                                      let max_total_cltv_expiry_delta = payment_params.max_total_cltv_expiry_delta
 +                                              .checked_sub(2*MEDIAN_HOP_CLTV_EXPIRY_DELTA)
 +                                              .unwrap_or(payment_params.max_total_cltv_expiry_delta);
                                        let hop_total_cltv_delta = ($next_hops_cltv_delta as u32)
                                                .checked_add($candidate.cltv_expiry_delta())
                                                .unwrap_or(u32::max_value());
        Ok(route)
  }
  
 +// When an adversarial intermediary node observes a payment, it may be able to infer its
 +// 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]) {
 +      let network_channels = network_graph.channels();
 +      let network_nodes = network_graph.nodes();
 +
 +      for path in route.paths.iter_mut() {
 +              let mut shadow_ctlv_expiry_delta_offset: u32 = 0;
 +
 +              // Choose the last publicly known node as the starting point for the random walk
 +              if let Some(starting_hop) = path.iter().rev().find(|h| network_nodes.contains_key(&NodeId::from_pubkey(&h.pubkey))) {
 +                      let mut cur_node_id = NodeId::from_pubkey(&starting_hop.pubkey);
 +
 +                      // Init PRNG with path nonce
 +                      let mut path_nonce = [0u8; 12];
 +                      path_nonce.copy_from_slice(&cur_node_id.as_slice()[..12]);
 +                      let mut prng = ChaCha20::new(random_seed_bytes, &path_nonce);
 +                      let mut random_path_bytes = [0u8; ::core::mem::size_of::<usize>()];
 +
 +                      // Pick a random path length in [1 .. 3]
 +                      prng.process_in_place(&mut random_path_bytes);
 +                      let random_walk_length = usize::from_be_bytes(random_path_bytes).wrapping_rem(3).wrapping_add(1);
 +
 +                      for _random_hop in 0..random_walk_length {
 +                              if let Some(cur_node) = network_nodes.get(&cur_node_id) {
 +                                      // Randomly choose the next hop
 +                                      prng.process_in_place(&mut random_path_bytes);
 +                                      if let Some(random_channel) = usize::from_be_bytes(random_path_bytes).checked_rem(cur_node.channels.len())
 +                                              .and_then(|index| cur_node.channels.get(index))
 +                                              .and_then(|id| network_channels.get(id)) {
 +                                                      random_channel.as_directed_from(&cur_node_id).map(|(dir_info, next_id)| {
 +                                                              dir_info.direction().map(|channel_update_info|
 +                                                                      shadow_ctlv_expiry_delta_offset = shadow_ctlv_expiry_delta_offset
 +                                                                              .checked_add(channel_update_info.cltv_expiry_delta.into())
 +                                                                              .unwrap_or(shadow_ctlv_expiry_delta_offset));
 +                                                              cur_node_id = *next_id;
 +                                                      });
 +                                              }
 +                              }
 +                      }
 +              } else {
 +                      // If the entire path is private, choose a random offset from multiples of
 +                      // MEDIAN_HOP_CLTV_EXPIRY_DELTA
 +                      let mut prng = ChaCha20::new(random_seed_bytes, &[0u8; 8]);
 +                      let mut random_bytes = [0u8; 4];
 +                      prng.process_in_place(&mut random_bytes);
 +                      let random_walk_length = u32::from_be_bytes(random_bytes).wrapping_rem(3).wrapping_add(1);
 +                      shadow_ctlv_expiry_delta_offset = random_walk_length * MEDIAN_HOP_CLTV_EXPIRY_DELTA;
 +              }
 +
 +              // Limit the total offset to reduce the worst-case locked liquidity timevalue
 +              const MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET: u32 = 3*144;
 +              shadow_ctlv_expiry_delta_offset = cmp::min(shadow_ctlv_expiry_delta_offset, MAX_SHADOW_CLTV_EXPIRY_DELTA_OFFSET);
 +
 +              // Limit the offset so we never exceed the max_total_cltv_expiry_delta. To improve plausibility,
 +              // we choose the limit to be the largest possible multiple of MEDIAN_HOP_CLTV_EXPIRY_DELTA.
 +              let path_total_cltv_expiry_delta: u32 = path.iter().map(|h| h.cltv_expiry_delta).sum();
 +              let mut max_path_offset = payment_params.max_total_cltv_expiry_delta - path_total_cltv_expiry_delta;
 +              max_path_offset = cmp::max(
 +                      max_path_offset - (max_path_offset % MEDIAN_HOP_CLTV_EXPIRY_DELTA),
 +                      max_path_offset % MEDIAN_HOP_CLTV_EXPIRY_DELTA);
 +              shadow_ctlv_expiry_delta_offset = cmp::min(shadow_ctlv_expiry_delta_offset, max_path_offset);
 +
 +              // Add 'shadow' CLTV offset to the final hop
 +              if let Some(last_hop) = path.last_mut() {
 +                      last_hop.cltv_expiry_delta = last_hop.cltv_expiry_delta
 +                              .checked_add(shadow_ctlv_expiry_delta_offset).unwrap_or(last_hop.cltv_expiry_delta);
 +              }
 +      }
 +}
 +
  #[cfg(test)]
  mod tests {
 -      use routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters, Score};
        use routing::network_graph::{NetworkGraph, NetGraphMsgHandler, NodeId};
 -      use routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees};
 +      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 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};
        use ln::channelmanager;
        use util::test_utils;
 +      use util::chacha20::ChaCha20;
        use util::ser::Writeable;
        #[cfg(c_bindings)]
        use util::ser::Writer;
                        },
                        funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
                        short_channel_id,
+                       inbound_scid_alias: None,
                        channel_value_satoshis: 0,
                        user_channel_id: 0,
                        balance_msat: 0,
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
                let payment_params = PaymentParameters::from_node_id(nodes[2]);
                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();
  
                // Simple route to 2 via 1
  
 -              if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph, None, 0, 42, Arc::clone(&logger), &scorer) {
 +              if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 0, 42, Arc::clone(&logger), &scorer, &random_seed_bytes) {
                        assert_eq!(err, "Cannot send a payment of 0 msat");
                } else { panic!(); }
  
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 2);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[1]);
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
                let payment_params = PaymentParameters::from_node_id(nodes[2]);
                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();
  
                // Simple route to 2 via 1
  
                let our_chans = vec![get_channel_details(Some(2), our_id, InitFeatures::from_le_bytes(vec![0b11]), 100000)];
  
 -              if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph, Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer) {
 +              if let Err(LightningError{err, action: ErrorAction::IgnoreError}) =
 +                      get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes) {
                        assert_eq!(err, "First hop cannot have our_node_pubkey as a destination.");
                } else { panic!(); }
  
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 2);
        }
  
                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);
 +              let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                // Simple route to 2 via 1
  
                });
  
                // Not possible to send 199_999_999, because the minimum on channel=2 is 200_000_000.
 -              if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph, None, 199_999_999, 42, Arc::clone(&logger), &scorer) {
 +              if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, 42, Arc::clone(&logger), &scorer, &random_seed_bytes) {
                        assert_eq!(err, "Failed to find a path to the given destination");
                } else { panic!(); }
  
                });
  
                // A payment above the minimum should pass
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 199_999_999, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 199_999_999, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 2);
        }
  
                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);
 +              let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                // A route to node#2 via two paths.
                // One path allows transferring 35-40 sats, another one also allows 35-40 sats.
                        excess_data: Vec::new()
                });
  
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 60_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                // Overpay fees to hit htlc_minimum_msat.
                let overpaid_fees = route.paths[0][0].fee_msat + route.paths[1][0].fee_msat;
                // TODO: this could be better balanced to overpay 10k and not 15k.
                        excess_data: Vec::new()
                });
  
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 60_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 60_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                // Fine to overpay for htlc_minimum_msat if it allows us to save fee.
                assert_eq!(route.paths.len(), 1);
                assert_eq!(route.paths[0][0].short_channel_id, 12);
                let fees = route.paths[0][0].fee_msat;
                assert_eq!(fees, 5_000);
  
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 50_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                // Not fine to overpay for htlc_minimum_msat if it requires paying more than fee on
                // the other channel.
                assert_eq!(route.paths.len(), 1);
                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);
 +              let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
 +              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 {
                });
  
                // If all the channels require some features we don't understand, route should fail
 -              if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer) {
 +              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) {
                        assert_eq!(err, "Failed to find a path to the given destination");
                } else { panic!(); }
  
                // If we specify a channel to node7, that overrides our local channel view and that gets used
                let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
 -              let route = get_route(&our_id, &payment_params, &network_graph, Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 2);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[7]);
                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);
 +              let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                // Disable nodes 1, 2, and 8 by requiring unknown feature bits
                let unknown_features = NodeFeatures::known().set_unknown_feature_required();
                add_or_update_node(&net_graph_msg_handler, &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, None, 100, 42, Arc::clone(&logger), &scorer) {
 +              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) {
                        assert_eq!(err, "Failed to find a path to the given destination");
                } else { panic!(); }
  
                // If we specify a channel to node7, that overrides our local channel view and that gets used
                let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
 -              let route = get_route(&our_id, &payment_params, &network_graph, Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 2);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[7]);
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, 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);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                // Route to 1 via 2 and 3 because our channel to 1 is disabled
                let payment_params = PaymentParameters::from_node_id(nodes[0]);
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 3);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[1]);
                // If we specify a channel to node7, that overrides our local channel view and that gets used
                let payment_params = PaymentParameters::from_node_id(nodes[2]);
                let our_chans = vec![get_channel_details(Some(42), nodes[7].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
 -              let route = get_route(&our_id, &payment_params, &network_graph, Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 2);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[7]);
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, 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);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                // Simple test across 2, 3, 5, and 4 via a last_hop channel
                // Tests the behaviour when the RouteHint contains a suboptimal hop.
                invalid_last_hops.push(invalid_last_hop);
                {
                        let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(invalid_last_hops);
 -                      if let Err(LightningError{err, action: ErrorAction::IgnoreError}) = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer) {
 +                      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) {
                                assert_eq!(err, "Route hint cannot have the payee as the source.");
                        } else { panic!(); }
                }
  
                let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops_multi_private_channels(&nodes));
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 5);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[1]);
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
                let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(empty_last_hop(&nodes));
                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();
  
                // Test handling of an empty RouteHint passed in Invoice.
  
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 5);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[1]);
                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());
                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();
                // Test through channels 2, 3, 0xff00, 0xff01.
                // Test shows that multiple hop hints are considered.
  
                        excess_data: Vec::new()
                });
  
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 4);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[1]);
                        excess_data: Vec::new()
                });
  
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &[42u8; 32]).unwrap();
                assert_eq!(route.paths[0].len(), 4);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[1]);
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
                let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops_with_public_channel(&nodes));
                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();
                // This test shows that public routes can be present in the invoice
                // which would be handled in the same manner.
  
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 5);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[1]);
                let (secp_ctx, network_graph, _, _, logger) = build_graph();
                let (_, 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);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                // Simple test with outbound channel to 4 to test that last_hops and first_hops connect
                let our_chans = vec![get_channel_details(Some(42), nodes[3].clone(), InitFeatures::from_le_bytes(vec![0b11]), 250_000_000)];
                let mut last_hops = last_hops(&nodes);
                let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops.clone());
 -              let route = get_route(&our_id, &payment_params, &network_graph, Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 2);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[3]);
  
                // Revert to via 6 as the fee on 8 goes up
                let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops);
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 4);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[1]);
                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
 -              let route = get_route(&our_id, &payment_params, &network_graph, None, 2000, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 2000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                assert_eq!(route.paths[0].len(), 5);
  
                assert_eq!(route.paths[0][0].pubkey, nodes[1]);
                let payment_params = PaymentParameters::from_node_id(target_node_id).with_route_hints(vec![last_hops]);
                let our_chans = vec![get_channel_details(Some(42), middle_node_id, InitFeatures::from_le_bytes(vec![0b11]), outbound_capacity_msat)];
                let scorer = test_utils::TestScorer::with_penalty(0);
 -              get_route(&source_node_id, &payment_params, &NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash()), Some(&our_chans.iter().collect::<Vec<_>>()), route_val, 42, &test_utils::TestLogger::new(), &scorer)
 +              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)
        }
  
        #[test]
                let (secp_ctx, network_graph, mut net_graph_msg_handler, 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);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let payment_params = PaymentParameters::from_node_id(nodes[2]).with_features(InvoiceFeatures::known());
  
                // We will use a simple single-path route from
                {
                        // 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, None, 250_000_001, 42, Arc::clone(&logger), &scorer) {
 +                                      &our_id, &payment_params, &network_graph.read_only(), None, 250_000_001, 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 an exact amount we have should be fine.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 250_000_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 250_000_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.len(), 2);
                {
                        // 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, Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_001, 42, Arc::clone(&logger), &scorer) {
 +                                      &our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_001, 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 an exact amount we have should be fine.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&our_chans.iter().collect::<Vec<_>>()), 200_000_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.len(), 2);
                {
                        // 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, None, 15_001, 42, Arc::clone(&logger), &scorer) {
 +                                      &our_id, &payment_params, &network_graph.read_only(), None, 15_001, 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 an exact amount we have should be fine.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 15_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.len(), 2);
                {
                        // 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, None, 15_001, 42, Arc::clone(&logger), &scorer) {
 +                                      &our_id, &payment_params, &network_graph.read_only(), None, 15_001, 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 an exact amount we have should be fine.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 15_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 15_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.len(), 2);
                {
                        // 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, None, 10_001, 42, Arc::clone(&logger), &scorer) {
 +                                      &our_id, &payment_params, &network_graph.read_only(), None, 10_001, 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 an exact amount we have should be fine.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 10_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 10_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let path = route.paths.last().unwrap();
                        assert_eq!(path.len(), 2);
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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[3]).with_features(InvoiceFeatures::known());
  
                // Path via {node7, node2, node4} is channels {12, 13, 6, 11}.
                {
                        // 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, None, 60_000, 42, Arc::clone(&logger), &scorer) {
 +                                      &our_id, &payment_params, &network_graph.read_only(), None, 60_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 49 sats (just a bit below the capacity).
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 49_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 49_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
  
                {
                        // Attempt to route an exact amount is also fine
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 50_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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]);
  
                // Path via node0 is channels {1, 3}. Limit them to 100 and 50 sats (total limit 50).
                });
  
                {
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 50_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 50_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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());
  
                // We need a route consisting of 3 paths:
                {
                        // 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, None, 300_000, 42, Arc::clone(&logger), &scorer) {
 +                                      &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!(); }
                }
                {
                        // 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, None, 250_000, 42, Arc::clone(&logger), &scorer).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 {
  
                {
                        // Attempt to route an exact amount is also fine
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 290_000, 42, Arc::clone(&logger), &scorer).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 {
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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[3]).with_features(InvoiceFeatures::known());
  
                // We need a route consisting of 3 paths:
                {
                        // 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, None, 350_000, 42, Arc::clone(&logger), &scorer) {
 +                                      &our_id, &payment_params, &network_graph.read_only(), None, 350_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 300 sats (exact amount we can route).
                        // Our algorithm should provide us with these 3 paths, 100 sats each.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 300_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 300_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 3);
  
                        let mut total_amount_paid_msat = 0;
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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[3]).with_features(InvoiceFeatures::known());
  
                // This test checks that if we have two cheaper paths and one more expensive path,
                {
                        // Now, attempt to route 180 sats.
                        // Our algorithm should provide us with these 2 paths.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 180_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 180_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 2);
  
                        let mut total_value_transferred_msat = 0;
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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[3]).with_features(InvoiceFeatures::known());
  
                // We need a route consisting of 2 paths:
                {
                        // 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, None, 210_000, 42, Arc::clone(&logger), &scorer) {
 +                                      &our_id, &payment_params, &network_graph.read_only(), None, 210_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 200 sats (exact amount we can route).
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 200_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 200_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 2);
  
                        let mut total_amount_paid_msat = 0;
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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(PublicKey::from_slice(&[02; 33]).unwrap()).with_features(InvoiceFeatures::known())
                        .with_route_hints(vec![RouteHint(vec![RouteHintHop {
                                src_node_id: nodes[2],
  
                // 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, None, 100_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let 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
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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());
  
                // We need a route consisting of 3 paths:
                {
                        // 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, None, 150_000, 42, Arc::clone(&logger), &scorer) {
 +                                      &our_id, &payment_params, &network_graph.read_only(), None, 150_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 125 sats (just a bit below the capacity of 3 channels).
                        // Our algorithm should provide us with these 3 paths.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 125_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 125_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 {
  
                {
                        // Attempt to route without the last small cheap channel
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 2);
                        let mut total_amount_paid_msat = 0;
                        for path in &route.paths {
                // "previous hop" being set to node 3, creating a loop in the path.
                let secp_ctx = Secp256k1::new();
                let logger = Arc::new(test_utils::TestLogger::new());
 -              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 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 (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);
  
                {
                        // Now ensure the route flows simply over nodes 1 and 4 to 6.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 10_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network.read_only(), None, 10_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].len(), 3);
  
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
                let payment_params = PaymentParameters::from_node_id(nodes[2]);
  
                // We modify the graph to set the htlc_maximum of channel 2 to below the value we wish to
                {
                        // Now, attempt to route 90 sats, which is exactly 90 sats at the last hop, plus the
                        // 200% fee charged channel 13 in the 1-to-2 direction.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].len(), 2);
  
                let (secp_ctx, network_graph, net_graph_msg_handler, _, 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());
  
                // We modify the graph to set the htlc_minimum of channel 2 and 4 as needed - channel 2
                        // Now, attempt to route 90 sats, hitting the htlc_minimum on channel 4, but
                        // overshooting the htlc_maximum on channel 2. Thus, we should pick the (absurdly
                        // expensive) channels 12-13 path.
 -                      let route = get_route(&our_id, &payment_params, &network_graph, None, 90_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 90_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].len(), 2);
  
                let network_graph = NetworkGraph::new(genesis_block(Network::Testnet).header.block_hash());
                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);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                {
 -                      let route = get_route(&our_id, &payment_params, &network_graph, Some(&[
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
                                &get_channel_details(Some(3), nodes[0], InitFeatures::known(), 200_000),
                                &get_channel_details(Some(2), nodes[0], InitFeatures::known(), 10_000),
 -                      ]), 100_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      ]), 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 1);
                        assert_eq!(route.paths[0].len(), 1);
  
                        assert_eq!(route.paths[0][0].fee_msat, 100_000);
                }
                {
 -                      let route = get_route(&our_id, &payment_params, &network_graph, Some(&[
 +                      let route = get_route(&our_id, &payment_params, &network_graph.read_only(), Some(&[
                                &get_channel_details(Some(3), nodes[0], InitFeatures::known(), 50_000),
                                &get_channel_details(Some(2), nodes[0], InitFeatures::known(), 50_000),
 -                      ]), 100_000, 42, Arc::clone(&logger), &scorer).unwrap();
 +                      ]), 100_000, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                        assert_eq!(route.paths.len(), 2);
                        assert_eq!(route.paths[0].len(), 1);
                        assert_eq!(route.paths[1].len(), 1);
  
                // Without penalizing each hop 100 msats, a longer path with lower fees is chosen.
                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 route = get_route(
 -                      &our_id, &payment_params, &network_graph, None, 100, 42,
 -                      Arc::clone(&logger), &scorer
 +                      &our_id, &payment_params, &network_graph.read_only(), None, 100, 42,
 +                      Arc::clone(&logger), &scorer, &random_seed_bytes
                ).unwrap();
                let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
  
                // from nodes[2] rather than channel 6, 11, and 8, even though the longer path is cheaper.
                let scorer = test_utils::TestScorer::with_penalty(100);
                let route = get_route(
 -                      &our_id, &payment_params, &network_graph, None, 100, 42,
 -                      Arc::clone(&logger), &scorer
 +                      &our_id, &payment_params, &network_graph.read_only(), None, 100, 42,
 +                      Arc::clone(&logger), &scorer, &random_seed_bytes
                ).unwrap();
                let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
  
  
        #[test]
        fn avoids_routing_through_bad_channels_and_nodes() {
 -              let (secp_ctx, network_graph, _, _, logger) = build_graph();
 +              let (secp_ctx, network, _, _, logger) = build_graph();
                let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
                let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes));
 +              let network_graph = network.read_only();
  
                // A path to nodes[6] exists when no penalties are applied to any channel.
                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 route = get_route(
                        &our_id, &payment_params, &network_graph, None, 100, 42,
 -                      Arc::clone(&logger), &scorer
 +                      Arc::clone(&logger), &scorer, &random_seed_bytes
                ).unwrap();
                let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
  
                let scorer = BadChannelScorer { short_channel_id: 6 };
                let route = get_route(
                        &our_id, &payment_params, &network_graph, None, 100, 42,
 -                      Arc::clone(&logger), &scorer
 +                      Arc::clone(&logger), &scorer, &random_seed_bytes
                ).unwrap();
                let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
  
                let scorer = BadNodeScorer { node_id: NodeId::from_pubkey(&nodes[2]) };
                match get_route(
                        &our_id, &payment_params, &network_graph, None, 100, 42,
 -                      Arc::clone(&logger), &scorer
 +                      Arc::clone(&logger), &scorer, &random_seed_bytes
                ) {
                        Err(LightningError { err, .. } ) => {
                                assert_eq!(err, "Failed to find a path to the given destination");
  
        #[test]
        fn limits_total_cltv_delta() {
 -              let (secp_ctx, network_graph, _, _, logger) = build_graph();
 +              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 feasible_max_total_cltv_delta = 1008;
                let feasible_payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes))
                        .with_max_total_cltv_expiry_delta(feasible_max_total_cltv_delta);
 -              let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer).unwrap();
 +              let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
 +              let route = get_route(&our_id, &feasible_payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
                let path = route.paths[0].iter().map(|hop| hop.short_channel_id).collect::<Vec<_>>();
                assert_ne!(path.len(), 0);
  
                let fail_max_total_cltv_delta = 23;
                let fail_payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes))
                        .with_max_total_cltv_expiry_delta(fail_max_total_cltv_delta);
 -              match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer)
 +              match get_route(&our_id, &fail_payment_params, &network_graph, None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes)
                {
                        Err(LightningError { err, .. } ) => {
                                assert_eq!(err, "Failed to find a path to the given destination");
                }
        }
  
 +      #[test]
 +      fn adds_and_limits_cltv_offset() {
 +              let (secp_ctx, network_graph, _, _, logger) = build_graph();
 +              let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
 +
 +              let scorer = test_utils::TestScorer::with_penalty(0);
 +
 +              let payment_params = PaymentParameters::from_node_id(nodes[6]).with_route_hints(last_hops(&nodes));
 +              let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
 +              let route = get_route(&our_id, &payment_params, &network_graph.read_only(), None, 100, 42, Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
 +              assert_eq!(route.paths.len(), 1);
 +
 +              let cltv_expiry_deltas_before = route.paths[0].iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
 +
 +              // Check whether the offset added to the last hop by default is in [1 .. DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA]
 +              let mut route_default = route.clone();
 +              add_random_cltv_offset(&mut route_default, &payment_params, &network_graph.read_only(), &random_seed_bytes);
 +              let cltv_expiry_deltas_default = route_default.paths[0].iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
 +              assert_eq!(cltv_expiry_deltas_before.split_last().unwrap().1, cltv_expiry_deltas_default.split_last().unwrap().1);
 +              assert!(cltv_expiry_deltas_default.last() > cltv_expiry_deltas_before.last());
 +              assert!(cltv_expiry_deltas_default.last().unwrap() <= &DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA);
 +
 +              // Check that no offset is added when we restrict the max_total_cltv_expiry_delta
 +              let mut route_limited = route.clone();
 +              let limited_max_total_cltv_expiry_delta = cltv_expiry_deltas_before.iter().sum();
 +              let limited_payment_params = payment_params.with_max_total_cltv_expiry_delta(limited_max_total_cltv_expiry_delta);
 +              add_random_cltv_offset(&mut route_limited, &limited_payment_params, &network_graph.read_only(), &random_seed_bytes);
 +              let cltv_expiry_deltas_limited = route_limited.paths[0].iter().map(|h| h.cltv_expiry_delta).collect::<Vec<u32>>();
 +              assert_eq!(cltv_expiry_deltas_before, cltv_expiry_deltas_limited);
 +      }
 +
 +      #[test]
 +      fn adds_plausible_cltv_offset() {
 +              let (secp_ctx, network, _, _, logger) = build_graph();
 +              let (_, our_id, _, nodes) = get_nodes(&secp_ctx);
 +              let network_graph = network.read_only();
 +              let network_nodes = network_graph.nodes();
 +              let network_channels = network_graph.channels();
 +              let scorer = test_utils::TestScorer::with_penalty(0);
 +              let payment_params = PaymentParameters::from_node_id(nodes[3]);
 +              let keys_manager = test_utils::TestKeysInterface::new(&[4u8; 32], Network::Testnet);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
 +
 +              let mut route = get_route(&our_id, &payment_params, &network_graph, None, 100, 0,
 +                                                                Arc::clone(&logger), &scorer, &random_seed_bytes).unwrap();
 +              add_random_cltv_offset(&mut route, &payment_params, &network_graph, &random_seed_bytes);
 +
 +              let mut path_plausibility = vec![];
 +
 +              for p in route.paths {
 +                      // 1. Select random observation point
 +                      let mut prng = ChaCha20::new(&random_seed_bytes, &[0u8; 12]);
 +                      let mut random_bytes = [0u8; ::core::mem::size_of::<usize>()];
 +
 +                      prng.process_in_place(&mut random_bytes);
 +                      let random_path_index = usize::from_be_bytes(random_bytes).wrapping_rem(p.len());
 +                      let observation_point = NodeId::from_pubkey(&p.get(random_path_index).unwrap().pubkey);
 +
 +                      // 2. Calculate what CLTV expiry delta we would observe there
 +                      let observed_cltv_expiry_delta: u32 = p[random_path_index..].iter().map(|h| h.cltv_expiry_delta).sum();
 +
 +                      // 3. Starting from the observation point, find candidate paths
 +                      let mut candidates: VecDeque<(NodeId, Vec<u32>)> = VecDeque::new();
 +                      candidates.push_back((observation_point, vec![]));
 +
 +                      let mut found_plausible_candidate = false;
 +
 +                      'candidate_loop: while let Some((cur_node_id, cur_path_cltv_deltas)) = candidates.pop_front() {
 +                              if let Some(remaining) = observed_cltv_expiry_delta.checked_sub(cur_path_cltv_deltas.iter().sum::<u32>()) {
 +                                      if remaining == 0 || remaining.wrapping_rem(40) == 0 || remaining.wrapping_rem(144) == 0 {
 +                                              found_plausible_candidate = true;
 +                                              break 'candidate_loop;
 +                                      }
 +                              }
 +
 +                              if let Some(cur_node) = network_nodes.get(&cur_node_id) {
 +                                      for channel_id in &cur_node.channels {
 +                                              if let Some(channel_info) = network_channels.get(&channel_id) {
 +                                                      if let Some((dir_info, next_id)) = channel_info.as_directed_from(&cur_node_id) {
 +                                                              if let Some(channel_update_info) = dir_info.direction() {
 +                                                                      let next_cltv_expiry_delta = channel_update_info.cltv_expiry_delta as u32;
 +                                                                      if cur_path_cltv_deltas.iter().sum::<u32>()
 +                                                                              .saturating_add(next_cltv_expiry_delta) <= observed_cltv_expiry_delta {
 +                                                                              let mut new_path_cltv_deltas = cur_path_cltv_deltas.clone();
 +                                                                              new_path_cltv_deltas.push(next_cltv_expiry_delta);
 +                                                                              candidates.push_back((*next_id, new_path_cltv_deltas));
 +                                                                      }
 +                                                              }
 +                                                      }
 +                                              }
 +                                      }
 +                              }
 +                      }
 +
 +                      path_plausibility.push(found_plausible_candidate);
 +              }
 +              assert!(path_plausibility.iter().all(|x| *x));
 +      }
 +
        #[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.
        #[test]
        #[cfg(not(feature = "no-std"))]
        fn generate_routes() {
 +              use routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters};
 +
                let mut d = match super::test_utils::get_route_file() {
                        Ok(f) => f,
                        Err(e) => {
                        },
                };
                let graph = NetworkGraph::read(&mut d).unwrap();
 +              let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                // First, get 100 (source, destination) pairs for which route-getting actually succeeds...
                let mut seed = random_init_seed() as usize;
                                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, None, amt, 42, &test_utils::TestLogger::new(), &scorer).is_ok() {
 +                              if get_route(src, &payment_params, &graph.read_only(), None, amt, 42, &test_utils::TestLogger::new(), &scorer, &random_seed_bytes).is_ok() {
                                        continue 'load_endpoints;
                                }
                        }
        #[test]
        #[cfg(not(feature = "no-std"))]
        fn generate_routes_mpp() {
 +              use routing::scoring::{ProbabilisticScorer, ProbabilisticScoringParameters};
 +
                let mut d = match super::test_utils::get_route_file() {
                        Ok(f) => f,
                        Err(e) => {
                        },
                };
                let graph = NetworkGraph::read(&mut d).unwrap();
 +              let keys_manager = test_utils::TestKeysInterface::new(&[0u8; 32], Network::Testnet);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                // First, get 100 (source, destination) pairs for which route-getting actually succeeds...
                let mut seed = random_init_seed() as usize;
                                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, None, amt, 42, &test_utils::TestLogger::new(), &scorer).is_ok() {
 +                              if get_route(src, &payment_params, &graph.read_only(), None, amt, 42, &test_utils::TestLogger::new(), &scorer, &random_seed_bytes).is_ok() {
                                        continue 'load_endpoints;
                                }
                        }
@@@ -5325,7 -5066,6 +5326,7 @@@ mod benches 
        use bitcoin::hashes::Hash;
        use bitcoin::secp256k1::{PublicKey, Secp256k1, SecretKey};
        use chain::transaction::OutPoint;
 +      use chain::keysinterface::{KeysManager,KeysInterface};
        use ln::channelmanager::{ChannelCounterparty, ChannelDetails};
        use ln::features::{InitFeatures, InvoiceFeatures};
        use routing::scoring::{FixedPenaltyScorer, ProbabilisticScorer, ProbabilisticScoringParameters, Scorer};
                                txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0
                        }),
                        short_channel_id: Some(1),
+                       inbound_scid_alias: None,
                        channel_value_satoshis: 10_000_000,
                        user_channel_id: 0,
                        balance_msat: 10_000_000,
        ) {
                let nodes = graph.read_only().nodes().clone();
                let payer = payer_pubkey();
 +              let keys_manager = KeysManager::new(&[0u8; 32], 42, 42);
 +              let random_seed_bytes = keys_manager.get_secure_random_bytes();
  
                // First, get 100 (source, destination) pairs for which route-getting actually succeeds...
                let mut routes = Vec::new();
                                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;
 -                              if let Ok(route) = get_route(&payer, &params, &graph, Some(&[&first_hop]), amt, 42, &DummyLogger{}, &scorer) {
 +                              if let Ok(route) = get_route(&payer, &params, &graph.read_only(), Some(&[&first_hop]), amt, 42, &DummyLogger{}, &scorer, &random_seed_bytes) {
                                        routes.push(route);
                                        route_endpoints.push((first_hop, params, amt));
                                        continue 'load_endpoints;
                let mut idx = 0;
                bench.iter(|| {
                        let (first_hop, params, amt) = &route_endpoints[idx % route_endpoints.len()];
 -                      assert!(get_route(&payer, params, &graph, Some(&[first_hop]), *amt, 42, &DummyLogger{}, &scorer).is_ok());
 +                      assert!(get_route(&payer, params, &graph.read_only(), Some(&[first_hop]), *amt, 42, &DummyLogger{}, &scorer, &random_seed_bytes).is_ok());
                        idx += 1;
                });
        }