From e31773bd74197082c327fdeb878f28664ee65e21 Mon Sep 17 00:00:00 2001 From: Jeffrey Czyz Date: Tue, 2 Nov 2021 16:06:05 -0500 Subject: [PATCH] Persist channel scores --- src/disk.rs | 23 +++++++++++++++++++++++ src/main.rs | 25 +++++++++++++++++++++---- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/disk.rs b/src/disk.rs index b641ebb..7be070c 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -3,6 +3,7 @@ use bitcoin::secp256k1::key::PublicKey; use bitcoin::BlockHash; use chrono::Utc; use lightning::routing::network_graph::NetworkGraph; +use lightning::routing::scorer::Scorer; use lightning::util::logger::{Logger, Record}; use lightning::util::ser::{Readable, Writeable, Writer}; use std::collections::HashMap; @@ -92,3 +93,25 @@ pub(crate) fn read_network(path: &Path, genesis_hash: BlockHash) -> NetworkGraph } NetworkGraph::new(genesis_hash) } + +pub(crate) fn persist_scorer(path: &Path, scorer: &Scorer) -> 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 = scorer.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_scorer(path: &Path) -> Scorer { + if let Ok(file) = File::open(path) { + if let Ok(scorer) = Scorer::read(&mut BufReader::new(file)) { + return scorer; + } + } + Scorer::default() +} diff --git a/src/main.rs b/src/main.rs index b85fb4b..421069b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -596,9 +596,26 @@ async fn start_ldk() { )); }; - // Step 16: Create InvoicePayer + // Step 16: Initialize routing Scorer + let scorer_path = format!("{}/scorer", ldk_data_dir.clone()); + let scorer = Arc::new(Mutex::new(disk::read_scorer(Path::new(&scorer_path)))); + let scorer_persist = Arc::clone(&scorer); + tokio::spawn(async move { + let mut interval = tokio::time::interval(Duration::from_secs(600)); + loop { + interval.tick().await; + if disk::persist_scorer(Path::new(&scorer_path), &scorer_persist.lock().unwrap()) + .is_err() + { + // Persistence errors here are non-fatal as channels will be re-scored as payments + // fail, but they may indicate a disk error which could be fatal elsewhere. + eprintln!("Warning: Failed to persist scorer, check your disk and permissions"); + } + } + }); + + // Step 17: Create InvoicePayer let router = DefaultRouter::new(network_graph.clone(), logger.clone()); - let scorer = Arc::new(Mutex::new(Scorer::default())); let invoice_payer = Arc::new(InvoicePayer::new( channel_manager.clone(), router, @@ -608,12 +625,12 @@ async fn start_ldk() { payment::RetryAttempts(5), )); - // Step 17: Persist ChannelManager + // Step 18: Persist ChannelManager let data_dir = ldk_data_dir.clone(); let persist_channel_manager_callback = move |node: &ChannelManager| FilesystemPersister::persist_manager(data_dir.clone(), &*node); - // Step 18: Background Processing + // Step 19: Background Processing let background_processor = BackgroundProcessor::start( persist_channel_manager_callback, invoice_payer.clone(), -- 2.30.2