X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-persister%2Fsrc%2Flib.rs;h=c23baf8ad34bccb7ea7efcaa32639a43f4b23c42;hb=7181b53aa47b8c25aca01fda9661508d0ec7be59;hp=d68a06d71b4fe58ec1af2bcb1117df8f1dddd7e5;hpb=58e4ce251e202cacadb82341ed16d299057fc646;p=rust-lightning diff --git a/lightning-persister/src/lib.rs b/lightning-persister/src/lib.rs index d68a06d7..c23baf8a 100644 --- a/lightning-persister/src/lib.rs +++ b/lightning-persister/src/lib.rs @@ -3,8 +3,10 @@ #![deny(broken_intra_doc_links)] #![deny(missing_docs)] -#![cfg_attr(all(test, feature = "unstable"), feature(test))] -#[cfg(all(test, feature = "unstable"))] extern crate test; +#![cfg_attr(docsrs, feature(doc_auto_cfg))] + +#![cfg_attr(all(test, feature = "_bench_unstable"), feature(test))] +#[cfg(all(test, feature = "_bench_unstable"))] extern crate test; mod util; @@ -13,19 +15,13 @@ extern crate bitcoin; extern crate libc; use bitcoin::hash_types::{BlockHash, Txid}; -use bitcoin::hashes::hex::{FromHex, ToHex}; -use crate::util::DiskWriteable; -use lightning::chain; -use lightning::chain::chaininterface::{BroadcasterInterface, FeeEstimator}; -use lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr}; -use lightning::chain::channelmonitor; +use bitcoin::hashes::hex::FromHex; +use lightning::chain::channelmonitor::ChannelMonitor; 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::{ReadableArgs, Writeable}; +use lightning::util::persist::KVStorePersister; use std::fs; -use std::io::{Cursor, Error}; +use std::io::Cursor; use std::ops::Deref; use std::path::{Path, PathBuf}; @@ -45,25 +41,6 @@ pub struct FilesystemPersister { path_to_channel_data: String, } -impl DiskWriteable for ChannelMonitor { - fn write_to_file(&self, writer: &mut fs::File) -> Result<(), Error> { - self.write(writer) - } -} - -impl DiskWriteable for ChannelManager -where - M::Target: chain::Watch, - T::Target: BroadcasterInterface, - K::Target: KeysInterface, - F::Target: FeeEstimator, - L::Target: Logger, -{ - fn write_to_file(&self, writer: &mut fs::File) -> Result<(), std::io::Error> { - self.write(writer) - } -} - impl FilesystemPersister { /// Initialize a new FilesystemPersister and set the path to the individual channels' /// files. @@ -78,36 +55,14 @@ 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( - data_dir: String, - manager: &ChannelManager - ) -> Result<(), std::io::Error> - where - M::Target: chain::Watch, - T::Target: BroadcasterInterface, - K::Target: KeysInterface, - F::Target: FeeEstimator, - L::Target: Logger, - { - let path = PathBuf::from(data_dir); - util::write_to_file(path, "manager".to_string(), manager) - } - /// Read `ChannelMonitor`s from disk. pub fn read_channelmonitors ( &self, keys_manager: K ) -> Result)>, std::io::Error> where K::Target: KeysInterface + Sized, { - let path = self.path_to_monitor_data(); + let mut path = PathBuf::from(&self.path_to_channel_data); + path.push("monitors"); if !Path::new(&path).exists() { return Ok(Vec::new()); } @@ -122,6 +77,12 @@ impl FilesystemPersister { "Invalid ChannelMonitor file name", )); } + if filename.unwrap().ends_with(".tmp") { + // If we were in the middle of committing an new update and crashed, it should be + // safe to ignore the update - we should never have returned to the caller and + // irrevocably committed to the new state in any way. + continue; + } let txid = Txid::from_hex(filename.unwrap().split_at(64).0); if txid.is_err() { @@ -158,17 +119,11 @@ impl FilesystemPersister { } } -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_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_monitor_data(), filename, monitor) - .map_err(|_| ChannelMonitorUpdateErr::PermanentFailure) +impl KVStorePersister for FilesystemPersister { + fn persist(&self, key: &str, object: &W) -> std::io::Result<()> { + let mut dest_file = PathBuf::from(self.path_to_channel_data.clone()); + dest_file.push(key); + util::write_to_file(dest_file, object) } } @@ -180,13 +135,13 @@ mod tests { use bitcoin::blockdata::block::{Block, BlockHeader}; use bitcoin::hashes::hex::FromHex; use bitcoin::Txid; - use lightning::chain::channelmonitor::{Persist, ChannelMonitorUpdateErr}; + use lightning::chain::ChannelMonitorUpdateErr; + use lightning::chain::chainmonitor::Persist; use lightning::chain::transaction::OutPoint; - use lightning::{check_closed_broadcast, check_added_monitors}; + use lightning::{check_closed_broadcast, check_closed_event, check_added_monitors}; use lightning::ln::features::InitFeatures; use lightning::ln::functional_test_utils::*; - use lightning::ln::msgs::ErrorAction; - use lightning::util::events::{MessageSendEventsProvider, MessageSendEvent}; + use lightning::util::events::{ClosureReason, MessageSendEventsProvider}; use lightning::util::test_utils; use std::fs; #[cfg(target_os = "windows")] @@ -259,6 +214,7 @@ mod tests { // Force close because cooperative close doesn't result in any persisted // updates. nodes[0].node.force_close_channel(&nodes[0].node.list_channels()[0].channel_id).unwrap(); + check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed); check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); @@ -268,6 +224,7 @@ mod tests { 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], true); + check_closed_event!(nodes[1], 1, ClosureReason::CommitmentTxConfirmed); check_added_monitors!(nodes[1], 1); // Make sure everything is persisted as expected after close. @@ -291,7 +248,10 @@ mod tests { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); nodes[1].node.force_close_channel(&chan.2).unwrap(); + check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed); let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); + let update_map = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap(); + let update_id = update_map.get(&added_monitors[0].0.to_channel_id()).unwrap(); // Set the persister's directory to read-only, which should result in // returning a permanent failure when we then attempt to persist a @@ -305,7 +265,7 @@ mod tests { txid: Txid::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), index: 0 }; - match persister.persist_new_channel(test_txo, &added_monitors[0].1) { + match persister.persist_new_channel(test_txo, &added_monitors[0].1, update_id.2) { Err(ChannelMonitorUpdateErr::PermanentFailure) => {}, _ => panic!("unexpected result from persisting new channel") } @@ -327,7 +287,10 @@ mod tests { let nodes = create_network(2, &node_cfgs, &node_chanmgrs); let chan = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); nodes[1].node.force_close_channel(&chan.2).unwrap(); + check_closed_event!(nodes[1], 1, ClosureReason::HolderForceClosed); let mut added_monitors = nodes[1].chain_monitor.added_monitors.lock().unwrap(); + let update_map = nodes[1].chain_monitor.latest_monitor_update_id.lock().unwrap(); + let update_id = update_map.get(&added_monitors[0].0.to_channel_id()).unwrap(); // Create the persister with an invalid directory name and test that the // channel fails to open because the directories fail to be created. There @@ -339,7 +302,7 @@ mod tests { txid: Txid::from_hex("8984484a580b825b9972d7adb15050b3ab624ccd731946b3eeddb92f4e7ef6be").unwrap(), index: 0 }; - match persister.persist_new_channel(test_txo, &added_monitors[0].1) { + match persister.persist_new_channel(test_txo, &added_monitors[0].1, update_id.2) { Err(ChannelMonitorUpdateErr::PermanentFailure) => {}, _ => panic!("unexpected result from persisting new channel") } @@ -349,7 +312,7 @@ mod tests { } } -#[cfg(all(test, feature = "unstable"))] +#[cfg(all(test, feature = "_bench_unstable"))] pub mod bench { use test::Bencher;