X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=f0b23c08619632c4ab14d45f5322d51cc017c38d;hb=7d8dc7ac1a05606e6422e0b4126b95717adc075d;hp=51462b6dd4edcbc9c2fb857b7dc78f78179abb48;hpb=a89996564cdc9e8708b147b2a5e7b11b59adfc8e;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 51462b6d..f0b23c08 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -37,7 +37,7 @@ use bitcoin::secp256k1; use ln::msgs::DecodeError; use ln::chan_utils; use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCType, ChannelTransactionParameters, HolderCommitmentTransaction}; -use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash}; +use ln::channelmanager::{BestBlock, HTLCSource, PaymentPreimage, PaymentHash}; use ln::onchaintx::{OnchainTxHandler, InputDescriptors}; use chain; use chain::WatchedOutput; @@ -465,11 +465,13 @@ pub(crate) struct ClaimRequest { pub(crate) witness_data: InputMaterial } -/// An entry for an [`OnchainEvent`], stating the block height when the event was observed. +/// An entry for an [`OnchainEvent`], stating the block height when the event was observed and the +/// transaction causing it. /// /// Used to determine when the on-chain event can be considered safe from a chain reorganization. #[derive(PartialEq)] struct OnchainEventEntry { + txid: Txid, height: u32, event: OnchainEvent, } @@ -480,7 +482,7 @@ impl OnchainEventEntry { } fn has_reached_confirmation_threshold(&self, height: u32) -> bool { - self.confirmation_threshold() == height + height >= self.confirmation_threshold() } } @@ -706,7 +708,7 @@ pub(crate) struct ChannelMonitorImpl { // Used to track on-chain events (i.e., transactions part of channels confirmed on chain) on // which to take actions once they reach enough confirmations. Each entry includes the // transaction's id and the height when the transaction was confirmed on chain. - onchain_events_waiting_threshold_conf: Vec, + onchain_events_awaiting_threshold_conf: Vec, // If we get serialized out and re-read, we need to make sure that the chain monitoring // interface knows about the TXOs that we want to be notified of spends of. We could probably @@ -733,15 +735,19 @@ pub(crate) struct ChannelMonitorImpl { // remote monitor out-of-order with regards to the block view. holder_tx_signed: bool, - // We simply modify last_block_hash in Channel's block_connected so that serialization is + // We simply modify best_block in Channel's block_connected so that serialization is // consistent but hopefully the users' copy handles block_connected in a consistent way. // (we do *not*, however, update them in update_monitor to ensure any local user copies keep - // their last_block_hash from its state and not based on updated copies that didn't run through + // their best_block from its state and not based on updated copies that didn't run through // the full block_connected). - last_block_hash: BlockHash, + best_block: BestBlock, + secp_ctx: Secp256k1, //TODO: dedup this a bit... } +/// Transaction outputs to watch for on-chain spends. +pub type TransactionOutputs = (Txid, Vec<(u32, TxOut)>); + #[cfg(any(test, feature = "fuzztarget", feature = "_test_utils"))] /// Used only in testing and fuzztarget to check serialization roundtrips don't change the /// underlying object @@ -784,7 +790,7 @@ impl PartialEq for ChannelMonitorImpl { self.payment_preimages != other.payment_preimages || self.pending_monitor_events != other.pending_monitor_events || self.pending_events.len() != other.pending_events.len() || // We trust events to round-trip properly - self.onchain_events_waiting_threshold_conf != other.onchain_events_waiting_threshold_conf || + self.onchain_events_awaiting_threshold_conf != other.onchain_events_awaiting_threshold_conf || self.outputs_to_watch != other.outputs_to_watch || self.lockdown_from_offchain != other.lockdown_from_offchain || self.holder_tx_signed != other.holder_tx_signed @@ -950,10 +956,12 @@ impl Writeable for ChannelMonitorImpl { event.write(writer)?; } - self.last_block_hash.write(writer)?; + self.best_block.block_hash().write(writer)?; + writer.write_all(&byte_utils::be32_to_array(self.best_block.height()))?; - writer.write_all(&byte_utils::be64_to_array(self.onchain_events_waiting_threshold_conf.len() as u64))?; - for ref entry in self.onchain_events_waiting_threshold_conf.iter() { + writer.write_all(&byte_utils::be64_to_array(self.onchain_events_awaiting_threshold_conf.len() as u64))?; + for ref entry in self.onchain_events_awaiting_threshold_conf.iter() { + entry.txid.write(writer)?; writer.write_all(&byte_utils::be32_to_array(entry.height))?; match entry.event { OnchainEvent::HTLCUpdate { ref htlc_update } => { @@ -993,7 +1001,7 @@ impl ChannelMonitor { funding_redeemscript: Script, channel_value_satoshis: u64, commitment_transaction_number_obscure_factor: u64, initial_holder_commitment_tx: HolderCommitmentTransaction, - last_block_hash: BlockHash) -> ChannelMonitor { + best_block: BestBlock) -> ChannelMonitor { assert!(commitment_transaction_number_obscure_factor <= (1 << 48)); let our_channel_close_key_hash = WPubkeyHash::hash(&shutdown_pubkey.serialize()); @@ -1072,7 +1080,7 @@ impl ChannelMonitor { pending_monitor_events: Vec::new(), pending_events: Vec::new(), - onchain_events_waiting_threshold_conf: Vec::new(), + onchain_events_awaiting_threshold_conf: Vec::new(), outputs_to_watch, onchain_tx_handler, @@ -1080,7 +1088,8 @@ impl ChannelMonitor { lockdown_from_offchain: false, holder_tx_signed: false, - last_block_hash, + best_block, + secp_ctx, }), } @@ -1270,7 +1279,7 @@ impl ChannelMonitor { broadcaster: B, fee_estimator: F, logger: L, - ) -> Vec<(Txid, Vec<(u32, TxOut)>)> + ) -> Vec where B::Target: BroadcasterInterface, F::Target: FeeEstimator, @@ -1297,6 +1306,89 @@ impl ChannelMonitor { self.inner.lock().unwrap().block_disconnected( header, height, broadcaster, fee_estimator, logger) } + + /// Processes transactions confirmed in a block with the given header and height, returning new + /// outputs to watch. See [`block_connected`] for details. + /// + /// Used instead of [`block_connected`] by clients that are notified of transactions rather than + /// blocks. See [`chain::Confirm`] for calling expectations. + /// + /// [`block_connected`]: Self::block_connected + pub fn transactions_confirmed( + &self, + header: &BlockHeader, + txdata: &TransactionData, + height: u32, + broadcaster: B, + fee_estimator: F, + logger: L, + ) -> Vec + where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { + self.inner.lock().unwrap().transactions_confirmed( + header, txdata, height, broadcaster, fee_estimator, logger) + } + + /// Processes a transaction that was reorganized out of the chain. + /// + /// Used instead of [`block_disconnected`] by clients that are notified of transactions rather + /// than blocks. See [`chain::Confirm`] for calling expectations. + /// + /// [`block_disconnected`]: Self::block_disconnected + pub fn transaction_unconfirmed( + &self, + txid: &Txid, + broadcaster: B, + fee_estimator: F, + logger: L, + ) where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { + self.inner.lock().unwrap().transaction_unconfirmed( + txid, broadcaster, fee_estimator, logger); + } + + /// Updates the monitor with the current best chain tip, returning new outputs to watch. See + /// [`block_connected`] for details. + /// + /// Used instead of [`block_connected`] by clients that are notified of transactions rather than + /// blocks. See [`chain::Confirm`] for calling expectations. + /// + /// [`block_connected`]: Self::block_connected + pub fn best_block_updated( + &self, + header: &BlockHeader, + height: u32, + broadcaster: B, + fee_estimator: F, + logger: L, + ) -> Vec + where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { + self.inner.lock().unwrap().best_block_updated( + header, height, broadcaster, fee_estimator, 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 inner = self.inner.lock().unwrap(); + let mut txids: Vec = inner.onchain_events_awaiting_threshold_conf + .iter() + .map(|entry| entry.txid) + .chain(inner.onchain_tx_handler.get_relevant_txids().into_iter()) + .collect(); + txids.sort_unstable(); + txids.dedup(); + txids + } } impl ChannelMonitorImpl { @@ -1590,7 +1682,7 @@ impl ChannelMonitorImpl { /// HTLC-Success/HTLC-Timeout transactions. /// Return updates for HTLC pending in the channel and failed automatically by the broadcast of /// revoked counterparty commitment tx - fn check_spend_counterparty_transaction(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec, (Txid, Vec<(u32, TxOut)>)) where L::Target: Logger { + fn check_spend_counterparty_transaction(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec, TransactionOutputs) where L::Target: Logger { // Most secp and related errors trying to create keys means we have no hope of constructing // a spend transaction...so we return no transactions to broadcast let mut claimable_outpoints = Vec::new(); @@ -1655,7 +1747,7 @@ impl ChannelMonitorImpl { if let Some(ref outpoints) = self.counterparty_claimable_outpoints.get($txid) { for &(ref htlc, ref source_option) in outpoints.iter() { if let &Some(ref source) = source_option { - self.onchain_events_waiting_threshold_conf.retain(|ref entry| { + self.onchain_events_awaiting_threshold_conf.retain(|ref entry| { if entry.height != height { return true; } match entry.event { OnchainEvent::HTLCUpdate { ref htlc_update } => { @@ -1665,13 +1757,14 @@ impl ChannelMonitorImpl { } }); let entry = OnchainEventEntry { + txid: *$txid, height, event: OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone()) }, }; log_info!(logger, "Failing HTLC with payment_hash {} from {} counterparty commitment tx due to broadcast of revoked counterparty commitment transaction, waiting for confirmation (at height {})", log_bytes!(htlc.payment_hash.0), $commitment_tx, entry.confirmation_threshold()); - self.onchain_events_waiting_threshold_conf.push(entry); + self.onchain_events_awaiting_threshold_conf.push(entry); } } } @@ -1720,7 +1813,7 @@ impl ChannelMonitorImpl { } } log_trace!(logger, "Failing HTLC with payment_hash {} from {} counterparty commitment tx due to broadcast of counterparty commitment transaction", log_bytes!(htlc.payment_hash.0), $commitment_tx); - self.onchain_events_waiting_threshold_conf.retain(|ref entry| { + self.onchain_events_awaiting_threshold_conf.retain(|ref entry| { if entry.height != height { return true; } match entry.event { OnchainEvent::HTLCUpdate { ref htlc_update } => { @@ -1729,7 +1822,8 @@ impl ChannelMonitorImpl { _ => true, } }); - self.onchain_events_waiting_threshold_conf.push(OnchainEventEntry { + self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry { + txid: *$txid, height, event: OnchainEvent::HTLCUpdate { htlc_update: ((**source).clone(), htlc.payment_hash.clone()) @@ -1799,7 +1893,7 @@ impl ChannelMonitorImpl { } /// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key - fn check_spend_counterparty_htlc(&mut self, tx: &Transaction, commitment_number: u64, height: u32, logger: &L) -> (Vec, Option<(Txid, Vec<(u32, TxOut)>)>) where L::Target: Logger { + fn check_spend_counterparty_htlc(&mut self, tx: &Transaction, commitment_number: u64, height: u32, logger: &L) -> (Vec, Option) where L::Target: Logger { let htlc_txid = tx.txid(); if tx.input.len() != 1 || tx.output.len() != 1 || tx.input[0].witness.len() != 5 { return (Vec::new(), None) @@ -1868,15 +1962,15 @@ impl ChannelMonitorImpl { /// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet) /// revoked using data in holder_claimable_outpoints. /// Should not be used if check_spend_revoked_transaction succeeds. - fn check_spend_holder_transaction(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec, (Txid, Vec<(u32, TxOut)>)) where L::Target: Logger { + fn check_spend_holder_transaction(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec, TransactionOutputs) where L::Target: Logger { let commitment_txid = tx.txid(); let mut claim_requests = Vec::new(); let mut watch_outputs = Vec::new(); macro_rules! wait_threshold_conf { - ($height: expr, $source: expr, $commitment_tx: expr, $payment_hash: expr) => { - self.onchain_events_waiting_threshold_conf.retain(|ref entry| { - if entry.height != $height { return true; } + ($source: expr, $commitment_tx: expr, $payment_hash: expr) => { + self.onchain_events_awaiting_threshold_conf.retain(|ref entry| { + if entry.height != height { return true; } match entry.event { OnchainEvent::HTLCUpdate { ref htlc_update } => { htlc_update.0 != $source @@ -1885,11 +1979,12 @@ impl ChannelMonitorImpl { } }); let entry = OnchainEventEntry { + txid: commitment_txid, height, event: OnchainEvent::HTLCUpdate { htlc_update: ($source, $payment_hash) }, }; log_trace!(logger, "Failing HTLC with payment_hash {} from {} holder commitment tx due to broadcast of transaction, waiting confirmation (at height{})", log_bytes!($payment_hash.0), $commitment_tx, entry.confirmation_threshold()); - self.onchain_events_waiting_threshold_conf.push(entry); + self.onchain_events_awaiting_threshold_conf.push(entry); } } @@ -1925,7 +2020,7 @@ impl ChannelMonitorImpl { for &(ref htlc, _, ref source) in &$holder_tx.htlc_outputs { if htlc.transaction_output_index.is_none() { if let &Some(ref source) = source { - wait_threshold_conf!(height, source.clone(), "lastest", htlc.payment_hash.clone()); + wait_threshold_conf!(source.clone(), "lastest", htlc.payment_hash.clone()); } } } @@ -1990,10 +2085,58 @@ impl ChannelMonitorImpl { return res } - pub fn block_connected(&mut self, header: &BlockHeader, txdata: &TransactionData, height: u32, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<(u32, TxOut)>)> + pub fn block_connected(&mut self, header: &BlockHeader, txdata: &TransactionData, height: u32, broadcaster: B, fee_estimator: F, logger: L) -> Vec where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, + { + let block_hash = header.block_hash(); + log_trace!(logger, "New best block {} at height {}", block_hash, height); + self.best_block = BestBlock::new(block_hash, height); + + self.transactions_confirmed(header, txdata, height, broadcaster, fee_estimator, logger) + } + + fn best_block_updated( + &mut self, + header: &BlockHeader, + height: u32, + broadcaster: B, + fee_estimator: F, + logger: L, + ) -> Vec + where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { + let block_hash = header.block_hash(); + log_trace!(logger, "New best block {} at height {}", block_hash, height); + + if height > self.best_block.height() { + self.best_block = BestBlock::new(block_hash, height); + self.block_confirmed(height, vec![], vec![], vec![], broadcaster, fee_estimator, logger) + } else { + self.best_block = BestBlock::new(block_hash, height); + self.onchain_events_awaiting_threshold_conf.retain(|ref entry| entry.height <= height); + self.onchain_tx_handler.block_disconnected(height + 1, broadcaster, fee_estimator, logger); + Vec::new() + } + } + + fn transactions_confirmed( + &mut self, + header: &BlockHeader, + txdata: &TransactionData, + height: u32, + broadcaster: B, + fee_estimator: F, + logger: L, + ) -> Vec + where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, { let txn_matched = self.filter_block(txdata); for tx in &txn_matched { @@ -2049,11 +2192,28 @@ impl ChannelMonitorImpl { self.is_paying_spendable_output(&tx, height, &logger); } + + self.block_confirmed(height, txn_matched, watch_outputs, claimable_outpoints, broadcaster, fee_estimator, logger) + } + + fn block_confirmed( + &mut self, + height: u32, + txn_matched: Vec<&Transaction>, + mut watch_outputs: Vec, + mut claimable_outpoints: Vec, + broadcaster: B, + fee_estimator: F, + logger: L, + ) -> Vec + where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { let should_broadcast = self.would_broadcast_at_height(height, &logger); if should_broadcast { claimable_outpoints.push(ClaimRequest { absolute_timelock: height, aggregable: false, outpoint: BitcoinOutPoint { txid: self.funding_info.0.txid.clone(), vout: self.funding_info.0.index as u32 }, witness_data: InputMaterial::Funding { funding_redeemscript: self.funding_redeemscript.clone() }}); - } - if should_broadcast { self.pending_monitor_events.push(MonitorEvent::CommitmentTxBroadcasted(self.funding_info.0)); let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript); self.holder_tx_signed = true; @@ -2065,33 +2225,67 @@ impl ChannelMonitorImpl { claimable_outpoints.append(&mut new_outpoints); } - let onchain_events_waiting_threshold_conf = - self.onchain_events_waiting_threshold_conf.drain(..).collect::>(); - for entry in onchain_events_waiting_threshold_conf { + // Find which on-chain events have reached their confirmation threshold. + let onchain_events_awaiting_threshold_conf = + self.onchain_events_awaiting_threshold_conf.drain(..).collect::>(); + let mut onchain_events_reaching_threshold_conf = Vec::new(); + for entry in onchain_events_awaiting_threshold_conf { if entry.has_reached_confirmation_threshold(height) { - match entry.event { - OnchainEvent::HTLCUpdate { htlc_update } => { - log_trace!(logger, "HTLC {} failure update has got enough confirmations to be passed upstream", log_bytes!((htlc_update.1).0)); - self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate { - payment_hash: htlc_update.1, - payment_preimage: None, - source: htlc_update.0, - })); - }, - OnchainEvent::MaturingOutput { descriptor } => { - log_trace!(logger, "Descriptor {} has got enough confirmations to be passed upstream", log_spendable!(descriptor)); - self.pending_events.push(Event::SpendableOutputs { - outputs: vec![descriptor] - }); + onchain_events_reaching_threshold_conf.push(entry); + } else { + self.onchain_events_awaiting_threshold_conf.push(entry); + } + } + + // Used to check for duplicate HTLC resolutions. + #[cfg(debug_assertions)] + let unmatured_htlcs: Vec<_> = self.onchain_events_awaiting_threshold_conf + .iter() + .filter_map(|entry| match &entry.event { + OnchainEvent::HTLCUpdate { htlc_update } => Some(htlc_update.0.clone()), + OnchainEvent::MaturingOutput { .. } => None, + }) + .collect(); + #[cfg(debug_assertions)] + let mut matured_htlcs = Vec::new(); + + // Produce actionable events from on-chain events having reached their threshold. + for entry in onchain_events_reaching_threshold_conf.drain(..) { + match entry.event { + OnchainEvent::HTLCUpdate { htlc_update } => { + // Check for duplicate HTLC resolutions. + #[cfg(debug_assertions)] + { + debug_assert!( + unmatured_htlcs.iter().find(|&htlc| htlc == &htlc_update.0).is_none(), + "An unmature HTLC transaction conflicts with a maturing one; failed to \ + call either transaction_unconfirmed for the conflicting transaction \ + or block_disconnected for a block containing it."); + debug_assert!( + matured_htlcs.iter().find(|&htlc| htlc == &htlc_update.0).is_none(), + "A matured HTLC transaction conflicts with a maturing one; failed to \ + call either transaction_unconfirmed for the conflicting transaction \ + or block_disconnected for a block containing it."); + matured_htlcs.push(htlc_update.0.clone()); } + + log_trace!(logger, "HTLC {} failure update has got enough confirmations to be passed upstream", log_bytes!((htlc_update.1).0)); + self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate { + payment_hash: htlc_update.1, + payment_preimage: None, + source: htlc_update.0, + })); + }, + OnchainEvent::MaturingOutput { descriptor } => { + log_trace!(logger, "Descriptor {} has got enough confirmations to be passed upstream", log_spendable!(descriptor)); + self.pending_events.push(Event::SpendableOutputs { + outputs: vec![descriptor] + }); } - } else { - self.onchain_events_waiting_threshold_conf.push(entry); } } self.onchain_tx_handler.update_claims_view(&txn_matched, claimable_outpoints, Some(height), &&*broadcaster, &&*fee_estimator, &&*logger); - self.last_block_hash = block_hash; // Determine new outputs to watch by comparing against previously known outputs to watch, // updating the latter in the process. @@ -2126,11 +2320,26 @@ impl ChannelMonitorImpl { //We may discard: //- htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected //- maturing spendable output has transaction paying us has been disconnected - self.onchain_events_waiting_threshold_conf.retain(|ref entry| entry.height != height); + self.onchain_events_awaiting_threshold_conf.retain(|ref entry| entry.height < height); self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator, logger); - self.last_block_hash = header.prev_blockhash; + self.best_block = BestBlock::new(header.prev_blockhash, height - 1); + } + + fn transaction_unconfirmed( + &mut self, + txid: &Txid, + broadcaster: B, + fee_estimator: F, + logger: L, + ) where + B::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, + { + self.onchain_events_awaiting_threshold_conf.retain(|ref entry| entry.txid != *txid); + self.onchain_tx_handler.transaction_unconfirmed(txid, broadcaster, fee_estimator, logger); } /// Filters a block's `txdata` for transactions spending watched outputs or for any child @@ -2358,7 +2567,7 @@ impl ChannelMonitorImpl { })); } } else { - self.onchain_events_waiting_threshold_conf.retain(|ref entry| { + self.onchain_events_awaiting_threshold_conf.retain(|ref entry| { if entry.height != height { return true; } match entry.event { OnchainEvent::HTLCUpdate { ref htlc_update } => { @@ -2368,11 +2577,12 @@ impl ChannelMonitorImpl { } }); let entry = OnchainEventEntry { + txid: tx.txid(), height, event: OnchainEvent::HTLCUpdate { htlc_update: (source, payment_hash) }, }; log_info!(logger, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting for confirmation (at height{})", log_bytes!(payment_hash.0), entry.confirmation_threshold()); - self.onchain_events_waiting_threshold_conf.push(entry); + self.onchain_events_awaiting_threshold_conf.push(entry); } } } @@ -2432,11 +2642,12 @@ impl ChannelMonitorImpl { } if let Some(spendable_output) = spendable_output { let entry = OnchainEventEntry { + txid: tx.txid(), height: height, event: OnchainEvent::MaturingOutput { descriptor: spendable_output.clone() }, }; log_trace!(logger, "Maturing {} until {}", log_spendable!(spendable_output), entry.confirmation_threshold()); - self.onchain_events_waiting_threshold_conf.push(entry); + self.onchain_events_awaiting_threshold_conf.push(entry); } } } @@ -2504,6 +2715,29 @@ where } } +impl chain::Confirm for (ChannelMonitor, T, F, L) +where + T::Target: BroadcasterInterface, + F::Target: FeeEstimator, + L::Target: Logger, +{ + fn transactions_confirmed(&self, header: &BlockHeader, txdata: &TransactionData, height: u32) { + self.0.transactions_confirmed(header, txdata, height, &*self.1, &*self.2, &*self.3); + } + + fn transaction_unconfirmed(&self, txid: &Txid) { + self.0.transaction_unconfirmed(txid, &*self.1, &*self.2, &*self.3); + } + + fn best_block_updated(&self, header: &BlockHeader, height: u32) { + self.0.best_block_updated(header, height, &*self.1, &*self.2, &*self.3); + } + + fn get_relevant_txids(&self) -> Vec { + self.0.get_relevant_txids() + } +} + const MAX_ALLOC_SIZE: usize = 64*1024; impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> @@ -2699,11 +2933,12 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> } } - let last_block_hash: BlockHash = Readable::read(reader)?; + let best_block = BestBlock::new(Readable::read(reader)?, Readable::read(reader)?); let waiting_threshold_conf_len: u64 = Readable::read(reader)?; - let mut onchain_events_waiting_threshold_conf = Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128)); + let mut onchain_events_awaiting_threshold_conf = Vec::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128)); for _ in 0..waiting_threshold_conf_len { + let txid = Readable::read(reader)?; let height = Readable::read(reader)?; let event = match ::read(reader)? { 0 => { @@ -2721,7 +2956,7 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> }, _ => return Err(DecodeError::InvalidValue), }; - onchain_events_waiting_threshold_conf.push(OnchainEventEntry { height, event }); + onchain_events_awaiting_threshold_conf.push(OnchainEventEntry { txid, height, event }); } let outputs_to_watch_len: u64 = Readable::read(reader)?; @@ -2745,7 +2980,7 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> let mut secp_ctx = Secp256k1::new(); secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes()); - Ok((last_block_hash.clone(), ChannelMonitor { + Ok((best_block.block_hash(), ChannelMonitor { inner: Mutex::new(ChannelMonitorImpl { latest_update_id, commitment_transaction_number_obscure_factor, @@ -2782,7 +3017,7 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> pending_monitor_events, pending_events, - onchain_events_waiting_threshold_conf, + onchain_events_awaiting_threshold_conf, outputs_to_watch, onchain_tx_handler, @@ -2790,7 +3025,8 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> lockdown_from_offchain, holder_tx_signed, - last_block_hash, + best_block, + secp_ctx, }), })) @@ -2799,7 +3035,6 @@ impl<'a, Signer: Sign, K: KeysInterface> ReadableArgs<&'a K> #[cfg(test)] mod tests { - use bitcoin::blockdata::constants::genesis_block; use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::opcodes; use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, SigHashType}; @@ -2813,7 +3048,7 @@ mod tests { use hex; use chain::channelmonitor::ChannelMonitor; use chain::transaction::OutPoint; - use ln::channelmanager::{PaymentPreimage, PaymentHash}; + use ln::channelmanager::{BestBlock, PaymentPreimage, PaymentHash}; use ln::onchaintx::{OnchainTxHandler, InputDescriptors}; use ln::chan_utils; use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; @@ -2909,13 +3144,13 @@ mod tests { }; // Prune with one old state and a holder commitment tx holding a few overlaps with the // old state. - let last_block_hash = genesis_block(Network::Testnet).block_hash(); + let best_block = BestBlock::from_genesis(Network::Testnet); let monitor = ChannelMonitor::new(Secp256k1::new(), keys, &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0, &Script::new(), (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()), &channel_parameters, Script::new(), 46, 0, - HolderCommitmentTransaction::dummy(), last_block_hash); + HolderCommitmentTransaction::dummy(), best_block); monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..10])).unwrap(); let dummy_txid = dummy_tx.txid();