X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=bd0c15484283b5a12d0c815d13afb9310acb688e;hb=c86cacd29d72c0af62cfd29d78dcf17a6d8f8c71;hp=b535e4b6cad34edbad3121e77f84d0976c3da0ee;hpb=33b745f54e7d3ed7b34c40f27e9b2945f50b5d87;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index b535e4b6..bd0c1548 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -1311,7 +1311,7 @@ impl ChannelMonitor { &self, updates: &ChannelMonitorUpdate, broadcaster: &B, - fee_estimator: F, + fee_estimator: &F, logger: &L, ) -> Result<(), ()> where @@ -1672,6 +1672,8 @@ impl ChannelMonitor { /// Returns the descriptors for relevant outputs (i.e., those that we can spend) within the /// transaction if they exist and the transaction has at least [`ANTI_REORG_DELAY`] + /// confirmations. For [`SpendableOutputDescriptor::DelayedPaymentOutput`] descriptors to be + /// returned, the transaction must have at least `max(ANTI_REORG_DELAY, to_self_delay)` /// confirmations. /// /// Descriptors returned by this method are primarily exposed via [`Event::SpendableOutputs`] @@ -1680,8 +1682,7 @@ impl ChannelMonitor { /// missed/unhandled descriptors. For the purpose of gathering historical records, if the /// channel close has fully resolved (i.e., [`ChannelMonitor::get_claimable_balances`] returns /// an empty set), you can retrieve all spendable outputs by providing all descendant spending - /// transactions starting from the channel's funding or closing transaction that have at least - /// [`ANTI_REORG_DELAY`] confirmations. + /// transactions starting from the channel's funding transaction and going down three levels. /// /// `tx` is a transaction we'll scan the outputs of. Any transaction can be provided. If any /// outputs which can be spent by us are found, at least one descriptor is returned. @@ -1690,11 +1691,26 @@ impl ChannelMonitor { pub fn get_spendable_outputs(&self, tx: &Transaction, confirmation_height: u32) -> Vec { let inner = self.inner.lock().unwrap(); let current_height = inner.best_block.height; - if current_height.saturating_sub(ANTI_REORG_DELAY) + 1 >= confirmation_height { - inner.get_spendable_outputs(tx) - } else { - Vec::new() - } + let mut spendable_outputs = inner.get_spendable_outputs(tx); + spendable_outputs.retain(|descriptor| { + let mut conf_threshold = current_height.saturating_sub(ANTI_REORG_DELAY) + 1; + if let SpendableOutputDescriptor::DelayedPaymentOutput(descriptor) = descriptor { + conf_threshold = cmp::min(conf_threshold, + current_height.saturating_sub(descriptor.to_self_delay as u32) + 1); + } + conf_threshold >= confirmation_height + }); + spendable_outputs + } + + #[cfg(test)] + pub fn get_counterparty_payment_script(&self) -> Script{ + self.inner.lock().unwrap().counterparty_payment_script.clone() + } + + #[cfg(test)] + pub fn set_counterparty_payment_script(&self, script: Script) { + self.inner.lock().unwrap().counterparty_payment_script = script; } } @@ -1735,7 +1751,19 @@ impl ChannelMonitorImpl { }, OnchainEvent::MaturingOutput { descriptor: SpendableOutputDescriptor::DelayedPaymentOutput(ref descriptor) } - if descriptor.outpoint.index as u32 == htlc_commitment_tx_output_idx => { + if event.transaction.as_ref().map(|tx| tx.input.iter().enumerate() + .any(|(input_idx, inp)| + Some(inp.previous_output.txid) == confirmed_txid && + inp.previous_output.vout == htlc_commitment_tx_output_idx && + // A maturing output for an HTLC claim will always be at the same + // index as the HTLC input. This is true pre-anchors, as there's + // only 1 input and 1 output. This is also true post-anchors, + // because we have a SIGHASH_SINGLE|ANYONECANPAY signature from our + // channel counterparty. + descriptor.outpoint.index as usize == input_idx + )) + .unwrap_or(false) + => { debug_assert!(holder_delayed_output_pending.is_none()); holder_delayed_output_pending = Some(event.confirmation_threshold()); }, @@ -1876,8 +1904,7 @@ impl ChannelMonitor { /// confirmations on the claim transaction. /// /// Note that for `ChannelMonitors` which track a channel which went on-chain with versions of - /// LDK prior to 0.0.111, balances may not be fully captured if our counterparty broadcasted - /// a revoked state. + /// LDK prior to 0.0.111, not all or excess balances may be included. /// /// See [`Balance`] for additional details on the types of claimable balances which /// may be returned here and their meanings. @@ -2504,6 +2531,18 @@ impl ChannelMonitorImpl { { self.payment_preimages.insert(payment_hash.clone(), payment_preimage.clone()); + let confirmed_spend_txid = self.funding_spend_confirmed.or_else(|| { + self.onchain_events_awaiting_threshold_conf.iter().find_map(|event| match event.event { + OnchainEvent::FundingSpendConfirmation { .. } => Some(event.txid), + _ => None, + }) + }); + let confirmed_spend_txid = if let Some(txid) = confirmed_spend_txid { + txid + } else { + return; + }; + // If the channel is force closed, try to claim the output from this preimage. // First check if a counterparty commitment transaction has been broadcasted: macro_rules! claim_htlcs { @@ -2513,14 +2552,24 @@ impl ChannelMonitorImpl { } } if let Some(txid) = self.current_counterparty_commitment_txid { - if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { - claim_htlcs!(*commitment_number, txid); + if txid == confirmed_spend_txid { + if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { + claim_htlcs!(*commitment_number, txid); + } else { + debug_assert!(false); + log_error!(logger, "Detected counterparty commitment tx on-chain without tracking commitment number"); + } return; } } if let Some(txid) = self.prev_counterparty_commitment_txid { - if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { - claim_htlcs!(*commitment_number, txid); + if txid == confirmed_spend_txid { + if let Some(commitment_number) = self.counterparty_commitment_txn_on_chain.get(&txid) { + claim_htlcs!(*commitment_number, txid); + } else { + debug_assert!(false); + log_error!(logger, "Detected counterparty commitment tx on-chain without tracking commitment number"); + } return; } } @@ -2531,13 +2580,22 @@ impl ChannelMonitorImpl { // *we* sign a holder commitment transaction, not when e.g. a watchtower broadcasts one of our // holder commitment transactions. if self.broadcasted_holder_revokable_script.is_some() { - // Assume that the broadcasted commitment transaction confirmed in the current best - // block. Even if not, its a reasonable metric for the bump criteria on the HTLC - // transactions. - let (claim_reqs, _) = self.get_broadcasted_holder_claims(&self.current_holder_commitment_tx, self.best_block.height()); - self.onchain_tx_handler.update_claims_view_from_requests(claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger); - if let Some(ref tx) = self.prev_holder_signed_commitment_tx { - let (claim_reqs, _) = self.get_broadcasted_holder_claims(&tx, self.best_block.height()); + let holder_commitment_tx = if self.current_holder_commitment_tx.txid == confirmed_spend_txid { + Some(&self.current_holder_commitment_tx) + } else if let Some(prev_holder_commitment_tx) = &self.prev_holder_signed_commitment_tx { + if prev_holder_commitment_tx.txid == confirmed_spend_txid { + Some(prev_holder_commitment_tx) + } else { + None + } + } else { + None + }; + if let Some(holder_commitment_tx) = holder_commitment_tx { + // Assume that the broadcasted commitment transaction confirmed in the current best + // block. Even if not, its a reasonable metric for the bump criteria on the HTLC + // transactions. + let (claim_reqs, _) = self.get_broadcasted_holder_claims(&holder_commitment_tx, self.best_block.height()); self.onchain_tx_handler.update_claims_view_from_requests(claim_reqs, self.best_block.height(), self.best_block.height(), broadcaster, fee_estimator, logger); } } @@ -2557,7 +2615,7 @@ impl ChannelMonitorImpl { self.pending_monitor_events.push(MonitorEvent::HolderForceClosed(self.funding_info.0)); } - pub fn update_monitor(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: F, logger: &L) -> Result<(), ()> + pub fn update_monitor(&mut self, updates: &ChannelMonitorUpdate, broadcaster: &B, fee_estimator: &F, logger: &L) -> Result<(), ()> where B::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, @@ -2597,7 +2655,7 @@ impl ChannelMonitorImpl { panic!("Attempted to apply ChannelMonitorUpdates out of order, check the update_id before passing an update to update_monitor!"); } let mut ret = Ok(()); - let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&*fee_estimator); + let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&**fee_estimator); for update in updates.updates.iter() { match update { ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, claimed_htlcs, nondust_htlc_sources } => { @@ -4043,6 +4101,7 @@ impl ChannelMonitorImpl { output: outp.clone(), channel_keys_id: self.channel_keys_id, channel_value_satoshis: self.channel_value_satoshis, + channel_transaction_parameters: Some(self.onchain_tx_handler.channel_transaction_parameters.clone()), })); } if self.shutdown_script.as_ref() == Some(&outp.script_pubkey) { @@ -4145,7 +4204,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP 1 => { None }, _ => return Err(DecodeError::InvalidValue), }; - let counterparty_payment_script = Readable::read(reader)?; + let mut counterparty_payment_script: Script = Readable::read(reader)?; let shutdown_script = { let script =