Merge pull request #3127 from wvanlint/non_strict_forwarding
[rust-lightning] / lightning-rapid-gossip-sync / src / lib.rs
index 00aac9fd35873a8b31a218c2fa692a1664302c9a..c6951301cd774d701aa476f4612b5209e80b54ef 100644 (file)
@@ -1,7 +1,5 @@
-// Prefix these with `rustdoc::` when we update our MSRV to be >= 1.52 to remove warnings.
-#![deny(broken_intra_doc_links)]
-#![deny(private_intra_doc_links)]
-
+#![deny(rustdoc::broken_intra_doc_links)]
+#![deny(rustdoc::private_intra_doc_links)]
 #![deny(missing_docs)]
 #![deny(unsafe_code)]
 #![deny(non_upper_case_globals)]
 //! # use lightning::util::logger::{Logger, Record};
 //! # struct FakeLogger {}
 //! # impl Logger for FakeLogger {
-//! #     fn log(&self, record: &Record) { unimplemented!() }
+//! #     fn log(&self, record: Record) { }
 //! # }
 //! # let logger = FakeLogger {};
 //!
 //! let network_graph = NetworkGraph::new(Network::Bitcoin, &logger);
 //! let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
 //! let snapshot_contents: &[u8] = &[0; 0];
-//! let new_last_sync_timestamp_result = rapid_sync.update_network_graph(snapshot_contents);
+//! // In no-std you need to provide the current time in unix epoch seconds
+//! // otherwise you can use update_network_graph
+//! let current_time_unix = 0;
+//! let new_last_sync_timestamp_result = rapid_sync.update_network_graph_no_std(snapshot_contents, Some(current_time_unix));
 //! ```
 
 #![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
 
-// Allow and import test features for benching
-#![cfg_attr(all(test, feature = "_bench_unstable"), feature(test))]
-#[cfg(all(test, feature = "_bench_unstable"))]
-extern crate test;
+#[cfg(ldk_bench)]
+extern crate criterion;
 
 #[cfg(not(feature = "std"))]
 extern crate alloc;
 
-#[cfg(feature = "std")]
-use std::fs::File;
 use core::ops::Deref;
 use core::sync::atomic::{AtomicBool, Ordering};
+#[cfg(feature = "std")]
+use std::fs::File;
 
 use lightning::io;
+use lightning::ln::msgs::{DecodeError, LightningError};
 use lightning::routing::gossip::NetworkGraph;
 use lightning::util::logger::Logger;
 
-pub use crate::error::GraphSyncError;
-
-/// Error types that these functions can return
-mod error;
-
 /// Core functionality of this crate
 mod processing;
 
+/// All-encompassing standard error type that processing can return
+#[derive(Debug)]
+pub enum GraphSyncError {
+       /// Error trying to read the update data, typically due to an erroneous data length indication
+       /// that is greater than the actual amount of data provided
+       DecodeError(DecodeError),
+       /// Error applying the patch to the network graph, usually the result of updates that are too
+       /// old or missing prerequisite data to the application of updates out of order
+       LightningError(LightningError),
+}
+
+impl From<io::Error> for GraphSyncError {
+       fn from(error: io::Error) -> Self {
+               Self::DecodeError(DecodeError::Io(error.kind()))
+       }
+}
+
+impl From<bitcoin::secp256k1::Error> for GraphSyncError {
+       fn from(_: bitcoin::secp256k1::Error) -> Self {
+               Self::DecodeError(DecodeError::InvalidValue)
+       }
+}
+
+impl From<DecodeError> for GraphSyncError {
+       fn from(error: DecodeError) -> Self {
+               Self::DecodeError(error)
+       }
+}
+
+impl From<LightningError> for GraphSyncError {
+       fn from(error: LightningError) -> Self {
+               Self::LightningError(error)
+       }
+}
+
 /// The main Rapid Gossip Sync object.
 ///
 /// See [crate-level documentation] for usage.
 ///
 /// [crate-level documentation]: crate
