X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchainmonitor.rs;h=de826d054d3716bd41df35e03706ac3e900c1322;hb=6bdd3a3a9d082c98d6e0e18f651b4e5f0b273888;hp=240084af5733cf867649826f8a4cb4ee32a66372;hpb=4e82003261e11ece5d5fb3b13f686c9f7a0d2aaf;p=rust-lightning diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs index 240084af..de826d05 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -29,7 +29,7 @@ //! [`ChannelMonitor`]: ../channelmonitor/struct.ChannelMonitor.html //! [`MonitorEvent`]: ../channelmonitor/enum.MonitorEvent.html -use bitcoin::blockdata::block::BlockHeader; +use bitcoin::blockdata::block::{Block, BlockHeader}; use chain; use chain::Filter; @@ -37,13 +37,13 @@ use chain::chaininterface::{BroadcasterInterface, FeeEstimator}; use chain::channelmonitor; use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent, Persist}; use chain::transaction::{OutPoint, TransactionData}; -use chain::keysinterface::ChannelKeys; +use chain::keysinterface::Sign; use util::logger::Logger; use util::events; use util::events::Event; use std::collections::{HashMap, hash_map}; -use std::sync::Mutex; +use std::sync::RwLock; use std::ops::Deref; /// An implementation of [`chain::Watch`] for monitoring channels. @@ -56,15 +56,15 @@ use std::ops::Deref; /// [`chain::Watch`]: ../trait.Watch.html /// [`ChannelManager`]: ../../ln/channelmanager/struct.ChannelManager.html /// [module-level documentation]: index.html -pub struct ChainMonitor +pub struct ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, - P::Target: channelmonitor::Persist, + P::Target: channelmonitor::Persist, { /// The monitors - pub monitors: Mutex>>, + pub monitors: RwLock>>, chain_source: Option, broadcaster: T, logger: L, @@ -72,12 +72,12 @@ pub struct ChainMonitor ChainMonitor +impl ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, - P::Target: channelmonitor::Persist, + P::Target: channelmonitor::Persist, { /// Dispatches to per-channel monitors, which are responsible for updating their on-chain view /// of a channel and reacting accordingly based on transactions in the connected block. See @@ -93,8 +93,8 @@ where C::Target: chain::Filter, /// [`chain::Watch::release_pending_monitor_events`]: ../trait.Watch.html#tymethod.release_pending_monitor_events /// [`chain::Filter`]: ../trait.Filter.html pub fn block_connected(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) { - let mut monitors = self.monitors.lock().unwrap(); - for monitor in monitors.values_mut() { + let monitors = self.monitors.read().unwrap(); + for monitor in monitors.values() { let mut txn_outputs = monitor.block_connected(header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger); if let Some(ref chain_source) = self.chain_source { @@ -113,8 +113,8 @@ where C::Target: chain::Filter, /// /// [`ChannelMonitor::block_disconnected`]: ../channelmonitor/struct.ChannelMonitor.html#method.block_disconnected pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) { - let mut monitors = self.monitors.lock().unwrap(); - for monitor in monitors.values_mut() { + let monitors = self.monitors.read().unwrap(); + for monitor in monitors.values() { monitor.block_disconnected(header, disconnected_height, &*self.broadcaster, &*self.fee_estimator, &*self.logger); } } @@ -130,7 +130,7 @@ where C::Target: chain::Filter, /// [`chain::Filter`]: ../trait.Filter.html pub fn new(chain_source: Option, broadcaster: T, logger: L, feeest: F, persister: P) -> Self { Self { - monitors: Mutex::new(HashMap::new()), + monitors: RwLock::new(HashMap::new()), chain_source, broadcaster, logger, @@ -140,15 +140,34 @@ where C::Target: chain::Filter, } } -impl chain::Watch for ChainMonitor +impl +chain::Listen for ChainMonitor +where + ChannelSigner: Sign, + C::Target: chain::Filter, + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + P::Target: channelmonitor::Persist, +{ + fn block_connected(&self, block: &Block, height: u32) { + let txdata: Vec<_> = block.txdata.iter().enumerate().collect(); + ChainMonitor::block_connected(self, &block.header, &txdata, height); + } + + fn block_disconnected(&self, header: &BlockHeader, height: u32) { + ChainMonitor::block_disconnected(self, header, height); + } +} + +impl +chain::Watch for ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, - P::Target: channelmonitor::Persist, + P::Target: channelmonitor::Persist, { - type Keys = ChanSigner; - /// Adds the monitor that watches the channel referred to by the given outpoint. /// /// Calls back to [`chain::Filter`] with the funding transaction and outputs to watch. @@ -157,8 +176,8 @@ where C::Target: chain::Filter, /// monitors lock. /// /// [`chain::Filter`]: ../trait.Filter.html - fn watch_channel(&self, funding_outpoint: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { - let mut monitors = self.monitors.lock().unwrap(); + fn watch_channel(&self, funding_outpoint: OutPoint, monitor: ChannelMonitor) -> Result<(), ChannelMonitorUpdateErr> { + let mut monitors = self.monitors.write().unwrap(); let entry = match monitors.entry(funding_outpoint) { hash_map::Entry::Occupied(_) => { log_error!(self.logger, "Failed to add new channel data: channel monitor for given outpoint is already present"); @@ -190,21 +209,28 @@ where C::Target: chain::Filter, /// `ChainMonitor` monitors lock. fn update_channel(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr> { // Update the monitor that watches the channel referred to by the given outpoint. - let mut monitors = self.monitors.lock().unwrap(); - match monitors.get_mut(&funding_txo) { + let monitors = self.monitors.read().unwrap(); + match monitors.get(&funding_txo) { None => { log_error!(self.logger, "Failed to update channel monitor: no such monitor registered"); + + // We should never ever trigger this from within ChannelManager. Technically a + // user could use this object with some proxying in between which makes this + // possible, but in tests and fuzzing, this should be a panic. + #[cfg(any(test, feature = "fuzztarget"))] + panic!("ChannelManager generated a channel update for a channel that was not yet registered!"); + #[cfg(not(any(test, feature = "fuzztarget")))] Err(ChannelMonitorUpdateErr::PermanentFailure) }, - Some(orig_monitor) => { - log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor)); - let update_res = orig_monitor.update_monitor(&update, &self.broadcaster, &self.fee_estimator, &self.logger); + Some(monitor) => { + log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(monitor)); + let update_res = monitor.update_monitor(&update, &self.broadcaster, &self.fee_estimator, &self.logger); if let Err(e) = &update_res { log_error!(self.logger, "Failed to update channel monitor: {:?}", e); } // Even if updating the monitor returns an error, the monitor's state will // still be changed. So, persist the updated monitor despite the error. - let persist_res = self.persister.update_persisted_channel(funding_txo, &update, orig_monitor); + let persist_res = self.persister.update_persisted_channel(funding_txo, &update, monitor); if let Err(ref e) = persist_res { log_error!(self.logger, "Failed to persist channel monitor update: {:?}", e); } @@ -219,24 +245,24 @@ where C::Target: chain::Filter, fn release_pending_monitor_events(&self) -> Vec { let mut pending_monitor_events = Vec::new(); - for chan in self.monitors.lock().unwrap().values_mut() { - pending_monitor_events.append(&mut chan.get_and_clear_pending_monitor_events()); + for monitor in self.monitors.read().unwrap().values() { + pending_monitor_events.append(&mut monitor.get_and_clear_pending_monitor_events()); } pending_monitor_events } } -impl events::EventsProvider for ChainMonitor +impl events::EventsProvider for ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, - P::Target: channelmonitor::Persist, + P::Target: channelmonitor::Persist, { fn get_and_clear_pending_events(&self) -> Vec { let mut pending_events = Vec::new(); - for chan in self.monitors.lock().unwrap().values_mut() { - pending_events.append(&mut chan.get_and_clear_pending_events()); + for monitor in self.monitors.read().unwrap().values() { + pending_events.append(&mut monitor.get_and_clear_pending_events()); } pending_events }