d301180d605202690aa24dd96bbf1bfa2c18d7c2
[ldk-sample] / src / disk.rs
1 use crate::{cli, InboundPaymentInfoStorage, NetworkGraph, OutboundPaymentInfoStorage};
2 use bitcoin::secp256k1::PublicKey;
3 use bitcoin::Network;
4 use chrono::Utc;
5 use lightning::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringDecayParameters};
6 use lightning::util::logger::{Logger, Record};
7 use lightning::util::ser::{Readable, ReadableArgs, Writer};
8 use std::collections::HashMap;
9 use std::fs;
10 use std::fs::File;
11 use std::io::{BufRead, BufReader};
12 use std::net::SocketAddr;
13 use std::path::Path;
14 use std::sync::Arc;
15
16 pub(crate) const INBOUND_PAYMENTS_FNAME: &str = "inbound_payments";
17 pub(crate) const OUTBOUND_PAYMENTS_FNAME: &str = "outbound_payments";
18
19 pub(crate) struct FilesystemLogger {
20         data_dir: String,
21 }
22 impl FilesystemLogger {
23         pub(crate) fn new(data_dir: String) -> Self {
24                 let logs_path = format!("{}/logs", data_dir);
25                 fs::create_dir_all(logs_path.clone()).unwrap();
26                 Self { data_dir: logs_path }
27         }
28 }
29 impl Logger for FilesystemLogger {
30         fn log(&self, record: &Record) {
31                 let raw_log = record.args.to_string();
32                 let log = format!(
33                         "{} {:<5} [{}:{}] {}\n",
34                         // Note that a "real" lightning node almost certainly does *not* want subsecond
35                         // precision for message-receipt information as it makes log entries a target for
36                         // deanonymization attacks. For testing, however, its quite useful.
37                         Utc::now().format("%Y-%m-%d %H:%M:%S%.3f"),
38                         record.level.to_string(),
39                         record.module_path,
40                         record.line,
41                         raw_log
42                 );
43                 let logs_file_path = format!("{}/logs.txt", self.data_dir.clone());
44                 fs::OpenOptions::new()
45                         .create(true)
46                         .append(true)
47                         .open(logs_file_path)
48                         .unwrap()
49                         .write_all(log.as_bytes())
50                         .unwrap();
51         }
52 }
53 pub(crate) fn persist_channel_peer(path: &Path, peer_info: &str) -> std::io::Result<()> {
54         let mut file = fs::OpenOptions::new().create(true).append(true).open(path)?;
55         file.write_all(format!("{}\n", peer_info).as_bytes())
56 }
57
58 pub(crate) fn read_channel_peer_data(
59         path: &Path,
60 ) -> Result<HashMap<PublicKey, SocketAddr>, std::io::Error> {
61         let mut peer_data = HashMap::new();
62         if !Path::new(&path).exists() {
63                 return Ok(HashMap::new());
64         }
65         let file = File::open(path)?;
66         let reader = BufReader::new(file);
67         for line in reader.lines() {
68                 match cli::parse_peer_info(line.unwrap()) {
69                         Ok((pubkey, socket_addr)) => {
70                                 peer_data.insert(pubkey, socket_addr);
71                         }
72                         Err(e) => return Err(e),
73                 }
74         }
75         Ok(peer_data)
76 }
77
78 pub(crate) fn read_network(
79         path: &Path, network: Network, logger: Arc<FilesystemLogger>,
80 ) -> NetworkGraph {
81         if let Ok(file) = File::open(path) {
82                 if let Ok(graph) = NetworkGraph::read(&mut BufReader::new(file), logger.clone()) {
83                         return graph;
84                 }
85         }
86         NetworkGraph::new(network, logger)
87 }
88
89 pub(crate) fn read_inbound_payment_info(path: &Path) -> InboundPaymentInfoStorage {
90         if let Ok(file) = File::open(path) {
91                 if let Ok(info) = InboundPaymentInfoStorage::read(&mut BufReader::new(file)) {
92                         return info;
93                 }
94         }
95         InboundPaymentInfoStorage { payments: HashMap::new() }
96 }
97
98 pub(crate) fn read_outbound_payment_info(path: &Path) -> OutboundPaymentInfoStorage {
99         if let Ok(file) = File::open(path) {
100                 if let Ok(info) = OutboundPaymentInfoStorage::read(&mut BufReader::new(file)) {
101                         return info;
102                 }
103         }
104         OutboundPaymentInfoStorage { payments: HashMap::new() }
105 }
106
107 pub(crate) fn read_scorer(
108         path: &Path, graph: Arc<NetworkGraph>, logger: Arc<FilesystemLogger>,
109 ) -> ProbabilisticScorer<Arc<NetworkGraph>, Arc<FilesystemLogger>> {
110         let params = ProbabilisticScoringDecayParameters::default();
111         if let Ok(file) = File::open(path) {
112                 let args = (params.clone(), Arc::clone(&graph), Arc::clone(&logger));
113                 if let Ok(scorer) = ProbabilisticScorer::read(&mut BufReader::new(file), args) {
114                         return scorer;
115                 }
116         }
117         ProbabilisticScorer::new(params, graph, logger)
118 }