+// 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)]
//! ```
//! 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
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;
/// 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<u32, GraphSyncError> {
- 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<NG: Deref<Target=NetworkGraph<L>>, L: Deref>
+where L::Target: Logger {
+ network_graph: NG,
+ is_initial_sync_complete: AtomicBool
+}
+
+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) -> 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<u32, GraphSyncError> {
+ 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)]
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() {
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)
#[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);
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())