Remove unreachable `Err` cases on `derive_{public,private}_key`
[rust-lightning] / lightning / src / chain / channelmonitor.rs
index e225f1f095820f49f46d7d8250ca2502a2d40d41..a93985e094816ed153dcc51eca4e6f971c30eff1 100644 (file)
@@ -826,6 +826,13 @@ pub(crate) struct ChannelMonitorImpl<Signer: Sign> {
        /// spending CSV for revocable outputs).
        htlcs_resolved_on_chain: Vec<IrrevocablyResolvedHTLC>,
 
+       /// The set of `SpendableOutput` events which we have already passed upstream to be claimed.
+       /// These are tracked explicitly to ensure that we don't generate the same events redundantly
+       /// if users duplicatively confirm old transactions. Specifically for transactions claiming a
+       /// revoked remote outpoint we otherwise have no tracking at all once they've reached
+       /// [`ANTI_REORG_DELAY`], so we have to track them here.
+       spendable_txids_confirmed: Vec<Txid>,
+
        // 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
@@ -1071,6 +1078,7 @@ impl<Signer: Sign> Writeable for ChannelMonitorImpl<Signer> {
                        (7, self.funding_spend_seen, required),
                        (9, self.counterparty_node_id, option),
                        (11, self.confirmed_commitment_tx_counterparty_output, option),
+                       (13, self.spendable_txids_confirmed, vec_type),
                });
 
                Ok(())
@@ -1179,6 +1187,7 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
                        funding_spend_confirmed: None,
                        confirmed_commitment_tx_counterparty_output: None,
                        htlcs_resolved_on_chain: Vec::new(),
+                       spendable_txids_confirmed: Vec::new(),
 
                        best_block,
                        counterparty_node_id: Some(counterparty_node_id),
@@ -1309,9 +1318,11 @@ impl<Signer: Sign> ChannelMonitor<Signer> {
        /// Gets the list of pending events which were generated by previous actions, clearing the list
        /// in the process.
        ///
-       /// This is called by ChainMonitor::get_and_clear_pending_events() and is equivalent to
-       /// EventsProvider::get_and_clear_pending_events() except that it requires &mut self as we do
-       /// no internal locking in ChannelMonitors.
+       /// This is called by the [`EventsProvider::process_pending_events`] implementation for
+       /// [`ChainMonitor`].
+       ///
+       /// [`EventsProvider::process_pending_events`]: crate::util::events::EventsProvider::process_pending_events
+       /// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor
        pub fn get_and_clear_pending_events(&self) -> Vec<Event> {
                self.inner.lock().unwrap().get_and_clear_pending_events()
        }
@@ -2433,7 +2444,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                        let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
                        let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
                        let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint));
-                       let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.counterparty_commitment_params.counterparty_delayed_payment_base_key));
+                       let delayed_key = chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
 
                        let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.counterparty_commitment_params.on_counterparty_tx_csv, &delayed_key);
                        let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
