X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-persister%2Fsrc%2Flib.rs;h=afcda803397597f12d0d3a597dcf7bff44b3c248;hb=4fc05af870b9598adccb39ef96a79cd1635baf84;hp=0257eb50ef9d1172f9be86e8d5428a16b6fe26ee;hpb=a368093803dc66ae19a00a6dbbdb6650656b2379;p=rust-lightning diff --git a/lightning-persister/src/lib.rs b/lightning-persister/src/lib.rs index 0257eb50..afcda803 100644 --- a/lightning-persister/src/lib.rs +++ b/lightning-persister/src/lib.rs @@ -1,3 +1,8 @@ +//! Utilities that handle persisting Rust-Lightning data to disk via standard filesystem APIs. + +#![deny(broken_intra_doc_links)] +#![deny(missing_docs)] + mod util; extern crate lightning; @@ -10,13 +15,14 @@ use lightning::chain; use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; use lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr}; use lightning::chain::channelmonitor; -use lightning::chain::keysinterface::{ChannelKeys, KeysInterface}; +use lightning::chain::keysinterface::{Sign, KeysInterface}; use lightning::chain::transaction::OutPoint; use lightning::ln::channelmanager::ChannelManager; use lightning::util::logger::Logger; use lightning::util::ser::Writeable; use std::fs; use std::io::Error; +use std::path::PathBuf; use std::sync::Arc; #[cfg(test)] @@ -44,19 +50,18 @@ pub struct FilesystemPersister { path_to_channel_data: String, } -impl DiskWriteable for ChannelMonitor { +impl DiskWriteable for ChannelMonitor { fn write_to_file(&self, writer: &mut fs::File) -> Result<(), Error> { self.write(writer) } } -impl DiskWriteable for ChannelManager, Arc, Arc, Arc, Arc> -where ChanSigner: ChannelKeys + Writeable, - M: chain::Watch, - T: BroadcasterInterface, - K: KeysInterface, - F: FeeEstimator, - L: Logger, +impl DiskWriteable for ChannelManager, Arc, Arc, Arc, Arc> +where M: chain::Watch, + T: BroadcasterInterface, + K: KeysInterface, + F: FeeEstimator, + L: Logger, { fn write_to_file(&self, writer: &mut fs::File) -> Result<(), std::io::Error> { self.write(writer) @@ -72,71 +77,79 @@ impl FilesystemPersister { } } + /// Get the directory which was provided when this persister was initialized. pub fn get_data_dir(&self) -> String { self.path_to_channel_data.clone() } + pub(crate) fn path_to_monitor_data(&self) -> PathBuf { + let mut path = PathBuf::from(self.path_to_channel_data.clone()); + path.push("monitors"); + path + } + /// Writes the provided `ChannelManager` to the path provided at `FilesystemPersister` /// initialization, within a file called "manager". - pub fn persist_manager( + pub fn persist_manager( data_dir: String, - manager: &ChannelManager, Arc, Arc, Arc, Arc> + manager: &ChannelManager, Arc, Arc, Arc, Arc> ) -> Result<(), std::io::Error> - where ChanSigner: ChannelKeys + Writeable, - M: chain::Watch, - T: BroadcasterInterface, - K: KeysInterface, - F: FeeEstimator, - L: Logger + where Signer: Sign, + M: chain::Watch, + T: BroadcasterInterface, + K: KeysInterface, + F: FeeEstimator, + L: Logger { - util::write_to_file(data_dir, "manager".to_string(), manager) + let path = PathBuf::from(data_dir); + util::write_to_file(path, "manager".to_string(), manager) } #[cfg(test)] fn load_channel_data(&self, keys: &Keys) -> - Result>, ChannelMonitorUpdateErr> { - if let Err(_) = fs::create_dir_all(&self.path_to_channel_data) { - return Err(ChannelMonitorUpdateErr::PermanentFailure); - } - let mut res = HashMap::new(); - for file_option in fs::read_dir(&self.path_to_channel_data).unwrap() { - let file = file_option.unwrap(); - let owned_file_name = file.file_name(); - let filename = owned_file_name.to_str(); - if !filename.is_some() || !filename.unwrap().is_ascii() || filename.unwrap().len() < 65 { + Result>, ChannelMonitorUpdateErr> { + if let Err(_) = fs::create_dir_all(self.path_to_monitor_data()) { return Err(ChannelMonitorUpdateErr::PermanentFailure); } + let mut res = HashMap::new(); + for file_option in fs::read_dir(self.path_to_monitor_data()).unwrap() { + let file = file_option.unwrap(); + let owned_file_name = file.file_name(); + let filename = owned_file_name.to_str(); + if !filename.is_some() || !filename.unwrap().is_ascii() || filename.unwrap().len() < 65 { + return Err(ChannelMonitorUpdateErr::PermanentFailure); + } - let txid = Txid::from_hex(filename.unwrap().split_at(64).0); - if txid.is_err() { return Err(ChannelMonitorUpdateErr::PermanentFailure); } + let txid = Txid::from_hex(filename.unwrap().split_at(64).0); + if txid.is_err() { return Err(ChannelMonitorUpdateErr::PermanentFailure); } - let index = filename.unwrap().split_at(65).1.split('.').next().unwrap().parse(); - if index.is_err() { return Err(ChannelMonitorUpdateErr::PermanentFailure); } + let index = filename.unwrap().split_at(65).1.split('.').next().unwrap().parse(); + if index.is_err() { return Err(ChannelMonitorUpdateErr::PermanentFailure); } - let contents = fs::read(&file.path()); - if contents.is_err() { return Err(ChannelMonitorUpdateErr::PermanentFailure); } + let contents = fs::read(&file.path()); + if contents.is_err() { return Err(ChannelMonitorUpdateErr::PermanentFailure); } - if let Ok((_, loaded_monitor)) = - <(BlockHash, ChannelMonitor)>::read(&mut Cursor::new(&contents.unwrap()), keys) { - res.insert(OutPoint { txid: txid.unwrap(), index: index.unwrap() }, loaded_monitor); - } else { - return Err(ChannelMonitorUpdateErr::PermanentFailure); + if let Ok((_, loaded_monitor)) = + <(BlockHash, ChannelMonitor)>::read(&mut Cursor::new(&contents.unwrap()), keys) { + res.insert(OutPoint { txid: txid.unwrap(), index: index.unwrap() }, loaded_monitor); + } else { + return Err(ChannelMonitorUpdateErr::PermanentFailure); + } } + Ok(res) } - Ok(res) - } } -impl channelmonitor::Persist for FilesystemPersister { - fn persist_new_channel(&self, funding_txo: OutPoint, monitor: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { +impl channelmonitor::Persist for FilesystemPersister { + fn persist_new_channel(&self, funding_txo: OutPoint, monitor: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { let filename = format!("{}_{}", funding_txo.txid.to_hex(), funding_txo.index); - util::write_to_file(self.path_to_channel_data.clone(), filename, monitor) + util::write_to_file(self.path_to_monitor_data(), filename, monitor) .map_err(|_| ChannelMonitorUpdateErr::PermanentFailure) } - fn update_persisted_channel(&self, funding_txo: OutPoint, _update: &ChannelMonitorUpdate, monitor: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { + fn update_persisted_channel(&self, funding_txo: OutPoint, _update: &ChannelMonitorUpdate, monitor: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { let filename = format!("{}_{}", funding_txo.txid.to_hex(), funding_txo.index); - util::write_to_file(self.path_to_channel_data.clone(), filename, monitor) + util::write_to_file(self.path_to_monitor_data(), filename, monitor) .map_err(|_| ChannelMonitorUpdateErr::PermanentFailure) } } @@ -234,8 +247,8 @@ mod tests { let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); assert_eq!(node_txn.len(), 1); - let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; - connect_block(&nodes[1], &Block { header, txdata: vec![node_txn[0].clone(), node_txn[0].clone()]}, 1); + let header = BlockHeader { version: 0x20000000, prev_blockhash: nodes[0].best_block_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 }; + connect_block(&nodes[1], &Block { header, txdata: vec![node_txn[0].clone(), node_txn[0].clone()]}); check_closed_broadcast!(nodes[1], false); check_added_monitors!(nodes[1], 1);