//! servicing [`ChannelMonitor`] updates from the client.
use bitcoin::blockdata::block::{Block, BlockHeader};
+use bitcoin::hash_types::Txid;
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;
P::Target: channelmonitor::Persist<ChannelSigner>,
{
/// 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`].
///
/// 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) {
+ fn process_chain_data<FN>(&self, header: &BlockHeader, txdata: &TransactionData, process: FN)
+ where
+ FN: Fn(&ChannelMonitor<ChannelSigner>, &TransactionData) -> Vec<TransactionOutputs>
+ {
let mut dependent_txdata = Vec::new();
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);
+ let mut txn_outputs = process(monitor, txdata);
// Register any new outputs with the chain source for filtering, storing any dependent
// 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);
dependent_txdata.sort_unstable_by_key(|(index, _tx)| *index);
dependent_txdata.dedup_by_key(|(index, _tx)| *index);
let txdata: Vec<_> = dependent_txdata.iter().map(|(index, tx)| (*index, tx)).collect();
- self.block_connected(header, &txdata, height);
- }
- }
-
- /// 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);
+ self.process_chain_data(header, &txdata, process);
}
}
}
}
-impl<ChannelSigner: Sign, C: Deref + Send + Sync, T: Deref + Send + Sync, F: Deref + Send + Sync, L: Deref + Send + Sync, P: Deref + Send + Sync>
+impl<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
chain::Listen for ChainMonitor<ChannelSigner, C, T, F, L, P>
where
- ChannelSigner: Sign,
C::Target: chain::Filter,
T::Target: BroadcasterInterface,
F::Target: FeeEstimator,
P::Target: channelmonitor::Persist<ChannelSigner>,
{
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<ChannelSigner: Sign, C: Deref, T: Deref, F: Deref, L: Deref, P: Deref>
+chain::Confirm for ChainMonitor<ChannelSigner, C, T, F, L, P>
+where
+ C::Target: chain::Filter,
+ T::Target: BroadcasterInterface,
+ F::Target: FeeEstimator,
+ L::Target: Logger,
+ P::Target: channelmonitor::Persist<ChannelSigner>,
+{
+ 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<Txid> {
+ 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
}
}
-impl<ChannelSigner: Sign, C: Deref + Sync + Send, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, P: Deref + Sync + Send>
+impl<ChannelSigner: Sign, C: Deref , T: Deref , F: Deref , L: Deref , P: Deref >
chain::Watch<ChannelSigner> for ChainMonitor<ChannelSigner, C, T, F, L, P>
where C::Target: chain::Filter,
T::Target: BroadcasterInterface,
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))