-pub struct RapidGossipSync<NG: Deref<Target=NetworkGraph<L>>, L: Deref>
-where L::Target: Logger {
+pub struct RapidGossipSync<NG: Deref<Target = NetworkGraph<L>>, L: Deref>
+where
+       L::Target: Logger,
+{
        network_graph: NG,
        logger: L,
-       is_initial_sync_complete: AtomicBool
+       is_initial_sync_complete: AtomicBool,
 }
 
-impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
+impl<NG: Deref<Target = NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L>
+where
+       L::Target: Logger,
+{
        /// Instantiate a new [`RapidGossipSync`] instance.
        pub fn new(network_graph: NG, logger: L) -> Self {
-               Self {
-                       network_graph,
-                       logger,
-                       is_initial_sync_complete: AtomicBool::new(false)
-               }
+               Self { network_graph, logger, is_initial_sync_complete: AtomicBool::new(false) }
        }
 
        /// Sync gossip data from a file.
@@ -117,8 +148,7 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
        ///
        #[cfg(feature = "std")]
        pub fn sync_network_graph_with_file_path(
-               &self,
-               sync_path: &str,
+               &self, sync_path: &str,
        ) -> Result<u32, GraphSyncError> {
                let mut file = File::open(sync_path)?;
                self.update_network_graph_from_byte_stream(&mut file)
@@ -128,6 +158,7 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
        /// Returns the last sync timestamp to be used the next time rapid sync data is queried.
        ///
        /// `update_data`: `&[u8]` binary stream that comprises the update data
+       #[cfg(feature = "std")]
        pub fn update_network_graph(&self, update_data: &[u8]) -> Result<u32, GraphSyncError> {
                let mut read_cursor = io::Cursor::new(update_data);
                self.update_network_graph_from_byte_stream(&mut read_cursor)
@@ -138,7 +169,9 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
        ///
        /// `update_data`: `&[u8]` binary stream that comprises the update data
        /// `current_time_unix`: `Option<u64>` optional current timestamp to verify data age
-       pub fn update_network_graph_no_std(&self, update_data: &[u8], current_time_unix: Option<u64>) -> Result<u32, GraphSyncError> {
+       pub fn update_network_graph_no_std(
+               &self, update_data: &[u8], current_time_unix: Option<u64>,
+       ) -> Result<u32, GraphSyncError> {
                let mut read_cursor = io::Cursor::new(update_data);
                self.update_network_graph_from_byte_stream_no_std(&mut read_cursor, current_time_unix)
        }
@@ -146,7 +179,7 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
        /// Gets a reference to the underlying [`NetworkGraph`] which was provided in
        /// [`RapidGossipSync::new`].
        ///
-       /// (C-not exported) as bindings don't support a reference-to-a-reference yet
+       /// This is not exported to bindings users as bindings don't support a reference-to-a-reference yet
        pub fn network_graph(&self) -> &NG {
                &self.network_graph
        }
@@ -164,10 +197,10 @@ mod tests {
 
        use bitcoin::Network;
 
+       use crate::{GraphSyncError, RapidGossipSync};
        use lightning::ln::msgs::DecodeError;
        use lightning::routing::gossip::NetworkGraph;
        use lightning::util::test_utils::TestLogger;
-       use crate::RapidGossipSync;
 
        #[test]
        fn test_sync_from_file() {
@@ -263,9 +296,8 @@ mod tests {
 
                let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
                let start = std::time::Instant::now();
-               let sync_result = rapid_sync
-                       .sync_network_graph_with_file_path("./res/full_graph.lngossip");
-               if let Err(crate::error::GraphSyncError::DecodeError(DecodeError::Io(io_error))) = &sync_result {
+               let sync_result = rapid_sync.sync_network_graph_with_file_path("./res/full_graph.lngossip");
+               if let Err(GraphSyncError::DecodeError(DecodeError::Io(io_error))) = &sync_result {
                        let error_string = format!("Input file lightning-rapid-gossip-sync/res/full_graph.lngossip is missing! Download it from https://bitcoin.ninja/ldk-compressed_graph-285cb27df79-2022-07-21.bin\n\n{:?}", io_error);
                        #[cfg(not(require_route_graph_test))]
                        {
@@ -283,36 +315,42 @@ mod tests {
        }
 }
 
-#[cfg(all(test, feature = "_bench_unstable"))]
+#[cfg(ldk_bench)]
+/// Benches
 pub mod bench {
-       use test::Bencher;
-
        use bitcoin::Network;
 
-       use lightning::ln::msgs::DecodeError;
+       use criterion::Criterion;
+
+       use std::fs;
+
        use lightning::routing::gossip::NetworkGraph;
        use lightning::util::test_utils::TestLogger;
 
        use crate::RapidGossipSync;
 
-       #[bench]
-       fn bench_reading_full_graph_from_file(b: &mut Bencher) {
+       /// Bench!
+       pub fn bench_reading_full_graph_from_file(b: &mut Criterion) {
                let logger = TestLogger::new();
-               b.iter(|| {
+               b.bench_function("read_full_graph_from_rgs", |b| b.iter(|| {
                        let network_graph = NetworkGraph::new(Network::Bitcoin, &logger);
                        let rapid_sync = RapidGossipSync::new(&network_graph, &logger);
-                       let sync_result = rapid_sync.sync_network_graph_with_file_path("./res/full_graph.lngossip");
-                       if let Err(crate::error::GraphSyncError::DecodeError(DecodeError::Io(io_error))) = &sync_result {
-                               let error_string = format!("Input file lightning-rapid-gossip-sync/res/full_graph.lngossip is missing! Download it from https://bitcoin.ninja/ldk-compressed_graph-bc08df7542-2022-05-05.bin\n\n{:?}", io_error);
-                               #[cfg(not(require_route_graph_test))]
-                               {
-                                       println!("{}", error_string);
-                                       return;
-                               }
-                               #[cfg(require_route_graph_test)]
-                               panic!("{}", error_string);
-                       }
-                       assert!(sync_result.is_ok())
-               });
+                       let mut file = match fs::read("../lightning-rapid-gossip-sync/res/full_graph.lngossip") {
+                               Ok(f) => f,
+                               Err(io_error) => {
+                                       let error_string = format!(
+                                               "Input file lightning-rapid-gossip-sync/res/full_graph.lngossip is missing! Download it from https://bitcoin.ninja/ldk-compressed_graph-bc08df7542-2022-05-05.bin\n\n{:?}",
+                                               io_error);
+                                       #[cfg(not(require_route_graph_test))]
+                                       {
+                                               println!("{}", error_string);
+                                               return;
+                                       }
+                                       #[cfg(require_route_graph_test)]
+                                       panic!("{}", error_string);
+                               },
+                       };
+                       rapid_sync.update_network_graph_no_std(&mut file, None).unwrap();
+               }));
        }
 }