X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchainmonitor.rs;h=0d3f87645ce4c4c1250d2d42a3a085f419ac13a6;hb=7aa2caccd884cd7d40ee146323c2a65b7ea39407;hp=8c2e761fa46dad5445dece213b4fc38e85f01475;hpb=93d20ff63e7b2b41804f46a4e1e342f82ede1d27;p=rust-lightning diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs index 8c2e761f..0d3f8764 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -30,16 +30,17 @@ use chain; use chain::{Filter, WatchedOutput}; use chain::chaininterface::{BroadcasterInterface, FeeEstimator}; use chain::channelmonitor; -use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent, Persist, TransactionOutputs}; +use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, Balance, MonitorEvent, Persist, TransactionOutputs}; use chain::transaction::{OutPoint, TransactionData}; use chain::keysinterface::Sign; use util::logger::Logger; use util::events; -use util::events::Event; +use util::events::EventHandler; +use ln::channelmanager::ChannelDetails; -use std::collections::{HashMap, hash_map}; -use std::sync::RwLock; -use std::ops::Deref; +use prelude::*; +use sync::RwLock; +use core::ops::Deref; /// An implementation of [`chain::Watch`] for monitoring channels. /// @@ -74,7 +75,7 @@ where C::Target: chain::Filter, 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 + /// of a channel and reacting accordingly based on transactions in the given chain data. See /// [`ChannelMonitor::block_connected`] for details. Any HTLCs that were resolved on chain will /// be returned by [`chain::Watch::release_pending_monitor_events`]. /// @@ -82,13 +83,6 @@ where C::Target: chain::Filter, /// calls must not exclude any transactions matching the new outputs nor any in-block /// descendants of such transactions. It is not necessary to re-fetch the block to obtain /// updated `txdata`. - pub fn block_connected(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) { - self.process_chain_data(header, txdata, |monitor, txdata| { - monitor.block_connected( - header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger) - }); - } - fn process_chain_data(&self, header: &BlockHeader, txdata: &TransactionData, process: FN) where FN: Fn(&ChannelMonitor, &TransactionData) -> Vec @@ -129,16 +123,6 @@ where C::Target: chain::Filter, } } - /// Dispatches to per-channel monitors, which are responsible for updating their on-chain view - /// of a channel based on the disconnected block. See [`ChannelMonitor::block_disconnected`] for - /// details. - pub fn block_disconnected(&self, header: &BlockHeader, disconnected_height: u32) { - let monitors = self.monitors.read().unwrap(); - for monitor in monitors.values() { - monitor.block_disconnected(header, disconnected_height, &*self.broadcaster, &*self.fee_estimator, &*self.logger); - } - } - /// Creates a new `ChainMonitor` used to watch on-chain activity pertaining to channels. /// /// When an optional chain source implementing [`chain::Filter`] is provided, the chain monitor @@ -156,12 +140,45 @@ where C::Target: chain::Filter, persister, } } + + /// Gets the balances in the contained [`ChannelMonitor`]s which are claimable on-chain or + /// claims which are awaiting confirmation. + /// + /// Includes the balances from each [`ChannelMonitor`] *except* those included in + /// `ignored_channels`, allowing you to filter out balances from channels which are still open + /// (and whose balance should likely be pulled from the [`ChannelDetails`]). + /// + /// See [`ChannelMonitor::get_claimable_balances`] for more details on the exact criteria for + /// inclusion in the return value. + pub fn get_claimable_balances(&self, ignored_channels: &[&ChannelDetails]) -> Vec { + let mut ret = Vec::new(); + let monitors = self.monitors.read().unwrap(); + for (_, monitor) in monitors.iter().filter(|(funding_outpoint, _)| { + for chan in ignored_channels { + if chan.funding_txo.as_ref() == Some(funding_outpoint) { + return false; + } + } + true + }) { + ret.append(&mut monitor.get_claimable_balances()); + } + ret + } + + #[cfg(any(test, feature = "fuzztarget", feature = "_test_utils"))] + pub fn get_and_clear_pending_events(&self) -> Vec { + use util::events::EventsProvider; + let events = core::cell::RefCell::new(Vec::new()); + let event_handler = |event: &events::Event| events.borrow_mut().push(event.clone()); + self.process_pending_events(&event_handler); + events.into_inner() + } } -impl +impl chain::Listen for ChainMonitor where - ChannelSigner: Sign, C::Target: chain::Filter, T::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -169,19 +186,28 @@ where P::Target: channelmonitor::Persist, { fn block_connected(&self, block: &Block, height: u32) { + let header = &block.header; let txdata: Vec<_> = block.txdata.iter().enumerate().collect(); - ChainMonitor::block_connected(self, &block.header, &txdata, height); + log_debug!(self.logger, "New best block {} at height {} provided via block_connected", header.block_hash(), height); + self.process_chain_data(header, &txdata, |monitor, txdata| { + monitor.block_connected( + header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger) + }); } fn block_disconnected(&self, header: &BlockHeader, height: u32) { - ChainMonitor::block_disconnected(self, header, height); + let monitors = self.monitors.read().unwrap(); + log_debug!(self.logger, "Latest block {} at height {} removed via block_disconnected", header.block_hash(), height); + for monitor in monitors.values() { + monitor.block_disconnected( + header, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger); + } } } impl chain::Confirm for ChainMonitor where - ChannelSigner: Sign, C::Target: chain::Filter, T::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -189,6 +215,7 @@ where P::Target: channelmonitor::Persist, { fn transactions_confirmed(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) { + log_debug!(self.logger, "{} provided transactions confirmed at height {} in block {}", txdata.len(), height, header.block_hash()); self.process_chain_data(header, txdata, |monitor, txdata| { monitor.transactions_confirmed( header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger) @@ -196,6 +223,7 @@ where } fn transaction_unconfirmed(&self, txid: &Txid) { + log_debug!(self.logger, "Transaction {} reorganized out of chain", txid); let monitors = self.monitors.read().unwrap(); for monitor in monitors.values() { monitor.transaction_unconfirmed(txid, &*self.broadcaster, &*self.fee_estimator, &*self.logger); @@ -203,6 +231,7 @@ where } fn best_block_updated(&self, header: &BlockHeader, height: u32) { + log_debug!(self.logger, "New best block {} at height {} provided via best_block_updated", header.block_hash(), height); self.process_chain_data(header, &[], |monitor, txdata| { // While in practice there shouldn't be any recursive calls when given empty txdata, // it's still possible if a chain::Filter implementation returns a transaction. @@ -225,7 +254,7 @@ where } } -impl +impl chain::Watch for ChainMonitor where C::Target: chain::Filter, T::Target: BroadcasterInterface, @@ -317,12 +346,20 @@ impl even L::Target: Logger, P::Target: channelmonitor::Persist, { - fn get_and_clear_pending_events(&self) -> Vec { + /// Processes [`SpendableOutputs`] events produced from each [`ChannelMonitor`] upon maturity. + /// + /// An [`EventHandler`] may safely call back to the provider, though this shouldn't be needed in + /// order to handle these events. + /// + /// [`SpendableOutputs`]: events::Event::SpendableOutputs + fn process_pending_events(&self, handler: H) where H::Target: EventHandler { let mut pending_events = Vec::new(); for monitor in self.monitors.read().unwrap().values() { pending_events.append(&mut monitor.get_and_clear_pending_events()); } - pending_events + for event in pending_events.drain(..) { + handler.handle_event(&event); + } } } @@ -331,7 +368,6 @@ mod tests { use ::{check_added_monitors, get_local_commitment_txn}; use ln::features::InitFeatures; use ln::functional_test_utils::*; - use util::events::EventsProvider; use util::events::MessageSendEventsProvider; use util::test_utils::{OnRegisterOutput, TxOutReference}; @@ -353,7 +389,7 @@ mod tests { let (commitment_tx, htlc_tx) = { let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 5_000_000).0; let mut txn = get_local_commitment_txn!(nodes[0], channel.2); - claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage, 5_000_000); + claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage); assert_eq!(txn.len(), 2); (txn.remove(0), txn.remove(0))