From bfaec717ae54979e53c2a34e872dd27f5553eced Mon Sep 17 00:00:00 2001 From: Valentine Wallace Date: Fri, 26 Feb 2021 11:33:51 -0500 Subject: [PATCH] persist: Persist ChannelMonitors in their own directory. --- lightning-persister/src/lib.rs | 58 +++++++++++++++++++-------------- lightning-persister/src/util.rs | 24 +++++++------- 2 files changed, 45 insertions(+), 37 deletions(-) diff --git a/lightning-persister/src/lib.rs b/lightning-persister/src/lib.rs index 6f414a09f..2226bcba6 100644 --- a/lightning-persister/src/lib.rs +++ b/lightning-persister/src/lib.rs @@ -17,6 +17,7 @@ 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)] @@ -75,6 +76,12 @@ impl FilesystemPersister { 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( @@ -88,54 +95,55 @@ impl FilesystemPersister { 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 { + 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> { 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> { 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) } } diff --git a/lightning-persister/src/util.rs b/lightning-persister/src/util.rs index daacb00f0..1825980ad 100644 --- a/lightning-persister/src/util.rs +++ b/lightning-persister/src/util.rs @@ -17,10 +17,9 @@ pub(crate) trait DiskWriteable { fn write_to_file(&self, writer: &mut fs::File) -> Result<(), std::io::Error>; } -pub(crate) fn get_full_filepath(filepath: String, filename: String) -> String { - let mut path = PathBuf::from(filepath); - path.push(filename); - path.to_str().unwrap().to_string() +pub(crate) fn get_full_filepath(mut filepath: PathBuf, filename: String) -> String { + filepath.push(filename); + filepath.to_str().unwrap().to_string() } #[cfg(target_os = "windows")] @@ -40,7 +39,7 @@ fn path_to_windows_str>(path: T) -> Vec(path: String, filename: String, data: &D) -> std::io::Result<()> { +pub(crate) fn write_to_file(path: PathBuf, filename: String, data: &D) -> std::io::Result<()> { fs::create_dir_all(path.clone())?; // Do a crazy dance with lots of fsync()s to be overly cautious here... // We never want to end up in a state where we've lost the old data, or end up using the @@ -92,6 +91,7 @@ mod tests { use std::fs; use std::io; use std::io::Write; + use std::path::PathBuf; struct TestWriteable{} impl DiskWriteable for TestWriteable { @@ -113,7 +113,7 @@ mod tests { let mut perms = fs::metadata(path.to_string()).unwrap().permissions(); perms.set_readonly(true); fs::set_permissions(path.to_string(), perms).unwrap(); - match write_to_file(path.to_string(), filename, &test_writeable) { + match write_to_file(PathBuf::from(path.to_string()), filename, &test_writeable) { Err(e) => assert_eq!(e.kind(), io::ErrorKind::PermissionDenied), _ => panic!("Unexpected error message") } @@ -131,10 +131,10 @@ mod tests { fn test_rename_failure() { let test_writeable = TestWriteable{}; let filename = "test_rename_failure_filename"; - let path = "test_rename_failure_dir"; + let path = PathBuf::from("test_rename_failure_dir"); // Create the channel data file and make it a directory. - fs::create_dir_all(get_full_filepath(path.to_string(), filename.to_string())).unwrap(); - match write_to_file(path.to_string(), filename.to_string(), &test_writeable) { + fs::create_dir_all(get_full_filepath(path.clone(), filename.to_string())).unwrap(); + match write_to_file(path.clone(), filename.to_string(), &test_writeable) { Err(e) => assert_eq!(e.kind(), io::ErrorKind::Other), _ => panic!("Unexpected Ok(())") } @@ -151,9 +151,9 @@ mod tests { } let filename = "test_diskwriteable_failure"; - let path = "test_diskwriteable_failure_dir"; + let path = PathBuf::from("test_diskwriteable_failure_dir"); let test_writeable = FailingWriteable{}; - match write_to_file(path.to_string(), filename.to_string(), &test_writeable) { + match write_to_file(path.clone(), filename.to_string(), &test_writeable) { Err(e) => { assert_eq!(e.kind(), std::io::ErrorKind::Other); assert_eq!(e.get_ref().unwrap().to_string(), "expected failure"); @@ -170,7 +170,7 @@ mod tests { fn test_tmp_file_creation_failure() { let test_writeable = TestWriteable{}; let filename = "test_tmp_file_creation_failure_filename".to_string(); - let path = "test_tmp_file_creation_failure_dir".to_string(); + let path = PathBuf::from("test_tmp_file_creation_failure_dir"); // Create the tmp file and make it a directory. let tmp_path = get_full_filepath(path.clone(), format!("{}.tmp", filename.clone())); -- 2.39.5