From: Matt Corallo Date: Wed, 26 May 2021 00:11:44 +0000 (+0000) Subject: Persist network graph X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=6200c113694be7df65299cf468dad93073c4dd07;p=ldk-sample Persist network graph --- diff --git a/src/disk.rs b/src/disk.rs index 827cb7e..2c1834a 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -1,11 +1,13 @@ use crate::cli; use bitcoin::secp256k1::key::PublicKey; +use bitcoin::BlockHash; +use lightning::routing::network_graph::NetworkGraph; use lightning::util::logger::{Logger, Record}; -use lightning::util::ser::Writer; +use lightning::util::ser::{Readable, Writeable, Writer}; use std::collections::HashMap; use std::fs; use std::fs::File; -use std::io::{BufRead, BufReader}; +use std::io::{BufRead, BufReader, BufWriter}; use std::net::SocketAddr; use std::path::Path; use time::OffsetDateTime; @@ -65,3 +67,25 @@ pub(crate) fn read_channel_peer_data( } Ok(peer_data) } + +pub(crate) fn persist_network(path: &Path, network_graph: &NetworkGraph) -> std::io::Result<()> { + let mut tmp_path = path.to_path_buf().into_os_string(); + tmp_path.push(".tmp"); + let file = fs::OpenOptions::new().write(true).create(true).open(&tmp_path)?; + let write_res = network_graph.write(&mut BufWriter::new(file)); + if let Err(e) = write_res.and_then(|_| fs::rename(&tmp_path, path)) { + let _ = fs::remove_file(&tmp_path); + Err(e) + } else { + Ok(()) + } +} + +pub(crate) fn read_network(path: &Path, genesis_hash: BlockHash) -> NetworkGraph { + if let Ok(file) = File::open(path) { + if let Ok(graph) = NetworkGraph::read(&mut BufReader::new(file)) { + return graph; + } + } + NetworkGraph::new(genesis_hash) +} diff --git a/src/main.rs b/src/main.rs index 892fd0e..cba93f6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -426,13 +426,33 @@ async fn start_ldk() { } // Step 11: Optional: Initialize the NetGraphMsgHandler - // XXX persist routing data let genesis = genesis_block(args.network).header.block_hash(); - let router = Arc::new(NetGraphMsgHandler::new( - genesis, + let network_graph_path = format!("{}/network_graph", ldk_data_dir.clone()); + let network_graph = disk::read_network(Path::new(&network_graph_path), genesis); + let router = Arc::new(NetGraphMsgHandler::from_net_graph( None::>, logger.clone(), + network_graph, )); + let router_persist = Arc::clone(&router); + tokio::spawn(async move { + let mut interval = tokio::time::interval(Duration::from_secs(600)); + loop { + interval.tick().await; + if disk::persist_network( + Path::new(&network_graph_path), + &*router_persist.network_graph.read().unwrap(), + ) + .is_err() + { + // Persistence errors here are non-fatal as we can just fetch the routing graph + // again later, but they may indicate a disk error which could be fatal elsewhere. + eprintln!( + "Warning: Failed to persist network graph, check your disk and permissions" + ); + } + } + }); // Step 12: Initialize the PeerManager let channel_manager: Arc = Arc::new(channel_manager);