X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-rapid-gossip-sync%2Fsrc%2Flib.rs;h=70758e1fe07e6a5ae0f5a430ac374ee3ae5708be;hb=8c6cb9953a3b00ce3da25fbdfd8ada0ec48fc63f;hp=4ab1028c7393e3781c45673a9e70852046f2c14b;hpb=08ab6581f1c6254a7765340c5c7a553db58d3a89;p=rust-lightning diff --git a/lightning-rapid-gossip-sync/src/lib.rs b/lightning-rapid-gossip-sync/src/lib.rs index 4ab1028c..70758e1f 100644 --- a/lightning-rapid-gossip-sync/src/lib.rs +++ b/lightning-rapid-gossip-sync/src/lib.rs @@ -1,6 +1,9 @@ +// 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(missing_docs)] #![deny(unsafe_code)] -#![deny(broken_intra_doc_links)] #![deny(non_upper_case_globals)] #![deny(non_camel_case_types)] #![deny(non_snake_case)] @@ -29,11 +32,20 @@ //! ``` //! use bitcoin::blockdata::constants::genesis_block; //! use bitcoin::Network; -//! use lightning::routing::network_graph::NetworkGraph; +//! use lightning::routing::gossip::NetworkGraph; +//! use lightning_rapid_gossip_sync::RapidGossipSync; +//! +//! # use lightning::util::logger::{Logger, Record}; +//! # struct FakeLogger {} +//! # impl Logger for FakeLogger { +//! # fn log(&self, record: &Record) { unimplemented!() } +//! # } +//! # let logger = FakeLogger {}; //! //! let block_hash = genesis_block(Network::Bitcoin).header.block_hash(); -//! let network_graph = NetworkGraph::new(block_hash); -//! let new_last_sync_timestamp_result = lightning_rapid_gossip_sync::sync_network_graph_with_file_path(&network_graph, "./rapid_sync.lngossip"); +//! let network_graph = NetworkGraph::new(block_hash, &logger); +//! let rapid_sync = RapidGossipSync::new(&network_graph); +//! let new_last_sync_timestamp_result = rapid_sync.sync_network_graph_with_file_path("./rapid_sync.lngossip"); //! ``` //! //! The primary benefit this syncing mechanism provides is that given a trusted server, a @@ -57,8 +69,11 @@ extern crate test; use std::fs::File; +use std::ops::Deref; +use std::sync::atomic::{AtomicBool, Ordering}; -use lightning::routing::network_graph; +use lightning::routing::gossip::NetworkGraph; +use lightning::util::logger::Logger; use crate::error::GraphSyncError; @@ -68,19 +83,52 @@ pub mod error; /// Core functionality of this crate pub mod processing; -/// Sync gossip data from a file -/// Returns the last sync timestamp to be used the next time rapid sync data is queried. -/// -/// `network_graph`: The network graph to apply the updates to +/// Rapid Gossip Sync struct +/// See [crate-level documentation] for usage. /// -/// `sync_path`: Path to the file where the gossip update data is located -/// -pub fn sync_network_graph_with_file_path( - network_graph: &network_graph::NetworkGraph, - sync_path: &str, -) -> Result { - let mut file = File::open(sync_path)?; - processing::update_network_graph_from_byte_stream(&network_graph, &mut file) +/// [crate-level documentation]: crate +pub struct RapidGossipSync>, L: Deref> +where L::Target: Logger { + network_graph: NG, + is_initial_sync_complete: AtomicBool +} + +impl>, L: Deref> RapidGossipSync where L::Target: Logger { + /// Instantiate a new [`RapidGossipSync`] instance + pub fn new(network_graph: NG) -> Self { + Self { + network_graph, + is_initial_sync_complete: AtomicBool::new(false) + } + } + + /// Sync gossip data from a file + /// Returns the last sync timestamp to be used the next time rapid sync data is queried. + /// + /// `network_graph`: The network graph to apply the updates to + /// + /// `sync_path`: Path to the file where the gossip update data is located + /// + pub fn sync_network_graph_with_file_path( + &self, + sync_path: &str, + ) -> Result { + let mut file = File::open(sync_path)?; + self.update_network_graph_from_byte_stream(&mut file) + } + + /// 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 + pub fn network_graph(&self) -> &NG { + &self.network_graph + } + + /// Returns whether a rapid gossip sync has completed at least once + pub fn is_initial_sync_complete(&self) -> bool { + self.is_initial_sync_complete.load(Ordering::Acquire) + } } #[cfg(test)] @@ -91,9 +139,9 @@ mod tests { use bitcoin::Network; use lightning::ln::msgs::DecodeError; - use lightning::routing::network_graph::NetworkGraph; - - use crate::sync_network_graph_with_file_path; + use lightning::routing::gossip::NetworkGraph; + use lightning::util::test_utils::TestLogger; + use crate::RapidGossipSync; #[test] fn test_sync_from_file() { @@ -152,11 +200,13 @@ mod tests { let graph_sync_test_file = sync_test.get_test_file_path(); let block_hash = genesis_block(Network::Bitcoin).block_hash(); - let network_graph = NetworkGraph::new(block_hash); + let logger = TestLogger::new(); + let network_graph = NetworkGraph::new(block_hash, &logger); assert_eq!(network_graph.read_only().channels().len(), 0); - let sync_result = sync_network_graph_with_file_path(&network_graph, &graph_sync_test_file); + let rapid_sync = RapidGossipSync::new(&network_graph); + let sync_result = rapid_sync.sync_network_graph_with_file_path(&graph_sync_test_file); if sync_result.is_err() { panic!("Unexpected sync result: {:?}", sync_result) @@ -183,20 +233,23 @@ mod tests { #[test] fn measure_native_read_from_file() { let block_hash = genesis_block(Network::Bitcoin).block_hash(); - let network_graph = NetworkGraph::new(block_hash); + let logger = TestLogger::new(); + let network_graph = NetworkGraph::new(block_hash, &logger); assert_eq!(network_graph.read_only().channels().len(), 0); + let rapid_sync = RapidGossipSync::new(&network_graph); let start = std::time::Instant::now(); - let sync_result = - sync_network_graph_with_file_path(&network_graph, "./res/full_graph.lngossip"); + 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-graph-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); + 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))] { println!("{}", error_string); return; } + #[cfg(require_route_graph_test)] panic!("{}", error_string); } let elapsed = start.elapsed(); @@ -215,26 +268,27 @@ pub mod bench { use bitcoin::Network; use lightning::ln::msgs::DecodeError; - use lightning::routing::network_graph::NetworkGraph; + use lightning::routing::gossip::NetworkGraph; + use lightning::util::test_utils::TestLogger; - use crate::sync_network_graph_with_file_path; + use crate::RapidGossipSync; #[bench] fn bench_reading_full_graph_from_file(b: &mut Bencher) { let block_hash = genesis_block(Network::Bitcoin).block_hash(); + let logger = TestLogger::new(); b.iter(|| { - let network_graph = NetworkGraph::new(block_hash); - let sync_result = sync_network_graph_with_file_path( - &network_graph, - "./res/full_graph.lngossip", - ); + let network_graph = NetworkGraph::new(block_hash, &logger); + let rapid_sync = RapidGossipSync::new(&network_graph); + 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-graph-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); + 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())