X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchainmonitor.rs;h=95a786f696dbc29174324f540590166c36d09553;hb=7d8dc7ac1a05606e6422e0b4126b95717adc075d;hp=ecdd6c3f28395d814ebb98f6315810a70038409e;hpb=f57c8856b59a0e2a2030ec43b7a736e211e3d0c9;p=rust-lightning diff --git a/lightning/src/chain/chainmonitor.rs b/lightning/src/chain/chainmonitor.rs index ecdd6c3f..95a786f6 100644 --- a/lightning/src/chain/chainmonitor.rs +++ b/lightning/src/chain/chainmonitor.rs @@ -25,13 +25,12 @@ use bitcoin::blockdata::block::{Block, BlockHeader}; use bitcoin::hash_types::Txid; -use bitcoin::blockdata::transaction::TxOut; use chain; use chain::{Filter, WatchedOutput}; use chain::chaininterface::{BroadcasterInterface, FeeEstimator}; use chain::channelmonitor; -use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent, Persist}; +use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateErr, MonitorEvent, Persist, TransactionOutputs}; use chain::transaction::{OutPoint, TransactionData}; use chain::keysinterface::Sign; use util::logger::Logger; @@ -75,7 +74,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`]. /// @@ -83,59 +82,9 @@ 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) - }); - } - - /// Dispatches to per-channel monitors, which are responsible for updating their on-chain view - /// of a channel and reacting accordingly to newly confirmed transactions. For details, see - /// [`ChannelMonitor::transactions_confirmed`]. - /// - /// Used instead of [`block_connected`] by clients that are notified of transactions rather than - /// blocks. May be called before or after [`update_best_block`] for transactions in the - /// corresponding block. See [`update_best_block`] for further calling expectations. - /// - /// [`block_connected`]: Self::block_connected - /// [`update_best_block`]: Self::update_best_block - pub fn transactions_confirmed(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) { - self.process_chain_data(header, txdata, |monitor, txdata| { - monitor.transactions_confirmed( - header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger) - }); - } - - /// Dispatches to per-channel monitors, which are responsible for updating their on-chain view - /// of a channel and reacting accordingly based on the new chain tip. For details, see - /// [`ChannelMonitor::update_best_block`]. - /// - /// Used instead of [`block_connected`] by clients that are notified of transactions rather than - /// blocks. May be called before or after [`transactions_confirmed`] for the corresponding - /// block. - /// - /// Must be called after new blocks become available for the most recent block. Intermediary - /// blocks, however, may be safely skipped. In the event of a chain re-organization, this only - /// needs to be called for the most recent block assuming `transaction_unconfirmed` is called - /// for any affected transactions. - /// - /// [`block_connected`]: Self::block_connected - /// [`transactions_confirmed`]: Self::transactions_confirmed - /// [`transaction_unconfirmed`]: Self::transaction_unconfirmed - pub fn update_best_block(&self, header: &BlockHeader, height: u32) { - 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. - debug_assert!(txdata.is_empty()); - monitor.update_best_block( - header, 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<(Txid, Vec<(u32, TxOut)>)> + FN: Fn(&ChannelMonitor, &TransactionData) -> Vec { let mut dependent_txdata = Vec::new(); let monitors = self.monitors.read().unwrap(); @@ -146,15 +95,15 @@ where C::Target: chain::Filter, // transactions from within the block that previously had not been included in txdata. if let Some(ref chain_source) = self.chain_source { let block_hash = header.block_hash(); - for (txid, outputs) in txn_outputs.drain(..) { - for (idx, output) in outputs.iter() { + for (txid, mut outputs) in txn_outputs.drain(..) { + for (idx, output) in outputs.drain(..) { // Register any new outputs with the chain source for filtering and recurse // if it indicates that there are dependent transactions within the block // that had not been previously included in txdata. let output = WatchedOutput { block_hash: Some(block_hash), - outpoint: OutPoint { txid, index: *idx as u16 }, - script_pubkey: output.script_pubkey.clone(), + outpoint: OutPoint { txid, index: idx as u16 }, + script_pubkey: output.script_pubkey, }; if let Some(tx) = chain_source.register_output(output) { dependent_txdata.push(tx); @@ -173,46 +122,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); - } - } - - /// Dispatches to per-channel monitors, which are responsible for updating their on-chain view - /// of a channel based on transactions unconfirmed as a result of a chain reorganization. See - /// [`ChannelMonitor::transaction_unconfirmed`] for details. - /// - /// Used instead of [`block_disconnected`] by clients that are notified of transactions rather - /// than blocks. May be called before or after [`update_best_block`] for transactions in the - /// corresponding block. See [`update_best_block`] for further calling expectations. - /// - /// [`block_disconnected`]: Self::block_disconnected - /// [`update_best_block`]: Self::update_best_block - pub fn transaction_unconfirmed(&self, txid: &Txid) { - let monitors = self.monitors.read().unwrap(); - for monitor in monitors.values() { - monitor.transaction_unconfirmed(txid, &*self.broadcaster, &*self.fee_estimator, &*self.logger); - } - } - - /// Returns the set of txids that should be monitored for re-organization out of the chain. - pub fn get_relevant_txids(&self) -> Vec { - let mut txids = Vec::new(); - let monitors = self.monitors.read().unwrap(); - for monitor in monitors.values() { - txids.append(&mut monitor.get_relevant_txids()); - } - - txids.sort_unstable(); - txids.dedup(); - txids - } - /// 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 @@ -232,7 +141,7 @@ where C::Target: chain::Filter, } } -impl +impl chain::Listen for ChainMonitor where ChannelSigner: Sign, @@ -243,12 +152,67 @@ 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); + 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(); + 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, + L::Target: Logger, + P::Target: channelmonitor::Persist, +{ + fn transactions_confirmed(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) { + self.process_chain_data(header, txdata, |monitor, txdata| { + monitor.transactions_confirmed( + header, txdata, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger) + }); + } + + fn transaction_unconfirmed(&self, txid: &Txid) { + let monitors = self.monitors.read().unwrap(); + for monitor in monitors.values() { + monitor.transaction_unconfirmed(txid, &*self.broadcaster, &*self.fee_estimator, &*self.logger); + } + } + + fn best_block_updated(&self, header: &BlockHeader, height: u32) { + 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. + debug_assert!(txdata.is_empty()); + monitor.best_block_updated( + header, height, &*self.broadcaster, &*self.fee_estimator, &*self.logger) + }); + } + + fn get_relevant_txids(&self) -> Vec { + let mut txids = Vec::new(); + let monitors = self.monitors.read().unwrap(); + for monitor in monitors.values() { + txids.append(&mut monitor.get_relevant_txids()); + } + + txids.sort_unstable(); + txids.dedup(); + txids } }