@@ -2549,17 +2560,12 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                if let Ok(revocation_pubkey) = chan_utils::derive_public_revocation_key(
                                        &self.secp_ctx, &per_commitment_point, &self.holder_revocation_basepoint)
                                {
-                                       if let Ok(delayed_key) = chan_utils::derive_public_key(&self.secp_ctx,
+                                       let delayed_key = chan_utils::derive_public_key(&self.secp_ctx,
                                                &per_commitment_point,
-                                               &self.counterparty_commitment_params.counterparty_delayed_payment_base_key)
-                                       {
-                                               Some(chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
-                                                       self.counterparty_commitment_params.on_counterparty_tx_csv,
-                                                       &delayed_key).to_v0_p2wsh())
-                                       } else {
-                                               debug_assert!(false, "Failed to derive a delayed payment key for a commitment state we accepted");
-                                               None
-                                       }
+                                               &self.counterparty_commitment_params.counterparty_delayed_payment_base_key);
+                                       Some(chan_utils::get_revokeable_redeemscript(&revocation_pubkey,
+                                               self.counterparty_commitment_params.on_counterparty_tx_csv,
+                                               &delayed_key).to_v0_p2wsh())
                                } else {
                                        debug_assert!(false, "Failed to derive a revocation pubkey key for a commitment state we accepted");
                                        None
@@ -2858,7 +2864,37 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
 
                let mut watch_outputs = Vec::new();
                let mut claimable_outpoints = Vec::new();
-               for tx in &txn_matched {
+               'tx_iter: for tx in &txn_matched {
+                       let txid = tx.txid();
+                       // If a transaction has already been confirmed, ensure we don't bother processing it duplicatively.
+                       if Some(txid) == self.funding_spend_confirmed {
+                               log_debug!(logger, "Skipping redundant processing of funding-spend tx {} as it was previously confirmed", txid);
+                               continue 'tx_iter;
+                       }
+                       for ev in self.onchain_events_awaiting_threshold_conf.iter() {
+                               if ev.txid == txid {
+                                       if let Some(conf_hash) = ev.block_hash {
+                                               assert_eq!(header.block_hash(), conf_hash,
+                                                       "Transaction {} was already confirmed and is being re-confirmed in a different block.\n\
+                                                       This indicates a severe bug in the transaction connection logic - a reorg should have been processed first!", ev.txid);
+                                       }
+                                       log_debug!(logger, "Skipping redundant processing of confirming tx {} as it was previously confirmed", txid);
+                                       continue 'tx_iter;
+                               }
+                       }
+                       for htlc in self.htlcs_resolved_on_chain.iter() {
+                               if Some(txid) == htlc.resolving_txid {
+                                       log_debug!(logger, "Skipping redundant processing of HTLC resolution tx {} as it was previously confirmed", txid);
+                                       continue 'tx_iter;
+                               }
+                       }
+                       for spendable_txid in self.spendable_txids_confirmed.iter() {
+                               if txid == *spendable_txid {
+                                       log_debug!(logger, "Skipping redundant processing of spendable tx {} as it was previously confirmed", txid);
+                                       continue 'tx_iter;
+                               }
+                       }
+
                        if tx.input.len() == 1 {
                                // Assuming our keys were not leaked (in which case we're screwed no matter what),
                                // commitment transactions and HTLC transactions will all only ever have one input,
@@ -2868,7 +2904,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                if prevout.txid == self.funding_info.0.txid && prevout.vout == self.funding_info.0.index as u32 {
                                        let mut balance_spendable_csv = None;
                                        log_info!(logger, "Channel {} closed by funding output spend in txid {}.",
-                                               log_bytes!(self.funding_info.0.to_channel_id()), tx.txid());
+                                               log_bytes!(self.funding_info.0.to_channel_id()), txid);
                                        self.funding_spend_seen = true;
                                        let mut commitment_tx_to_counterparty_output = None;
                                        if (tx.input[0].sequence.0 >> 8*3) as u8 == 0x80 && (tx.lock_time.0 >> 8*3) as u8 == 0x20 {
@@ -2891,7 +2927,6 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                                        }
                                                }
                                        }
-                                       let txid = tx.txid();
                                        self.onchain_events_awaiting_threshold_conf.push(OnchainEventEntry {
                                                txid,
                                                transaction: Some((*tx).clone()),
@@ -3040,6 +3075,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                                        self.pending_events.push(Event::SpendableOutputs {
                                                outputs: vec![descriptor]
                                        });
+                                       self.spendable_txids_confirmed.push(entry.txid);
                                },
                                OnchainEvent::HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => {
                                        self.htlcs_resolved_on_chain.push(IrrevocablyResolvedHTLC {
@@ -3109,10 +3145,24 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
                F::Target: FeeEstimator,
                L::Target: Logger,
        {
-               self.onchain_events_awaiting_threshold_conf.retain(|ref entry| if entry.txid == *txid {
-                       log_info!(logger, "Removing onchain event with txid {}", txid);
-                       false
-               } else { true });
+               let mut removed_height = None;
+               for entry in self.onchain_events_awaiting_threshold_conf.iter() {
+                       if entry.txid == *txid {
+                               removed_height = Some(entry.height);
+                               break;
+                       }
+               }
+
+               if let Some(removed_height) = removed_height {
+                       log_info!(logger, "transaction_unconfirmed of txid {} implies height {} was reorg'd out", txid, removed_height);
+                       self.onchain_events_awaiting_threshold_conf.retain(|ref entry| if entry.height >= removed_height {
+                               log_info!(logger, "Transaction {} reorg'd out", entry.txid);
+                               false
+                       } else { true });
+               }
+
+               debug_assert!(!self.onchain_events_awaiting_threshold_conf.iter().any(|ref entry| entry.txid == *txid));
+
                self.onchain_tx_handler.transaction_unconfirmed(txid, broadcaster, fee_estimator, logger);
        }
 
@@ -3549,8 +3599,8 @@ where
 
 const MAX_ALLOC_SIZE: usize = 64*1024;
 
-impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
-               for (BlockHash, ChannelMonitor<Signer>) {
+impl<'a, K: KeysInterface> ReadableArgs<&'a K>
+               for (BlockHash, ChannelMonitor<K::Signer>) {
        fn read<R: io::Read>(reader: &mut R, keys_manager: &'a K) -> Result<Self, DecodeError> {
                macro_rules! unwrap_obj {
                        ($key: expr) => {
@@ -3734,7 +3784,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                                return Err(DecodeError::InvalidValue);
                        }
                }
-               let onchain_tx_handler: OnchainTxHandler<Signer> = ReadableArgs::read(reader, keys_manager)?;
+               let onchain_tx_handler: OnchainTxHandler<K::Signer> = ReadableArgs::read(reader, keys_manager)?;
 
                let lockdown_from_offchain = Readable::read(reader)?;
                let holder_tx_signed = Readable::read(reader)?;
@@ -3761,6 +3811,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                let mut funding_spend_seen = Some(false);
                let mut counterparty_node_id = None;
                let mut confirmed_commitment_tx_counterparty_output = None;
+               let mut spendable_txids_confirmed = Some(Vec::new());
                read_tlv_fields!(reader, {
                        (1, funding_spend_confirmed, option),
                        (3, htlcs_resolved_on_chain, vec_type),
@@ -3768,6 +3819,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                        (7, funding_spend_seen, option),
                        (9, counterparty_node_id, option),
                        (11, confirmed_commitment_tx_counterparty_output, option),
+                       (13, spendable_txids_confirmed, vec_type),
                });
 
                let mut secp_ctx = Secp256k1::new();
@@ -3820,6 +3872,7 @@ impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
                        funding_spend_confirmed,
                        confirmed_commitment_tx_counterparty_output,
                        htlcs_resolved_on_chain: htlcs_resolved_on_chain.unwrap(),
+                       spendable_txids_confirmed: spendable_txids_confirmed.unwrap(),
 
                        best_block,
                        counterparty_node_id,
@@ -4028,7 +4081,7 @@ mod tests {
                        SecretKey::from_slice(&[41; 32]).unwrap(),
                        [41; 32],
                        0,
-                       [0; 32]
+                       [0; 32],
                );
 
                let counterparty_pubkeys = ChannelPublicKeys {
@@ -4049,6 +4102,7 @@ mod tests {
                        }),
                        funding_outpoint: Some(funding_outpoint),
                        opt_anchors: None,
+                       opt_non_zero_fee_anchors: None,
                };
                // Prune with one old state and a holder commitment tx holding a few overlaps with the
                // old state.