Merge pull request #1421 from TheBlueMatt/2022-04-less-gossip-trace-spam
authorMatt Corallo <649246+TheBlueMatt@users.noreply.github.com>
Wed, 27 Apr 2022 15:59:48 +0000 (15:59 +0000)
committerGitHub <noreply@github.com>
Wed, 27 Apr 2022 15:59:48 +0000 (15:59 +0000)
Log gossip query msgs at GOSSIP instead of TRACE as they're huge

34 files changed:
.github/workflows/build.yml
fuzz/src/router.rs
lightning-background-processor/Cargo.toml
lightning-background-processor/src/lib.rs
lightning-block-sync/Cargo.toml
lightning-block-sync/src/init.rs
lightning-block-sync/src/lib.rs
lightning-block-sync/src/poll.rs
lightning-block-sync/src/rest.rs
lightning-block-sync/src/rpc.rs
lightning-block-sync/src/test_utils.rs
lightning-invoice/src/de.rs
lightning-invoice/src/lib.rs
lightning-invoice/src/utils.rs
lightning-persister/src/lib.rs
lightning-persister/src/util.rs
lightning/src/ln/chanmon_update_fail_tests.rs
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_test_utils.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/inbound_payment.rs [new file with mode: 0644]
lightning/src/ln/mod.rs
lightning/src/ln/onion_route_tests.rs
lightning/src/ln/payment_tests.rs
lightning/src/ln/priv_short_conf_tests.rs
lightning/src/ln/reorg_tests.rs
lightning/src/ln/shutdown_tests.rs
lightning/src/routing/network_graph.rs
lightning/src/routing/router.rs
lightning/src/routing/scoring.rs
lightning/src/util/events.rs
lightning/src/util/mod.rs
lightning/src/util/persist.rs [new file with mode: 0644]

index 90e08b398bccd3dd4ee6b8593bc74d1492f40030..cff1713440035a0b76d89a9e6c88904c97c0b87e 100644 (file)
@@ -191,7 +191,7 @@ jobs:
           done
       - name: Upload coverage
         if: matrix.coverage
-        uses: codecov/codecov-action@v2
+        uses: codecov/codecov-action@v3
         with:
           # Could you use this to fake the coverage report for your PR? Sure.
           # Will anyone be impressed by your amazing coverage? No
index bff177b19091b47b6b7f2184e1e826240d63a838..b0f052dbc646f613a1d8c038c88c96c3604ef88e 100644 (file)
@@ -213,6 +213,8 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                                        features: InitFeatures::known(),
                                                                        unspendable_punishment_reserve: 0,
                                                                        forwarding_info: None,
+                                                                       outbound_htlc_minimum_msat: None,
+                                                                       outbound_htlc_maximum_msat: None,
                                                                },
                                                                funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
                                                                channel_type: None,
@@ -227,6 +229,8 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                                                is_usable: true, is_public: true,
                                                                balance_msat: 0,
                                                                outbound_capacity_msat: 0,
+                                                               inbound_htlc_minimum_msat: None,
+                                                               inbound_htlc_maximum_msat: None,
                                                        });
                                                }
                                                Some(&first_hops_vec[..])
index bd6d54d871a2a20a49392f34e5810e64e6e0a8b7..16ec763fb8c3a4f48f5bb3ea773e4372b12984f3 100644 (file)
@@ -16,8 +16,8 @@ rustdoc-args = ["--cfg", "docsrs"]
 [dependencies]
 bitcoin = "0.27"
 lightning = { version = "0.0.106", path = "../lightning", features = ["std"] }
-lightning-persister = { version = "0.0.106", path = "../lightning-persister" }
 
 [dev-dependencies]
 lightning = { version = "0.0.106", path = "../lightning", features = ["_test_utils"] }
 lightning-invoice = { version = "0.14.0", path = "../lightning-invoice" }
