X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning-persister%2Fsrc%2Flib.rs;h=88b103c713fa9fee0f06c1289f15ebc61e24763b;hb=da26ede7e226fcdfbc6e8ea257bcd9e05d5075d8;hp=ce4733433d72737e6d6d0e50a009c87734534ffe;hpb=94aa47b510b4ab393011c971802efbbd289879d9;p=rust-lightning diff --git a/lightning-persister/src/lib.rs b/lightning-persister/src/lib.rs index ce473343..88b103c7 100644 --- a/lightning-persister/src/lib.rs +++ b/lightning-persister/src/lib.rs @@ -12,24 +12,22 @@ extern crate lightning; extern crate bitcoin; extern crate libc; -use bitcoin::{BlockHash, Txid}; +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 lightning::chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate}; +use lightning::chain::chainmonitor; 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 std::collections::HashMap; use std::fs; use std::io::{Cursor, Error}; use std::ops::Deref; use std::path::{Path, PathBuf}; -use std::sync::Arc; /// FilesystemPersister persists channel data on disk, where each channel's /// data is stored in a file named after its funding outpoint. @@ -53,12 +51,13 @@ impl DiskWriteable for ChannelMonitor { } } -impl DiskWriteable for ChannelManager, Arc, Arc, Arc, Arc> -where M: chain::Watch, - T: BroadcasterInterface, - K: KeysInterface, - F: FeeEstimator, - L: Logger, +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) @@ -87,16 +86,16 @@ impl FilesystemPersister { /// 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 ) -> Result<(), std::io::Error> - where Signer: Sign, - M: chain::Watch, - T: BroadcasterInterface, - K: KeysInterface, - F: FeeEstimator, - L: Logger + 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) @@ -105,14 +104,14 @@ impl FilesystemPersister { /// Read `ChannelMonitor`s from disk. pub fn read_channelmonitors ( &self, keys_manager: K - ) -> Result)>, std::io::Error> - where K::Target: KeysInterface + Sized + ) -> Result)>, std::io::Error> + where K::Target: KeysInterface + Sized, { let path = self.path_to_monitor_data(); if !Path::new(&path).exists() { - return Ok(HashMap::new()); + return Ok(Vec::new()); } - let mut outpoint_to_channelmonitor = HashMap::new(); + let mut res = Vec::new(); for file_option in fs::read_dir(path).unwrap() { let file = file_option.unwrap(); let owned_file_name = file.file_name(); @@ -144,10 +143,10 @@ impl FilesystemPersister { let mut buffer = Cursor::new(&contents); match <(BlockHash, ChannelMonitor)>::read(&mut buffer, &*keys_manager) { Ok((blockhash, channel_monitor)) => { - outpoint_to_channelmonitor.insert( - OutPoint { txid: txid.unwrap(), index: index.unwrap() }, - (blockhash, channel_monitor), - ); + if channel_monitor.get_funding_txo().0.txid != txid.unwrap() || channel_monitor.get_funding_txo().0.index != index.unwrap() { + return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "ChannelMonitor was stored in the wrong file")); + } + res.push((blockhash, channel_monitor)); } Err(e) => return Err(std::io::Error::new( std::io::ErrorKind::InvalidData, @@ -155,21 +154,21 @@ impl FilesystemPersister { )) } } - Ok(outpoint_to_channelmonitor) + Ok(res) } } -impl channelmonitor::Persist for FilesystemPersister { - fn persist_new_channel(&self, funding_txo: OutPoint, monitor: &ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { +impl chainmonitor::Persist for FilesystemPersister { + fn persist_new_channel(&self, funding_txo: OutPoint, monitor: &ChannelMonitor) -> Result<(), chain::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) + .map_err(|_| chain::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<(), chain::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) + .map_err(|_| chain::ChannelMonitorUpdateErr::PermanentFailure) } } @@ -181,13 +180,14 @@ 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, Event, MessageSendEventsProvider, MessageSendEvent}; use lightning::util::test_utils; use std::fs; #[cfg(target_os = "windows")] @@ -227,21 +227,21 @@ mod tests { // Check that the persisted channel data is empty before any channels are // open. let mut persisted_chan_data_0 = persister_0.read_channelmonitors(nodes[0].keys_manager).unwrap(); - assert_eq!(persisted_chan_data_0.keys().len(), 0); + assert_eq!(persisted_chan_data_0.len(), 0); let mut persisted_chan_data_1 = persister_1.read_channelmonitors(nodes[1].keys_manager).unwrap(); - assert_eq!(persisted_chan_data_1.keys().len(), 0); + assert_eq!(persisted_chan_data_1.len(), 0); // Helper to make sure the channel is on the expected update ID. macro_rules! check_persisted_data { ($expected_update_id: expr) => { persisted_chan_data_0 = persister_0.read_channelmonitors(nodes[0].keys_manager).unwrap(); - assert_eq!(persisted_chan_data_0.keys().len(), 1); - for (_, mon) in persisted_chan_data_0.values() { + assert_eq!(persisted_chan_data_0.len(), 1); + for (_, mon) in persisted_chan_data_0.iter() { assert_eq!(mon.get_latest_update_id(), $expected_update_id); } persisted_chan_data_1 = persister_1.read_channelmonitors(nodes[1].keys_manager).unwrap(); - assert_eq!(persisted_chan_data_1.keys().len(), 1); - for (_, mon) in persisted_chan_data_1.values() { + assert_eq!(persisted_chan_data_1.len(), 1); + for (_, mon) in persisted_chan_data_1.iter() { assert_eq!(mon.get_latest_update_id(), $expected_update_id); } } @@ -252,15 +252,16 @@ mod tests { check_persisted_data!(0); // Send a few payments and make sure the monitors are updated to the latest. - send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000, 8_000_000); + send_payment(&nodes[0], &vec!(&nodes[1])[..], 8000000); check_persisted_data!(5); - send_payment(&nodes[1], &vec!(&nodes[0])[..], 4000000, 4_000_000); + send_payment(&nodes[1], &vec!(&nodes[0])[..], 4000000); check_persisted_data!(10); // 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_broadcast!(nodes[0], false); + check_closed_event!(nodes[0], 1, ClosureReason::HolderForceClosed); + check_closed_broadcast!(nodes[0], true); check_added_monitors!(nodes[0], 1); let node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap(); @@ -268,7 +269,8 @@ 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], false); + 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. @@ -292,6 +294,7 @@ 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(); // Set the persister's directory to read-only, which should result in @@ -328,6 +331,7 @@ 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(); // Create the persister with an invalid directory name and test that the