+lightning-persister = { version = "0.0.106", path = "../lightning-persister" }
index 73f420c98a429ddba67b20490bf9dbb060a9e034..e23737c0adcf16fec641c0d48aac940645c54716 100644 (file)
@@ -20,6 +20,7 @@ use lightning::ln::peer_handler::{CustomMessageHandler, PeerManager, SocketDescr
 use lightning::routing::network_graph::{NetworkGraph, NetGraphMsgHandler};
 use lightning::util::events::{Event, EventHandler, EventsProvider};
 use lightning::util::logger::Logger;
+use lightning::util::persist::Persister;
 use std::sync::Arc;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::thread;
@@ -80,22 +81,6 @@ const FIRST_NETWORK_PRUNE_TIMER: u64 = 60;
 #[cfg(test)]
 const FIRST_NETWORK_PRUNE_TIMER: u64 = 1;
 
-/// Trait that handles persisting a [`ChannelManager`] and [`NetworkGraph`] to disk.
-pub trait Persister<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
-where
-       M::Target: 'static + chain::Watch<Signer>,
-       T::Target: 'static + BroadcasterInterface,
-       K::Target: 'static + KeysInterface<Signer = Signer>,
-       F::Target: 'static + FeeEstimator,
-       L::Target: 'static + Logger,
-{
-       /// Persist the given [`ChannelManager`] to disk, returning an error if persistence failed
-       /// (which will cause the [`BackgroundProcessor`] which called this method to exit).
-       fn persist_manager(&self, channel_manager: &ChannelManager<Signer, M, T, K, F, L>) -> Result<(), std::io::Error>;
-
-       /// Persist the given [`NetworkGraph`] to disk, returning an error if persistence failed.
-       fn persist_graph(&self, network_graph: &NetworkGraph) -> Result<(), std::io::Error>;
-}
 
 /// Decorates an [`EventHandler`] with common functionality provided by standard [`EventHandler`]s.
 struct DecoratingEventHandler<
@@ -138,12 +123,12 @@ impl BackgroundProcessor {
        ///
        /// [`Persister::persist_manager`] is responsible for writing out the [`ChannelManager`] to disk, and/or
        /// uploading to one or more backup services. See [`ChannelManager::write`] for writing out a
-       /// [`ChannelManager`]. See [`FilesystemPersister::persist_manager`] for Rust-Lightning's
+       /// [`ChannelManager`]. See the `lightning-persister` crate for LDK's
        /// provided implementation.
        ///
        /// [`Persister::persist_graph`] is responsible for writing out the [`NetworkGraph`] to disk. See
-       /// [`NetworkGraph::write`] for writing out a [`NetworkGraph`]. See [`FilesystemPersister::persist_network_graph`]
-       /// for Rust-Lightning's provided implementation.
+       /// [`NetworkGraph::write`] for writing out a [`NetworkGraph`]. See the `lightning-persister` crate
+       /// for LDK's provided implementation.
        ///
        /// Typically, users should either implement [`Persister::persist_manager`] to never return an
        /// error or call [`join`] and handle any error that may arise. For the latter case,
@@ -161,8 +146,8 @@ impl BackgroundProcessor {
        /// [`stop`]: Self::stop
        /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager
        /// [`ChannelManager::write`]: lightning::ln::channelmanager::ChannelManager#impl-Writeable
-       /// [`FilesystemPersister::persist_manager`]: lightning_persister::FilesystemPersister::persist_manager
-       /// [`FilesystemPersister::persist_network_graph`]: lightning_persister::FilesystemPersister::persist_network_graph
+       /// [`Persister::persist_manager`]: lightning::util::persist::Persister::persist_manager
+       /// [`Persister::persist_graph`]: lightning::util::persist::Persister::persist_graph
        /// [`NetworkGraph`]: lightning::routing::network_graph::NetworkGraph
        /// [`NetworkGraph::write`]: lightning::routing::network_graph::NetworkGraph#impl-Writeable
        pub fn start<
@@ -180,7 +165,7 @@ impl BackgroundProcessor {
                CMH: 'static + Deref + Send + Sync,
                RMH: 'static + Deref + Send + Sync,
                EH: 'static + EventHandler + Send,
-               PS: 'static + Send + Persister<Signer, CW, T, K, F, L>,
+               PS: 'static + Deref + Send,
                M: 'static + Deref<Target = ChainMonitor<Signer, CF, T, F, L, P>> + Send + Sync,
                CM: 'static + Deref<Target = ChannelManager<Signer, CW, T, K, F, L>> + Send + Sync,
                NG: 'static + Deref<Target = NetGraphMsgHandler<G, CA, L>> + Send + Sync,
@@ -202,6 +187,7 @@ impl BackgroundProcessor {
                CMH::Target: 'static + ChannelMessageHandler,
                RMH::Target: 'static + RoutingMessageHandler,
                UMH::Target: 'static + CustomMessageHandler,
+               PS::Target: 'static + Persister<Signer, CW, T, K, F, L>
        {
                let stop_thread = Arc::new(AtomicBool::new(false));
                let stop_thread_clone = stop_thread.clone();
@@ -217,10 +203,22 @@ impl BackgroundProcessor {
                        let mut have_pruned = false;
 
                        loop {
-                               peer_manager.process_events(); // Note that this may block on ChannelManager's locking
                                channel_manager.process_pending_events(&event_handler);
                                chain_monitor.process_pending_events(&event_handler);
 
+                               // Note that the PeerManager::process_events may block on ChannelManager's locks,
+                               // hence it comes last here. When the ChannelManager finishes whatever it's doing,
+                               // we want to ensure we get into `persist_manager` as quickly as we can, especially
+                               // without running the normal event processing above and handing events to users.
+                               //
+                               // Specifically, on an *extremely* slow machine, we may see ChannelManager start
+                               // processing a message effectively at any point during this loop. In order to
+                               // minimize the time between such processing completing and persisting the updated
+                               // ChannelManager, we want to minimize methods blocking on a ChannelManager
+                               // generally, and as a fallback place such blocking only immediately before
+                               // persistence.
+                               peer_manager.process_events();
+
                                // We wait up to 100ms, but track how long it takes to detect being put to sleep,
                                // see `await_start`'s use below.
                                let await_start = Instant::now();
@@ -349,10 +347,9 @@ mod tests {
        use bitcoin::blockdata::constants::genesis_block;
        use bitcoin::blockdata::transaction::{Transaction, TxOut};
        use bitcoin::network::constants::Network;
-       use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
-       use lightning::chain::{BestBlock, Confirm, chainmonitor, self};
+       use lightning::chain::{BestBlock, Confirm, chainmonitor};
        use lightning::chain::channelmonitor::ANTI_REORG_DELAY;
-       use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeysInterface, KeysManager, Sign};
+       use lightning::chain::keysinterface::{InMemorySigner, Recipient, KeysInterface, KeysManager};
        use lightning::chain::transaction::OutPoint;
        use lightning::get_event_msg;
        use lightning::ln::channelmanager::{BREAKDOWN_TIMEOUT, ChainParameters, ChannelManager, SimpleArcChannelManager};
@@ -362,14 +359,13 @@ mod tests {
        use lightning::routing::network_graph::{NetworkGraph, NetGraphMsgHandler};
        use lightning::util::config::UserConfig;
        use lightning::util::events::{Event, MessageSendEventsProvider, MessageSendEvent};
-       use lightning::util::logger::Logger;
        use lightning::util::ser::Writeable;
        use lightning::util::test_utils;
+       use lightning::util::persist::KVStorePersister;
        use lightning_invoice::payment::{InvoicePayer, RetryAttempts};
        use lightning_invoice::utils::DefaultRouter;
        use lightning_persister::FilesystemPersister;
        use std::fs;
-       use std::ops::Deref;
        use std::path::PathBuf;
        use std::sync::{Arc, Mutex};
        use std::time::Duration;
@@ -412,14 +408,15 @@ mod tests {
        }
 
        struct Persister {
-               data_dir: String,
                graph_error: Option<(std::io::ErrorKind, &'static str)>,
-               manager_error: Option<(std::io::ErrorKind, &'static str)>
+               manager_error: Option<(std::io::ErrorKind, &'static str)>,
+               filesystem_persister: FilesystemPersister,
        }
 
        impl Persister {
                fn new(data_dir: String) -> Self {
-                       Self { data_dir, graph_error: None, manager_error: None }
+                       let filesystem_persister = FilesystemPersister::new(data_dir.clone());
+                       Self { graph_error: None, manager_error: None, filesystem_persister }
                }
 
                fn with_graph_error(self, error: std::io::ErrorKind, message: &'static str) -> Self {
@@ -431,25 +428,21 @@ mod tests {
                }
        }
 
-       impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L:Deref> super::Persister<Signer, M, T, K, F, L> for Persister where
-               M::Target: 'static + chain::Watch<Signer>,
-               T::Target: 'static + BroadcasterInterface,
-               K::Target: 'static + KeysInterface<Signer = Signer>,
-               F::Target: 'static + FeeEstimator,
-               L::Target: 'static + Logger,
-       {
-               fn persist_manager(&self, channel_manager: &ChannelManager<Signer, M, T, K, F, L>) -> Result<(), std::io::Error> {
-                       match self.manager_error {
-                               None => FilesystemPersister::persist_manager(self.data_dir.clone(), channel_manager),
-                               Some((error, message)) => Err(std::io::Error::new(error, message)),
+       impl KVStorePersister for Persister {
+               fn persist<W: Writeable>(&self, key: &str, object: &W) -> std::io::Result<()> {
+                       if key == "manager" {
+                               if let Some((error, message)) = self.manager_error {
+                                       return Err(std::io::Error::new(error, message))
+                               }
                        }
-               }
 
-               fn persist_graph(&self, network_graph: &NetworkGraph) -> Result<(), std::io::Error> {
-                       match self.graph_error {
-                               None => FilesystemPersister::persist_network_graph(self.data_dir.clone(), network_graph),
-                               Some((error, message)) => Err(std::io::Error::new(error, message)),
+                       if key == "network_graph" {
+                               if let Some((error, message)) = self.graph_error {
+                                       return Err(std::io::Error::new(error, message))
+                               }
                        }
+
+                       self.filesystem_persister.persist(key, object)
                }
        }
 
@@ -576,7 +569,7 @@ mod tests {
 
                // Initiate the background processors to watch each node.
                let data_dir = nodes[0].persister.get_data_dir();
-               let persister = Persister::new(data_dir);
+               let persister = Arc::new(Persister::new(data_dir));
                let event_handler = |_: &_| {};
                let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].net_graph_msg_handler.clone(), nodes[0].peer_manager.clone(), nodes[0].logger.clone());
 
@@ -637,7 +630,7 @@ mod tests {
                // `FRESHNESS_TIMER`.
                let nodes = create_nodes(1, "test_timer_tick_called".to_string());
                let data_dir = nodes[0].persister.get_data_dir();
-               let persister = Persister::new(data_dir);
+               let persister = Arc::new(Persister::new(data_dir));
                let event_handler = |_: &_| {};
                let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].net_graph_msg_handler.clone(), nodes[0].peer_manager.clone(), nodes[0].logger.clone());
                loop {
@@ -660,7 +653,7 @@ mod tests {
                open_channel!(nodes[0], nodes[1], 100000);
 
                let data_dir = nodes[0].persister.get_data_dir();
-               let persister = Persister::new(data_dir).with_manager_error(std::io::ErrorKind::Other, "test");
+               let persister = Arc::new(Persister::new(data_dir).with_manager_error(std::io::ErrorKind::Other, "test"));
                let event_handler = |_: &_| {};
                let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].net_graph_msg_handler.clone(), nodes[0].peer_manager.clone(), nodes[0].logger.clone());
                match bg_processor.join() {
@@ -677,7 +670,7 @@ mod tests {
                // Test that if we encounter an error during network graph persistence, an error gets returned.
                let nodes = create_nodes(2, "test_persist_network_graph_error".to_string());
                let data_dir = nodes[0].persister.get_data_dir();
-               let persister = Persister::new(data_dir).with_graph_error(std::io::ErrorKind::Other, "test");
+               let persister = Arc::new(Persister::new(data_dir).with_graph_error(std::io::ErrorKind::Other, "test"));
                let event_handler = |_: &_| {};
                let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].net_graph_msg_handler.clone(), nodes[0].peer_manager.clone(), nodes[0].logger.clone());
 
@@ -695,7 +688,7 @@ mod tests {
                let mut nodes = create_nodes(2, "test_background_event_handling".to_string());
                let channel_value = 100000;
                let data_dir = nodes[0].persister.get_data_dir();
-               let persister = Persister::new(data_dir.clone());
+               let persister = Arc::new(Persister::new(data_dir.clone()));
 
                // Set up a background event handler for FundingGenerationReady events.
                let (sender, receiver) = std::sync::mpsc::sync_channel(1);
@@ -726,7 +719,8 @@ mod tests {
                // Set up a background event handler for SpendableOutputs events.
                let (sender, receiver) = std::sync::mpsc::sync_channel(1);
                let event_handler = move |event: &Event| sender.send(event.clone()).unwrap();
-               let bg_processor = BackgroundProcessor::start(Persister::new(data_dir), event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].net_graph_msg_handler.clone(), nodes[0].peer_manager.clone(), nodes[0].logger.clone());
+               let persister = Arc::new(Persister::new(data_dir));
+               let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].net_graph_msg_handler.clone(), nodes[0].peer_manager.clone(), nodes[0].logger.clone());
 
                // Force close the channel and check that the SpendableOutputs event was handled.
                nodes[0].node.force_close_channel(&nodes[0].node.list_channels()[0].channel_id).unwrap();
@@ -752,7 +746,7 @@ mod tests {
 
                // Initiate the background processors to watch each node.
                let data_dir = nodes[0].persister.get_data_dir();
-               let persister = Persister::new(data_dir);
+               let persister = Arc::new(Persister::new(data_dir));
                let scorer = Arc::new(Mutex::new(test_utils::TestScorer::with_penalty(0)));
                let router = DefaultRouter::new(Arc::clone(&nodes[0].network_graph), Arc::clone(&nodes[0].logger), random_seed_bytes);
                let invoice_payer = Arc::new(InvoicePayer::new(Arc::clone(&nodes[0].node), router, scorer, Arc::clone(&nodes[0].logger), |_: &_| {}, RetryAttempts(2)));
index 67edb09eee4ac43ac74f42bde6e6cf6439d55944..673034081588e373b6590aff9a4db111987862af 100644 (file)
@@ -20,6 +20,7 @@ rpc-client = [ "serde", "serde_json", "chunked_transfer" ]
 [dependencies]
 bitcoin = "0.27"
 lightning = { version = "0.0.106", path = "../lightning" }
+futures = { version = "0.3" }
 tokio = { version = "1.0", features = [ "io-util", "net", "time" ], optional = true }
 serde = { version = "1.0", features = ["derive"], optional = true }
 serde_json = { version = "1.0", optional = true }
index d971cadcf8aea0d47a400a7a87cb4d20aaa213eb..f5d839d21ca31931ca08199a24c00e8f14867f06 100644 (file)
@@ -10,14 +10,16 @@ use bitcoin::network::constants::Network;
 
 use lightning::chain;
 
+use std::ops::Deref;
+
 /// Returns a validated block header of the source's best chain tip.
 ///
 /// Upon success, the returned header can be used to initialize [`SpvClient`]. Useful during a fresh
 /// start when there are no chain listeners to sync yet.
 ///
 /// [`SpvClient`]: crate::SpvClient
-pub async fn validate_best_block_header<B: BlockSource>(block_source: &mut B) ->
-BlockSourceResult<ValidatedBlockHeader> {
+pub async fn validate_best_block_header<B: Deref>(block_source: B) ->
+BlockSourceResult<ValidatedBlockHeader> where B::Target: BlockSource {
        let (best_block_hash, best_block_height) = block_source.get_best_block().await?;
        block_source
                .get_header(&best_block_hash, best_block_height).await?
@@ -67,7 +69,7 @@ BlockSourceResult<ValidatedBlockHeader> {
 ///    C: chain::Filter,
 ///    P: chainmonitor::Persist<S>,
 /// >(
-///    block_source: &mut B,
+///    block_source: &B,
 ///    chain_monitor: &ChainMonitor<S, &C, &T, &F, &L, &P>,
 ///    config: UserConfig,
 ///    keys_manager: &K,
@@ -121,13 +123,13 @@ BlockSourceResult<ValidatedBlockHeader> {
 /// [`SpvClient`]: crate::SpvClient
 /// [`ChannelManager`]: lightning::ln::channelmanager::ChannelManager
 /// [`ChannelMonitor`]: lightning::chain::channelmonitor::ChannelMonitor
-pub async fn synchronize_listeners<'a, B: BlockSource, C: Cache, L: chain::Listen + ?Sized>(
-       block_source: &mut B,
+pub async fn synchronize_listeners<B: Deref + Sized + Send + Sync, C: Cache, L: chain::Listen + ?Sized>(
+       block_source: B,
        network: Network,
        header_cache: &mut C,
-       mut chain_listeners: Vec<(BlockHash, &'a L)>,
-) -> BlockSourceResult<ValidatedBlockHeader> {
-       let best_header = validate_best_block_header(block_source).await?;
+       mut chain_listeners: Vec<(BlockHash, &L)>,
+) -> BlockSourceResult<ValidatedBlockHeader> where B::Target: BlockSource {
+       let best_header = validate_best_block_header(&*block_source).await?;
 
        // Fetch the header for the block hash paired with each listener.
        let mut chain_listeners_with_old_headers = Vec::new();
@@ -236,7 +238,7 @@ mod tests {
 
        #[tokio::test]
        async fn sync_from_same_chain() {
-               let mut chain = Blockchain::default().with_height(4);
+               let chain = Blockchain::default().with_height(4);
 
                let listener_1 = MockChainListener::new()
                        .expect_block_connected(*chain.at_height(2))
@@ -254,7 +256,7 @@ mod tests {
                        (chain.at_height(3).block_hash, &listener_3 as &dyn chain::Listen),
                ];
                let mut cache = chain.header_cache(0..=4);
-               match synchronize_listeners(&mut chain, Network::Bitcoin, &mut cache, listeners).await {
+               match synchronize_listeners(&chain, Network::Bitcoin, &mut cache, listeners).await {
                        Ok(header) => assert_eq!(header, chain.tip()),
                        Err(e) => panic!("Unexpected error: {:?}", e),
                }
@@ -262,7 +264,7 @@ mod tests {
 
        #[tokio::test]
        async fn sync_from_different_chains() {
-               let mut main_chain = Blockchain::default().with_height(4);
+               let main_chain = Blockchain::default().with_height(4);
                let fork_chain_1 = main_chain.fork_at_height(1);
                let fork_chain_2 = main_chain.fork_at_height(2);
                let fork_chain_3 = main_chain.fork_at_height(3);
@@ -291,7 +293,7 @@ mod tests {
                let mut cache = fork_chain_1.header_cache(2..=4);
                cache.extend(fork_chain_2.header_cache(3..=4));
                cache.extend(fork_chain_3.header_cache(4..=4));
-               match synchronize_listeners(&mut main_chain, Network::Bitcoin, &mut cache, listeners).await {
+               match synchronize_listeners(&main_chain, Network::Bitcoin, &mut cache, listeners).await {
                        Ok(header) => assert_eq!(header, main_chain.tip()),
                        Err(e) => panic!("Unexpected error: {:?}", e),
                }
@@ -299,7 +301,7 @@ mod tests {
 
        #[tokio::test]
        async fn sync_from_overlapping_chains() {
-               let mut main_chain = Blockchain::default().with_height(4);
+               let main_chain = Blockchain::default().with_height(4);
                let fork_chain_1 = main_chain.fork_at_height(1);
                let fork_chain_2 = fork_chain_1.fork_at_height(2);
                let fork_chain_3 = fork_chain_2.fork_at_height(3);
@@ -334,7 +336,7 @@ mod tests {
                let mut cache = fork_chain_1.header_cache(2..=4);
                cache.extend(fork_chain_2.header_cache(3..=4));
                cache.extend(fork_chain_3.header_cache(4..=4));
-               match synchronize_listeners(&mut main_chain, Network::Bitcoin, &mut cache, listeners).await {
+               match synchronize_listeners(&main_chain, Network::Bitcoin, &mut cache, listeners).await {
                        Ok(header) => assert_eq!(header, main_chain.tip()),
                        Err(e) => panic!("Unexpected error: {:?}", e),
                }
@@ -342,7 +344,7 @@ mod tests {
 
        #[tokio::test]
        async fn cache_connected_and_keep_disconnected_blocks() {
-               let mut main_chain = Blockchain::default().with_height(2);
+               let main_chain = Blockchain::default().with_height(2);
                let fork_chain = main_chain.fork_at_height(1);
                let new_tip = main_chain.tip();
                let old_tip = fork_chain.tip();
@@ -353,7 +355,7 @@ mod tests {
 
                let listeners = vec![(old_tip.block_hash, &listener as &dyn chain::Listen)];
                let mut cache = fork_chain.header_cache(2..=2);
-               match synchronize_listeners(&mut main_chain, Network::Bitcoin, &mut cache, listeners).await {
+               match synchronize_listeners(&main_chain, Network::Bitcoin, &mut cache, listeners).await {
                        Ok(_) => {
                                assert!(cache.contains_key(&new_tip.block_hash));
                                assert!(cache.contains_key(&old_tip.block_hash));
index 8854aa3e8e4bf8186b6cc119451e62ddc6710fae..321dd57e4713a638c86ba4fc033a89473d0129af 100644 (file)
@@ -61,11 +61,11 @@ pub trait BlockSource : Sync + Send {
        ///
        /// Implementations that cannot find headers based on the hash should return a `Transient` error
        /// when `height_hint` is `None`.
-       fn get_header<'a>(&'a mut self, header_hash: &'a BlockHash, height_hint: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData>;
+       fn get_header<'a>(&'a self, header_hash: &'a BlockHash, height_hint: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData>;
 
        /// Returns the block for a given hash. A headers-only block source should return a `Transient`
        /// error.
-       fn get_block<'a>(&'a mut self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block>;
+       fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block>;
 
        /// Returns the hash of the best block and, optionally, its height.
        ///
@@ -73,7 +73,7 @@ pub trait BlockSource : Sync + Send {
        /// to allow for a more efficient lookup.
        ///
        /// [`get_header`]: Self::get_header
-       fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<(BlockHash, Option<u32>)>;
+       fn get_best_block<'a>(&'a self) -> AsyncBlockSourceResult<(BlockHash, Option<u32>)>;
 }
 
 /// Result type for `BlockSource` requests.
index c59652ea51716db9c7d24c3d9015c2e73f13833b..6e30d2e86d20d268529bd37d942492db810d84b6 100644 (file)
@@ -6,7 +6,7 @@ use bitcoin::blockdata::block::Block;
 use bitcoin::hash_types::BlockHash;
 use bitcoin::network::constants::Network;
 
-use std::ops::DerefMut;
+use std::ops::Deref;
 
 /// The `Poll` trait defines behavior for polling block sources for a chain tip and retrieving
 /// related chain data. It serves as an adapter for `BlockSource`.
@@ -17,15 +17,15 @@ use std::ops::DerefMut;
 /// [`ChainPoller`]: ../struct.ChainPoller.html
 pub trait Poll {
        /// Returns a chain tip in terms of its relationship to the provided chain tip.
-       fn poll_chain_tip<'a>(&'a mut self, best_known_chain_tip: ValidatedBlockHeader) ->
+       fn poll_chain_tip<'a>(&'a self, best_known_chain_tip: ValidatedBlockHeader) ->
                AsyncBlockSourceResult<'a, ChainTip>;
 
        /// Returns the header that preceded the given header in the chain.
-       fn look_up_previous_header<'a>(&'a mut self, header: &'a ValidatedBlockHeader) ->
+       fn look_up_previous_header<'a>(&'a self, header: &'a ValidatedBlockHeader) ->
                AsyncBlockSourceResult<'a, ValidatedBlockHeader>;
 
        /// Returns the block associated with the given header.
-       fn fetch_block<'a>(&'a mut self, header: &'a ValidatedBlockHeader) ->
+       fn fetch_block<'a>(&'a self, header: &'a ValidatedBlockHeader) ->
                AsyncBlockSourceResult<'a, ValidatedBlock>;
 }
 
@@ -170,12 +170,12 @@ mod sealed {
 ///
 /// Other `Poll` implementations should be built using `ChainPoller` as it provides the simplest way
 /// of validating chain data and checking consistency.
-pub struct ChainPoller<B: DerefMut<Target=T> + Sized, T: BlockSource> {
+pub struct ChainPoller<B: Deref<Target=T> + Sized + Send + Sync, T: BlockSource + ?Sized> {
        block_source: B,
        network: Network,
 }
 
-impl<B: DerefMut<Target=T> + Sized, T: BlockSource> ChainPoller<B, T> {
+impl<B: Deref<Target=T> + Sized + Send + Sync, T: BlockSource + ?Sized> ChainPoller<B, T> {
        /// Creates a new poller for the given block source.
        ///
        /// If the `network` parameter is mainnet, then the difficulty between blocks is checked for
@@ -185,8 +185,8 @@ impl<B: DerefMut<Target=T> + Sized, T: BlockSource> ChainPoller<B, T> {
        }
 }
 
-impl<B: DerefMut<Target=T> + Sized + Send + Sync, T: BlockSource> Poll for ChainPoller<B, T> {
-       fn poll_chain_tip<'a>(&'a mut self, best_known_chain_tip: ValidatedBlockHeader) ->
+impl<B: Deref<Target=T> + Sized + Send + Sync, T: BlockSource + ?Sized> Poll for ChainPoller<B, T> {
+       fn poll_chain_tip<'a>(&'a self, best_known_chain_tip: ValidatedBlockHeader) ->
                AsyncBlockSourceResult<'a, ChainTip>
        {
                Box::pin(async move {
@@ -206,7 +206,7 @@ impl<B: DerefMut<Target=T> + Sized + Send + Sync, T: BlockSource> Poll for Chain
                })
        }
 
-       fn look_up_previous_header<'a>(&'a mut self, header: &'a ValidatedBlockHeader) ->
+       fn look_up_previous_header<'a>(&'a self, header: &'a ValidatedBlockHeader) ->
                AsyncBlockSourceResult<'a, ValidatedBlockHeader>
        {
                Box::pin(async move {
@@ -225,7 +225,7 @@ impl<B: DerefMut<Target=T> + Sized + Send + Sync, T: BlockSource> Poll for Chain
                })
        }
 
-       fn fetch_block<'a>(&'a mut self, header: &'a ValidatedBlockHeader) ->
+       fn fetch_block<'a>(&'a self, header: &'a ValidatedBlockHeader) ->
                AsyncBlockSourceResult<'a, ValidatedBlock>
        {
                Box::pin(async move {
@@ -249,7 +249,7 @@ mod tests {
                let best_known_chain_tip = chain.tip();
                chain.disconnect_tip();
 
-               let mut poller = ChainPoller::new(&mut chain, Network::Bitcoin);
+               let poller = ChainPoller::new(&chain, Network::Bitcoin);
                match poller.poll_chain_tip(best_known_chain_tip).await {
                        Err(e) => {
                                assert_eq!(e.kind(), BlockSourceErrorKind::Transient);
@@ -261,10 +261,10 @@ mod tests {
 
        #[tokio::test]
        async fn poll_chain_without_headers() {
-               let mut chain = Blockchain::default().with_height(1).without_headers();
+               let chain = Blockchain::default().with_height(1).without_headers();
                let best_known_chain_tip = chain.at_height(0);
 
-               let mut poller = ChainPoller::new(&mut chain, Network::Bitcoin);
+               let poller = ChainPoller::new(&chain, Network::Bitcoin);
                match poller.poll_chain_tip(best_known_chain_tip).await {
                        Err(e) => {
                                assert_eq!(e.kind(), BlockSourceErrorKind::Persistent);
@@ -283,7 +283,7 @@ mod tests {
                chain.blocks.last_mut().unwrap().header.bits =
                        BlockHeader::compact_target_from_u256(&Uint256::from_be_bytes([0; 32]));
 
-               let mut poller = ChainPoller::new(&mut chain, Network::Bitcoin);
+               let poller = ChainPoller::new(&chain, Network::Bitcoin);
                match poller.poll_chain_tip(best_known_chain_tip).await {
                        Err(e) => {
                                assert_eq!(e.kind(), BlockSourceErrorKind::Persistent);
@@ -295,10 +295,10 @@ mod tests {
 
        #[tokio::test]
        async fn poll_chain_with_malformed_headers() {
-               let mut chain = Blockchain::default().with_height(1).malformed_headers();
+               let chain = Blockchain::default().with_height(1).malformed_headers();
                let best_known_chain_tip = chain.at_height(0);
 
-               let mut poller = ChainPoller::new(&mut chain, Network::Bitcoin);
+               let poller = ChainPoller::new(&chain, Network::Bitcoin);
                match poller.poll_chain_tip(best_known_chain_tip).await {
                        Err(e) => {
                                assert_eq!(e.kind(), BlockSourceErrorKind::Persistent);
@@ -310,10 +310,10 @@ mod tests {
 
        #[tokio::test]
        async fn poll_chain_with_common_tip() {
-               let mut chain = Blockchain::default().with_height(0);
+               let chain = Blockchain::default().with_height(0);
                let best_known_chain_tip = chain.tip();
 
-               let mut poller = ChainPoller::new(&mut chain, Network::Bitcoin);
+               let poller = ChainPoller::new(&chain, Network::Bitcoin);
                match poller.poll_chain_tip(best_known_chain_tip).await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok(tip) => assert_eq!(tip, ChainTip::Common),
@@ -330,7 +330,7 @@ mod tests {
                let worse_chain_tip = chain.tip();
                assert_eq!(best_known_chain_tip.chainwork, worse_chain_tip.chainwork);
 
-               let mut poller = ChainPoller::new(&mut chain, Network::Bitcoin);
+               let poller = ChainPoller::new(&chain, Network::Bitcoin);
                match poller.poll_chain_tip(best_known_chain_tip).await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok(tip) => assert_eq!(tip, ChainTip::Worse(worse_chain_tip)),
@@ -345,7 +345,7 @@ mod tests {
                chain.disconnect_tip();
                let worse_chain_tip = chain.tip();
 
-               let mut poller = ChainPoller::new(&mut chain, Network::Bitcoin);
+               let poller = ChainPoller::new(&chain, Network::Bitcoin);
                match poller.poll_chain_tip(best_known_chain_tip).await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok(tip) => assert_eq!(tip, ChainTip::Worse(worse_chain_tip)),
@@ -354,12 +354,12 @@ mod tests {
 
        #[tokio::test]
        async fn poll_chain_with_better_tip() {
-               let mut chain = Blockchain::default().with_height(1);
+               let chain = Blockchain::default().with_height(1);
                let best_known_chain_tip = chain.at_height(0);
 
                let better_chain_tip = chain.tip();
 
-               let mut poller = ChainPoller::new(&mut chain, Network::Bitcoin);
+               let poller = ChainPoller::new(&chain, Network::Bitcoin);
                match poller.poll_chain_tip(best_known_chain_tip).await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
                        Ok(tip) => assert_eq!(tip, ChainTip::Better(better_chain_tip)),
index e04bb86d4270f9c7aec1bc06f49a62b7af2e056a..2ddfed7dad84b12dc43d5ac318b31b223ca74051 100644 (file)
@@ -8,13 +8,15 @@ use bitcoin::blockdata::block::Block;
 use bitcoin::hash_types::BlockHash;
 use bitcoin::hashes::hex::ToHex;
 
+use futures::lock::Mutex;
+
 use std::convert::TryFrom;
 use std::convert::TryInto;
 
 /// A simple REST client for requesting resources using HTTP `GET`.
 pub struct RestClient {
        endpoint: HttpEndpoint,
-       client: HttpClient,
+       client: Mutex<HttpClient>,
 }
 
 impl RestClient {
@@ -22,35 +24,35 @@ impl RestClient {
        ///
        /// The endpoint should contain the REST path component (e.g., http://127.0.0.1:8332/rest).
        pub fn new(endpoint: HttpEndpoint) -> std::io::Result<Self> {
-               let client = HttpClient::connect(&endpoint)?;
+               let client = Mutex::new(HttpClient::connect(&endpoint)?);
                Ok(Self { endpoint, client })
        }
 
        /// Requests a resource encoded in `F` format and interpreted as type `T`.
-       pub async fn request_resource<F, T>(&mut self, resource_path: &str) -> std::io::Result<T>
+       pub async fn request_resource<F, T>(&self, resource_path: &str) -> std::io::Result<T>
        where F: TryFrom<Vec<u8>, Error = std::io::Error> + TryInto<T, Error = std::io::Error> {
                let host = format!("{}:{}", self.endpoint.host(), self.endpoint.port());
                let uri = format!("{}/{}", self.endpoint.path().trim_end_matches("/"), resource_path);
-               self.client.get::<F>(&uri, &host).await?.try_into()
+               self.client.lock().await.get::<F>(&uri, &host).await?.try_into()
        }
 }
 
 impl BlockSource for RestClient {
-       fn get_header<'a>(&'a mut self, header_hash: &'a BlockHash, _height: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
+       fn get_header<'a>(&'a self, header_hash: &'a BlockHash, _height: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
                Box::pin(async move {
                        let resource_path = format!("headers/1/{}.json", header_hash.to_hex());
                        Ok(self.request_resource::<JsonResponse, _>(&resource_path).await?)
                })
        }
 
-       fn get_block<'a>(&'a mut self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
+       fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
                Box::pin(async move {
                        let resource_path = format!("block/{}.bin", header_hash.to_hex());
                        Ok(self.request_resource::<BinaryResponse, _>(&resource_path).await?)
                })
        }
 
-       fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<'a, (BlockHash, Option<u32>)> {
+       fn get_best_block<'a>(&'a self) -> AsyncBlockSourceResult<'a, (BlockHash, Option<u32>)> {
                Box::pin(async move {
                        Ok(self.request_resource::<JsonResponse, _>("chaininfo.json").await?)
                })
@@ -81,7 +83,7 @@ mod tests {
        #[tokio::test]
        async fn request_unknown_resource() {
                let server = HttpServer::responding_with_not_found();
-               let mut client = RestClient::new(server.endpoint()).unwrap();
+               let client = RestClient::new(server.endpoint()).unwrap();
 
                match client.request_resource::<BinaryResponse, u32>("/").await {
                        Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::Other),
@@ -92,7 +94,7 @@ mod tests {
        #[tokio::test]
        async fn request_malformed_resource() {
                let server = HttpServer::responding_with_ok(MessageBody::Content("foo"));
-               let mut client = RestClient::new(server.endpoint()).unwrap();
+               let client = RestClient::new(server.endpoint()).unwrap();
 
                match client.request_resource::<BinaryResponse, u32>("/").await {
                        Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::InvalidData),
@@ -103,7 +105,7 @@ mod tests {
        #[tokio::test]
        async fn request_valid_resource() {
                let server = HttpServer::responding_with_ok(MessageBody::Content(42));
-               let mut client = RestClient::new(server.endpoint()).unwrap();
+               let client = RestClient::new(server.endpoint()).unwrap();
 
                match client.request_resource::<BinaryResponse, u32>("/").await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
index 88199688aefd1a48fd128aac5c45f319f947c90e..1e0aa9d93fc45e9113c8a78ff2c545e551df50ba 100644 (file)
@@ -8,6 +8,8 @@ use bitcoin::blockdata::block::Block;
 use bitcoin::hash_types::BlockHash;
 use bitcoin::hashes::hex::ToHex;
 
+use futures::lock::Mutex;
+
 use serde_json;
 
 use std::convert::TryFrom;
@@ -18,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
 pub struct RpcClient {
        basic_auth: String,
        endpoint: HttpEndpoint,
-       client: HttpClient,
+       client: Mutex<HttpClient>,
        id: AtomicUsize,
 }
 
@@ -27,7 +29,7 @@ impl RpcClient {
        /// credentials should be a base64 encoding of a user name and password joined by a colon, as is
        /// required for HTTP basic access authentication.
        pub fn new(credentials: &str, endpoint: HttpEndpoint) -> std::io::Result<Self> {
-               let client = HttpClient::connect(&endpoint)?;
+               let client = Mutex::new(HttpClient::connect(&endpoint)?);
                Ok(Self {
                        basic_auth: "Basic ".to_string() + credentials,
                        endpoint,
@@ -37,7 +39,7 @@ impl RpcClient {
        }
 
        /// Calls a method with the response encoded in JSON format and interpreted as type `T`.
-       pub async fn call_method<T>(&mut self, method: &str, params: &[serde_json::Value]) -> std::io::Result<T>
+       pub async fn call_method<T>(&self, method: &str, params: &[serde_json::Value]) -> std::io::Result<T>
        where JsonResponse: TryFrom<Vec<u8>, Error = std::io::Error> + TryInto<T, Error = std::io::Error> {
                let host = format!("{}:{}", self.endpoint.host(), self.endpoint.port());
                let uri = self.endpoint.path();
@@ -47,7 +49,7 @@ impl RpcClient {
                        "id": &self.id.fetch_add(1, Ordering::AcqRel).to_string()
                });
 
-               let mut response = match self.client.post::<JsonResponse>(&uri, &host, &self.basic_auth, content).await {
+               let mut response = match self.client.lock().await.post::<JsonResponse>(&uri, &host, &self.basic_auth, content).await {
                        Ok(JsonResponse(response)) => response,
                        Err(e) if e.kind() == std::io::ErrorKind::Other => {
                                match e.get_ref().unwrap().downcast_ref::<HttpError>() {
@@ -82,14 +84,14 @@ impl RpcClient {
 }
 
 impl BlockSource for RpcClient {
-       fn get_header<'a>(&'a mut self, header_hash: &'a BlockHash, _height: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
+       fn get_header<'a>(&'a self, header_hash: &'a BlockHash, _height: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
                Box::pin(async move {
                        let header_hash = serde_json::json!(header_hash.to_hex());
                        Ok(self.call_method("getblockheader", &[header_hash]).await?)
                })
        }
 
-       fn get_block<'a>(&'a mut self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
+       fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
                Box::pin(async move {
                        let header_hash = serde_json::json!(header_hash.to_hex());
                        let verbosity = serde_json::json!(0);
@@ -97,7 +99,7 @@ impl BlockSource for RpcClient {
                })
        }
 
-       fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<'a, (BlockHash, Option<u32>)> {
+       fn get_best_block<'a>(&'a self) -> AsyncBlockSourceResult<'a, (BlockHash, Option<u32>)> {
                Box::pin(async move {
                        Ok(self.call_method("getblockchaininfo", &[]).await?)
                })
@@ -127,7 +129,7 @@ mod tests {
        #[tokio::test]
        async fn call_method_returning_unknown_response() {
                let server = HttpServer::responding_with_not_found();
-               let mut client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
+               let client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
 
                match client.call_method::<u64>("getblockcount", &[]).await {
                        Err(e) => assert_eq!(e.kind(), std::io::ErrorKind::Other),
@@ -139,7 +141,7 @@ mod tests {
        async fn call_method_returning_malfomred_response() {
                let response = serde_json::json!("foo");
                let server = HttpServer::responding_with_ok(MessageBody::Content(response));
-               let mut client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
+               let client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
 
                match client.call_method::<u64>("getblockcount", &[]).await {
                        Err(e) => {
@@ -156,7 +158,7 @@ mod tests {
                        "error": { "code": -8, "message": "invalid parameter" },
                });
                let server = HttpServer::responding_with_server_error(response);
-               let mut client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
+               let client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
 
                let invalid_block_hash = serde_json::json!("foo");
                match client.call_method::<u64>("getblock", &[invalid_block_hash]).await {
@@ -172,7 +174,7 @@ mod tests {
        async fn call_method_returning_missing_result() {
                let response = serde_json::json!({ "result": null });
                let server = HttpServer::responding_with_ok(MessageBody::Content(response));
-               let mut client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
+               let client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
 
                match client.call_method::<u64>("getblockcount", &[]).await {
                        Err(e) => {
@@ -187,7 +189,7 @@ mod tests {
        async fn call_method_returning_malformed_result() {
                let response = serde_json::json!({ "result": "foo" });
                let server = HttpServer::responding_with_ok(MessageBody::Content(response));
-               let mut client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
+               let client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
 
                match client.call_method::<u64>("getblockcount", &[]).await {
                        Err(e) => {
@@ -202,7 +204,7 @@ mod tests {
        async fn call_method_returning_valid_result() {
                let response = serde_json::json!({ "result": 654470 });
                let server = HttpServer::responding_with_ok(MessageBody::Content(response));
-               let mut client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
+               let client = RpcClient::new(CREDENTIALS, server.endpoint()).unwrap();
 
                match client.call_method::<u64>("getblockcount", &[]).await {
                        Err(e) => panic!("Unexpected error: {:?}", e),
index 8c37c94d8ec4c2146d978170fd66ccf1fae75172..fe57c0c606d02d5cfbc5bf79f3bba1637904711f 100644 (file)
@@ -113,7 +113,7 @@ impl Blockchain {
 }
 
 impl BlockSource for Blockchain {
-       fn get_header<'a>(&'a mut self, header_hash: &'a BlockHash, _height_hint: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
+       fn get_header<'a>(&'a self, header_hash: &'a BlockHash, _height_hint: Option<u32>) -> AsyncBlockSourceResult<'a, BlockHeaderData> {
                Box::pin(async move {
                        if self.without_headers {
                                return Err(BlockSourceError::persistent("header not found"));
@@ -133,7 +133,7 @@ impl BlockSource for Blockchain {
                })
        }
 
-       fn get_block<'a>(&'a mut self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
+       fn get_block<'a>(&'a self, header_hash: &'a BlockHash) -> AsyncBlockSourceResult<'a, Block> {
                Box::pin(async move {
                        for (height, block) in self.blocks.iter().enumerate() {
                                if block.header.block_hash() == *header_hash {
@@ -150,7 +150,7 @@ impl BlockSource for Blockchain {
                })
        }
 
-       fn get_best_block<'a>(&'a mut self) -> AsyncBlockSourceResult<'a, (BlockHash, Option<u32>)> {
+       fn get_best_block<'a>(&'a self) -> AsyncBlockSourceResult<'a, (BlockHash, Option<u32>)> {
                Box::pin(async move {
                        match self.blocks.last() {
                                None => Err(BlockSourceError::transient("empty chain")),
index 9e96849a274c24d9ba1a08845b8d69622c75a4ff..5de2b038e8b2d29a25df42705d5d7d378009a7fb 100644 (file)
@@ -23,8 +23,8 @@ use secp256k1::recovery::{RecoveryId, RecoverableSignature};
 use secp256k1::key::PublicKey;
 
 use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiry, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
-       SemanticError, PrivateRoute, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawInvoice, constants, SignedRawInvoice,
-       RawDataPart, InvoiceFeatures};
+       SemanticError, PrivateRoute, ParseError, ParseOrSemanticError, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawInvoice,
+       constants, SignedRawInvoice, RawDataPart, InvoiceFeatures};
 
 use self::hrp_sm::parse_hrp;
 
@@ -619,46 +619,6 @@ impl FromBase32 for PrivateRoute {
        }
 }
 
-/// Errors that indicate what is wrong with the invoice. They have some granularity for debug
-/// reasons, but should generally result in an "invalid BOLT11 invoice" message for the user.
-#[allow(missing_docs)]
-#[derive(PartialEq, Debug, Clone)]
-pub enum ParseError {
-       Bech32Error(bech32::Error),
-       ParseAmountError(ParseIntError),
-       MalformedSignature(secp256k1::Error),
-       BadPrefix,
-       UnknownCurrency,
-       UnknownSiPrefix,
-       MalformedHRP,
-       TooShortDataPart,
-       UnexpectedEndOfTaggedFields,
-       DescriptionDecodeError(str::Utf8Error),
-       PaddingError,
-       IntegerOverflowError,
-       InvalidSegWitProgramLength,
-       InvalidPubKeyHashLength,
-       InvalidScriptHashLength,
-       InvalidRecoveryId,
-       InvalidSliceLength(String),
-
-       /// Not an error, but used internally to signal that a part of the invoice should be ignored
-       /// according to BOLT11
-       Skip,
-}
-
-/// Indicates that something went wrong while parsing or validating the invoice. Parsing errors
-/// should be mostly seen as opaque and are only there for debugging reasons. Semantic errors
-/// like wrong signatures, missing fields etc. could mean that someone tampered with the invoice.
-#[derive(PartialEq, Debug, Clone)]
-pub enum ParseOrSemanticError {
-       /// The invoice couldn't be decoded
-       ParseError(ParseError),
-
-       /// The invoice could be decoded but violates the BOLT11 standard
-       SemanticError(::SemanticError),
-}
-
 impl Display for ParseError {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
                match *self {
index 1dd7123a486d1077f1295b7655b1fac497cfb57f..5784607dde937b85fa384ed65a630d7af1d3ca3a 100644 (file)
@@ -53,9 +53,11 @@ use secp256k1::recovery::RecoverableSignature;
 
 use core::fmt::{Display, Formatter, self};
 use core::iter::FilterMap;
+use core::num::ParseIntError;
 use core::ops::Deref;
 use core::slice::Iter;
 use core::time::Duration;
+use core::str;
 
 mod de;
 mod ser;
@@ -86,7 +88,45 @@ mod sync {
 #[cfg(not(feature = "std"))]
 mod sync;
 
-pub use de::{ParseError, ParseOrSemanticError};
+/// Errors that indicate what is wrong with the invoice. They have some granularity for debug
+/// reasons, but should generally result in an "invalid BOLT11 invoice" message for the user.
+#[allow(missing_docs)]
+#[derive(PartialEq, Debug, Clone)]
+pub enum ParseError {
+       Bech32Error(bech32::Error),
+       ParseAmountError(ParseIntError),
+       MalformedSignature(secp256k1::Error),
+       BadPrefix,
+       UnknownCurrency,
+       UnknownSiPrefix,
+       MalformedHRP,
+       TooShortDataPart,
+       UnexpectedEndOfTaggedFields,
+       DescriptionDecodeError(str::Utf8Error),
+       PaddingError,
+       IntegerOverflowError,
+       InvalidSegWitProgramLength,
+       InvalidPubKeyHashLength,
+       InvalidScriptHashLength,
+       InvalidRecoveryId,
+       InvalidSliceLength(String),
+
+       /// Not an error, but used internally to signal that a part of the invoice should be ignored
+       /// according to BOLT11
+       Skip,
+}
+
+/// Indicates that something went wrong while parsing or validating the invoice. Parsing errors
+/// should be mostly seen as opaque and are only there for debugging reasons. Semantic errors
+/// like wrong signatures, missing fields etc. could mean that someone tampered with the invoice.
+#[derive(PartialEq, Debug, Clone)]
+pub enum ParseOrSemanticError {
+       /// The invoice couldn't be decoded
+       ParseError(ParseError),
+
+       /// The invoice could be decoded but violates the BOLT11 standard
+       SemanticError(::SemanticError),
+}
 
 /// The number of bits used to represent timestamps as defined in BOLT 11.
 const TIMESTAMP_BITS: usize = 35;
index 62820cfe11007027ecc2ec7802a5a4946767e1c6..a2edc43afc7a17b02f1b7eb13906e9d7837f874e 100644 (file)
@@ -13,6 +13,7 @@ use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 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::inbound_payment::{create, create_from_hash, ExpandedKey};
 use lightning::ln::msgs::LightningError;
 use lightning::routing::scoring::Score;
 use lightning::routing::network_graph::{NetworkGraph, RoutingFees};
@@ -38,9 +39,12 @@ use sync::Mutex;
 ///   may be too long for QR code scanning. To fix this, `PhantomRouteHints::channels` may be pared
 ///   down
 ///
-/// `payment_hash` and `payment_secret` come from [`ChannelManager::create_inbound_payment`] or
-/// [`ChannelManager::create_inbound_payment_for_hash`]. These values can be retrieved from any
-/// participating node.
+/// `payment_hash` can be specified if you have a specific need for a custom payment hash (see the difference
+/// between [`ChannelManager::create_inbound_payment`] and [`ChannelManager::create_inbound_payment_for_hash`]).
+/// If `None` is provided for `payment_hash`, then one will be created.
+///
+/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
+/// in excess of the current time.
 ///
 /// Note that the provided `keys_manager`'s `KeysInterface` implementation must support phantom
 /// invoices in its `sign_invoice` implementation ([`PhantomKeysManager`] satisfies this
@@ -48,15 +52,17 @@ use sync::Mutex;
 ///
 /// [`PhantomKeysManager`]: lightning::chain::keysinterface::PhantomKeysManager
 /// [`ChannelManager::get_phantom_route_hints`]: lightning::ln::channelmanager::ChannelManager::get_phantom_route_hints
+/// [`ChannelManager::create_inbound_payment`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment
+/// [`ChannelManager::create_inbound_payment_for_hash`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
 /// [`PhantomRouteHints::channels`]: lightning::ln::channelmanager::PhantomRouteHints::channels
 pub fn create_phantom_invoice<Signer: Sign, K: Deref>(
-       amt_msat: Option<u64>, description: String, payment_hash: PaymentHash, payment_secret: PaymentSecret,
+       amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, description: String, invoice_expiry_delta_secs: u32,
        phantom_route_hints: Vec<PhantomRouteHints>, keys_manager: K, network: Currency,
 ) -> Result<Invoice, SignOrCreationError<()>> where K::Target: KeysInterface {
        let description = Description::new(description).map_err(SignOrCreationError::CreationError)?;
        let description = InvoiceDescription::Direct(&description,);
        _create_phantom_invoice::<Signer, K>(
-               amt_msat, description, payment_hash, payment_secret, phantom_route_hints, keys_manager, network,
+               amt_msat, payment_hash, description, invoice_expiry_delta_secs, phantom_route_hints, keys_manager, network,
        )
 }
 
@@ -76,9 +82,12 @@ pub fn create_phantom_invoice<Signer: Sign, K: Deref>(
 ///
 /// `description_hash` is a SHA-256 hash of the description text
 ///
-/// `payment_hash` and `payment_secret` come from [`ChannelManager::create_inbound_payment`] or
-/// [`ChannelManager::create_inbound_payment_for_hash`]. These values can be retrieved from any
-/// participating node.
+/// `payment_hash` can be specified if you have a specific need for a custom payment hash (see the difference
+/// between [`ChannelManager::create_inbound_payment`] and [`ChannelManager::create_inbound_payment_for_hash`]).
+/// If `None` is provided for `payment_hash`, then one will be created.
+///
+/// `invoice_expiry_delta_secs` describes the number of seconds that the invoice is valid for
+/// in excess of the current time.
 ///
 /// Note that the provided `keys_manager`'s `KeysInterface` implementation must support phantom
 /// invoices in its `sign_invoice` implementation ([`PhantomKeysManager`] satisfies this
@@ -86,28 +95,28 @@ pub fn create_phantom_invoice<Signer: Sign, K: Deref>(
 ///
 /// [`PhantomKeysManager`]: lightning::chain::keysinterface::PhantomKeysManager
 /// [`ChannelManager::get_phantom_route_hints`]: lightning::ln::channelmanager::ChannelManager::get_phantom_route_hints
+/// [`ChannelManager::create_inbound_payment`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment
+/// [`ChannelManager::create_inbound_payment_for_hash`]: lightning::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
 /// [`PhantomRouteHints::channels`]: lightning::ln::channelmanager::PhantomRouteHints::channels
 pub fn create_phantom_invoice_with_description_hash<Signer: Sign, K: Deref>(
-       amt_msat: Option<u64>, description_hash: Sha256, payment_hash: PaymentHash,
-       payment_secret: PaymentSecret, phantom_route_hints: Vec<PhantomRouteHints>,
-       keys_manager: K, network: Currency,
+       amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, invoice_expiry_delta_secs: u32,
+       description_hash: Sha256, phantom_route_hints: Vec<PhantomRouteHints>, keys_manager: K, network: Currency,
 ) -> Result<Invoice, SignOrCreationError<()>> where K::Target: KeysInterface
 {
-
        _create_phantom_invoice::<Signer, K>(
-               amt_msat,
-               InvoiceDescription::Hash(&description_hash),
-               payment_hash, payment_secret, phantom_route_hints, keys_manager, network,
+               amt_msat, payment_hash, InvoiceDescription::Hash(&description_hash),
+               invoice_expiry_delta_secs, phantom_route_hints, keys_manager, network,
        )
 }
 
 #[cfg(feature = "std")]
 fn _create_phantom_invoice<Signer: Sign, K: Deref>(
-       amt_msat: Option<u64>, description: InvoiceDescription, payment_hash: PaymentHash,
-       payment_secret: PaymentSecret, phantom_route_hints: Vec<PhantomRouteHints>,
-       keys_manager: K, network: Currency,
+       amt_msat: Option<u64>, payment_hash: Option<PaymentHash>, description: InvoiceDescription,
+       invoice_expiry_delta_secs: u32, phantom_route_hints: Vec<PhantomRouteHints>, keys_manager: K, network: Currency,
 ) -> Result<Invoice, SignOrCreationError<()>> where K::Target: KeysInterface
 {
+       use std::time::{SystemTime, UNIX_EPOCH};
+
        if phantom_route_hints.len() == 0 {
                return Err(SignOrCreationError::CreationError(
                        CreationError::MissingRouteHints,
@@ -120,6 +129,35 @@ fn _create_phantom_invoice<Signer: Sign, K: Deref>(
                InvoiceDescription::Hash(hash) => InvoiceBuilder::new(network).description_hash(hash.0),
        };
 
+       // If we ever see performance here being too slow then we should probably take this ExpandedKey as a parameter instead.
+       let keys = ExpandedKey::new(&keys_manager.get_inbound_payment_key_material());
+       let (payment_hash, payment_secret) = if let Some(payment_hash) = payment_hash {
+               let payment_secret = create_from_hash(
+                       &keys,
+                       amt_msat,
+                       payment_hash,
+                       invoice_expiry_delta_secs,
+                       SystemTime::now()
+                               .duration_since(UNIX_EPOCH)
+                               .expect("Time must be > 1970")
+                               .as_secs(),
+               )
+               .map_err(|_| SignOrCreationError::CreationError(CreationError::InvalidAmount))?;
+               (payment_hash, payment_secret)
+       } else {
+               create(
+                       &keys,
+                       amt_msat,
+                       invoice_expiry_delta_secs,
+                       &keys_manager,
+                       SystemTime::now()
+                               .duration_since(UNIX_EPOCH)
+                               .expect("Time must be > 1970")
+                               .as_secs(),
+               )
+               .map_err(|_| SignOrCreationError::CreationError(CreationError::InvalidAmount))?
+       };
+
        let mut invoice = invoice
                .current_timestamp()
                .payment_hash(Hash::from_slice(&payment_hash.0).unwrap())
@@ -374,8 +412,8 @@ fn filter_channels(channels: Vec<ChannelDetails>, min_inbound_capacity_msat: Opt
                                proportional_millionths: forwarding_info.fee_proportional_millionths,
                        },
                        cltv_expiry_delta: forwarding_info.cltv_expiry_delta,
-                       htlc_minimum_msat: None,
-                       htlc_maximum_msat: None,}])
+                       htlc_minimum_msat: channel.inbound_htlc_minimum_msat,
+                       htlc_maximum_msat: channel.inbound_htlc_maximum_msat,}])
        };
        // If all channels are private, return the route hint for the highest inbound capacity channel
        // per counterparty node. If channels with an higher inbound capacity than the
@@ -497,10 +535,13 @@ mod test {
 
                // Invoice SCIDs should always use inbound SCID aliases over the real channel ID, if one is
                // available.
+               let chan = &nodes[1].node.list_usable_channels()[0];
                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());
+               assert_eq!(invoice.route_hints()[0].0[0].short_channel_id, chan.inbound_scid_alias.unwrap());
+
+               assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan.inbound_htlc_minimum_msat);
+               assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan.inbound_htlc_maximum_msat);
 
                let payment_params = PaymentParameters::from_node_id(invoice.recover_payee_pub_key())
                        .with_features(invoice.features().unwrap().clone())
@@ -747,23 +788,25 @@ mod test {
                nodes[2].node.handle_channel_update(&nodes[0].node.get_our_node_id(), &chan_0_2.0);
 
                let payment_amt = 10_000;
-               let (payment_preimage, payment_hash, payment_secret) = {
-                       if user_generated_pmt_hash {
-                               let payment_preimage = PaymentPreimage([1; 32]);
-                               let payment_hash = PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner());
-                               let payment_secret = nodes[1].node.create_inbound_payment_for_hash(payment_hash, Some(payment_amt), 3600).unwrap();
-                               (payment_preimage, payment_hash, payment_secret)
-                       } else {
-                               let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600).unwrap();
-                               let payment_preimage = nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap();
-                               (payment_preimage, payment_hash, payment_secret)
-                       }
-               };
                let route_hints = vec![
                        nodes[1].node.get_phantom_route_hints(),
                        nodes[2].node.get_phantom_route_hints(),
                ];
-               let invoice = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(Some(payment_amt), "test".to_string(), payment_hash, payment_secret, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
+
+               let user_payment_preimage = PaymentPreimage([1; 32]);
+               let payment_hash = if user_generated_pmt_hash {
+                       Some(PaymentHash(Sha256::hash(&user_payment_preimage.0[..]).into_inner()))
+               } else {
+                       None
+               };
+
+               let invoice = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(Some(payment_amt), payment_hash, "test".to_string(), 3600, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
+               let (payment_hash, payment_secret) = (PaymentHash(invoice.payment_hash().into_inner()), *invoice.payment_secret());
+               let payment_preimage = if user_generated_pmt_hash {
+                       user_payment_preimage
+               } else {
+                       nodes[1].node.get_payment_preimage(payment_hash, payment_secret).unwrap()
+               };
 
                assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
                assert_eq!(invoice.description(), InvoiceDescription::Direct(&Description("test".to_string())));
@@ -839,6 +882,40 @@ mod test {
                }
        }
 
+       #[test]
+       #[cfg(feature = "std")]
+       fn test_multi_node_hints_has_htlc_min_max_values() {
+               let mut chanmon_cfgs = create_chanmon_cfgs(3);
+               let seed_1 = [42 as u8; 32];
+               let seed_2 = [43 as u8; 32];
+               let cross_node_seed = [44 as u8; 32];
+               chanmon_cfgs[1].keys_manager.backing = PhantomKeysManager::new(&seed_1, 43, 44, &cross_node_seed);
+               chanmon_cfgs[2].keys_manager.backing = PhantomKeysManager::new(&seed_2, 43, 44, &cross_node_seed);
+               let node_cfgs = create_node_cfgs(3, &chanmon_cfgs);
+               let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]);
+               let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
+
+               create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+               create_unannounced_chan_between_nodes_with_value(&nodes, 0, 2, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+
+               let payment_amt = 20_000;
+               let (payment_hash, _payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600).unwrap();
+               let route_hints = vec![
+                       nodes[1].node.get_phantom_route_hints(),
+                       nodes[2].node.get_phantom_route_hints(),
+               ];
+
+               let invoice = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(Some(payment_amt), Some(payment_hash), "test".to_string(), 3600, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
+
+               let chan_0_1 = &nodes[1].node.list_usable_channels()[0];
+               assert_eq!(invoice.route_hints()[0].0[0].htlc_minimum_msat, chan_0_1.inbound_htlc_minimum_msat);
+               assert_eq!(invoice.route_hints()[0].0[0].htlc_maximum_msat, chan_0_1.inbound_htlc_maximum_msat);
+
+               let chan_0_2 = &nodes[2].node.list_usable_channels()[0];
+               assert_eq!(invoice.route_hints()[1].0[0].htlc_minimum_msat, chan_0_2.inbound_htlc_minimum_msat);
+               assert_eq!(invoice.route_hints()[1].0[0].htlc_maximum_msat, chan_0_2.inbound_htlc_maximum_msat);
+       }
+
        #[test]
        #[cfg(feature = "std")]
        fn create_phantom_invoice_with_description_hash() {
@@ -848,14 +925,13 @@ mod test {
                let nodes = create_network(3, &node_cfgs, &node_chanmgrs);
 
                let payment_amt = 20_000;
-               let (payment_hash, payment_secret) = nodes[1].node.create_inbound_payment(Some(payment_amt), 3600).unwrap();
                let route_hints = vec![
                        nodes[1].node.get_phantom_route_hints(),
                        nodes[2].node.get_phantom_route_hints(),
                ];
 
                let description_hash = crate::Sha256(Hash::hash("Description hash phantom invoice".as_bytes()));
-               let invoice = ::utils::create_phantom_invoice_with_description_hash::<EnforcingSigner,&test_utils::TestKeysInterface>(Some(payment_amt), description_hash, payment_hash, payment_secret, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
+               let invoice = ::utils::create_phantom_invoice_with_description_hash::<EnforcingSigner,&test_utils::TestKeysInterface>(Some(payment_amt), None, 3600, description_hash, route_hints, &nodes[1].keys_manager, Currency::BitcoinTestnet).unwrap();
 
                assert_eq!(invoice.amount_pico_btc(), Some(200_000));
                assert_eq!(invoice.min_final_cltv_expiry(), MIN_FINAL_CLTV_EXPIRY as u64);
@@ -1158,7 +1234,6 @@ mod test {
                mut chan_ids_to_match: HashSet<u64>,
                nodes_contains_public_channels: bool
        ){
-               let (payment_hash, payment_secret) = invoice_node.node.create_inbound_payment(invoice_amt, 3600).unwrap();
                let phantom_route_hints = network_multi_nodes.iter()
                        .map(|node| node.node.get_phantom_route_hints())
                        .collect::<Vec<PhantomRouteHints>>();
@@ -1166,7 +1241,7 @@ mod test {
                        .map(|route_hint| route_hint.phantom_scid)
                        .collect::<HashSet<u64>>();
 
-               let invoice = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(invoice_amt, "test".to_string(), payment_hash, payment_secret, phantom_route_hints, &invoice_node.keys_manager, Currency::BitcoinTestnet).unwrap();
+               let invoice = ::utils::create_phantom_invoice::<EnforcingSigner, &test_utils::TestKeysInterface>(invoice_amt, None, "test".to_string(), 3600, phantom_route_hints, &invoice_node.keys_manager, Currency::BitcoinTestnet).unwrap();
 
                let invoice_hints = invoice.private_routes();
 
index da64cb375da11d71f517bcd31c47c5686796b088..c23baf8ad34bccb7ea7efcaa32639a43f4b23c42 100644 (file)
@@ -15,20 +15,13 @@ extern crate bitcoin;
 extern crate libc;
 
 use bitcoin::hash_types::{BlockHash, Txid};
-use bitcoin::hashes::hex::{FromHex, ToHex};
-use lightning::routing::network_graph::NetworkGraph;
-use crate::util::DiskWriteable;
-use lightning::chain;
-use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator};
-use lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate};
-use lightning::chain::chainmonitor;
+use bitcoin::hashes::hex::FromHex;
+use lightning::chain::channelmonitor::ChannelMonitor;
 use lightning::chain::keysinterface::{Sign, KeysInterface};
-use lightning::chain::transaction::OutPoint;
-use lightning::ln::channelmanager::ChannelManager;
-use lightning::util::logger::Logger;
 use lightning::util::ser::{ReadableArgs, Writeable};
+use lightning::util::persist::KVStorePersister;
 use std::fs;
-use std::io::{Cursor, Error};
+use std::io::Cursor;
 use std::ops::Deref;
 use std::path::{Path, PathBuf};
 
@@ -48,31 +41,6 @@ pub struct FilesystemPersister {
        path_to_channel_data: String,
 }
 
-impl<Signer: Sign> DiskWriteable for ChannelMonitor<Signer> {
-       fn write_to_file(&self, writer: &mut fs::File) -> Result<(), Error> {
-               self.write(writer)
-       }
-}
-
-impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> DiskWriteable for ChannelManager<Signer, M, T, K, F, L>
-where
-       M::Target: chain::Watch<Signer>,
-       T::Target: BroadcasterInterface,
-       K::Target: KeysInterface<Signer=Signer>,
-       F::Target: FeeEstimator,
-       L::Target: Logger,
-{
-       fn write_to_file(&self, writer: &mut fs::File) -> Result<(), std::io::Error> {
-               self.write(writer)
-       }
-}
-
-impl DiskWriteable for NetworkGraph {
-       fn write_to_file(&self, writer: &mut fs::File) -> Result<(), std::io::Error> {
-               self.write(writer)
-       }
-}
-
 impl FilesystemPersister {
        /// Initialize a new FilesystemPersister and set the path to the individual channels'
        /// files.
@@ -87,43 +55,14 @@ impl FilesystemPersister {
                self.path_to_channel_data.clone()
        }
 
-       pub(crate) fn path_to_monitor_data(&self) -> PathBuf {
-               let mut path = PathBuf::from(self.path_to_channel_data.clone());
-               path.push("monitors");
-               path
-       }
-
-       /// Writes the provided `ChannelManager` to the path provided at `FilesystemPersister`
-       /// initialization, within a file called "manager".
-       pub fn persist_manager<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>(
-               data_dir: String,
-               manager: &ChannelManager<Signer, M, T, K, F, L>
-       ) -> Result<(), std::io::Error>
-       where
-               M::Target: chain::Watch<Signer>,
-               T::Target: BroadcasterInterface,
-               K::Target: KeysInterface<Signer=Signer>,
-               F::Target: FeeEstimator,
-               L::Target: Logger,
-       {
-               let path = PathBuf::from(data_dir);
-               util::write_to_file(path, "manager".to_string(), manager)
-       }
-
-       /// Write the provided `NetworkGraph` to the path provided at `FilesystemPersister`
-       /// initialization, within a file called "network_graph"
-       pub fn persist_network_graph(data_dir: String, network_graph: &NetworkGraph) -> Result<(), std::io::Error> {
-               let path = PathBuf::from(data_dir);
-               util::write_to_file(path, "network_graph".to_string(), network_graph)
-       }
-
        /// Read `ChannelMonitor`s from disk.
        pub fn read_channelmonitors<Signer: Sign, K: Deref> (
                &self, keys_manager: K
        ) -> Result<Vec<(BlockHash, ChannelMonitor<Signer>)>, std::io::Error>
                where K::Target: KeysInterface<Signer=Signer> + Sized,
        {
-               let path = self.path_to_monitor_data();
+               let mut path = PathBuf::from(&self.path_to_channel_data);
+               path.push("monitors");
                if !Path::new(&path).exists() {
                        return Ok(Vec::new());
                }
@@ -180,22 +119,11 @@ impl FilesystemPersister {
        }
 }
 
-impl<ChannelSigner: Sign> chainmonitor::Persist<ChannelSigner> for FilesystemPersister {
-       // TODO: We really need a way for the persister to inform the user that its time to crash/shut
-       // down once these start returning failure.
-       // A PermanentFailure implies we need to shut down since we're force-closing channels without
-       // even broadcasting!
-
-       fn persist_new_channel(&self, funding_txo: OutPoint, monitor: &ChannelMonitor<ChannelSigner>, _update_id: chainmonitor::MonitorUpdateId) -> Result<(), chain::ChannelMonitorUpdateErr> {
-               let filename = format!("{}_{}", funding_txo.txid.to_hex(), funding_txo.index);
-               util::write_to_file(self.path_to_monitor_data(), filename, monitor)
-                       .map_err(|_| chain::ChannelMonitorUpdateErr::PermanentFailure)
-       }
-
-       fn update_persisted_channel(&self, funding_txo: OutPoint, _update: &Option<ChannelMonitorUpdate>, monitor: &ChannelMonitor<ChannelSigner>, _update_id: chainmonitor::MonitorUpdateId) -> Result<(), chain::ChannelMonitorUpdateErr> {
-               let filename = format!("{}_{}", funding_txo.txid.to_hex(), funding_txo.index);
-               util::write_to_file(self.path_to_monitor_data(), filename, monitor)
-                       .map_err(|_| chain::ChannelMonitorUpdateErr::PermanentFailure)
+impl KVStorePersister for FilesystemPersister {
+       fn persist<W: Writeable>(&self, key: &str, object: &W) -> std::io::Result<()> {
+               let mut dest_file = PathBuf::from(self.path_to_channel_data.clone());
+               dest_file.push(key);
+               util::write_to_file(dest_file, object)
        }
 }
 
index 73b28985bfff6ae8b484e5f0d76c62e4091b3541..4adbb33e5b26fd886fb64d05d3d315efd3f28b16 100644 (file)
@@ -2,26 +2,20 @@
 extern crate winapi;
 
 use std::fs;
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
+use std::io::BufWriter;
 
 #[cfg(not(target_os = "windows"))]
 use std::os::unix::io::AsRawFd;
 
+use lightning::util::ser::Writeable;
+
 #[cfg(target_os = "windows")]
 use {
        std::ffi::OsStr,
        std::os::windows::ffi::OsStrExt
 };
 
-pub(crate) trait DiskWriteable {
-       fn write_to_file(&self, writer: &mut fs::File) -> Result<(), std::io::Error>;
-}
-
-pub(crate) fn get_full_filepath(mut filepath: PathBuf, filename: String) -> String {
-       filepath.push(filename);
-       filepath.to_str().unwrap().to_string()
-}
-
 #[cfg(target_os = "windows")]
 macro_rules! call {
        ($e: expr) => (
@@ -39,45 +33,43 @@ fn path_to_windows_str<T: AsRef<OsStr>>(path: T) -> Vec<winapi::shared::ntdef::W
 }
 
 #[allow(bare_trait_objects)]
-pub(crate) fn write_to_file<D: DiskWriteable>(path: PathBuf, filename: String, data: &D) -> std::io::Result<()> {
-       fs::create_dir_all(path.clone())?;
+pub(crate) fn write_to_file<W: Writeable>(dest_file: PathBuf, data: &W) -> std::io::Result<()> {
+       let mut tmp_file = dest_file.clone();
+       tmp_file.set_extension("tmp");
+
+       let parent_directory = dest_file.parent().unwrap();
+       fs::create_dir_all(parent_directory)?;
        // Do a crazy dance with lots of fsync()s to be overly cautious here...
        // We never want to end up in a state where we've lost the old data, or end up using the
        // old data on power loss after we've returned.
        // The way to atomically write a file on Unix platforms is:
        // open(tmpname), write(tmpfile), fsync(tmpfile), close(tmpfile), rename(), fsync(dir)
-       let filename_with_path = get_full_filepath(path, filename);
-       let tmp_filename = format!("{}.tmp", filename_with_path.clone());
-
        {
                // Note that going by rust-lang/rust@d602a6b, on MacOS it is only safe to use
                // rust stdlib 1.36 or higher.
-               let mut f = fs::File::create(&tmp_filename)?;
-               data.write_to_file(&mut f)?;
-               f.sync_all()?;
+               let mut buf = BufWriter::new(fs::File::create(&tmp_file)?);
+               data.write(&mut buf)?;
+               buf.into_inner()?.sync_all()?;
        }
        // Fsync the parent directory on Unix.
        #[cfg(not(target_os = "windows"))]
        {
-               fs::rename(&tmp_filename, &filename_with_path)?;
-               let path = Path::new(&filename_with_path).parent().unwrap();
-               let dir_file = fs::OpenOptions::new().read(true).open(path)?;
+               fs::rename(&tmp_file, &dest_file)?;
+               let dir_file = fs::OpenOptions::new().read(true).open(parent_directory)?;
                unsafe { libc::fsync(dir_file.as_raw_fd()); }
        }
        #[cfg(target_os = "windows")]
        {
-               let src = PathBuf::from(tmp_filename.clone());
-               let dst = PathBuf::from(filename_with_path.clone());
-               if Path::new(&filename_with_path.clone()).exists() {
+               if dest_file.exists() {
                        unsafe {winapi::um::winbase::ReplaceFileW(
-                               path_to_windows_str(dst).as_ptr(), path_to_windows_str(src).as_ptr(), std::ptr::null(),
+                               path_to_windows_str(dest_file).as_ptr(), path_to_windows_str(tmp_file).as_ptr(), std::ptr::null(),
                                winapi::um::winbase::REPLACEFILE_IGNORE_MERGE_ERRORS,
                                std::ptr::null_mut() as *mut winapi::ctypes::c_void,
                                std::ptr::null_mut() as *mut winapi::ctypes::c_void
                        )};
                } else {
                        call!(unsafe {winapi::um::winbase::MoveFileExW(
-                               path_to_windows_str(src).as_ptr(), path_to_windows_str(dst).as_ptr(),
+                               path_to_windows_str(tmp_file).as_ptr(), path_to_windows_str(dest_file).as_ptr(),
                                winapi::um::winbase::MOVEFILE_WRITE_THROUGH | winapi::um::winbase::MOVEFILE_REPLACE_EXISTING
                        )});
                }
@@ -87,15 +79,16 @@ pub(crate) fn write_to_file<D: DiskWriteable>(path: PathBuf, filename: String, d
 
 #[cfg(test)]
 mod tests {
-       use super::{DiskWriteable, get_full_filepath, write_to_file};
+       use lightning::util::ser::{Writer, Writeable};
+
+       use super::{write_to_file};
        use std::fs;
        use std::io;
-       use std::io::Write;
        use std::path::PathBuf;
 
        struct TestWriteable{}
-       impl DiskWriteable for TestWriteable {
-               fn write_to_file(&self, writer: &mut fs::File) -> Result<(), io::Error> {
+       impl Writeable for TestWriteable {
+               fn write<W: Writer>(&self, writer: &mut W) -> Result<(), std::io::Error> {
                        writer.write_all(&[42; 1])
                }
        }
@@ -113,7 +106,9 @@ mod tests {
                let mut perms = fs::metadata(path.to_string()).unwrap().permissions();
                perms.set_readonly(true);
                fs::set_permissions(path.to_string(), perms).unwrap();
-               match write_to_file(PathBuf::from(path.to_string()), filename, &test_writeable) {
+               let mut dest_file = PathBuf::from(path);
+               dest_file.push(filename);
+               match write_to_file(dest_file, &test_writeable) {
                        Err(e) => assert_eq!(e.kind(), io::ErrorKind::PermissionDenied),
                        _ => panic!("Unexpected error message")
                }
@@ -131,10 +126,12 @@ mod tests {
        fn test_rename_failure() {
                let test_writeable = TestWriteable{};
                let filename = "test_rename_failure_filename";
-               let path = PathBuf::from("test_rename_failure_dir");
+               let path = "test_rename_failure_dir";
+               let mut dest_file = PathBuf::from(path);
+               dest_file.push(filename);
                // Create the channel data file and make it a directory.
-               fs::create_dir_all(get_full_filepath(path.clone(), filename.to_string())).unwrap();
-               match write_to_file(path.clone(), filename.to_string(), &test_writeable) {
+               fs::create_dir_all(dest_file.clone()).unwrap();
+               match write_to_file(dest_file, &test_writeable) {
                        Err(e) => assert_eq!(e.raw_os_error(), Some(libc::EISDIR)),
                        _ => panic!("Unexpected Ok(())")
                }
@@ -144,16 +141,18 @@ mod tests {
        #[test]
        fn test_diskwriteable_failure() {
                struct FailingWriteable {}
-               impl DiskWriteable for FailingWriteable {
-                       fn write_to_file(&self, _writer: &mut fs::File) -> Result<(), std::io::Error> {
+               impl Writeable for FailingWriteable {
+                       fn write<W: Writer>(&self, _writer: &mut W) -> Result<(), std::io::Error> {
                                Err(std::io::Error::new(std::io::ErrorKind::Other, "expected failure"))
                        }
                }
 
                let filename = "test_diskwriteable_failure";
-               let path = PathBuf::from("test_diskwriteable_failure_dir");
+               let path = "test_diskwriteable_failure_dir";
                let test_writeable = FailingWriteable{};
-               match write_to_file(path.clone(), filename.to_string(), &test_writeable) {
+               let mut dest_file = PathBuf::from(path);
+               dest_file.push(filename);
+               match write_to_file(dest_file, &test_writeable) {
                        Err(e) => {
                                assert_eq!(e.kind(), std::io::ErrorKind::Other);
                                assert_eq!(e.get_ref().unwrap().to_string(), "expected failure");
@@ -170,12 +169,13 @@ mod tests {
        fn test_tmp_file_creation_failure() {
                let test_writeable = TestWriteable{};
                let filename = "test_tmp_file_creation_failure_filename".to_string();
-               let path = PathBuf::from("test_tmp_file_creation_failure_dir");
-
-               // Create the tmp file and make it a directory.
-               let tmp_path = get_full_filepath(path.clone(), format!("{}.tmp", filename.clone()));
-               fs::create_dir_all(tmp_path).unwrap();
-               match write_to_file(path, filename, &test_writeable) {
+               let path = "test_tmp_file_creation_failure_dir";
+               let mut dest_file = PathBuf::from(path);
+               dest_file.push(filename);
+               let mut tmp_file = dest_file.clone();
+               tmp_file.set_extension("tmp");
+               fs::create_dir_all(tmp_file).unwrap();
+               match write_to_file(dest_file, &test_writeable) {
                        Err(e) => {
                                #[cfg(not(target_os = "windows"))]
                                assert_eq!(e.raw_os_error(), Some(libc::EISDIR));
index 94af00c7c72e8eebd3263a0a16e50a93c2e32cd7..58fe30ba2618026311066f347da4a99f2d5f4c3f 100644 (file)
@@ -1102,7 +1102,7 @@ fn test_monitor_update_fail_reestablish() {
        assert!(updates.update_fee.is_none());
        assert_eq!(updates.update_fulfill_htlcs.len(), 1);
        nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
-       expect_payment_forwarded!(nodes[1], Some(1000), false);
+       expect_payment_forwarded!(nodes[1], nodes[0], Some(1000), false);
        check_added_monitors!(nodes[1], 1);
        assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
        commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
@@ -2087,7 +2087,7 @@ fn test_fail_htlc_on_broadcast_after_claim() {
        nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &cs_updates.update_fulfill_htlcs[0]);
        let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        check_added_monitors!(nodes[1], 1);
-       expect_payment_forwarded!(nodes[1], Some(1000), false);
+       expect_payment_forwarded!(nodes[1], nodes[0], Some(1000), false);
 
        mine_transaction(&nodes[1], &bs_txn[0]);
        check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed);
@@ -2423,7 +2423,7 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
        let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs);
 
        create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
-       let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known()).2;
+       let chan_id_2 = create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known()).2;
 
        let (payment_preimage, payment_hash, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 100_000);
 
@@ -2450,7 +2450,7 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
        }
 
        let fulfill_msg = msgs::UpdateFulfillHTLC {
-               channel_id: chan_2,
+               channel_id: chan_id_2,
                htlc_id: 0,
                payment_preimage,
        };
@@ -2468,7 +2468,7 @@ fn do_test_reconnect_dup_htlc_claims(htlc_status: HTLCStatusAtDupClaim, second_f
                assert_eq!(fulfill_msg, cs_updates.update_fulfill_htlcs[0]);
        }
        nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &fulfill_msg);
-       expect_payment_forwarded!(nodes[1], Some(1000), false);
+       expect_payment_forwarded!(nodes[1], nodes[0], Some(1000), false);
        check_added_monitors!(nodes[1], 1);
 
        let mut bs_updates = None;
index 9ccdf816ad398d764d599b62e45e0e1274391572..b0551bf8323f1617f7cba4c991c783221c778c46 100644 (file)
@@ -4321,11 +4321,15 @@ impl<Signer: Sign> Channel<Signer> {
        }
 
        /// Allowed in any state (including after shutdown)
-       #[cfg(test)]
        pub fn get_holder_htlc_minimum_msat(&self) -> u64 {
                self.holder_htlc_minimum_msat
        }
 
+       /// Allowed in any state (including after shutdown), but will return none before TheirInitSent
+       pub fn get_holder_htlc_maximum_msat(&self) -> Option<u64> {
+               self.get_htlc_maximum_msat(self.holder_max_htlc_value_in_flight_msat)
+       }
+
        /// Allowed in any state (including after shutdown)
        pub fn get_announced_htlc_max_msat(&self) -> u64 {
                return cmp::min(
@@ -4343,6 +4347,21 @@ impl<Signer: Sign> Channel<Signer> {
                self.counterparty_htlc_minimum_msat
        }
 
+       /// Allowed in any state (including after shutdown), but will return none before TheirInitSent
+       pub fn get_counterparty_htlc_maximum_msat(&self) -> Option<u64> {
+               self.get_htlc_maximum_msat(self.counterparty_max_htlc_value_in_flight_msat)
+       }
+
+       fn get_htlc_maximum_msat(&self, party_max_htlc_value_in_flight_msat: u64) -> Option<u64> {
+               self.counterparty_selected_channel_reserve_satoshis.map(|counterparty_reserve| {
+                       let holder_reserve = self.holder_selected_channel_reserve_satoshis;
+                       cmp::min(
+                               (self.channel_value_satoshis - counterparty_reserve - holder_reserve) * 1000,
+                               party_max_htlc_value_in_flight_msat
+                       )
+               })
+       }
+
        pub fn get_value_satoshis(&self) -> u64 {
                self.channel_value_satoshis
        }
index 7acd99e3eba491baca576de6e9282d2317907385..93746f0fde05cbc6b3ae3272a6851f36ef7d993c 100644 (file)
@@ -40,7 +40,7 @@ use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitor
 use chain::transaction::{OutPoint, TransactionData};
 // Since this struct is returned in `list_channels` methods, expose it here in case users want to
 // construct one themselves.
-use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
+use ln::{inbound_payment, PaymentHash, PaymentPreimage, PaymentSecret};
 use ln::channel::{Channel, ChannelError, ChannelUpdateStatus, UpdateFulfillCommitFetch};
 use ln::features::{ChannelTypeFeatures, InitFeatures, NodeFeatures};
 use routing::router::{PaymentParameters, Route, RouteHop, RoutePath, RouteParameters};
@@ -71,276 +71,6 @@ use core::ops::Deref;
 use std::time::Instant;
 use util::crypto::sign;
 
-mod inbound_payment {
-       use alloc::string::ToString;
-       use bitcoin::hashes::{Hash, HashEngine};
-       use bitcoin::hashes::cmp::fixed_time_eq;
-       use bitcoin::hashes::hmac::{Hmac, HmacEngine};
-       use bitcoin::hashes::sha256::Hash as Sha256;
-       use chain::keysinterface::{KeyMaterial, KeysInterface, Sign};
-       use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
-       use ln::channelmanager::APIError;
-       use ln::msgs;
-       use ln::msgs::MAX_VALUE_MSAT;
-       use util::chacha20::ChaCha20;
-       use util::crypto::hkdf_extract_expand_thrice;
-       use util::logger::Logger;
-
-       use core::convert::TryInto;
-       use core::ops::Deref;
-
-       const IV_LEN: usize = 16;
-       const METADATA_LEN: usize = 16;
-       const METADATA_KEY_LEN: usize = 32;
-       const AMT_MSAT_LEN: usize = 8;
-       // Used to shift the payment type bits to take up the top 3 bits of the metadata bytes, or to
-       // retrieve said payment type bits.
-       const METHOD_TYPE_OFFSET: usize = 5;
-
-       /// A set of keys that were HKDF-expanded from an initial call to
-       /// [`KeysInterface::get_inbound_payment_key_material`].
-       ///
-       /// [`KeysInterface::get_inbound_payment_key_material`]: crate::chain::keysinterface::KeysInterface::get_inbound_payment_key_material
-       pub(super) struct ExpandedKey {
-               /// The key used to encrypt the bytes containing the payment metadata (i.e. the amount and
-               /// expiry, included for payment verification on decryption).
-               metadata_key: [u8; 32],
-               /// The key used to authenticate an LDK-provided payment hash and metadata as previously
-               /// registered with LDK.
-               ldk_pmt_hash_key: [u8; 32],
-               /// The key used to authenticate a user-provided payment hash and metadata as previously
-               /// registered with LDK.
-               user_pmt_hash_key: [u8; 32],
-       }
-
-       impl ExpandedKey {
-               pub(super) fn new(key_material: &KeyMaterial) -> ExpandedKey {
-                       let (metadata_key, ldk_pmt_hash_key, user_pmt_hash_key) =
-                               hkdf_extract_expand_thrice(b"LDK Inbound Payment Key Expansion", &key_material.0);
-                       Self {
-                               metadata_key,
-                               ldk_pmt_hash_key,
-                               user_pmt_hash_key,
-                       }
-               }
-       }
-
-       enum Method {
-               LdkPaymentHash = 0,
-               UserPaymentHash = 1,
-       }
-
-       impl Method {
-               fn from_bits(bits: u8) -> Result<Method, u8> {
-                       match bits {
-                               bits if bits == Method::LdkPaymentHash as u8 => Ok(Method::LdkPaymentHash),
-                               bits if bits == Method::UserPaymentHash as u8 => Ok(Method::UserPaymentHash),
-                               unknown => Err(unknown),
-                       }
-               }
-       }
-
-       pub(super) fn create<Signer: Sign, K: Deref>(keys: &ExpandedKey, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32, keys_manager: &K, highest_seen_timestamp: u64) -> Result<(PaymentHash, PaymentSecret), ()>
-               where K::Target: KeysInterface<Signer = Signer>
-       {
-               let metadata_bytes = construct_metadata_bytes(min_value_msat, Method::LdkPaymentHash, invoice_expiry_delta_secs, highest_seen_timestamp)?;
-
-               let mut iv_bytes = [0 as u8; IV_LEN];
-               let rand_bytes = keys_manager.get_secure_random_bytes();
-               iv_bytes.copy_from_slice(&rand_bytes[..IV_LEN]);
-
-               let mut hmac = HmacEngine::<Sha256>::new(&keys.ldk_pmt_hash_key);
-               hmac.input(&iv_bytes);
-               hmac.input(&metadata_bytes);
-               let payment_preimage_bytes = Hmac::from_engine(hmac).into_inner();
-
-               let ldk_pmt_hash = PaymentHash(Sha256::hash(&payment_preimage_bytes).into_inner());
-               let payment_secret = construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key);
-               Ok((ldk_pmt_hash, payment_secret))
-       }
-
-       pub(super) fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option<u64>, payment_hash: PaymentHash, invoice_expiry_delta_secs: u32, highest_seen_timestamp: u64) -> Result<PaymentSecret, ()> {
-               let metadata_bytes = construct_metadata_bytes(min_value_msat, Method::UserPaymentHash, invoice_expiry_delta_secs, highest_seen_timestamp)?;
-
-               let mut hmac = HmacEngine::<Sha256>::new(&keys.user_pmt_hash_key);
-               hmac.input(&metadata_bytes);
-               hmac.input(&payment_hash.0);
-               let hmac_bytes = Hmac::from_engine(hmac).into_inner();
-
-               let mut iv_bytes = [0 as u8; IV_LEN];
-               iv_bytes.copy_from_slice(&hmac_bytes[..IV_LEN]);
-
-               Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key))
-       }
-
-       fn construct_metadata_bytes(min_value_msat: Option<u64>, payment_type: Method, invoice_expiry_delta_secs: u32, highest_seen_timestamp: u64) -> Result<[u8; METADATA_LEN], ()> {
-               if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
-                       return Err(());
-               }
-
-               let mut min_amt_msat_bytes: [u8; AMT_MSAT_LEN] = match min_value_msat {
-                       Some(amt) => amt.to_be_bytes(),
-                       None => [0; AMT_MSAT_LEN],
-               };
-               min_amt_msat_bytes[0] |= (payment_type as u8) << METHOD_TYPE_OFFSET;
-
-               // We assume that highest_seen_timestamp is pretty close to the current time - it's updated when
-               // we receive a new block with the maximum time we've seen in a header. It should never be more
-               // than two hours in the future.  Thus, we add two hours here as a buffer to ensure we
-               // absolutely never fail a payment too early.
-               // Note that we assume that received blocks have reasonably up-to-date timestamps.
-               let expiry_bytes = (highest_seen_timestamp + invoice_expiry_delta_secs as u64 + 7200).to_be_bytes();
-
-               let mut metadata_bytes: [u8; METADATA_LEN] = [0; METADATA_LEN];
-               metadata_bytes[..AMT_MSAT_LEN].copy_from_slice(&min_amt_msat_bytes);
-               metadata_bytes[AMT_MSAT_LEN..].copy_from_slice(&expiry_bytes);
-
-               Ok(metadata_bytes)
-       }
-
-       fn construct_payment_secret(iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METADATA_LEN], metadata_key: &[u8; METADATA_KEY_LEN]) -> PaymentSecret {
-               let mut payment_secret_bytes: [u8; 32] = [0; 32];
-               let (iv_slice, encrypted_metadata_slice) = payment_secret_bytes.split_at_mut(IV_LEN);
-               iv_slice.copy_from_slice(iv_bytes);
-
-               let chacha_block = ChaCha20::get_single_block(metadata_key, iv_bytes);
-               for i in 0..METADATA_LEN {
-                       encrypted_metadata_slice[i] = chacha_block[i] ^ metadata_bytes[i];
-               }
-               PaymentSecret(payment_secret_bytes)
-       }
-
-       /// Check that an inbound payment's `payment_data` field is sane.
-       ///
-       /// LDK does not store any data for pending inbound payments. Instead, we construct our payment
-       /// secret (and, if supplied by LDK, our payment preimage) to include encrypted metadata about the
-       /// payment.
-       ///
-       /// The metadata is constructed as:
-       ///   payment method (3 bits) || payment amount (8 bytes - 3 bits) || expiry (8 bytes)
-       /// and encrypted using a key derived from [`KeysInterface::get_inbound_payment_key_material`].
-       ///
-       /// Then on payment receipt, we verify in this method that the payment preimage and payment secret
-       /// match what was constructed.
-       ///
-       /// [`create_inbound_payment`] and [`create_inbound_payment_for_hash`] are called by the user to
-       /// construct the payment secret and/or payment hash that this method is verifying. If the former
-       /// method is called, then the payment method bits mentioned above are represented internally as
-       /// [`Method::LdkPaymentHash`]. If the latter, [`Method::UserPaymentHash`].
-       ///
-       /// For the former method, the payment preimage is constructed as an HMAC of payment metadata and
-       /// random bytes. Because the payment secret is also encoded with these random bytes and metadata
-       /// (with the metadata encrypted with a block cipher), we're able to authenticate the preimage on
-       /// payment receipt.
-       ///
-       /// For the latter, the payment secret instead contains an HMAC of the user-provided payment hash
-       /// and payment metadata (encrypted with a block cipher), allowing us to authenticate the payment
-       /// hash and metadata on payment receipt.
-       ///
-       /// See [`ExpandedKey`] docs for more info on the individual keys used.
-       ///
-       /// [`KeysInterface::get_inbound_payment_key_material`]: crate::chain::keysinterface::KeysInterface::get_inbound_payment_key_material
-       /// [`create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
-       /// [`create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
-       pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: msgs::FinalOnionHopData, highest_seen_timestamp: u64, keys: &ExpandedKey, logger: &L) -> Result<Option<PaymentPreimage>, ()>
-               where L::Target: Logger
-       {
-               let (iv_bytes, metadata_bytes) = decrypt_metadata(payment_data.payment_secret, keys);
-
-               let payment_type_res = Method::from_bits((metadata_bytes[0] & 0b1110_0000) >> METHOD_TYPE_OFFSET);
-               let mut amt_msat_bytes = [0; AMT_MSAT_LEN];
-               amt_msat_bytes.copy_from_slice(&metadata_bytes[..AMT_MSAT_LEN]);
-               // Zero out the bits reserved to indicate the payment type.
-               amt_msat_bytes[0] &= 0b00011111;
-               let min_amt_msat: u64 = u64::from_be_bytes(amt_msat_bytes.into());
-               let expiry = u64::from_be_bytes(metadata_bytes[AMT_MSAT_LEN..].try_into().unwrap());
-
-               // Make sure to check to check the HMAC before doing the other checks below, to mitigate timing
-               // attacks.
-               let mut payment_preimage = None;
-               match payment_type_res {
-                       Ok(Method::UserPaymentHash) => {
-                               let mut hmac = HmacEngine::<Sha256>::new(&keys.user_pmt_hash_key);
-                               hmac.input(&metadata_bytes[..]);
-                               hmac.input(&payment_hash.0);
-                               if !fixed_time_eq(&iv_bytes, &Hmac::from_engine(hmac).into_inner().split_at_mut(IV_LEN).0) {
-                                       log_trace!(logger, "Failing HTLC with user-generated payment_hash {}: unexpected payment_secret", log_bytes!(payment_hash.0));
-                                       return Err(())
-                               }
-                       },
-                       Ok(Method::LdkPaymentHash) => {
-                               match derive_ldk_payment_preimage(payment_hash, &iv_bytes, &metadata_bytes, keys) {
-                                       Ok(preimage) => payment_preimage = Some(preimage),
-                                       Err(bad_preimage_bytes) => {
-                                               log_trace!(logger, "Failing HTLC with payment_hash {} due to mismatching preimage {}", log_bytes!(payment_hash.0), log_bytes!(bad_preimage_bytes));
-                                               return Err(())
-                                       }
-                               }
-                       },
-                       Err(unknown_bits) => {
-                               log_trace!(logger, "Failing HTLC with payment hash {} due to unknown payment type {}", log_bytes!(payment_hash.0), unknown_bits);
-                               return Err(());
-                       }
-               }
-
-               if payment_data.total_msat < min_amt_msat {
-                       log_trace!(logger, "Failing HTLC with payment_hash {} due to total_msat {} being less than the minimum amount of {} msat", log_bytes!(payment_hash.0), payment_data.total_msat, min_amt_msat);
-                       return Err(())
-               }
-
-               if expiry < highest_seen_timestamp {
-                       log_trace!(logger, "Failing HTLC with payment_hash {}: expired payment", log_bytes!(payment_hash.0));
-                       return Err(())
-               }
-
-               Ok(payment_preimage)
-       }
-
-       pub(super) fn get_payment_preimage(payment_hash: PaymentHash, payment_secret: PaymentSecret, keys: &ExpandedKey) -> Result<PaymentPreimage, APIError> {
-               let (iv_bytes, metadata_bytes) = decrypt_metadata(payment_secret, keys);
-
-               match Method::from_bits((metadata_bytes[0] & 0b1110_0000) >> METHOD_TYPE_OFFSET) {
-                       Ok(Method::LdkPaymentHash) => {
-                               derive_ldk_payment_preimage(payment_hash, &iv_bytes, &metadata_bytes, keys)
-                                       .map_err(|bad_preimage_bytes| APIError::APIMisuseError {
-                                               err: format!("Payment hash {} did not match decoded preimage {}", log_bytes!(payment_hash.0), log_bytes!(bad_preimage_bytes))
-                                       })
-                       },
-                       Ok(Method::UserPaymentHash) => Err(APIError::APIMisuseError {
-                               err: "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash".to_string()
-                       }),
-                       Err(other) => Err(APIError::APIMisuseError { err: format!("Unknown payment type: {}", other) }),
-               }
-       }
-
-       fn decrypt_metadata(payment_secret: PaymentSecret, keys: &ExpandedKey) -> ([u8; IV_LEN], [u8; METADATA_LEN]) {
-               let mut iv_bytes = [0; IV_LEN];
-               let (iv_slice, encrypted_metadata_bytes) = payment_secret.0.split_at(IV_LEN);
-               iv_bytes.copy_from_slice(iv_slice);
-
-               let chacha_block = ChaCha20::get_single_block(&keys.metadata_key, &iv_bytes);
-               let mut metadata_bytes: [u8; METADATA_LEN] = [0; METADATA_LEN];
-               for i in 0..METADATA_LEN {
-                       metadata_bytes[i] = chacha_block[i] ^ encrypted_metadata_bytes[i];
-               }
-
-               (iv_bytes, metadata_bytes)
-       }
-
-       // Errors if the payment preimage doesn't match `payment_hash`. Returns the bad preimage bytes in
-       // this case.
-       fn derive_ldk_payment_preimage(payment_hash: PaymentHash, iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METADATA_LEN], keys: &ExpandedKey) -> Result<PaymentPreimage, [u8; 32]> {
-               let mut hmac = HmacEngine::<Sha256>::new(&keys.ldk_pmt_hash_key);
-               hmac.input(iv_bytes);
-               hmac.input(metadata_bytes);
-               let decoded_payment_preimage = Hmac::from_engine(hmac).into_inner();
-               if !fixed_time_eq(&payment_hash.0, &Sha256::hash(&decoded_payment_preimage).into_inner()) {
-                       return Err(decoded_payment_preimage);
-               }
-               return Ok(PaymentPreimage(decoded_payment_preimage))
-       }
-}
-
 // We hold various information about HTLC relay in the HTLC objects in Channel itself:
 //
 // Upon receipt of an HTLC from a peer, we'll give it a PendingHTLCStatus indicating if it should
@@ -1192,6 +922,12 @@ pub struct ChannelCounterparty {
        /// Information on the fees and requirements that the counterparty requires when forwarding
        /// payments to us through this channel.
        pub forwarding_info: Option<CounterpartyForwardingInfo>,
+       /// The smallest value HTLC (in msat) the remote peer will accept, for this channel. This field
+       /// is only `None` before we have received either the `OpenChannel` or `AcceptChannel` message
+       /// from the remote peer, or for `ChannelCounterparty` objects serialized prior to LDK 0.0.107.
+       pub outbound_htlc_minimum_msat: Option<u64>,
+       /// The largest value HTLC (in msat) the remote peer currently will accept, for this channel.
+       pub outbound_htlc_maximum_msat: Option<u64>,
 }
 
 /// Details of a channel, as returned by ChannelManager::list_channels and ChannelManager::list_usable_channels
@@ -1316,6 +1052,11 @@ pub struct ChannelDetails {
        pub is_usable: bool,
        /// True if this channel is (or will be) publicly-announced.
        pub is_public: bool,
+       /// The smallest value HTLC (in msat) we will accept, for this channel. This field
+       /// is only `None` for `ChannelDetails` objects serialized prior to LDK 0.0.107
+       pub inbound_htlc_minimum_msat: Option<u64>,
+       /// The largest value HTLC (in msat) we currently will accept, for this channel.
+       pub inbound_htlc_maximum_msat: Option<u64>,
 }
 
 impl ChannelDetails {
@@ -1940,6 +1681,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                features: InitFeatures::empty(),
                                                unspendable_punishment_reserve: to_remote_reserve_satoshis,
                                                forwarding_info: channel.counterparty_forwarding_info(),
+                                               // Ensures that we have actually received the `htlc_minimum_msat` value
+                                               // from the counterparty through the `OpenChannel` or `AcceptChannel`
+                                               // message (as they are always the first message from the counterparty).
+                                               // Else `Channel::get_counterparty_htlc_minimum_msat` could return the
+                                               // default `0` value set by `Channel::new_outbound`.
+                                               outbound_htlc_minimum_msat: if channel.have_received_message() {
+                                                       Some(channel.get_counterparty_htlc_minimum_msat()) } else { None },
+                                               outbound_htlc_maximum_msat: channel.get_counterparty_htlc_maximum_msat(),
                                        },
                                        funding_txo: channel.get_funding_txo(),
                                        // Note that accept_channel (or open_channel) is always the first message, so
@@ -1959,6 +1708,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                        is_funding_locked: channel.is_usable(),
                                        is_usable: channel.is_live(),
                                        is_public: channel.should_announce(),
+                                       inbound_htlc_minimum_msat: Some(channel.get_holder_htlc_minimum_msat()),
+                                       inbound_htlc_maximum_msat: channel.get_holder_htlc_maximum_msat()
                                });
                        }
                }
@@ -4292,7 +4043,10 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
                                                } else { None };
 
                                                let mut pending_events = self.pending_events.lock().unwrap();
+
+                                               let source_channel_id = Some(prev_outpoint.to_channel_id());
                                                pending_events.push(events::Event::PaymentForwarded {
+                                                       source_channel_id,
                                                        fee_earned_msat,
                                                        claim_from_onchain_tx: from_onchain,
                                                });
@@ -6167,6 +5921,8 @@ impl_writeable_tlv_based!(ChannelCounterparty, {
        (4, features, required),
        (6, unspendable_punishment_reserve, required),
        (8, forwarding_info, option),
+       (9, outbound_htlc_minimum_msat, option),
+       (11, outbound_htlc_maximum_msat, option),
 });
 
 impl_writeable_tlv_based!(ChannelDetails, {
@@ -6188,6 +5944,8 @@ impl_writeable_tlv_based!(ChannelDetails, {
        (28, is_funding_locked, required),
        (30, is_usable, required),
        (32, is_public, required),
+       (33, inbound_htlc_minimum_msat, option),
+       (35, inbound_htlc_maximum_msat, option),
 });
 
 impl_writeable_tlv_based!(PhantomRouteHints, {
@@ -7557,7 +7315,7 @@ mod tests {
                match inbound_payment::verify(bad_payment_hash, payment_data.clone(), nodes[0].node.highest_seen_timestamp.load(Ordering::Acquire) as u64, &nodes[0].node.inbound_payment_key, &nodes[0].logger) {
                        Ok(_) => panic!("Unexpected ok"),
                        Err(()) => {
-                               nodes[0].logger.assert_log_contains("lightning::ln::channelmanager::inbound_payment".to_string(), "Failing HTLC with user-generated payment_hash".to_string(), 1);
+                               nodes[0].logger.assert_log_contains("lightning::ln::inbound_payment".to_string(), "Failing HTLC with user-generated payment_hash".to_string(), 1);
                        }
                }
 
index aa6fdc97b4a897e1034fc3524880c9aa46b1ed44..9bbd6c0e92aad17decad799c6b866d67e3fe1958 100644 (file)
@@ -1171,19 +1171,18 @@ macro_rules! get_payment_preimage_hash {
 #[macro_export]
 macro_rules! get_route_and_payment_hash {
        ($send_node: expr, $recv_node: expr, $recv_value: expr) => {{
-               $crate::get_route_and_payment_hash!($send_node, $recv_node, vec![], $recv_value, TEST_FINAL_CLTV)
+               let payment_params = $crate::routing::router::PaymentParameters::from_node_id($recv_node.node.get_our_node_id())
+                       .with_features($crate::ln::features::InvoiceFeatures::known());
+               $crate::get_route_and_payment_hash!($send_node, $recv_node, payment_params, $recv_value, TEST_FINAL_CLTV)
        }};
-       ($send_node: expr, $recv_node: expr, $last_hops: expr, $recv_value: expr, $cltv: expr) => {{
+       ($send_node: expr, $recv_node: expr, $payment_params: 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.read_only(),
+                       &$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, &random_seed_bytes
                ).unwrap();
@@ -1328,12 +1327,16 @@ macro_rules! expect_payment_path_successful {
 }
 
 macro_rules! expect_payment_forwarded {
-       ($node: expr, $expected_fee: expr, $upstream_force_closed: expr) => {
+       ($node: expr, $source_node: expr, $expected_fee: expr, $upstream_force_closed: expr) => {
                let events = $node.node.get_and_clear_pending_events();
                assert_eq!(events.len(), 1);
                match events[0] {
-                       Event::PaymentForwarded { fee_earned_msat, claim_from_onchain_tx } => {
+                       Event::PaymentForwarded { fee_earned_msat, source_channel_id, claim_from_onchain_tx } => {
                                assert_eq!(fee_earned_msat, $expected_fee);
+                               if fee_earned_msat.is_some() {
+                                       // Is the event channel_id in one of the channels between the two nodes?
+                                       assert!($node.node.list_channels().iter().any(|x| x.counterparty.node_id == $source_node.node.get_our_node_id() && x.channel_id == source_channel_id.unwrap()));
+                               }
                                assert_eq!(claim_from_onchain_tx, $upstream_force_closed);
                        },
                        _ => panic!("Unexpected event"),
@@ -1572,11 +1575,11 @@ pub fn do_claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>,
                        }
                }
                macro_rules! mid_update_fulfill_dance {
-                       ($node: expr, $prev_node: expr, $new_msgs: expr) => {
+                       ($node: expr, $prev_node: expr, $next_node: expr, $new_msgs: expr) => {
                                {
                                        $node.node.handle_update_fulfill_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0);
                                        let fee = $node.node.channel_state.lock().unwrap().by_id.get(&next_msgs.as_ref().unwrap().0.channel_id).unwrap().config.forwarding_fee_base_msat;
-                                       expect_payment_forwarded!($node, Some(fee as u64), false);
+                                       expect_payment_forwarded!($node, $next_node, Some(fee as u64), false);
                                        expected_total_fee_msat += fee as u64;
                                        check_added_monitors!($node, 1);
                                        let new_next_msgs = if $new_msgs {
@@ -1600,7 +1603,14 @@ pub fn do_claim_payment_along_route<'a, 'b, 'c>(origin_node: &Node<'a, 'b, 'c>,
                        assert_eq!(expected_next_node, node.node.get_our_node_id());
                        let update_next_msgs = !skip_last || idx != expected_route.len() - 1;
                        if next_msgs.is_some() {
-                               mid_update_fulfill_dance!(node, prev_node, update_next_msgs);
+                               // Since we are traversing in reverse, next_node is actually the previous node
+                               let next_node: &Node;
+                               if idx == expected_route.len() - 1 {
+                                       next_node = origin_node;
+                               } else {
+                                       next_node = expected_route[expected_route.len() - 1 - idx - 1];
+                               }
+                               mid_update_fulfill_dance!(node, prev_node, next_node, update_next_msgs);
                        } else {
                                assert!(!update_next_msgs);
                                assert!(node.node.get_and_clear_pending_msg_events().is_empty());
index 525b4f33c438f0c01fda291ae90fbdab4f2c7867..d7bebca0e4dff41088c4583632a302f700124314 100644 (file)
@@ -2684,10 +2684,23 @@ fn test_htlc_on_chain_success() {
                Event::ChannelClosed { reason: ClosureReason::CommitmentTxConfirmed, .. } => {}
                _ => panic!("Unexpected event"),
        }
-       if let Event::PaymentForwarded { fee_earned_msat: Some(1000), claim_from_onchain_tx: true } = forwarded_events[1] {
-               } else { panic!(); }
-       if let Event::PaymentForwarded { fee_earned_msat: Some(1000), claim_from_onchain_tx: true } = forwarded_events[2] {
-               } else { panic!(); }
+       let chan_id = Some(chan_1.2);
+       match forwarded_events[1] {
+               Event::PaymentForwarded { fee_earned_msat, source_channel_id, claim_from_onchain_tx } => {
+                       assert_eq!(fee_earned_msat, Some(1000));
+                       assert_eq!(source_channel_id, chan_id);
+                       assert_eq!(claim_from_onchain_tx, true);
+               },
+               _ => panic!()
+       }
+       match forwarded_events[2] {
+               Event::PaymentForwarded { fee_earned_msat, source_channel_id, claim_from_onchain_tx } => {
+                       assert_eq!(fee_earned_msat, Some(1000));
+                       assert_eq!(source_channel_id, chan_id);
+                       assert_eq!(claim_from_onchain_tx, true);
+               },
+               _ => panic!()
+       }
        let events = nodes[1].node.get_and_clear_pending_msg_events();
        {
                let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap();
@@ -5104,8 +5117,9 @@ fn test_onchain_to_onchain_claim() {
                _ => panic!("Unexpected event"),
        }
        match events[1] {
-               Event::PaymentForwarded { fee_earned_msat, claim_from_onchain_tx } => {
+               Event::PaymentForwarded { fee_earned_msat, source_channel_id, claim_from_onchain_tx } => {
                        assert_eq!(fee_earned_msat, Some(1000));
+                       assert_eq!(source_channel_id, Some(chan_1.2));
                        assert_eq!(claim_from_onchain_tx, true);
                },
                _ => panic!("Unexpected event"),
@@ -5188,7 +5202,9 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
        // We reduce the final CLTV here by a somewhat arbitrary constant to keep it under the one-byte
        // script push size limit so that the below script length checks match
        // ACCEPTED_HTLC_SCRIPT_WEIGHT.
-       let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[3], vec![], 900000, TEST_FINAL_CLTV - 40);
+       let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id())
+               .with_features(InvoiceFeatures::known());
+       let (route, _, _, _) = get_route_and_payment_hash!(nodes[0], nodes[3], payment_params, 900000, TEST_FINAL_CLTV - 40);
        send_along_route_with_secret(&nodes[0], route, &[&[&nodes[1], &nodes[2], &nodes[3]]], 900000, duplicate_payment_hash, payment_secret);
 
        let commitment_txn = get_local_commitment_txn!(nodes[2], chan_2.2);
@@ -5271,7 +5287,7 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
        // Note that the fee paid is effectively double as the HTLC value (including the nodes[1] fee
        // and nodes[2] fee) is rounded down and then claimed in full.
        mine_transaction(&nodes[1], &htlc_success_txn[0]);
-       expect_payment_forwarded!(nodes[1], Some(196*2), true);
+       expect_payment_forwarded!(nodes[1], nodes[0], Some(196*2), true);
        let updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        assert!(updates.update_add_htlcs.is_empty());
        assert!(updates.update_fail_htlcs.is_empty());
@@ -6437,7 +6453,9 @@ fn test_update_add_htlc_bolt2_sender_cltv_expiry_too_high() {
        let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs);
        let _chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 0, InitFeatures::known(), InitFeatures::known());
 
-       let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], vec![], 100000000, 0);
+       let payment_params = PaymentParameters::from_node_id(nodes[1].node.get_our_node_id())
+               .with_features(InvoiceFeatures::known());
+       let (mut route, our_payment_hash, _, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[1], payment_params, 100000000, 0);
        route.paths[0].last_mut().unwrap().cltv_expiry_delta = 500000001;
        unwrap_send_err!(nodes[0].node.send_payment(&route, our_payment_hash, &Some(our_payment_secret)), true, APIError::RouteError { ref err },
                assert_eq!(err, &"Channel CLTV overflowed?"));
@@ -7537,7 +7555,9 @@ fn test_bump_penalty_txn_on_revoked_commitment() {
        let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1000000, 59000000, InitFeatures::known(), InitFeatures::known());
 
        let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
-       let (route,_, _, _) = get_route_and_payment_hash!(nodes[1], nodes[0], vec![], 3000000, 30);
+       let payment_params = PaymentParameters::from_node_id(nodes[0].node.get_our_node_id())
+               .with_features(InvoiceFeatures::known());
+       let (route,_, _, _) = get_route_and_payment_hash!(nodes[1], nodes[0], payment_params, 3000000, 30);
        send_along_route(&nodes[1], route, &vec!(&nodes[0])[..], 3000000);
 
        let revoked_txn = get_local_commitment_txn!(nodes[0], chan.2);
@@ -8849,7 +8869,7 @@ fn do_test_onchain_htlc_settlement_after_close(broadcast_alice: bool, go_onchain
        assert_eq!(carol_updates.update_fulfill_htlcs.len(), 1);
 
        nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &carol_updates.update_fulfill_htlcs[0]);
-       expect_payment_forwarded!(nodes[1], if go_onchain_before_fulfill || force_closing_node == 1 { None } else { Some(1000) }, false);
+       expect_payment_forwarded!(nodes[1], nodes[0], if go_onchain_before_fulfill || force_closing_node == 1 { None } else { Some(1000) }, false);
        // If Alice broadcasted but Bob doesn't know yet, here he prepares to tell her about the preimage.
        if !go_onchain_before_fulfill && broadcast_alice {
                let events = nodes[1].node.get_and_clear_pending_msg_events();
diff --git a/lightning/src/ln/inbound_payment.rs b/lightning/src/ln/inbound_payment.rs
new file mode 100644 (file)
index 0000000..8ed77e5
--- /dev/null
@@ -0,0 +1,299 @@
+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Utilities to generate inbound payment information in service of invoice creation.
+
+use alloc::string::ToString;
+use bitcoin::hashes::{Hash, HashEngine};
+use bitcoin::hashes::cmp::fixed_time_eq;
+use bitcoin::hashes::hmac::{Hmac, HmacEngine};
+use bitcoin::hashes::sha256::Hash as Sha256;
+use chain::keysinterface::{KeyMaterial, KeysInterface, Sign};
+use ln::{PaymentHash, PaymentPreimage, PaymentSecret};
+use ln::msgs;
+use ln::msgs::MAX_VALUE_MSAT;
+use util::chacha20::ChaCha20;
+use util::crypto::hkdf_extract_expand_thrice;
+use util::errors::APIError;
+use util::logger::Logger;
+
+use core::convert::TryInto;
+use core::ops::Deref;
+
+const IV_LEN: usize = 16;
+const METADATA_LEN: usize = 16;
+const METADATA_KEY_LEN: usize = 32;
+const AMT_MSAT_LEN: usize = 8;
+// Used to shift the payment type bits to take up the top 3 bits of the metadata bytes, or to
+// retrieve said payment type bits.
+const METHOD_TYPE_OFFSET: usize = 5;
+
+/// A set of keys that were HKDF-expanded from an initial call to
+/// [`KeysInterface::get_inbound_payment_key_material`].
+///
+/// [`KeysInterface::get_inbound_payment_key_material`]: crate::chain::keysinterface::KeysInterface::get_inbound_payment_key_material
+pub struct ExpandedKey {
+       /// The key used to encrypt the bytes containing the payment metadata (i.e. the amount and
+       /// expiry, included for payment verification on decryption).
+       metadata_key: [u8; 32],
+       /// The key used to authenticate an LDK-provided payment hash and metadata as previously
+       /// registered with LDK.
+       ldk_pmt_hash_key: [u8; 32],
+       /// The key used to authenticate a user-provided payment hash and metadata as previously
+       /// registered with LDK.
+       user_pmt_hash_key: [u8; 32],
+}
+
+impl ExpandedKey {
+       /// Create a  new [`ExpandedKey`] for generating an inbound payment hash and secret.
+       ///
+       /// It is recommended to cache this value and not regenerate it for each new inbound payment.
+       pub fn new(key_material: &KeyMaterial) -> ExpandedKey {
+               let (metadata_key, ldk_pmt_hash_key, user_pmt_hash_key) =
+                       hkdf_extract_expand_thrice(b"LDK Inbound Payment Key Expansion", &key_material.0);
+               Self {
+                       metadata_key,
+                       ldk_pmt_hash_key,
+                       user_pmt_hash_key,
+               }
+       }
+}
+
+enum Method {
+       LdkPaymentHash = 0,
+       UserPaymentHash = 1,
+}
+
+impl Method {
+       fn from_bits(bits: u8) -> Result<Method, u8> {
+               match bits {
+                       bits if bits == Method::LdkPaymentHash as u8 => Ok(Method::LdkPaymentHash),
+                       bits if bits == Method::UserPaymentHash as u8 => Ok(Method::UserPaymentHash),
+                       unknown => Err(unknown),
+               }
+       }
+}
+
+/// Equivalent to [`crate::ln::channelmanager::ChannelManager::create_inbound_payment`], but no
+/// `ChannelManager` is required. Useful for generating invoices for [phantom node payments] without
+/// a `ChannelManager`.
+///
+/// `keys` is generated by calling [`KeysInterface::get_inbound_payment_key_material`] and then
+/// calling [`ExpandedKey::new`] with its result. It is recommended to cache this value and not
+/// regenerate it for each new inbound payment.
+///
+/// `current_time` is a Unix timestamp representing the current time.
+///
+/// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
+pub fn create<Signer: Sign, K: Deref>(keys: &ExpandedKey, min_value_msat: Option<u64>, invoice_expiry_delta_secs: u32, keys_manager: &K, current_time: u64) -> Result<(PaymentHash, PaymentSecret), ()>
+       where K::Target: KeysInterface<Signer = Signer>
+{
+       let metadata_bytes = construct_metadata_bytes(min_value_msat, Method::LdkPaymentHash, invoice_expiry_delta_secs, current_time)?;
+
+       let mut iv_bytes = [0 as u8; IV_LEN];
+       let rand_bytes = keys_manager.get_secure_random_bytes();
+       iv_bytes.copy_from_slice(&rand_bytes[..IV_LEN]);
+
+       let mut hmac = HmacEngine::<Sha256>::new(&keys.ldk_pmt_hash_key);
+       hmac.input(&iv_bytes);
+       hmac.input(&metadata_bytes);
+       let payment_preimage_bytes = Hmac::from_engine(hmac).into_inner();
+
+       let ldk_pmt_hash = PaymentHash(Sha256::hash(&payment_preimage_bytes).into_inner());
+       let payment_secret = construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key);
+       Ok((ldk_pmt_hash, payment_secret))
+}
+
+/// Equivalent to [`crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash`],
+/// but no `ChannelManager` is required. Useful for generating invoices for [phantom node payments]
+/// without a `ChannelManager`.
+///
+/// See [`create`] for information on the `keys` and `current_time` parameters.
+///
+/// [phantom node payments]: crate::chain::keysinterface::PhantomKeysManager
+pub fn create_from_hash(keys: &ExpandedKey, min_value_msat: Option<u64>, payment_hash: PaymentHash, invoice_expiry_delta_secs: u32, current_time: u64) -> Result<PaymentSecret, ()> {
+       let metadata_bytes = construct_metadata_bytes(min_value_msat, Method::UserPaymentHash, invoice_expiry_delta_secs, current_time)?;
+
+       let mut hmac = HmacEngine::<Sha256>::new(&keys.user_pmt_hash_key);
+       hmac.input(&metadata_bytes);
+       hmac.input(&payment_hash.0);
+       let hmac_bytes = Hmac::from_engine(hmac).into_inner();
+
+       let mut iv_bytes = [0 as u8; IV_LEN];
+       iv_bytes.copy_from_slice(&hmac_bytes[..IV_LEN]);
+
+       Ok(construct_payment_secret(&iv_bytes, &metadata_bytes, &keys.metadata_key))
+}
+
+fn construct_metadata_bytes(min_value_msat: Option<u64>, payment_type: Method, invoice_expiry_delta_secs: u32, highest_seen_timestamp: u64) -> Result<[u8; METADATA_LEN], ()> {
+       if min_value_msat.is_some() && min_value_msat.unwrap() > MAX_VALUE_MSAT {
+               return Err(());
+       }
+
+       let mut min_amt_msat_bytes: [u8; AMT_MSAT_LEN] = match min_value_msat {
+               Some(amt) => amt.to_be_bytes(),
+               None => [0; AMT_MSAT_LEN],
+       };
+       min_amt_msat_bytes[0] |= (payment_type as u8) << METHOD_TYPE_OFFSET;
+
+       // We assume that highest_seen_timestamp is pretty close to the current time - it's updated when
+       // we receive a new block with the maximum time we've seen in a header. It should never be more
+       // than two hours in the future.  Thus, we add two hours here as a buffer to ensure we
+       // absolutely never fail a payment too early.
+       // Note that we assume that received blocks have reasonably up-to-date timestamps.
+       let expiry_bytes = (highest_seen_timestamp + invoice_expiry_delta_secs as u64 + 7200).to_be_bytes();
+
+       let mut metadata_bytes: [u8; METADATA_LEN] = [0; METADATA_LEN];
+       metadata_bytes[..AMT_MSAT_LEN].copy_from_slice(&min_amt_msat_bytes);
+       metadata_bytes[AMT_MSAT_LEN..].copy_from_slice(&expiry_bytes);
+
+       Ok(metadata_bytes)
+}
+
+fn construct_payment_secret(iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METADATA_LEN], metadata_key: &[u8; METADATA_KEY_LEN]) -> PaymentSecret {
+       let mut payment_secret_bytes: [u8; 32] = [0; 32];
+       let (iv_slice, encrypted_metadata_slice) = payment_secret_bytes.split_at_mut(IV_LEN);
+       iv_slice.copy_from_slice(iv_bytes);
+
+       let chacha_block = ChaCha20::get_single_block(metadata_key, iv_bytes);
+       for i in 0..METADATA_LEN {
+               encrypted_metadata_slice[i] = chacha_block[i] ^ metadata_bytes[i];
+       }
+       PaymentSecret(payment_secret_bytes)
+}
+
+/// Check that an inbound payment's `payment_data` field is sane.
+///
+/// LDK does not store any data for pending inbound payments. Instead, we construct our payment
+/// secret (and, if supplied by LDK, our payment preimage) to include encrypted metadata about the
+/// payment.
+///
+/// The metadata is constructed as:
+///   payment method (3 bits) || payment amount (8 bytes - 3 bits) || expiry (8 bytes)
+/// and encrypted using a key derived from [`KeysInterface::get_inbound_payment_key_material`].
+///
+/// Then on payment receipt, we verify in this method that the payment preimage and payment secret
+/// match what was constructed.
+///
+/// [`create_inbound_payment`] and [`create_inbound_payment_for_hash`] are called by the user to
+/// construct the payment secret and/or payment hash that this method is verifying. If the former
+/// method is called, then the payment method bits mentioned above are represented internally as
+/// [`Method::LdkPaymentHash`]. If the latter, [`Method::UserPaymentHash`].
+///
+/// For the former method, the payment preimage is constructed as an HMAC of payment metadata and
+/// random bytes. Because the payment secret is also encoded with these random bytes and metadata
+/// (with the metadata encrypted with a block cipher), we're able to authenticate the preimage on
+/// payment receipt.
+///
+/// For the latter, the payment secret instead contains an HMAC of the user-provided payment hash
+/// and payment metadata (encrypted with a block cipher), allowing us to authenticate the payment
+/// hash and metadata on payment receipt.
+///
+/// See [`ExpandedKey`] docs for more info on the individual keys used.
+///
+/// [`KeysInterface::get_inbound_payment_key_material`]: crate::chain::keysinterface::KeysInterface::get_inbound_payment_key_material
+/// [`create_inbound_payment`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment
+/// [`create_inbound_payment_for_hash`]: crate::ln::channelmanager::ChannelManager::create_inbound_payment_for_hash
+pub(super) fn verify<L: Deref>(payment_hash: PaymentHash, payment_data: msgs::FinalOnionHopData, highest_seen_timestamp: u64, keys: &ExpandedKey, logger: &L) -> Result<Option<PaymentPreimage>, ()>
+       where L::Target: Logger
+{
+       let (iv_bytes, metadata_bytes) = decrypt_metadata(payment_data.payment_secret, keys);
+
+       let payment_type_res = Method::from_bits((metadata_bytes[0] & 0b1110_0000) >> METHOD_TYPE_OFFSET);
+       let mut amt_msat_bytes = [0; AMT_MSAT_LEN];
+       amt_msat_bytes.copy_from_slice(&metadata_bytes[..AMT_MSAT_LEN]);
+       // Zero out the bits reserved to indicate the payment type.
+       amt_msat_bytes[0] &= 0b00011111;
+       let min_amt_msat: u64 = u64::from_be_bytes(amt_msat_bytes.into());
+       let expiry = u64::from_be_bytes(metadata_bytes[AMT_MSAT_LEN..].try_into().unwrap());
+
+       // Make sure to check to check the HMAC before doing the other checks below, to mitigate timing
+       // attacks.
+       let mut payment_preimage = None;
+       match payment_type_res {
+               Ok(Method::UserPaymentHash) => {
+                       let mut hmac = HmacEngine::<Sha256>::new(&keys.user_pmt_hash_key);
+                       hmac.input(&metadata_bytes[..]);
+                       hmac.input(&payment_hash.0);
+                       if !fixed_time_eq(&iv_bytes, &Hmac::from_engine(hmac).into_inner().split_at_mut(IV_LEN).0) {
+                               log_trace!(logger, "Failing HTLC with user-generated payment_hash {}: unexpected payment_secret", log_bytes!(payment_hash.0));
+                               return Err(())
+                       }
+               },
+               Ok(Method::LdkPaymentHash) => {
+                       match derive_ldk_payment_preimage(payment_hash, &iv_bytes, &metadata_bytes, keys) {
+                               Ok(preimage) => payment_preimage = Some(preimage),
+                               Err(bad_preimage_bytes) => {
+                                       log_trace!(logger, "Failing HTLC with payment_hash {} due to mismatching preimage {}", log_bytes!(payment_hash.0), log_bytes!(bad_preimage_bytes));
+                                       return Err(())
+                               }
+                       }
+               },
+               Err(unknown_bits) => {
+                       log_trace!(logger, "Failing HTLC with payment hash {} due to unknown payment type {}", log_bytes!(payment_hash.0), unknown_bits);
+                       return Err(());
+               }
+       }
+
+       if payment_data.total_msat < min_amt_msat {
+               log_trace!(logger, "Failing HTLC with payment_hash {} due to total_msat {} being less than the minimum amount of {} msat", log_bytes!(payment_hash.0), payment_data.total_msat, min_amt_msat);
+               return Err(())
+       }
+
+       if expiry < highest_seen_timestamp {
+               log_trace!(logger, "Failing HTLC with payment_hash {}: expired payment", log_bytes!(payment_hash.0));
+               return Err(())
+       }
+
+       Ok(payment_preimage)
+}
+
+pub(super) fn get_payment_preimage(payment_hash: PaymentHash, payment_secret: PaymentSecret, keys: &ExpandedKey) -> Result<PaymentPreimage, APIError> {
+       let (iv_bytes, metadata_bytes) = decrypt_metadata(payment_secret, keys);
+
+       match Method::from_bits((metadata_bytes[0] & 0b1110_0000) >> METHOD_TYPE_OFFSET) {
+               Ok(Method::LdkPaymentHash) => {
+                       derive_ldk_payment_preimage(payment_hash, &iv_bytes, &metadata_bytes, keys)
+                               .map_err(|bad_preimage_bytes| APIError::APIMisuseError {
+                                       err: format!("Payment hash {} did not match decoded preimage {}", log_bytes!(payment_hash.0), log_bytes!(bad_preimage_bytes))
+                               })
+               },
+               Ok(Method::UserPaymentHash) => Err(APIError::APIMisuseError {
+                       err: "Expected payment type to be LdkPaymentHash, instead got UserPaymentHash".to_string()
+               }),
+               Err(other) => Err(APIError::APIMisuseError { err: format!("Unknown payment type: {}", other) }),
+       }
+}
+
+fn decrypt_metadata(payment_secret: PaymentSecret, keys: &ExpandedKey) -> ([u8; IV_LEN], [u8; METADATA_LEN]) {
+       let mut iv_bytes = [0; IV_LEN];
+       let (iv_slice, encrypted_metadata_bytes) = payment_secret.0.split_at(IV_LEN);
+       iv_bytes.copy_from_slice(iv_slice);
+
+       let chacha_block = ChaCha20::get_single_block(&keys.metadata_key, &iv_bytes);
+       let mut metadata_bytes: [u8; METADATA_LEN] = [0; METADATA_LEN];
+       for i in 0..METADATA_LEN {
+               metadata_bytes[i] = chacha_block[i] ^ encrypted_metadata_bytes[i];
+       }
+
+       (iv_bytes, metadata_bytes)
+}
+
+// Errors if the payment preimage doesn't match `payment_hash`. Returns the bad preimage bytes in
+// this case.
+fn derive_ldk_payment_preimage(payment_hash: PaymentHash, iv_bytes: &[u8; IV_LEN], metadata_bytes: &[u8; METADATA_LEN], keys: &ExpandedKey) -> Result<PaymentPreimage, [u8; 32]> {
+       let mut hmac = HmacEngine::<Sha256>::new(&keys.ldk_pmt_hash_key);
+       hmac.input(iv_bytes);
+       hmac.input(metadata_bytes);
+       let decoded_payment_preimage = Hmac::from_engine(hmac).into_inner();
+       if !fixed_time_eq(&payment_hash.0, &Sha256::hash(&decoded_payment_preimage).into_inner()) {
+               return Err(decoded_payment_preimage);
+       }
+       return Ok(PaymentPreimage(decoded_payment_preimage))
+}
index 444c9685fdda6979708fdee6eb26797b0ddfe040..1e5f49f07df6a0cc5056e6ea26545cfac33d04ec 100644 (file)
@@ -23,6 +23,7 @@
 pub mod functional_test_utils;
 
 pub mod channelmanager;
+pub mod inbound_payment;
 pub mod msgs;
 pub mod peer_handler;
 pub mod chan_utils;
index 706fcb6c24d2057857992758a4750ac36bb70499..834791cba958de960d0c5f90868173f5097f0705 100644 (file)
@@ -16,9 +16,9 @@ use chain::keysinterface::{KeysInterface, Recipient};
 use ln::{PaymentHash, PaymentSecret};
 use ln::channelmanager::{HTLCForwardInfo, CLTV_FAR_FAR_AWAY, MIN_CLTV_EXPIRY_DELTA, PendingHTLCInfo, PendingHTLCRouting};
 use ln::onion_utils;
-use routing::network_graph::{NetworkUpdate, RoutingFees};
+use routing::network_graph::{NetworkUpdate, RoutingFees, NodeId};
 use routing::router::{get_route, PaymentParameters, Route, RouteHint, RouteHintHop};
-use ln::features::{InitFeatures, InvoiceFeatures};
+use ln::features::{InitFeatures, InvoiceFeatures, NodeFeatures};
 use ln::msgs;
 use ln::msgs::{ChannelMessageHandler, ChannelUpdate, OptionalField};
 use util::events::{Event, MessageSendEvent, MessageSendEventsProvider};
@@ -577,6 +577,168 @@ fn test_onion_failure() {
        }, true, Some(23), None, None);
 }
 
+#[test]
+fn test_default_to_onion_payload_tlv_format() {
+       // Tests that we default to creating tlv format onion payloads when no `NodeAnnouncementInfo`
+       // `features` for a node in the `network_graph` exists, or when the node isn't in the
+       // `network_graph`, and no other known `features` for the node exists.
+       let mut priv_channels_conf = UserConfig::default();
+       priv_channels_conf.channel_options.announced_channel = false;
+       let chanmon_cfgs = create_chanmon_cfgs(5);
+       let node_cfgs = create_node_cfgs(5, &chanmon_cfgs);
+       let node_chanmgrs = create_node_chanmgrs(5, &node_cfgs, &[None, None, None, None, Some(priv_channels_conf)]);
+       let mut nodes = create_network(5, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+       create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+       create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
+       create_unannounced_chan_between_nodes_with_value(&nodes, 3, 4, 100000, 10001, InitFeatures::known(), InitFeatures::known());
+
+       let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id());
+       let origin_node = &nodes[0];
+       let network_graph = origin_node.network_graph;
+
+       // Clears all the `NodeAnnouncementInfo` for all nodes of `nodes[0]`'s `network_graph`, so that
+       // their `features` aren't used when creating the `route`.
+       network_graph.clear_nodes_announcement_info();
+
+       let (announced_route, _, _, _) = get_route_and_payment_hash!(
+               origin_node, nodes[3], payment_params, 10_000, TEST_FINAL_CLTV);
+
+       let hops = &announced_route.paths[0];
+       // Assert that the hop between `nodes[1]` and `nodes[2]` defaults to supporting variable length
+       // onions, as `nodes[0]` has no `NodeAnnouncementInfo` `features` for `node[2]`
+       assert!(hops[1].node_features.supports_variable_length_onion());
+       // Assert that the hop between `nodes[2]` and `nodes[3]` defaults to supporting variable length
+       // onions, as `nodes[0]` has no `NodeAnnouncementInfo` `features` for `node[3]`, and no `InvoiceFeatures`
+       // for the `payment_params`, which would otherwise have been used.
+       assert!(hops[2].node_features.supports_variable_length_onion());
+       // Note that we do not assert that `hops[0]` (the channel between `nodes[0]` and `nodes[1]`)
+       // supports variable length onions, as the `InitFeatures` exchanged in the init message
+       // between the nodes will be used when creating the route. We therefore do not default to
+       // supporting variable length onions for that hop, as the `InitFeatures` in this case are
+       // `InitFeatures::known()`.
+
+       let unannounced_chan = &nodes[4].node.list_usable_channels()[0];
+
+       let last_hop = RouteHint(vec![RouteHintHop {
+               src_node_id: nodes[3].node.get_our_node_id(),
+               short_channel_id: unannounced_chan.short_channel_id.unwrap(),
+               fees: RoutingFees {
+                       base_msat: 0,
+                       proportional_millionths: 0,
+               },
+               cltv_expiry_delta: 42,
+               htlc_minimum_msat: None,
+               htlc_maximum_msat: None,
+       }]);
+
+       let unannounced_chan_params = PaymentParameters::from_node_id(nodes[4].node.get_our_node_id()).with_route_hints(vec![last_hop]);
+       let (unannounced_route, _, _, _) = get_route_and_payment_hash!(
+               origin_node, nodes[4], unannounced_chan_params, 10_000, TEST_FINAL_CLTV);
+
+       let unannounced_chan_hop = &unannounced_route.paths[0][3];
+       // Ensure that `nodes[4]` doesn't exist in `nodes[0]`'s `network_graph`, as it's not public.
+       assert!(&network_graph.read_only().nodes().get(&NodeId::from_pubkey(&nodes[4].node.get_our_node_id())).is_none());
+       // Assert that the hop between `nodes[3]` and `nodes[4]` defaults to supporting variable length
+       // onions, even though `nodes[4]` as `nodes[0]` doesn't exists in `nodes[0]`'s `network_graph`,
+       // and no `InvoiceFeatures` for the `payment_params` exists, which would otherwise have been
+       // used.
+       assert!(unannounced_chan_hop.node_features.supports_variable_length_onion());
+
+       let cur_height = nodes[0].best_block_info().1 + 1;
+       let (announced_route_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&announced_route.paths[0], 40000, &None, cur_height, &None).unwrap();
+       let (unannounced_route_paylods, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&unannounced_route.paths[0], 40000, &None, cur_height, &None).unwrap();
+
+       for onion_payloads in vec![announced_route_payloads, unannounced_route_paylods] {
+               for onion_payload in onion_payloads.iter() {
+                       match onion_payload.format {
+                               msgs::OnionHopDataFormat::Legacy {..} => {
+                                       panic!("Generated a `msgs::OnionHopDataFormat::Legacy` payload, even though that shouldn't have happend.");
+                               }
+                               _ => {}
+                       }
+               }
+       }
+}
+
+#[test]
+fn test_do_not_default_to_onion_payload_tlv_format_when_unsupported() {
+       // Tests that we do not default to creating tlv onions if either of these types features
+       // exists, which specifies no support for variable length onions for a specific hop, when
+       // creating a route:
+       // 1. `InitFeatures` to the counterparty node exchanged with the init message to the node.
+       // 2. `NodeFeatures` in the `NodeAnnouncementInfo` of a node in sender node's `network_graph`.
+       // 3. `InvoiceFeatures` specified by the receiving node, when no `NodeAnnouncementInfo`
+       // `features` exists for the receiver in the sender's `network_graph`.
+       let chanmon_cfgs = create_chanmon_cfgs(4);
+       let mut node_cfgs = create_node_cfgs(4, &chanmon_cfgs);
+
+       // Set `node[1]` config to `InitFeatures::empty()` which return `false` for
+       // `supports_variable_length_onion()`
+       let mut node_1_cfg = &mut node_cfgs[1];
+       node_1_cfg.features = InitFeatures::empty();
+
+       let node_chanmgrs = create_node_chanmgrs(4, &node_cfgs, &[None, None, None, None]);
+       let mut nodes = create_network(4, &node_cfgs, &node_chanmgrs);
+
+       create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known());
+       create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::known(), InitFeatures::known());
+       create_announced_chan_between_nodes(&nodes, 2, 3, InitFeatures::known(), InitFeatures::known());
+
+       let payment_params = PaymentParameters::from_node_id(nodes[3].node.get_our_node_id())
+               .with_features(InvoiceFeatures::empty());
+       let origin_node = &nodes[0];
+       let network_graph = origin_node.network_graph;
+       network_graph.clear_nodes_announcement_info();
+
+       // Set `NodeAnnouncementInfo` `features` which do not support variable length onions for
+       // `nodes[2]` in `nodes[0]`'s `network_graph`.
+       let nodes_2_unsigned_node_announcement = msgs::UnsignedNodeAnnouncement {
+               features: NodeFeatures::empty(),
+               timestamp: 0,
+               node_id: nodes[2].node.get_our_node_id(),
+               rgb: [32; 3],
+               alias: [16;32],
+               addresses: Vec::new(),
+               excess_address_data: Vec::new(),
+               excess_data: Vec::new(),
+       };
+       let _res = network_graph.update_node_from_unsigned_announcement(&nodes_2_unsigned_node_announcement);
+
+       let (route, _, _, _) = get_route_and_payment_hash!(
+               origin_node, nodes[3], payment_params, 10_000, TEST_FINAL_CLTV);
+
+       let hops = &route.paths[0];
+
+       // Assert that the hop between `nodes[0]` and `nodes[1]` doesn't support variable length
+       // onions, as as the `InitFeatures` exchanged (`InitFeatures::empty()`) in the init message
+       // between the nodes when setting up the channel is used when creating the `route` and that we
+       // therefore do not default to supporting variable length onions. Despite `nodes[0]` having no
+       // `NodeAnnouncementInfo` `features` for `node[1]`.
+       assert!(!hops[0].node_features.supports_variable_length_onion());
+       // Assert that the hop between `nodes[1]` and `nodes[2]` uses the `features` from
+       // `nodes_2_unsigned_node_announcement` that doesn't support variable length onions.
+       assert!(!hops[1].node_features.supports_variable_length_onion());
+       // Assert that the hop between `nodes[2]` and `nodes[3]` uses the `InvoiceFeatures` set to the
+       // `payment_params`, that doesn't support variable length onions. We therefore do not end up
+       // defaulting to supporting variable length onions, despite `nodes[0]` having no
+       // `NodeAnnouncementInfo` `features` for `node[3]`.
+       assert!(!hops[2].node_features.supports_variable_length_onion());
+
+       let cur_height = nodes[0].best_block_info().1 + 1;
+       let (onion_payloads, _htlc_msat, _htlc_cltv) = onion_utils::build_onion_payloads(&route.paths[0], 40000, &None, cur_height, &None).unwrap();
+
+       for onion_payload in onion_payloads.iter() {
+               match onion_payload.format {
+                       msgs::OnionHopDataFormat::Legacy {..} => {}
+                       _ => {
+                               panic!("Should have only have generated `msgs::OnionHopDataFormat::Legacy` payloads");
+                       }
+               }
+       }
+}
+
 macro_rules! get_phantom_route {
        ($nodes: expr, $amt: expr, $channel: expr) => {{
                let secp_ctx = Secp256k1::new();
index 346fb98b41eda3d895f9887575764db0ecc44503..46d5d22b49a07112f680086c3e701d902088fcd1 100644 (file)
@@ -495,7 +495,7 @@ fn do_retry_with_no_persist(confirm_before_reload: bool) {
        let bs_htlc_claim_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0);
        assert_eq!(bs_htlc_claim_txn.len(), 1);
        check_spends!(bs_htlc_claim_txn[0], as_commitment_tx);
-       expect_payment_forwarded!(nodes[1], None, false);
+       expect_payment_forwarded!(nodes[1], nodes[0], None, false);
 
        if !confirm_before_reload {
                mine_transaction(&nodes[0], &as_commitment_tx);
index d3d54467a2f421551d381be64e56d76c00f639cd..fa44a0655c1462cdf321fede0aeb0de83141626b 100644 (file)
@@ -16,8 +16,8 @@ use chain::channelmonitor::ChannelMonitor;
 use chain::keysinterface::{Recipient, KeysInterface};
 use ln::channelmanager::{ChannelManager, ChannelManagerReadArgs, MIN_CLTV_EXPIRY_DELTA};
 use routing::network_graph::RoutingFees;
-use routing::router::{RouteHint, RouteHintHop};
-use ln::features::InitFeatures;
+use routing::router::{PaymentParameters, RouteHint, RouteHintHop};
+use ln::features::{InitFeatures, InvoiceFeatures};
 use ln::msgs;
 use ln::msgs::{ChannelMessageHandler, RoutingMessageHandler, OptionalField};
 use util::enforcing_trait_impls::EnforcingSigner;
@@ -71,7 +71,10 @@ fn test_priv_forwarding_rejection() {
                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);
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+               .with_features(InvoiceFeatures::known())
+               .with_route_hints(last_hops);
+       let (route, our_payment_hash, our_payment_preimage, our_payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 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);
@@ -269,7 +272,10 @@ fn test_routed_scid_alias() {
                htlc_maximum_msat: None,
                htlc_minimum_msat: None,
        }])];
-       let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], hop_hints, 100_000, 42);
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+               .with_features(InvoiceFeatures::known())
+               .with_route_hints(hop_hints);
+       let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000, 42);
        assert_eq!(route.paths[0][1].short_channel_id, last_hop[0].inbound_scid_alias.unwrap());
        nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
        check_added_monitors!(nodes[0], 1);
@@ -419,7 +425,10 @@ fn test_inbound_scid_privacy() {
                htlc_maximum_msat: None,
                htlc_minimum_msat: None,
        }])];
-       let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], hop_hints.clone(), 100_000, 42);
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+               .with_features(InvoiceFeatures::known())
+               .with_route_hints(hop_hints.clone());
+       let (route, payment_hash, payment_preimage, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 100_000, 42);
        assert_eq!(route.paths[0][1].short_channel_id, last_hop[0].inbound_scid_alias.unwrap());
        nodes[0].node.send_payment(&route, payment_hash, &Some(payment_secret)).unwrap();
        check_added_monitors!(nodes[0], 1);
@@ -431,7 +440,10 @@ fn test_inbound_scid_privacy() {
        // what channel we're talking about.
        hop_hints[0].0[0].short_channel_id = last_hop[0].short_channel_id.unwrap();
 
-       let (route_2, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[2], hop_hints, 100_000, 42);
+       let payment_params_2 = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+               .with_features(InvoiceFeatures::known())
+               .with_route_hints(hop_hints);
+       let (route_2, payment_hash_2, _, payment_secret_2) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params_2, 100_000, 42);
        assert_eq!(route_2.paths[0][1].short_channel_id, last_hop[0].short_channel_id.unwrap());
        nodes[0].node.send_payment(&route_2, payment_hash_2, &Some(payment_secret_2)).unwrap();
        check_added_monitors!(nodes[0], 1);
@@ -479,7 +491,10 @@ fn test_scid_alias_returned() {
                htlc_maximum_msat: None,
                htlc_minimum_msat: None,
        }])];
-       let (mut route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], hop_hints, 10_000, 42);
+       let payment_params = PaymentParameters::from_node_id(nodes[2].node.get_our_node_id())
+               .with_features(InvoiceFeatures::known())
+               .with_route_hints(hop_hints);
+       let (mut route, payment_hash, _, payment_secret) = get_route_and_payment_hash!(nodes[0], nodes[2], payment_params, 10_000, 42);
        assert_eq!(route.paths[0][1].short_channel_id, nodes[2].node.list_usable_channels()[0].inbound_scid_alias.unwrap());
 
        route.paths[0][1].fee_msat = 10_000_000; // Overshoot the last channel's value
index 8eb39cfe92a98cacc6ab0bd854d85334a8ded939..7b36ae0fc4a9d2af97badcbb0c503a1262fdf64d 100644 (file)
@@ -138,7 +138,7 @@ fn do_test_onchain_htlc_reorg(local_commitment: bool, claim: bool) {
                // ChannelManager only polls chain::Watch::release_pending_monitor_events when we
                // probe it for events, so we probe non-message events here (which should just be the
                // PaymentForwarded event).
-               expect_payment_forwarded!(nodes[1], Some(1000), true);
+               expect_payment_forwarded!(nodes[1], nodes[0], Some(1000), true);
        } else {
                // Confirm the timeout tx and check that we fail the HTLC backwards
                let block = Block {
index 557aff84c0dad7c6d595e4a6da6f1bcf24d6fced..42c0e3b2f328cc1545edfdf3287dddab9e766ffe 100644 (file)
@@ -110,7 +110,7 @@ fn updates_shutdown_wait() {
        assert!(updates.update_fee.is_none());
        assert_eq!(updates.update_fulfill_htlcs.len(), 1);
        nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
-       expect_payment_forwarded!(nodes[1], Some(1000), false);
+       expect_payment_forwarded!(nodes[1], nodes[0], Some(1000), false);
        check_added_monitors!(nodes[1], 1);
        let updates_2 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
@@ -279,7 +279,7 @@ fn do_test_shutdown_rebroadcast(recv_count: u8) {
        assert!(updates.update_fee.is_none());
        assert_eq!(updates.update_fulfill_htlcs.len(), 1);
        nodes[1].node.handle_update_fulfill_htlc(&nodes[2].node.get_our_node_id(), &updates.update_fulfill_htlcs[0]);
-       expect_payment_forwarded!(nodes[1], Some(1000), false);
+       expect_payment_forwarded!(nodes[1], nodes[0], Some(1000), false);
        check_added_monitors!(nodes[1], 1);
        let updates_2 = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id());
        commitment_signed_dance!(nodes[1], nodes[2], updates.commitment_signed, false);
index 282c87051dd48f2c3b3a82db778cc20a78f7e2c5..39c2894b32c429b5115f4eee66c427bed21989b1 100644 (file)
@@ -1033,6 +1033,15 @@ impl NetworkGraph {
                }
        }
 
+       /// Clears the `NodeAnnouncementInfo` field for all nodes in the `NetworkGraph` for testing
+       /// purposes.
+       #[cfg(test)]
+       pub fn clear_nodes_announcement_info(&self) {
+               for node in self.nodes.write().unwrap().iter_mut() {
+                       node.1.announcement_info = None;
+               }
+       }
+
        /// For an already known node (from channel announcements), update its stored properties from a
        /// given node announcement.
        ///
index 6584eb5fb55472aad318e4449cd965a6434ebda4..212ac2f10cae7d62695f032c6fd8ab0a4e523ffa 100644 (file)
@@ -602,6 +602,17 @@ fn compute_fees(amount_msat: u64, channel_fees: RoutingFees) -> Option<u64> {
        }
 }
 
+/// The default `features` we assume for a node in a route, when no `features` are known about that
+/// specific node.
+///
+/// Default features are:
+/// * variable_length_onion_optional
+fn default_node_features() -> NodeFeatures {
+       let mut features = NodeFeatures::empty();
+       features.set_variable_length_onion_optional();
+       features
+}
+
 /// Finds a route from us (payer) to the given target node (payee).
 ///
 /// If the payee provided features in their invoice, they should be provided via `params.payee`.
@@ -1101,7 +1112,8 @@ where L::Target: Logger {
                } }
        }
 
-       let empty_node_features = NodeFeatures::empty();
+       let default_node_features = default_node_features();
+
        // Find ways (channels with destination) to reach a given node and store them
        // in the corresponding data structures (routing graph etc).
        // $fee_to_target_msat represents how much it costs to reach to this node from the payee,
@@ -1132,7 +1144,7 @@ where L::Target: Logger {
                                let features = if let Some(node_info) = $node.announcement_info.as_ref() {
                                        &node_info.features
                                } else {
-                                       &empty_node_features
+                                       &default_node_features
                                };
 
                                if !features.requires_unknown_bits() {
@@ -1312,7 +1324,7 @@ where L::Target: Logger {
                        // traversing the graph and arrange the path out of what we found.
                        if node_id == our_node_id {
                                let mut new_entry = dist.remove(&our_node_id).unwrap();
-                               let mut ordered_hops = vec!((new_entry.clone(), NodeFeatures::empty()));
+                               let mut ordered_hops = vec!((new_entry.clone(), default_node_features.clone()));
 
                                'path_walk: loop {
                                        let mut features_set = false;
@@ -1330,7 +1342,7 @@ where L::Target: Logger {
                                                        if let Some(node_info) = node.announcement_info.as_ref() {
                                                                ordered_hops.last_mut().unwrap().1 = node_info.features.clone();
                                                        } else {
-                                                               ordered_hops.last_mut().unwrap().1 = NodeFeatures::empty();
+                                                               ordered_hops.last_mut().unwrap().1 = default_node_features.clone();
                                                        }
                                                } else {
                                                        // We can fill in features for everything except hops which were
@@ -1357,7 +1369,7 @@ where L::Target: Logger {
                                        // so that fees paid for a HTLC forwarding on the current channel are
                                        // associated with the previous channel (where they will be subtracted).
                                        ordered_hops.last_mut().unwrap().0.fee_msat = new_entry.hop_use_fee_msat;
-                                       ordered_hops.push((new_entry.clone(), NodeFeatures::empty()));
+                                       ordered_hops.push((new_entry.clone(), default_node_features.clone()));
                                }
                                ordered_hops.last_mut().unwrap().0.fee_msat = value_contribution_msat;
                                ordered_hops.last_mut().unwrap().0.hop_use_fee_msat = 0;
@@ -1684,7 +1696,7 @@ fn add_random_cltv_offset(route: &mut Route, payment_params: &PaymentParameters,
 #[cfg(test)]
 mod tests {
        use routing::network_graph::{NetworkGraph, NetGraphMsgHandler, NodeId};
-       use routing::router::{get_route, add_random_cltv_offset, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA};
+       use routing::router::{get_route, add_random_cltv_offset, default_node_features, PaymentParameters, Route, RouteHint, RouteHintHop, RouteHop, RoutingFees, DEFAULT_MAX_TOTAL_CLTV_EXPIRY_DELTA};
        use routing::scoring::Score;
        use chain::transaction::OutPoint;
        use chain::keysinterface::KeysInterface;
@@ -1723,6 +1735,8 @@ mod tests {
                                node_id,
                                unspendable_punishment_reserve: 0,
                                forwarding_info: None,
+                               outbound_htlc_minimum_msat: None,
+                               outbound_htlc_maximum_msat: None,
                        },
                        funding_txo: Some(OutPoint { txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0 }),
                        channel_type: None,
@@ -1738,6 +1752,8 @@ mod tests {
                        force_close_spend_delay: None,
                        is_outbound: true, is_funding_locked: true,
                        is_usable: true, is_public: true,
+                       inbound_htlc_minimum_msat: None,
+                       inbound_htlc_maximum_msat: None,
                }
        }
 
@@ -2785,7 +2801,7 @@ mod tests {
                assert_eq!(route.paths[0][4].short_channel_id, 8);
                assert_eq!(route.paths[0][4].fee_msat, 100);
                assert_eq!(route.paths[0][4].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][4].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][4].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -2861,7 +2877,7 @@ mod tests {
                assert_eq!(route.paths[0][4].short_channel_id, 8);
                assert_eq!(route.paths[0][4].fee_msat, 100);
                assert_eq!(route.paths[0][4].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][4].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][4].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -2958,7 +2974,7 @@ mod tests {
                assert_eq!(route.paths[0][3].short_channel_id, last_hops[0].0[1].short_channel_id);
                assert_eq!(route.paths[0][3].fee_msat, 100);
                assert_eq!(route.paths[0][3].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][3].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][3].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -3023,14 +3039,14 @@ mod tests {
                assert_eq!(route.paths[0][2].short_channel_id, last_hops[0].0[0].short_channel_id);
                assert_eq!(route.paths[0][2].fee_msat, 0);
                assert_eq!(route.paths[0][2].cltv_expiry_delta, 129);
-               assert_eq!(route.paths[0][2].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][2].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][2].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
 
                assert_eq!(route.paths[0][3].pubkey, nodes[6]);
                assert_eq!(route.paths[0][3].short_channel_id, last_hops[0].0[1].short_channel_id);
                assert_eq!(route.paths[0][3].fee_msat, 100);
                assert_eq!(route.paths[0][3].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][3].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][3].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -3121,7 +3137,7 @@ mod tests {
                assert_eq!(route.paths[0][4].short_channel_id, 8);
                assert_eq!(route.paths[0][4].fee_msat, 100);
                assert_eq!(route.paths[0][4].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][4].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][4].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -3151,7 +3167,7 @@ mod tests {
                assert_eq!(route.paths[0][1].short_channel_id, 8);
                assert_eq!(route.paths[0][1].fee_msat, 100);
                assert_eq!(route.paths[0][1].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][1].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][1].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][1].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
 
                last_hops[0].0[0].fees.base_msat = 1000;
@@ -3188,7 +3204,7 @@ mod tests {
                assert_eq!(route.paths[0][3].short_channel_id, 10);
                assert_eq!(route.paths[0][3].fee_msat, 100);
                assert_eq!(route.paths[0][3].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][3].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][3].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][3].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
 
                // ...but still use 8 for larger payments as 6 has a variable feerate
@@ -3229,7 +3245,7 @@ mod tests {
                assert_eq!(route.paths[0][4].short_channel_id, 8);
                assert_eq!(route.paths[0][4].fee_msat, 2000);
                assert_eq!(route.paths[0][4].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][4].node_features.le_flags(), &Vec::<u8>::new()); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][4].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][4].channel_features.le_flags(), &Vec::<u8>::new()); // We can't learn any flags from invoices, sadly
        }
 
@@ -3281,7 +3297,7 @@ mod tests {
                assert_eq!(route.paths[0][1].short_channel_id, 8);
                assert_eq!(route.paths[0][1].fee_msat, 1000000);
                assert_eq!(route.paths[0][1].cltv_expiry_delta, 42);
-               assert_eq!(route.paths[0][1].node_features.le_flags(), &[0; 0]); // We dont pass flags in from invoices yet
+               assert_eq!(route.paths[0][1].node_features.le_flags(), default_node_features().le_flags()); // We dont pass flags in from invoices yet
                assert_eq!(route.paths[0][1].channel_features.le_flags(), &[0; 0]); // We can't learn any flags from invoices, sadly
        }
 
@@ -5444,6 +5460,8 @@ mod benches {
                                node_id,
                                unspendable_punishment_reserve: 0,
                                forwarding_info: None,
+                               outbound_htlc_minimum_msat: None,
+                               outbound_htlc_maximum_msat: None,
                        },
                        funding_txo: Some(OutPoint {
                                txid: bitcoin::Txid::from_slice(&[0; 32]).unwrap(), index: 0
@@ -5463,6 +5481,8 @@ mod benches {
                        is_funding_locked: true,
                        is_usable: true,
                        is_public: true,
+                       inbound_htlc_minimum_msat: None,
+                       inbound_htlc_maximum_msat: None,
                }
        }
 
index b7aa996ce2efae9622208e1293dcebf8b1b3d8b9..206cc0a83a5b0635acf3a98b48ba04fd4e0e4893 100644 (file)
@@ -701,6 +701,10 @@ impl<T: Time> ChannelLiquidity<T> {
 /// probabilities.
 const NEGATIVE_LOG10_UPPER_BOUND: u64 = 2;
 
+/// The rough cutoff at which our precision falls off and we should stop bothering to try to log a
+/// ratio, as X in 1/X.
+const PRECISION_LOWER_BOUND_DENOMINATOR: u64 = approx::LOWER_BITS_BOUND;
+
 /// The divisor used when computing the amount penalty.
 const AMOUNT_PENALTY_DIVISOR: u64 = 1 << 20;
 
@@ -721,33 +725,40 @@ impl<L: Deref<Target = u64>, T: Time, U: Deref<Target = T>> DirectedChannelLiqui
                        } else {
                                // Equivalent to hitting the else clause below with the amount equal to the
                                // effective capacity and without any certainty on the liquidity upper bound.
-                               let negative_log10_times_1024 = NEGATIVE_LOG10_UPPER_BOUND * 1024;
-                               self.combined_penalty_msat(amount_msat, negative_log10_times_1024, params)
+                               let negative_log10_times_2048 = NEGATIVE_LOG10_UPPER_BOUND * 2048;
+                               self.combined_penalty_msat(amount_msat, negative_log10_times_2048, params)
                        }
                } else {
                        let numerator = (max_liquidity_msat - amount_msat).saturating_add(1);
                        let denominator = (max_liquidity_msat - min_liquidity_msat).saturating_add(1);
-                       let negative_log10_times_1024 =
-                               approx::negative_log10_times_1024(numerator, denominator);
-                       self.combined_penalty_msat(amount_msat, negative_log10_times_1024, params)
+                       if amount_msat - min_liquidity_msat < denominator / PRECISION_LOWER_BOUND_DENOMINATOR {
+                               // If the failure probability is < 1.5625% (as 1 - numerator/denominator < 1/64),
+                               // don't bother trying to use the log approximation as it gets too noisy to be
+                               // particularly helpful, instead just round down to 0 and return the base penalty.
+                               params.base_penalty_msat
+                       } else {
+                               let negative_log10_times_2048 =
+                                       approx::negative_log10_times_2048(numerator, denominator);
+                               self.combined_penalty_msat(amount_msat, negative_log10_times_2048, params)
+                       }
                }
        }
 
        /// Computes the liquidity and amount penalties and adds them to the base penalty.
        #[inline(always)]
        fn combined_penalty_msat(
-               &self, amount_msat: u64, negative_log10_times_1024: u64,
+               &self, amount_msat: u64, negative_log10_times_2048: u64,
                params: ProbabilisticScoringParameters
        ) -> u64 {
                let liquidity_penalty_msat = {
                        // Upper bound the liquidity penalty to ensure some channel is selected.
                        let multiplier_msat = params.liquidity_penalty_multiplier_msat;
                        let max_penalty_msat = multiplier_msat.saturating_mul(NEGATIVE_LOG10_UPPER_BOUND);
-                       (negative_log10_times_1024.saturating_mul(multiplier_msat) / 1024).min(max_penalty_msat)
+                       (negative_log10_times_2048.saturating_mul(multiplier_msat) / 2048).min(max_penalty_msat)
                };
-               let amount_penalty_msat = negative_log10_times_1024
+               let amount_penalty_msat = negative_log10_times_2048
                        .saturating_mul(params.amount_penalty_multiplier_msat)
-                       .saturating_mul(amount_msat) / 1024 / AMOUNT_PENALTY_DIVISOR;
+                       .saturating_mul(amount_msat) / 2048 / AMOUNT_PENALTY_DIVISOR;
 
                params.base_penalty_msat
                        .saturating_add(liquidity_penalty_msat)
@@ -888,92 +899,284 @@ impl<G: Deref<Target = NetworkGraph>, T: Time> Score for ProbabilisticScorerUsin
 mod approx {
        const BITS: u32 = 64;
        const HIGHEST_BIT: u32 = BITS - 1;
-       const LOWER_BITS: u32 = 4;
-       const LOWER_BITS_BOUND: u64 = 1 << LOWER_BITS;
+       const LOWER_BITS: u32 = 6;
+       pub(super) const LOWER_BITS_BOUND: u64 = 1 << LOWER_BITS;
        const LOWER_BITMASK: u64 = (1 << LOWER_BITS) - 1;
 
-       /// Look-up table for `log10(x) * 1024` where row `i` is used for each `x` having `i` as the
+       /// Look-up table for `log10(x) * 2048` where row `i` is used for each `x` having `i` as the
        /// most significant bit. The next 4 bits of `x`, if applicable, are used for the second index.
-       const LOG10_TIMES_1024: [[u16; LOWER_BITS_BOUND as usize]; BITS as usize] = [
-               [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-               [308, 308, 308, 308, 308, 308, 308, 308, 489, 489, 489, 489, 489, 489, 489, 489],
-               [617, 617, 617, 617, 716, 716, 716, 716, 797, 797, 797, 797, 865, 865, 865, 865],
-               [925, 925, 977, 977, 1024, 1024, 1066, 1066, 1105, 1105, 1141, 1141, 1174, 1174, 1204, 1204],
-               [1233, 1260, 1285, 1309, 1332, 1354, 1375, 1394, 1413, 1431, 1449, 1466, 1482, 1497, 1513, 1527],
-               [1541, 1568, 1594, 1618, 1641, 1662, 1683, 1703, 1722, 1740, 1757, 1774, 1790, 1806, 1821, 1835],
-               [1850, 1876, 1902, 1926, 1949, 1970, 1991, 2011, 2030, 2048, 2065, 2082, 2098, 2114, 2129, 2144],
-               [2158, 2185, 2210, 2234, 2257, 2279, 2299, 2319, 2338, 2356, 2374, 2390, 2407, 2422, 2437, 2452],
-               [2466, 2493, 2518, 2542, 2565, 2587, 2608, 2627, 2646, 2665, 2682, 2699, 2715, 2731, 2746, 2760],
-               [2774, 2801, 2827, 2851, 2874, 2895, 2916, 2936, 2955, 2973, 2990, 3007, 3023, 3039, 3054, 3068],
-               [3083, 3110, 3135, 3159, 3182, 3203, 3224, 3244, 3263, 3281, 3298, 3315, 3331, 3347, 3362, 3377],
-               [3391, 3418, 3443, 3467, 3490, 3512, 3532, 3552, 3571, 3589, 3607, 3623, 3640, 3655, 3670, 3685],
-               [3699, 3726, 3751, 3775, 3798, 3820, 3841, 3860, 3879, 3898, 3915, 3932, 3948, 3964, 3979, 3993],
-               [4007, 4034, 4060, 4084, 4107, 4128, 4149, 4169, 4188, 4206, 4223, 4240, 4256, 4272, 4287, 4301],
-               [4316, 4343, 4368, 4392, 4415, 4436, 4457, 4477, 4496, 4514, 4531, 4548, 4564, 4580, 4595, 4610],
-               [4624, 4651, 4676, 4700, 4723, 4745, 4765, 4785, 4804, 4822, 4840, 4857, 4873, 4888, 4903, 4918],
-               [4932, 4959, 4984, 5009, 5031, 5053, 5074, 5093, 5112, 5131, 5148, 5165, 5181, 5197, 5212, 5226],
-               [5240, 5267, 5293, 5317, 5340, 5361, 5382, 5402, 5421, 5439, 5456, 5473, 5489, 5505, 5520, 5534],
-               [5549, 5576, 5601, 5625, 5648, 5670, 5690, 5710, 5729, 5747, 5764, 5781, 5797, 5813, 5828, 5843],
-               [5857, 5884, 5909, 5933, 5956, 5978, 5998, 6018, 6037, 6055, 6073, 6090, 6106, 6121, 6136, 6151],
-               [6165, 6192, 6217, 6242, 6264, 6286, 6307, 6326, 6345, 6364, 6381, 6398, 6414, 6430, 6445, 6459],
-               [6473, 6500, 6526, 6550, 6573, 6594, 6615, 6635, 6654, 6672, 6689, 6706, 6722, 6738, 6753, 6767],
-               [6782, 6809, 6834, 6858, 6881, 6903, 6923, 6943, 6962, 6980, 6998, 7014, 7030, 7046, 7061, 7076],
-               [7090, 7117, 7142, 7166, 7189, 7211, 7231, 7251, 7270, 7288, 7306, 7323, 7339, 7354, 7369, 7384],
-               [7398, 7425, 7450, 7475, 7497, 7519, 7540, 7560, 7578, 7597, 7614, 7631, 7647, 7663, 7678, 7692],
-               [7706, 7733, 7759, 7783, 7806, 7827, 7848, 7868, 7887, 7905, 7922, 7939, 7955, 7971, 7986, 8001],
-               [8015, 8042, 8067, 8091, 8114, 8136, 8156, 8176, 8195, 8213, 8231, 8247, 8263, 8279, 8294, 8309],
-               [8323, 8350, 8375, 8399, 8422, 8444, 8464, 8484, 8503, 8521, 8539, 8556, 8572, 8587, 8602, 8617],
-               [8631, 8658, 8684, 8708, 8730, 8752, 8773, 8793, 8811, 8830, 8847, 8864, 8880, 8896, 8911, 8925],
-               [8939, 8966, 8992, 9016, 9039, 9060, 9081, 9101, 9120, 9138, 9155, 9172, 9188, 9204, 9219, 9234],
-               [9248, 9275, 9300, 9324, 9347, 9369, 9389, 9409, 9428, 9446, 9464, 9480, 9497, 9512, 9527, 9542],
-               [9556, 9583, 9608, 9632, 9655, 9677, 9698, 9717, 9736, 9754, 9772, 9789, 9805, 9820, 9835, 9850],
-               [9864, 9891, 9917, 9941, 9963, 9985, 10006, 10026, 10044, 10063, 10080, 10097, 10113, 10129, 10144, 10158],
-               [10172, 10199, 10225, 10249, 10272, 10293, 10314, 10334, 10353, 10371, 10388, 10405, 10421, 10437, 10452, 10467],
-               [10481, 10508, 10533, 10557, 10580, 10602, 10622, 10642, 10661, 10679, 10697, 10713, 10730, 10745, 10760, 10775],
-               [10789, 10816, 10841, 10865, 10888, 10910, 10931, 10950, 10969, 10987, 11005, 11022, 11038, 11053, 11068, 11083],
-               [11097, 11124, 11150, 11174, 11196, 11218, 11239, 11259, 11277, 11296, 11313, 11330, 11346, 11362, 11377, 11391],
-               [11405, 11432, 11458, 11482, 11505, 11526, 11547, 11567, 11586, 11604, 11621, 11638, 11654, 11670, 11685, 11700],
-               [11714, 11741, 11766, 11790, 11813, 11835, 11855, 11875, 11894, 11912, 11930, 11946, 11963, 11978, 11993, 12008],
-               [12022, 12049, 12074, 12098, 12121, 12143, 12164, 12183, 12202, 12220, 12238, 12255, 12271, 12286, 12301, 12316],
-               [12330, 12357, 12383, 12407, 12429, 12451, 12472, 12492, 12511, 12529, 12546, 12563, 12579, 12595, 12610, 12624],
-               [12638, 12665, 12691, 12715, 12738, 12759, 12780, 12800, 12819, 12837, 12854, 12871, 12887, 12903, 12918, 12933],
-               [12947, 12974, 12999, 13023, 13046, 13068, 13088, 13108, 13127, 13145, 13163, 13179, 13196, 13211, 13226, 13241],
-               [13255, 13282, 13307, 13331, 13354, 13376, 13397, 13416, 13435, 13453, 13471, 13488, 13504, 13519, 13535, 13549],
-               [13563, 13590, 13616, 13640, 13662, 13684, 13705, 13725, 13744, 13762, 13779, 13796, 13812, 13828, 13843, 13857],
-               [13871, 13898, 13924, 13948, 13971, 13992, 14013, 14033, 14052, 14070, 14087, 14104, 14120, 14136, 14151, 14166],
-               [14180, 14207, 14232, 14256, 14279, 14301, 14321, 14341, 14360, 14378, 14396, 14412, 14429, 14444, 14459, 14474],
-               [14488, 14515, 14540, 14564, 14587, 14609, 14630, 14649, 14668, 14686, 14704, 14721, 14737, 14752, 14768, 14782],
-               [14796, 14823, 14849, 14873, 14895, 14917, 14938, 14958, 14977, 14995, 15012, 15029, 15045, 15061, 15076, 15090],
-               [15104, 15131, 15157, 15181, 15204, 15225, 15246, 15266, 15285, 15303, 15320, 15337, 15353, 15369, 15384, 15399],
-               [15413, 15440, 15465, 15489, 15512, 15534, 15554, 15574, 15593, 15611, 15629, 15645, 15662, 15677, 15692, 15707],
-               [15721, 15748, 15773, 15797, 15820, 15842, 15863, 15882, 15901, 15919, 15937, 15954, 15970, 15985, 16001, 16015],
-               [16029, 16056, 16082, 16106, 16128, 16150, 16171, 16191, 16210, 16228, 16245, 16262, 16278, 16294, 16309, 16323],
-               [16337, 16364, 16390, 16414, 16437, 16458, 16479, 16499, 16518, 16536, 16553, 16570, 16586, 16602, 16617, 16632],
-               [16646, 16673, 16698, 16722, 16745, 16767, 16787, 16807, 16826, 16844, 16862, 16878, 16895, 16910, 16925, 16940],
-               [16954, 16981, 17006, 17030, 17053, 17075, 17096, 17115, 17134, 17152, 17170, 17187, 17203, 17218, 17234, 17248],
-               [17262, 17289, 17315, 17339, 17361, 17383, 17404, 17424, 17443, 17461, 17478, 17495, 17511, 17527, 17542, 17556],
-               [17571, 17597, 17623, 17647, 17670, 17691, 17712, 17732, 17751, 17769, 17786, 17803, 17819, 17835, 17850, 17865],
-               [17879, 17906, 17931, 17955, 17978, 18000, 18020, 18040, 18059, 18077, 18095, 18111, 18128, 18143, 18158, 18173],
-               [18187, 18214, 18239, 18263, 18286, 18308, 18329, 18348, 18367, 18385, 18403, 18420, 18436, 18452, 18467, 18481],
-               [18495, 18522, 18548, 18572, 18595, 18616, 18637, 18657, 18676, 18694, 18711, 18728, 18744, 18760, 18775, 18789],
-               [18804, 18830, 18856, 18880, 18903, 18924, 18945, 18965, 18984, 19002, 19019, 19036, 19052, 19068, 19083, 19098],
-               [19112, 19139, 19164, 19188, 19211, 19233, 19253, 19273, 19292, 19310, 19328, 19344, 19361, 19376, 19391, 19406],
-               [19420, 19447, 19472, 19496, 19519, 19541, 19562, 19581, 19600, 19619, 19636, 19653, 19669, 19685, 19700, 19714],
+       const LOG10_TIMES_2048: [[u16; (LOWER_BITS_BOUND) as usize]; BITS as usize] = [
+               [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+               [617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617,
+                       617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617, 617,
+                       977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977,
+                       977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977, 977],
+               [1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233, 1233,
+                       1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431, 1431,
+                       1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594, 1594,
+                       1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731, 1731],
+               [1850, 1850, 1850, 1850, 1850, 1850, 1850, 1850, 1954, 1954, 1954, 1954, 1954, 1954, 1954, 1954,
+                       2048, 2048, 2048, 2048, 2048, 2048, 2048, 2048, 2133, 2133, 2133, 2133, 2133, 2133, 2133, 2133,
+                       2210, 2210, 2210, 2210, 2210, 2210, 2210, 2210, 2281, 2281, 2281, 2281, 2281, 2281, 2281, 2281,
+                       2347, 2347, 2347, 2347, 2347, 2347, 2347, 2347, 2409, 2409, 2409, 2409, 2409, 2409, 2409, 2409],
+               [2466, 2466, 2466, 2466, 2520, 2520, 2520, 2520, 2571, 2571, 2571, 2571, 2619, 2619, 2619, 2619,
+                       2665, 2665, 2665, 2665, 2708, 2708, 2708, 2708, 2749, 2749, 2749, 2749, 2789, 2789, 2789, 2789,
+                       2827, 2827, 2827, 2827, 2863, 2863, 2863, 2863, 2898, 2898, 2898, 2898, 2931, 2931, 2931, 2931,
+                       2964, 2964, 2964, 2964, 2995, 2995, 2995, 2995, 3025, 3025, 3025, 3025, 3054, 3054, 3054, 3054],
+               [3083, 3083, 3110, 3110, 3136, 3136, 3162, 3162, 3187, 3187, 3212, 3212, 3235, 3235, 3259, 3259,
+                       3281, 3281, 3303, 3303, 3324, 3324, 3345, 3345, 3366, 3366, 3386, 3386, 3405, 3405, 3424, 3424,
+                       3443, 3443, 3462, 3462, 3479, 3479, 3497, 3497, 3514, 3514, 3531, 3531, 3548, 3548, 3564, 3564,
+                       3580, 3580, 3596, 3596, 3612, 3612, 3627, 3627, 3642, 3642, 3656, 3656, 3671, 3671, 3685, 3685],
+               [3699, 3713, 3726, 3740, 3753, 3766, 3779, 3791, 3804, 3816, 3828, 3840, 3852, 3864, 3875, 3886,
+                       3898, 3909, 3919, 3930, 3941, 3951, 3962, 3972, 3982, 3992, 4002, 4012, 4022, 4031, 4041, 4050,
+                       4060, 4069, 4078, 4087, 4096, 4105, 4114, 4122, 4131, 4139, 4148, 4156, 4164, 4173, 4181, 4189,
+                       4197, 4205, 4213, 4220, 4228, 4236, 4243, 4251, 4258, 4266, 4273, 4280, 4287, 4294, 4302, 4309],
+               [4316, 4329, 4343, 4356, 4369, 4382, 4395, 4408, 4420, 4433, 4445, 4457, 4468, 4480, 4492, 4503,
+                       4514, 4525, 4536, 4547, 4557, 4568, 4578, 4589, 4599, 4609, 4619, 4629, 4638, 4648, 4657, 4667,
+                       4676, 4685, 4695, 4704, 4713, 4721, 4730, 4739, 4747, 4756, 4764, 4773, 4781, 4789, 4797, 4805,
+                       4813, 4821, 4829, 4837, 4845, 4852, 4860, 4867, 4875, 4882, 4889, 4897, 4904, 4911, 4918, 4925],
+               [4932, 4946, 4959, 4973, 4986, 4999, 5012, 5024, 5037, 5049, 5061, 5073, 5085, 5097, 5108, 5119,
+                       5131, 5142, 5153, 5163, 5174, 5184, 5195, 5205, 5215, 5225, 5235, 5245, 5255, 5264, 5274, 5283,
+                       5293, 5302, 5311, 5320, 5329, 5338, 5347, 5355, 5364, 5372, 5381, 5389, 5397, 5406, 5414, 5422,
+                       5430, 5438, 5446, 5453, 5461, 5469, 5476, 5484, 5491, 5499, 5506, 5513, 5520, 5527, 5535, 5542],
+               [5549, 5562, 5576, 5589, 5603, 5615, 5628, 5641, 5653, 5666, 5678, 5690, 5701, 5713, 5725, 5736,
+                       5747, 5758, 5769, 5780, 5790, 5801, 5811, 5822, 5832, 5842, 5852, 5862, 5871, 5881, 5890, 5900,
+                       5909, 5918, 5928, 5937, 5946, 5954, 5963, 5972, 5980, 5989, 5997, 6006, 6014, 6022, 6030, 6038,
+                       6046, 6054, 6062, 6070, 6078, 6085, 6093, 6100, 6108, 6115, 6122, 6130, 6137, 6144, 6151, 6158],
+               [6165, 6179, 6192, 6206, 6219, 6232, 6245, 6257, 6270, 6282, 6294, 6306, 6318, 6330, 6341, 6352,
+                       6364, 6375, 6386, 6396, 6407, 6417, 6428, 6438, 6448, 6458, 6468, 6478, 6488, 6497, 6507, 6516,
+                       6526, 6535, 6544, 6553, 6562, 6571, 6580, 6588, 6597, 6605, 6614, 6622, 6630, 6639, 6647, 6655,
+                       6663, 6671, 6679, 6686, 6694, 6702, 6709, 6717, 6724, 6732, 6739, 6746, 6753, 6761, 6768, 6775],
+               [6782, 6795, 6809, 6822, 6836, 6849, 6861, 6874, 6886, 6899, 6911, 6923, 6934, 6946, 6958, 6969,
+                       6980, 6991, 7002, 7013, 7023, 7034, 7044, 7055, 7065, 7075, 7085, 7095, 7104, 7114, 7124, 7133,
+                       7142, 7151, 7161, 7170, 7179, 7187, 7196, 7205, 7213, 7222, 7230, 7239, 7247, 7255, 7263, 7271,
+                       7279, 7287, 7295, 7303, 7311, 7318, 7326, 7333, 7341, 7348, 7355, 7363, 7370, 7377, 7384, 7391],
+               [7398, 7412, 7425, 7439, 7452, 7465, 7478, 7490, 7503, 7515, 7527, 7539, 7551, 7563, 7574, 7585,
+                       7597, 7608, 7619, 7629, 7640, 7651, 7661, 7671, 7681, 7691, 7701, 7711, 7721, 7731, 7740, 7749,
+                       7759, 7768, 7777, 7786, 7795, 7804, 7813, 7821, 7830, 7838, 7847, 7855, 7864, 7872, 7880, 7888,
+                       7896, 7904, 7912, 7919, 7927, 7935, 7942, 7950, 7957, 7965, 7972, 7979, 7986, 7994, 8001, 8008],
+               [8015, 8028, 8042, 8055, 8069, 8082, 8094, 8107, 8119, 8132, 8144, 8156, 8167, 8179, 8191, 8202,
+                       8213, 8224, 8235, 8246, 8256, 8267, 8277, 8288, 8298, 8308, 8318, 8328, 8337, 8347, 8357, 8366,
+                       8375, 8384, 8394, 8403, 8412, 8420, 8429, 8438, 8446, 8455, 8463, 8472, 8480, 8488, 8496, 8504,
+                       8512, 8520, 8528, 8536, 8544, 8551, 8559, 8566, 8574, 8581, 8588, 8596, 8603, 8610, 8617, 8624],
+               [8631, 8645, 8659, 8672, 8685, 8698, 8711, 8723, 8736, 8748, 8760, 8772, 8784, 8796, 8807, 8818,
+                       8830, 8841, 8852, 8862, 8873, 8884, 8894, 8904, 8914, 8924, 8934, 8944, 8954, 8964, 8973, 8982,
+                       8992, 9001, 9010, 9019, 9028, 9037, 9046, 9054, 9063, 9071, 9080, 9088, 9097, 9105, 9113, 9121,
+                       9129, 9137, 9145, 9152, 9160, 9168, 9175, 9183, 9190, 9198, 9205, 9212, 9219, 9227, 9234, 9241],
+               [9248, 9261, 9275, 9288, 9302, 9315, 9327, 9340, 9352, 9365, 9377, 9389, 9400, 9412, 9424, 9435,
+                       9446, 9457, 9468, 9479, 9490, 9500, 9510, 9521, 9531, 9541, 9551, 9561, 9570, 9580, 9590, 9599,
+                       9608, 9617, 9627, 9636, 9645, 9653, 9662, 9671, 9679, 9688, 9696, 9705, 9713, 9721, 9729, 9737,
+                       9745, 9753, 9761, 9769, 9777, 9784, 9792, 9799, 9807, 9814, 9821, 9829, 9836, 9843, 9850, 9857],
+               [9864, 9878, 9892, 9905, 9918, 9931, 9944, 9956, 9969, 9981, 9993, 10005, 10017, 10029, 10040, 10051,
+                       10063, 10074, 10085, 10095, 10106, 10117, 10127, 10137, 10147, 10157, 10167, 10177, 10187, 10197, 10206, 10215,
+                       10225, 10234, 10243, 10252, 10261, 10270, 10279, 10287, 10296, 10304, 10313, 10321, 10330, 10338, 10346, 10354,
+                       10362, 10370, 10378, 10385, 10393, 10401, 10408, 10416, 10423, 10431, 10438, 10445, 10452, 10460, 10467, 10474],
+               [10481, 10494, 10508, 10521, 10535, 10548, 10560, 10573, 10585, 10598, 10610, 10622, 10634, 10645, 10657, 10668,
+                       10679, 10690, 10701, 10712, 10723, 10733, 10743, 10754, 10764, 10774, 10784, 10794, 10803, 10813, 10823, 10832,
+                       10841, 10851, 10860, 10869, 10878, 10886, 10895, 10904, 10912, 10921, 10929, 10938, 10946, 10954, 10962, 10970,
+                       10978, 10986, 10994, 11002, 11010, 11017, 11025, 11032, 11040, 11047, 11054, 11062, 11069, 11076, 11083, 11090],
+               [11097, 11111, 11125, 11138, 11151, 11164, 11177, 11189, 11202, 11214, 11226, 11238, 11250, 11262, 11273, 11284,
+                       11296, 11307, 11318, 11328, 11339, 11350, 11360, 11370, 11380, 11390, 11400, 11410, 11420, 11430, 11439, 11448,
+                       11458, 11467, 11476, 11485, 11494, 11503, 11512, 11520, 11529, 11538, 11546, 11554, 11563, 11571, 11579, 11587,
+                       11595, 11603, 11611, 11618, 11626, 11634, 11641, 11649, 11656, 11664, 11671, 11678, 11685, 11693, 11700, 11707],
+               [11714, 11727, 11741, 11754, 11768, 11781, 11793, 11806, 11818, 11831, 11843, 11855, 11867, 11878, 11890, 11901,
+                       11912, 11923, 11934, 11945, 11956, 11966, 11976, 11987, 11997, 12007, 12017, 12027, 12036, 12046, 12056, 12065,
+                       12074, 12084, 12093, 12102, 12111, 12119, 12128, 12137, 12146, 12154, 12162, 12171, 12179, 12187, 12195, 12203,
+                       12211, 12219, 12227, 12235, 12243, 12250, 12258, 12265, 12273, 12280, 12287, 12295, 12302, 12309, 12316, 12323],
+               [12330, 12344, 12358, 12371, 12384, 12397, 12410, 12423, 12435, 12447, 12459, 12471, 12483, 12495, 12506, 12517,
+                       12529, 12540, 12551, 12561, 12572, 12583, 12593, 12603, 12613, 12623, 12633, 12643, 12653, 12663, 12672, 12682,
+                       12691, 12700, 12709, 12718, 12727, 12736, 12745, 12753, 12762, 12771, 12779, 12787, 12796, 12804, 12812, 12820,
+                       12828, 12836, 12844, 12851, 12859, 12867, 12874, 12882, 12889, 12897, 12904, 12911, 12918, 12926, 12933, 12940],
+               [12947, 12960, 12974, 12987, 13001, 13014, 13026, 13039, 13051, 13064, 13076, 13088, 13100, 13111, 13123, 13134,
+                       13145, 13156, 13167, 13178, 13189, 13199, 13209, 13220, 13230, 13240, 13250, 13260, 13269, 13279, 13289, 13298,
+                       13307, 13317, 13326, 13335, 13344, 13352, 13361, 13370, 13379, 13387, 13395, 13404, 13412, 13420, 13428, 13436,
+                       13444, 13452, 13460, 13468, 13476, 13483, 13491, 13498, 13506, 13513, 13521, 13528, 13535, 13542, 13549, 13556],
+               [13563, 13577, 13591, 13604, 13617, 13630, 13643, 13656, 13668, 13680, 13692, 13704, 13716, 13728, 13739, 13750,
+                       13762, 13773, 13784, 13794, 13805, 13816, 13826, 13836, 13846, 13857, 13866, 13876, 13886, 13896, 13905, 13915,
+                       13924, 13933, 13942, 13951, 13960, 13969, 13978, 13986, 13995, 14004, 14012, 14020, 14029, 14037, 14045, 14053,
+                       14061, 14069, 14077, 14084, 14092, 14100, 14107, 14115, 14122, 14130, 14137, 14144, 14151, 14159, 14166, 14173],
+               [14180, 14194, 14207, 14220, 14234, 14247, 14259, 14272, 14284, 14297, 14309, 14321, 14333, 14344, 14356, 14367,
+                       14378, 14389, 14400, 14411, 14422, 14432, 14443, 14453, 14463, 14473, 14483, 14493, 14502, 14512, 14522, 14531,
+                       14540, 14550, 14559, 14568, 14577, 14586, 14594, 14603, 14612, 14620, 14628, 14637, 14645, 14653, 14661, 14669,
+                       14677, 14685, 14693, 14701, 14709, 14716, 14724, 14731, 14739, 14746, 14754, 14761, 14768, 14775, 14782, 14789],
+               [14796, 14810, 14824, 14837, 14850, 14863, 14876, 14889, 14901, 14913, 14925, 14937, 14949, 14961, 14972, 14984,
+                       14995, 15006, 15017, 15027, 15038, 15049, 15059, 15069, 15079, 15090, 15099, 15109, 15119, 15129, 15138, 15148,
+                       15157, 15166, 15175, 15184, 15193, 15202, 15211, 15219, 15228, 15237, 15245, 15253, 15262, 15270, 15278, 15286,
+                       15294, 15302, 15310, 15317, 15325, 15333, 15340, 15348, 15355, 15363, 15370, 15377, 15384, 15392, 15399, 15406],
+               [15413, 15427, 15440, 15453, 15467, 15480, 15492, 15505, 15517, 15530, 15542, 15554, 15566, 15577, 15589, 15600,
+                       15611, 15622, 15633, 15644, 15655, 15665, 15676, 15686, 15696, 15706, 15716, 15726, 15736, 15745, 15755, 15764,
+                       15773, 15783, 15792, 15801, 15810, 15819, 15827, 15836, 15845, 15853, 15862, 15870, 15878, 15886, 15894, 15903,
+                       15910, 15918, 15926, 15934, 15942, 15949, 15957, 15964, 15972, 15979, 15987, 15994, 16001, 16008, 16015, 16022],
+               [16029, 16043, 16057, 16070, 16083, 16096, 16109, 16122, 16134, 16146, 16158, 16170, 16182, 16194, 16205, 16217,
+                       16228, 16239, 16250, 16260, 16271, 16282, 16292, 16302, 16312, 16323, 16332, 16342, 16352, 16362, 16371, 16381,
+                       16390, 16399, 16408, 16417, 16426, 16435, 16444, 16452, 16461, 16470, 16478, 16486, 16495, 16503, 16511, 16519,
+                       16527, 16535, 16543, 16550, 16558, 16566, 16573, 16581, 16588, 16596, 16603, 16610, 16618, 16625, 16632, 16639],
+               [16646, 16660, 16673, 16686, 16700, 16713, 16725, 16738, 16751, 16763, 16775, 16787, 16799, 16810, 16822, 16833,
+                       16844, 16855, 16866, 16877, 16888, 16898, 16909, 16919, 16929, 16939, 16949, 16959, 16969, 16978, 16988, 16997,
+                       17006, 17016, 17025, 17034, 17043, 17052, 17060, 17069, 17078, 17086, 17095, 17103, 17111, 17119, 17127, 17136,
+                       17143, 17151, 17159, 17167, 17175, 17182, 17190, 17197, 17205, 17212, 17220, 17227, 17234, 17241, 17248, 17255],
+               [17262, 17276, 17290, 17303, 17316, 17329, 17342, 17355, 17367, 17379, 17391, 17403, 17415, 17427, 17438, 17450,
+                       17461, 17472, 17483, 17493, 17504, 17515, 17525, 17535, 17546, 17556, 17565, 17575, 17585, 17595, 17604, 17614,
+                       17623, 17632, 17641, 17650, 17659, 17668, 17677, 17685, 17694, 17703, 17711, 17719, 17728, 17736, 17744, 17752,
+                       17760, 17768, 17776, 17784, 17791, 17799, 17806, 17814, 17821, 17829, 17836, 17843, 17851, 17858, 17865, 17872],
+               [17879, 17893, 17906, 17920, 17933, 17946, 17958, 17971, 17984, 17996, 18008, 18020, 18032, 18043, 18055, 18066,
+                       18077, 18088, 18099, 18110, 18121, 18131, 18142, 18152, 18162, 18172, 18182, 18192, 18202, 18211, 18221, 18230,
+                       18239, 18249, 18258, 18267, 18276, 18285, 18293, 18302, 18311, 18319, 18328, 18336, 18344, 18352, 18360, 18369,
+                       18377, 18384, 18392, 18400, 18408, 18415, 18423, 18430, 18438, 18445, 18453, 18460, 18467, 18474, 18481, 18488],
+               [18495, 18509, 18523, 18536, 18549, 18562, 18575, 18588, 18600, 18612, 18624, 18636, 18648, 18660, 18671, 18683,
+                       18694, 18705, 18716, 18726, 18737, 18748, 18758, 18768, 18779, 18789, 18799, 18808, 18818, 18828, 18837, 18847,
+                       18856, 18865, 18874, 18883, 18892, 18901, 18910, 18919, 18927, 18936, 18944, 18952, 18961, 18969, 18977, 18985,
+                       18993, 19001, 19009, 19017, 19024, 19032, 19039, 19047, 19054, 19062, 19069, 19076, 19084, 19091, 19098, 19105],
+               [19112, 19126, 19139, 19153, 19166, 19179, 19191, 19204, 19217, 19229, 19241, 19253, 19265, 19276, 19288, 19299,
+                       19310, 19321, 19332, 19343, 19354, 19364, 19375, 19385, 19395, 19405, 19415, 19425, 19435, 19444, 19454, 19463,
+                       19472, 19482, 19491, 19500, 19509, 19518, 19526, 19535, 19544, 19552, 19561, 19569, 19577, 19585, 19594, 19602,
+                       19610, 19617, 19625, 19633, 19641, 19648, 19656, 19663, 19671, 19678, 19686, 19693, 19700, 19707, 19714, 19721],
+               [19728, 19742, 19756, 19769, 19782, 19795, 19808, 19821, 19833, 19845, 19857, 19869, 19881, 19893, 19904, 19916,
+                       19927, 19938, 19949, 19960, 19970, 19981, 19991, 20001, 20012, 20022, 20032, 20041, 20051, 20061, 20070, 20080,
+                       20089, 20098, 20107, 20116, 20125, 20134, 20143, 20152, 20160, 20169, 20177, 20185, 20194, 20202, 20210, 20218,
+                       20226, 20234, 20242, 20250, 20257, 20265, 20272, 20280, 20287, 20295, 20302, 20309, 20317, 20324, 20331, 20338],
+               [20345, 20359, 20372, 20386, 20399, 20412, 20425, 20437, 20450, 20462, 20474, 20486, 20498, 20509, 20521, 20532,
+                       20543, 20554, 20565, 20576, 20587, 20597, 20608, 20618, 20628, 20638, 20648, 20658, 20668, 20677, 20687, 20696,
+                       20705, 20715, 20724, 20733, 20742, 20751, 20759, 20768, 20777, 20785, 20794, 20802, 20810, 20818, 20827, 20835,
+                       20843, 20850, 20858, 20866, 20874, 20881, 20889, 20896, 20904, 20911, 20919, 20926, 20933, 20940, 20947, 20954],
+               [20961, 20975, 20989, 21002, 21015, 21028, 21041, 21054, 21066, 21078, 21090, 21102, 21114, 21126, 21137, 21149,
+                       21160, 21171, 21182, 21193, 21203, 21214, 21224, 21234, 21245, 21255, 21265, 21274, 21284, 21294, 21303, 21313,
+                       21322, 21331, 21340, 21349, 21358, 21367, 21376, 21385, 21393, 21402, 21410, 21418, 21427, 21435, 21443, 21451,
+                       21459, 21467, 21475, 21483, 21490, 21498, 21505, 21513, 21520, 21528, 21535, 21542, 21550, 21557, 21564, 21571],
+               [21578, 21592, 21605, 21619, 21632, 21645, 21658, 21670, 21683, 21695, 21707, 21719, 21731, 21742, 21754, 21765,
+                       21776, 21787, 21798, 21809, 21820, 21830, 21841, 21851, 21861, 21871, 21881, 21891, 21901, 21910, 21920, 21929,
+                       21938, 21948, 21957, 21966, 21975, 21984, 21992, 22001, 22010, 22018, 22027, 22035, 22043, 22051, 22060, 22068,
+                       22076, 22083, 22091, 22099, 22107, 22114, 22122, 22129, 22137, 22144, 22152, 22159, 22166, 22173, 22180, 22187],
+               [22194, 22208, 22222, 22235, 22248, 22261, 22274, 22287, 22299, 22311, 22323, 22335, 22347, 22359, 22370, 22382,
+                       22393, 22404, 22415, 22426, 22436, 22447, 22457, 22467, 22478, 22488, 22498, 22507, 22517, 22527, 22536, 22546,
+                       22555, 22564, 22573, 22582, 22591, 22600, 22609, 22618, 22626, 22635, 22643, 22651, 22660, 22668, 22676, 22684,
+                       22692, 22700, 22708, 22716, 22723, 22731, 22738, 22746, 22753, 22761, 22768, 22775, 22783, 22790, 22797, 22804],
+               [22811, 22825, 22838, 22852, 22865, 22878, 22891, 22903, 22916, 22928, 22940, 22952, 22964, 22975, 22987, 22998,
+                       23009, 23020, 23031, 23042, 23053, 23063, 23074, 23084, 23094, 23104, 23114, 23124, 23134, 23143, 23153, 23162,
+                       23171, 23181, 23190, 23199, 23208, 23217, 23225, 23234, 23243, 23251, 23260, 23268, 23276, 23284, 23293, 23301,
+                       23309, 23316, 23324, 23332, 23340, 23347, 23355, 23363, 23370, 23377, 23385, 23392, 23399, 23406, 23413, 23420],
+               [23427, 23441, 23455, 23468, 23481, 23494, 23507, 23520, 23532, 23544, 23556, 23568, 23580, 23592, 23603, 23615,
+                       23626, 23637, 23648, 23659, 23669, 23680, 23690, 23700, 23711, 23721, 23731, 23740, 23750, 23760, 23769, 23779,
+                       23788, 23797, 23806, 23815, 23824, 23833, 23842, 23851, 23859, 23868, 23876, 23884, 23893, 23901, 23909, 23917,
+                       23925, 23933, 23941, 23949, 23956, 23964, 23972, 23979, 23986, 23994, 24001, 24008, 24016, 24023, 24030, 24037],
+               [24044, 24058, 24071, 24085, 24098, 24111, 24124, 24136, 24149, 24161, 24173, 24185, 24197, 24208, 24220, 24231,
+                       24242, 24253, 24264, 24275, 24286, 24296, 24307, 24317, 24327, 24337, 24347, 24357, 24367, 24376, 24386, 24395,
+                       24405, 24414, 24423, 24432, 24441, 24450, 24458, 24467, 24476, 24484, 24493, 24501, 24509, 24517, 24526, 24534,
+                       24542, 24550, 24557, 24565, 24573, 24580, 24588, 24596, 24603, 24610, 24618, 24625, 24632, 24639, 24646, 24653],
+               [24660, 24674, 24688, 24701, 24714, 24727, 24740, 24753, 24765, 24777, 24790, 24801, 24813, 24825, 24836, 24848,
+                       24859, 24870, 24881, 24892, 24902, 24913, 24923, 24933, 24944, 24954, 24964, 24973, 24983, 24993, 25002, 25012,
+                       25021, 25030, 25039, 25048, 25057, 25066, 25075, 25084, 25092, 25101, 25109, 25117, 25126, 25134, 25142, 25150,
+                       25158, 25166, 25174, 25182, 25189, 25197, 25205, 25212, 25219, 25227, 25234, 25241, 25249, 25256, 25263, 25270],
+               [25277, 25291, 25304, 25318, 25331, 25344, 25357, 25369, 25382, 25394, 25406, 25418, 25430, 25441, 25453, 25464,
+                       25475, 25486, 25497, 25508, 25519, 25529, 25540, 25550, 25560, 25570, 25580, 25590, 25600, 25609, 25619, 25628,
+                       25638, 25647, 25656, 25665, 25674, 25683, 25691, 25700, 25709, 25717, 25726, 25734, 25742, 25750, 25759, 25767,
+                       25775, 25783, 25790, 25798, 25806, 25813, 25821, 25829, 25836, 25843, 25851, 25858, 25865, 25872, 25879, 25886],
+               [25893, 25907, 25921, 25934, 25947, 25960, 25973, 25986, 25998, 26010, 26023, 26034, 26046, 26058, 26069, 26081,
+                       26092, 26103, 26114, 26125, 26135, 26146, 26156, 26166, 26177, 26187, 26197, 26206, 26216, 26226, 26235, 26245,
+                       26254, 26263, 26272, 26281, 26290, 26299, 26308, 26317, 26325, 26334, 26342, 26351, 26359, 26367, 26375, 26383,
+                       26391, 26399, 26407, 26415, 26422, 26430, 26438, 26445, 26453, 26460, 26467, 26474, 26482, 26489, 26496, 26503],
+               [26510, 26524, 26537, 26551, 26564, 26577, 26590, 26602, 26615, 26627, 26639, 26651, 26663, 26674, 26686, 26697,
+                       26708, 26719, 26730, 26741, 26752, 26762, 26773, 26783, 26793, 26803, 26813, 26823, 26833, 26842, 26852, 26861,
+                       26871, 26880, 26889, 26898, 26907, 26916, 26924, 26933, 26942, 26950, 26959, 26967, 26975, 26983, 26992, 27000,
+                       27008, 27016, 27023, 27031, 27039, 27046, 27054, 27062, 27069, 27076, 27084, 27091, 27098, 27105, 27112, 27119],
+               [27126, 27140, 27154, 27167, 27180, 27193, 27206, 27219, 27231, 27243, 27256, 27267, 27279, 27291, 27302, 27314,
+                       27325, 27336, 27347, 27358, 27368, 27379, 27389, 27399, 27410, 27420, 27430, 27439, 27449, 27459, 27468, 27478,
+                       27487, 27496, 27505, 27514, 27523, 27532, 27541, 27550, 27558, 27567, 27575, 27584, 27592, 27600, 27608, 27616,
+                       27624, 27632, 27640, 27648, 27655, 27663, 27671, 27678, 27686, 27693, 27700, 27707, 27715, 27722, 27729, 27736],
+               [27743, 27757, 27770, 27784, 27797, 27810, 27823, 27835, 27848, 27860, 27872, 27884, 27896, 27907, 27919, 27930,
+                       27941, 27952, 27963, 27974, 27985, 27995, 28006, 28016, 28026, 28036, 28046, 28056, 28066, 28075, 28085, 28094,
+                       28104, 28113, 28122, 28131, 28140, 28149, 28157, 28166, 28175, 28183, 28192, 28200, 28208, 28217, 28225, 28233,
+                       28241, 28249, 28256, 28264, 28272, 28280, 28287, 28295, 28302, 28309, 28317, 28324, 28331, 28338, 28345, 28352],
+               [28359, 28373, 28387, 28400, 28413, 28426, 28439, 28452, 28464, 28476, 28489, 28501, 28512, 28524, 28535, 28547,
+                       28558, 28569, 28580, 28591, 28601, 28612, 28622, 28633, 28643, 28653, 28663, 28672, 28682, 28692, 28701, 28711,
+                       28720, 28729, 28738, 28747, 28756, 28765, 28774, 28783, 28791, 28800, 28808, 28817, 28825, 28833, 28841, 28849,
+                       28857, 28865, 28873, 28881, 28888, 28896, 28904, 28911, 28919, 28926, 28933, 28941, 28948, 28955, 28962, 28969],
+               [28976, 28990, 29003, 29017, 29030, 29043, 29056, 29068, 29081, 29093, 29105, 29117, 29129, 29140, 29152, 29163,
+                       29174, 29185, 29196, 29207, 29218, 29228, 29239, 29249, 29259, 29269, 29279, 29289, 29299, 29308, 29318, 29327,
+                       29337, 29346, 29355, 29364, 29373, 29382, 29390, 29399, 29408, 29416, 29425, 29433, 29441, 29450, 29458, 29466,
+                       29474, 29482, 29489, 29497, 29505, 29513, 29520, 29528, 29535, 29542, 29550, 29557, 29564, 29571, 29578, 29585],
+               [29592, 29606, 29620, 29633, 29646, 29659, 29672, 29685, 29697, 29709, 29722, 29734, 29745, 29757, 29768, 29780,
+                       29791, 29802, 29813, 29824, 29834, 29845, 29855, 29866, 29876, 29886, 29896, 29906, 29915, 29925, 29934, 29944,
+                       29953, 29962, 29971, 29980, 29989, 29998, 30007, 30016, 30024, 30033, 30041, 30050, 30058, 30066, 30074, 30082,
+                       30090, 30098, 30106, 30114, 30121, 30129, 30137, 30144, 30152, 30159, 30166, 30174, 30181, 30188, 30195, 30202],
+               [30209, 30223, 30236, 30250, 30263, 30276, 30289, 30301, 30314, 30326, 30338, 30350, 30362, 30373, 30385, 30396,
+                       30407, 30418, 30429, 30440, 30451, 30461, 30472, 30482, 30492, 30502, 30512, 30522, 30532, 30541, 30551, 30560,
+                       30570, 30579, 30588, 30597, 30606, 30615, 30624, 30632, 30641, 30649, 30658, 30666, 30674, 30683, 30691, 30699,
+                       30707, 30715, 30722, 30730, 30738, 30746, 30753, 30761, 30768, 30775, 30783, 30790, 30797, 30804, 30811, 30818],
+               [30825, 30839, 30853, 30866, 30879, 30892, 30905, 30918, 30930, 30943, 30955, 30967, 30978, 30990, 31001, 31013,
+                       31024, 31035, 31046, 31057, 31067, 31078, 31088, 31099, 31109, 31119, 31129, 31139, 31148, 31158, 31167, 31177,
+                       31186, 31195, 31204, 31213, 31222, 31231, 31240, 31249, 31257, 31266, 31274, 31283, 31291, 31299, 31307, 31315,
+                       31323, 31331, 31339, 31347, 31354, 31362, 31370, 31377, 31385, 31392, 31399, 31407, 31414, 31421, 31428, 31435],
+               [31442, 31456, 31469, 31483, 31496, 31509, 31522, 31534, 31547, 31559, 31571, 31583, 31595, 31606, 31618, 31629,
+                       31640, 31652, 31662, 31673, 31684, 31694, 31705, 31715, 31725, 31735, 31745, 31755, 31765, 31774, 31784, 31793,
+                       31803, 31812, 31821, 31830, 31839, 31848, 31857, 31865, 31874, 31882, 31891, 31899, 31907, 31916, 31924, 31932,
+                       31940, 31948, 31955, 31963, 31971, 31979, 31986, 31994, 32001, 32008, 32016, 32023, 32030, 32037, 32044, 32052],
+               [32058, 32072, 32086, 32099, 32112, 32125, 32138, 32151, 32163, 32176, 32188, 32200, 32211, 32223, 32234, 32246,
+                       32257, 32268, 32279, 32290, 32300, 32311, 32321, 32332, 32342, 32352, 32362, 32372, 32381, 32391, 32400, 32410,
+                       32419, 32428, 32437, 32446, 32455, 32464, 32473, 32482, 32490, 32499, 32507, 32516, 32524, 32532, 32540, 32548,
+                       32556, 32564, 32572, 32580, 32587, 32595, 32603, 32610, 32618, 32625, 32632, 32640, 32647, 32654, 32661, 32668],
+               [32675, 32689, 32702, 32716, 32729, 32742, 32755, 32767, 32780, 32792, 32804, 32816, 32828, 32839, 32851, 32862,
+                       32873, 32885, 32895, 32906, 32917, 32927, 32938, 32948, 32958, 32968, 32978, 32988, 32998, 33007, 33017, 33026,
+                       33036, 33045, 33054, 33063, 33072, 33081, 33090, 33098, 33107, 33115, 33124, 33132, 33140, 33149, 33157, 33165,
+                       33173, 33181, 33188, 33196, 33204, 33212, 33219, 33227, 33234, 33241, 33249, 33256, 33263, 33270, 33278, 33285],
+               [33292, 33305, 33319, 33332, 33345, 33358, 33371, 33384, 33396, 33409, 33421, 33433, 33444, 33456, 33467, 33479,
+                       33490, 33501, 33512, 33523, 33533, 33544, 33554, 33565, 33575, 33585, 33595, 33605, 33614, 33624, 33633, 33643,
+                       33652, 33661, 33670, 33680, 33688, 33697, 33706, 33715, 33723, 33732, 33740, 33749, 33757, 33765, 33773, 33781,
+                       33789, 33797, 33805, 33813, 33820, 33828, 33836, 33843, 33851, 33858, 33865, 33873, 33880, 33887, 33894, 33901],
+               [33908, 33922, 33935, 33949, 33962, 33975, 33988, 34000, 34013, 34025, 34037, 34049, 34061, 34072, 34084, 34095,
+                       34106, 34118, 34128, 34139, 34150, 34160, 34171, 34181, 34191, 34201, 34211, 34221, 34231, 34240, 34250, 34259,
+                       34269, 34278, 34287, 34296, 34305, 34314, 34323, 34331, 34340, 34348, 34357, 34365, 34373, 34382, 34390, 34398,
+                       34406, 34414, 34422, 34429, 34437, 34445, 34452, 34460, 34467, 34475, 34482, 34489, 34496, 34503, 34511, 34518],
+               [34525, 34538, 34552, 34565, 34578, 34591, 34604, 34617, 34629, 34642, 34654, 34666, 34677, 34689, 34700, 34712,
+                       34723, 34734, 34745, 34756, 34766, 34777, 34787, 34798, 34808, 34818, 34828, 34838, 34847, 34857, 34866, 34876,
+                       34885, 34894, 34904, 34913, 34921, 34930, 34939, 34948, 34956, 34965, 34973, 34982, 34990, 34998, 35006, 35014,
+                       35022, 35030, 35038, 35046, 35053, 35061, 35069, 35076, 35084, 35091, 35098, 35106, 35113, 35120, 35127, 35134],
+               [35141, 35155, 35168, 35182, 35195, 35208, 35221, 35233, 35246, 35258, 35270, 35282, 35294, 35306, 35317, 35328,
+                       35340, 35351, 35361, 35372, 35383, 35393, 35404, 35414, 35424, 35434, 35444, 35454, 35464, 35473, 35483, 35492,
+                       35502, 35511, 35520, 35529, 35538, 35547, 35556, 35564, 35573, 35581, 35590, 35598, 35606, 35615, 35623, 35631,
+                       35639, 35647, 35655, 35662, 35670, 35678, 35685, 35693, 35700, 35708, 35715, 35722, 35729, 35736, 35744, 35751],
+               [35758, 35771, 35785, 35798, 35811, 35824, 35837, 35850, 35862, 35875, 35887, 35899, 35910, 35922, 35934, 35945,
+                       35956, 35967, 35978, 35989, 35999, 36010, 36020, 36031, 36041, 36051, 36061, 36071, 36080, 36090, 36099, 36109,
+                       36118, 36127, 36137, 36146, 36154, 36163, 36172, 36181, 36189, 36198, 36206, 36215, 36223, 36231, 36239, 36247,
+                       36255, 36263, 36271, 36279, 36287, 36294, 36302, 36309, 36317, 36324, 36331, 36339, 36346, 36353, 36360, 36367],
+               [36374, 36388, 36401, 36415, 36428, 36441, 36454, 36466, 36479, 36491, 36503, 36515, 36527, 36539, 36550, 36561,
+                       36573, 36584, 36594, 36605, 36616, 36626, 36637, 36647, 36657, 36667, 36677, 36687, 36697, 36706, 36716, 36725,
+                       36735, 36744, 36753, 36762, 36771, 36780, 36789, 36797, 36806, 36814, 36823, 36831, 36839, 36848, 36856, 36864,
+                       36872, 36880, 36888, 36895, 36903, 36911, 36918, 36926, 36933, 36941, 36948, 36955, 36962, 36969, 36977, 36984],
+               [36991, 37004, 37018, 37031, 37044, 37057, 37070, 37083, 37095, 37108, 37120, 37132, 37143, 37155, 37167, 37178,
+                       37189, 37200, 37211, 37222, 37232, 37243, 37253, 37264, 37274, 37284, 37294, 37304, 37313, 37323, 37332, 37342,
+                       37351, 37360, 37370, 37379, 37388, 37396, 37405, 37414, 37422, 37431, 37439, 37448, 37456, 37464, 37472, 37480,
+                       37488, 37496, 37504, 37512, 37520, 37527, 37535, 37542, 37550, 37557, 37564, 37572, 37579, 37586, 37593, 37600],
+               [37607, 37621, 37634, 37648, 37661, 37674, 37687, 37699, 37712, 37724, 37736, 37748, 37760, 37772, 37783, 37794,
+                       37806, 37817, 37828, 37838, 37849, 37859, 37870, 37880, 37890, 37900, 37910, 37920, 37930, 37939, 37949, 37958,
+                       37968, 37977, 37986, 37995, 38004, 38013, 38022, 38030, 38039, 38047, 38056, 38064, 38072, 38081, 38089, 38097,
+                       38105, 38113, 38121, 38128, 38136, 38144, 38151, 38159, 38166, 38174, 38181, 38188, 38195, 38202, 38210, 38217],
+               [38224, 38237, 38251, 38264, 38278, 38290, 38303, 38316, 38328, 38341, 38353, 38365, 38376, 38388, 38400, 38411,
+                       38422, 38433, 38444, 38455, 38465, 38476, 38486, 38497, 38507, 38517, 38527, 38537, 38546, 38556, 38565, 38575,
+                       38584, 38593, 38603, 38612, 38621, 38629, 38638, 38647, 38655, 38664, 38672, 38681, 38689, 38697, 38705, 38713,
+                       38721, 38729, 38737, 38745, 38753, 38760, 38768, 38775, 38783, 38790, 38797, 38805, 38812, 38819, 38826, 38833],
+               [38840, 38854, 38867, 38881, 38894, 38907, 38920, 38932, 38945, 38957, 38969, 38981, 38993, 39005, 39016, 39027,
+                       39039, 39050, 39061, 39071, 39082, 39092, 39103, 39113, 39123, 39133, 39143, 39153, 39163, 39172, 39182, 39191,
+                       39201, 39210, 39219, 39228, 39237, 39246, 39255, 39263, 39272, 39280, 39289, 39297, 39305, 39314, 39322, 39330,
+                       39338, 39346, 39354, 39361, 39369, 39377, 39384, 39392, 39399, 39407, 39414, 39421, 39428, 39436, 39443, 39450],
        ];
 
-       /// Approximate `log10(numerator / denominator) * 1024` using a look-up table.
+       /// Approximate `log10(numerator / denominator) * 2048` using a look-up table.
        #[inline]
-       pub fn negative_log10_times_1024(numerator: u64, denominator: u64) -> u64 {
+       pub fn negative_log10_times_2048(numerator: u64, denominator: u64) -> u64 {
                // Multiply the -1 through to avoid needing to use signed numbers.
-               (log10_times_1024(denominator) - log10_times_1024(numerator)) as u64
+               (log10_times_2048(denominator) - log10_times_2048(numerator)) as u64
        }
 
        #[inline]
-       fn log10_times_1024(x: u64) -> u16 {
+       fn log10_times_2048(x: u64) -> u16 {
                debug_assert_ne!(x, 0);
                let most_significant_bit = HIGHEST_BIT - x.leading_zeros();
                let lower_bits = (x >> most_significant_bit.saturating_sub(LOWER_BITS)) & LOWER_BITMASK;
-               LOG10_TIMES_1024[most_significant_bit as usize][lower_bits as usize]
+               LOG10_TIMES_2048[most_significant_bit as usize][lower_bits as usize]
        }
 
        #[cfg(test)]
@@ -981,19 +1184,21 @@ mod approx {
                use super::*;
 
                #[test]
-               fn prints_negative_log10_times_1024_lookup_table() {
+               fn prints_negative_log10_times_2048_lookup_table() {
                        for msb in 0..BITS {
                                for i in 0..LOWER_BITS_BOUND {
                                        let x = ((LOWER_BITS_BOUND + i) << (HIGHEST_BIT - LOWER_BITS)) >> (HIGHEST_BIT - msb);
-                                       let log10_times_1024 = ((x as f64).log10() * 1024.0).round() as u16;
-                                       assert_eq!(log10_times_1024, LOG10_TIMES_1024[msb as usize][i as usize]);
+                                       let log10_times_2048 = ((x as f64).log10() * 2048.0).round() as u16;
+                                       assert_eq!(log10_times_2048, LOG10_TIMES_2048[msb as usize][i as usize]);
 
                                        if i % LOWER_BITS_BOUND == 0 {
-                                               print!("\t\t[{}, ", log10_times_1024);
+                                               print!("\t\t[{}, ", log10_times_2048);
                                        } else if i % LOWER_BITS_BOUND == LOWER_BITS_BOUND - 1 {
-                                               println!("{}],", log10_times_1024);
+                                               println!("{}],", log10_times_2048);
+                                       } else if i % (LOWER_BITS_BOUND/4) == LOWER_BITS_BOUND/4 - 1 {
+                                               print!("{},\n\t\t\t", log10_times_2048);
                                        } else {
-                                               print!("{}, ", log10_times_1024);
+                                               print!("{}, ", log10_times_2048);
                                        }
                                }
                        }
@@ -1814,17 +2019,17 @@ mod tests {
                let target = target_node_id();
 
                assert_eq!(scorer.channel_penalty_msat(42, 1_024, 1_024_000, &source, &target), 0);
-               assert_eq!(scorer.channel_penalty_msat(42, 10_240, 1_024_000, &source, &target), 14);
-               assert_eq!(scorer.channel_penalty_msat(42, 102_400, 1_024_000, &source, &target), 43);
+               assert_eq!(scorer.channel_penalty_msat(42, 10_240, 1_024_000, &source, &target), 0);
+               assert_eq!(scorer.channel_penalty_msat(42, 102_400, 1_024_000, &source, &target), 47);
                assert_eq!(scorer.channel_penalty_msat(42, 1_024_000, 1_024_000, &source, &target), 2_000);
 
                assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 58);
                assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 125);
-               assert_eq!(scorer.channel_penalty_msat(42, 374, 1_024, &source, &target), 204);
-               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 301);
-               assert_eq!(scorer.channel_penalty_msat(42, 640, 1_024, &source, &target), 426);
+               assert_eq!(scorer.channel_penalty_msat(42, 374, 1_024, &source, &target), 198);
+               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 300);
+               assert_eq!(scorer.channel_penalty_msat(42, 640, 1_024, &source, &target), 425);
                assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 602);
-               assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 903);
+               assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 902);
        }
 
        #[test]
@@ -1862,13 +2067,13 @@ mod tests {
                let failed_path = payment_path_for_amount(500);
                let successful_path = payment_path_for_amount(200);
 
-               assert_eq!(scorer.channel_penalty_msat(41, 500, 1_000, &sender, &source), 300);
+               assert_eq!(scorer.channel_penalty_msat(41, 500, 1_000, &sender, &source), 301);
 
                scorer.payment_path_failed(&failed_path.iter().collect::<Vec<_>>(), 41);
-               assert_eq!(scorer.channel_penalty_msat(41, 500, 1_000, &sender, &source), 300);
+               assert_eq!(scorer.channel_penalty_msat(41, 500, 1_000, &sender, &source), 301);
 
                scorer.payment_path_successful(&successful_path.iter().collect::<Vec<_>>());
-               assert_eq!(scorer.channel_penalty_msat(41, 500, 1_000, &sender, &source), 300);
+               assert_eq!(scorer.channel_penalty_msat(41, 500, 1_000, &sender, &source), 301);
        }
 
        #[test]
@@ -1884,8 +2089,8 @@ mod tests {
                let path = payment_path_for_amount(500);
 
                assert_eq!(scorer.channel_penalty_msat(42, 250, 1_000, &source, &target), 128);
-               assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 300);
-               assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), 601);
+               assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 301);
+               assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), 602);
 
                scorer.payment_path_failed(&path.iter().collect::<Vec<_>>(), 43);
 
@@ -1907,8 +2112,8 @@ mod tests {
                let path = payment_path_for_amount(500);
 
                assert_eq!(scorer.channel_penalty_msat(42, 250, 1_000, &source, &target), 128);
-               assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 300);
-               assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), 601);
+               assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 301);
+               assert_eq!(scorer.channel_penalty_msat(42, 750, 1_000, &source, &target), 602);
 
                scorer.payment_path_failed(&path.iter().collect::<Vec<_>>(), 42);
 
@@ -1961,20 +2166,20 @@ mod tests {
                scorer.payment_path_failed(&payment_path_for_amount(128).iter().collect::<Vec<_>>(), 43);
 
                assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 0);
-               assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 97);
-               assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_409);
+               assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 93);
+               assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_479);
                assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), u64::max_value());
 
                SinceEpoch::advance(Duration::from_secs(9));
                assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 0);
-               assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 97);
-               assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_409);
+               assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 93);
+               assert_eq!(scorer.channel_penalty_msat(42, 768, 1_024, &source, &target), 1_479);
                assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), u64::max_value());
 
                SinceEpoch::advance(Duration::from_secs(1));
                assert_eq!(scorer.channel_penalty_msat(42, 64, 1_024, &source, &target), 0);
                assert_eq!(scorer.channel_penalty_msat(42, 128, 1_024, &source, &target), 34);
-               assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 1_773);
+               assert_eq!(scorer.channel_penalty_msat(42, 896, 1_024, &source, &target), 1_970);
                assert_eq!(scorer.channel_penalty_msat(42, 960, 1_024, &source, &target), u64::max_value());
 
                // Fully decay liquidity lower bound.
@@ -2008,7 +2213,7 @@ mod tests {
                assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 125);
 
                scorer.payment_path_failed(&payment_path_for_amount(512).iter().collect::<Vec<_>>(), 42);
-               assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 274);
+               assert_eq!(scorer.channel_penalty_msat(42, 256, 1_024, &source, &target), 281);
 
                // An unchecked right shift 64 bits or more in DirectedChannelLiquidity::decayed_offset_msat
                // would cause an overflow.
@@ -2031,30 +2236,30 @@ mod tests {
                let source = source_node_id();
                let target = target_node_id();
 
-               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 301);
+               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 300);
 
                // More knowledge gives higher confidence (256, 768), meaning a lower penalty.
                scorer.payment_path_failed(&payment_path_for_amount(768).iter().collect::<Vec<_>>(), 42);
                scorer.payment_path_failed(&payment_path_for_amount(256).iter().collect::<Vec<_>>(), 43);
-               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 274);
+               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 281);
 
                // Decaying knowledge gives less confidence (128, 896), meaning a higher penalty.
                SinceEpoch::advance(Duration::from_secs(10));
-               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 301);
+               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 291);
 
                // Reducing the upper bound gives more confidence (128, 832) that the payment amount (512)
                // is closer to the upper bound, meaning a higher penalty.
                scorer.payment_path_successful(&payment_path_for_amount(64).iter().collect::<Vec<_>>());
-               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 342);
+               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 331);
 
                // Increasing the lower bound gives more confidence (256, 832) that the payment amount (512)
                // is closer to the lower bound, meaning a lower penalty.
                scorer.payment_path_failed(&payment_path_for_amount(256).iter().collect::<Vec<_>>(), 43);
-               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 255);
+               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 245);
 
                // Further decaying affects the lower bound more than the upper bound (128, 928).
                SinceEpoch::advance(Duration::from_secs(10));
-               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 284);
+               assert_eq!(scorer.channel_penalty_msat(42, 512, 1_024, &source, &target), 280);
        }
 
        #[test]
@@ -2073,7 +2278,7 @@ mod tests {
                assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), u64::max_value());
 
                SinceEpoch::advance(Duration::from_secs(10));
-               assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 472);
+               assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 473);
 
                scorer.payment_path_failed(&payment_path_for_amount(250).iter().collect::<Vec<_>>(), 43);
                assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 300);
@@ -2110,13 +2315,36 @@ mod tests {
                let mut serialized_scorer = io::Cursor::new(&serialized_scorer);
                let deserialized_scorer =
                        <ProbabilisticScorer>::read(&mut serialized_scorer, (params, &network_graph)).unwrap();
-               assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 472);
+               assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 473);
 
                scorer.payment_path_failed(&payment_path_for_amount(250).iter().collect::<Vec<_>>(), 43);
                assert_eq!(scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 300);
 
                SinceEpoch::advance(Duration::from_secs(10));
-               assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 371);
+               assert_eq!(deserialized_scorer.channel_penalty_msat(42, 500, 1_000, &source, &target), 365);
+       }
+
+       #[test]
+       fn scores_realistic_payments() {
+               // Shows the scores of "realistic" sends of 100k sats over channels of 1-10m sats (with a
+               // 50k sat reserve).
+               let network_graph = network_graph();
+               let params = ProbabilisticScoringParameters::default();
+               let scorer = ProbabilisticScorer::new(params, &network_graph);
+               let source = source_node_id();
+               let target = target_node_id();
+
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 950_000_000, &source, &target), 3613);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 1_950_000_000, &source, &target), 1977);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 2_950_000_000, &source, &target), 1474);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 3_950_000_000, &source, &target), 1223);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 4_950_000_000, &source, &target), 877);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 5_950_000_000, &source, &target), 845);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 6_950_000_000, &source, &target), 500);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 7_450_000_000, &source, &target), 500);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 7_950_000_000, &source, &target), 500);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 8_950_000_000, &source, &target), 500);
+               assert_eq!(scorer.channel_penalty_msat(42, 100_000_000, 9_950_000_000, &source, &target), 500);
        }
 
        #[test]
index ea50398b5e54ad2d2d1c691dadd31b0f3fe341fb..d7eb16eee5267107224fd4b5ff2240f6b56ea1bb 100644 (file)
@@ -343,6 +343,9 @@ pub enum Event {
        /// This event is generated when a payment has been successfully forwarded through us and a
        /// forwarding fee earned.
        PaymentForwarded {
+               /// The channel between the source node and us. Optional because versions prior to 0.0.107
+               /// do not serialize this field.
+               source_channel_id: Option<[u8; 32]>,
                /// The fee, in milli-satoshis, which was earned as a result of the payment.
                ///
                /// Note that if we force-closed the channel over which we forwarded an HTLC while the HTLC
@@ -520,10 +523,11 @@ impl Writeable for Event {
                                        (0, VecWriteWrapper(outputs), required),
                                });
                        },
-                       &Event::PaymentForwarded { fee_earned_msat, claim_from_onchain_tx } => {
+                       &Event::PaymentForwarded { fee_earned_msat, source_channel_id, claim_from_onchain_tx } => {
                                7u8.write(writer)?;
                                write_tlv_fields!(writer, {
                                        (0, fee_earned_msat, option),
+                                       (1, source_channel_id, option),
                                        (2, claim_from_onchain_tx, required),
                                });
                        },
@@ -684,12 +688,14 @@ impl MaybeReadable for Event {
                        7u8 => {
                                let f = || {
                                        let mut fee_earned_msat = None;
+                                       let mut source_channel_id = None;
                                        let mut claim_from_onchain_tx = false;
                                        read_tlv_fields!(reader, {
                                                (0, fee_earned_msat, option),
+                                               (1, source_channel_id, option),
                                                (2, claim_from_onchain_tx, required),
                                        });
-                                       Ok(Some(Event::PaymentForwarded { fee_earned_msat, claim_from_onchain_tx }))
+                                       Ok(Some(Event::PaymentForwarded { fee_earned_msat, source_channel_id, claim_from_onchain_tx }))
                                };
                                f()
                        },
index a1e92a0f8cfe29ce2f72ff300b65f021645ab616..95826b7e06ee73e0a02b3e1b36cf8ac6ef9ed12e 100644 (file)
@@ -20,6 +20,7 @@ pub mod errors;
 pub mod ser;
 pub mod message_signing;
 pub mod invoice;
+pub mod persist;
 
 pub(crate) mod atomic_counter;
 pub(crate) mod byte_utils;
diff --git a/lightning/src/util/persist.rs b/lightning/src/util/persist.rs
new file mode 100644 (file)
index 0000000..9476331
--- /dev/null
@@ -0,0 +1,77 @@
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! This module contains a simple key-value store trait KVStorePersister that
+//! allows one to implement the persistence for [`ChannelManager`], [`NetworkGraph`],
+//! and [`ChannelMonitor`] all in one place.
+
+use core::ops::Deref;
+use bitcoin::hashes::hex::ToHex;
+use io::{self};
+
+use crate::{chain::{keysinterface::{Sign, KeysInterface}, self, transaction::{OutPoint}, chaininterface::{BroadcasterInterface, FeeEstimator}, chainmonitor::{Persist, MonitorUpdateId}, channelmonitor::{ChannelMonitor, ChannelMonitorUpdate}}, ln::channelmanager::ChannelManager, routing::network_graph::NetworkGraph};
+use super::{logger::Logger, ser::Writeable};
+
+/// Trait for a key-value store for persisting some writeable object at some key
+/// Implementing `KVStorePersister` provides auto-implementations for [`Persister`]
+/// and [`Persist`] traits.  It uses "manager", "network_graph",
+/// and "monitors/{funding_txo_id}_{funding_txo_index}" for keys.
+pub trait KVStorePersister {
+       /// Persist the given writeable using the provided key
+       fn persist<W: Writeable>(&self, key: &str, object: &W) -> io::Result<()>;
+}
+
+/// Trait that handles persisting a [`ChannelManager`] and [`NetworkGraph`] to disk.
+pub trait Persister<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
+       where M::Target: 'static + chain::Watch<Signer>,
+               T::Target: 'static + BroadcasterInterface,
+               K::Target: 'static + KeysInterface<Signer = Signer>,
+               F::Target: 'static + FeeEstimator,
+               L::Target: 'static + Logger,
+{
+       /// Persist the given ['ChannelManager'] to disk, returning an error if persistence failed.
+       fn persist_manager(&self, channel_manager: &ChannelManager<Signer, M, T, K, F, L>) -> Result<(), io::Error>;
+
+       /// Persist the given [`NetworkGraph`] to disk, returning an error if persistence failed.
+       fn persist_graph(&self, network_graph: &NetworkGraph) -> Result<(), io::Error>;
+}
+
+impl<A: KVStorePersister, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> Persister<Signer, M, T, K, F, L> for A
+       where M::Target: 'static + chain::Watch<Signer>,
+               T::Target: 'static + BroadcasterInterface,
+               K::Target: 'static + KeysInterface<Signer = Signer>,
+               F::Target: 'static + FeeEstimator,
+               L::Target: 'static + Logger,
+{
+       /// Persist the given ['ChannelManager'] to disk, returning an error if persistence failed.
+       fn persist_manager(&self, channel_manager: &ChannelManager<Signer, M, T, K, F, L>) -> Result<(), io::Error> {
+               self.persist("manager", channel_manager)
+       }
+
+       /// Persist the given [`NetworkGraph`] to disk, returning an error if persistence failed.
+       fn persist_graph(&self, network_graph: &NetworkGraph) -> Result<(), io::Error> {
+               self.persist("network_graph", network_graph)
+       }
+}
+
+impl<ChannelSigner: Sign, K: KVStorePersister> Persist<ChannelSigner> for K {
+       // TODO: We really need a way for the persister to inform the user that its time to crash/shut
+       // down once these start returning failure.
+       // A PermanentFailure implies we need to shut down since we're force-closing channels without
+       // even broadcasting!
+
+       fn persist_new_channel(&self, funding_txo: OutPoint, monitor: &ChannelMonitor<ChannelSigner>, _update_id: MonitorUpdateId) -> Result<(), chain::ChannelMonitorUpdateErr> {
+               let key = format!("monitors/{}_{}", funding_txo.txid.to_hex(), funding_txo.index);
+               self.persist(&key, monitor)
+                       .map_err(|_| chain::ChannelMonitorUpdateErr::PermanentFailure)
+       }
+
+       fn update_persisted_channel(&self, funding_txo: OutPoint, _update: &Option<ChannelMonitorUpdate>, monitor: &ChannelMonitor<ChannelSigner>, _update_id: MonitorUpdateId) -> Result<(), chain::ChannelMonitorUpdateErr> {
+               let key = format!("monitors/{}_{}", funding_txo.txid.to_hex(), funding_txo.index);
+               self.persist(&key, monitor)
+                       .map_err(|_| chain::ChannelMonitorUpdateErr::PermanentFailure)
+       }
+}