Merge pull request #3113 from TheBlueMatt/2024-04-async-monitor-fuzz
[rust-lightning] / lightning / src / chain / onchaintx.rs
index 6c29d147f02fb7239a7aaf86112b3c9cf2e7509f..e5757cfd1e52f5b1da358f4fd88a706052447147 100644 (file)
@@ -12,6 +12,7 @@
 //! OnchainTxHandler objects are fully-part of ChannelMonitor and encapsulates all
 //! building, tracking, bumping and notifications functions.
 
+use bitcoin::amount::Amount;
 use bitcoin::blockdata::locktime::absolute::LockTime;
 use bitcoin::blockdata::transaction::Transaction;
 use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
@@ -19,13 +20,14 @@ use bitcoin::blockdata::script::{Script, ScriptBuf};
 use bitcoin::hashes::{Hash, HashEngine};
 use bitcoin::hashes::sha256::Hash as Sha256;
 use bitcoin::hash_types::{Txid, BlockHash};
+use bitcoin::secp256k1::PublicKey;
 use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
 use bitcoin::secp256k1;
 
 use crate::chain::chaininterface::compute_feerate_sat_per_1000_weight;
-use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ChannelSigner, EntropySource, SignerProvider, ecdsa::WriteableEcdsaChannelSigner};
+use crate::sign::{ChannelDerivationParameters, HTLCDescriptor, ChannelSigner, EntropySource, SignerProvider, ecdsa::EcdsaChannelSigner};
 use crate::ln::msgs::DecodeError;
-use crate::ln::PaymentPreimage;
+use crate::ln::types::PaymentPreimage;
 use crate::ln::chan_utils::{self, ChannelTransactionParameters, HTLCOutputInCommitment, HolderCommitmentTransaction};
 use crate::chain::ClaimId;
 use crate::chain::chaininterface::{ConfirmationTarget, FeeEstimator, BroadcasterInterface, LowerBoundedFeeEstimator};
@@ -33,7 +35,7 @@ use crate::chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER};
 use crate::chain::package::{PackageSolvingData, PackageTemplate};
 use crate::chain::transaction::MaybeSignedTransaction;
 use crate::util::logger::Logger;
-use crate::util::ser::{Readable, ReadableArgs, MaybeReadable, UpgradableRequired, Writer, Writeable, VecWriter};
+use crate::util::ser::{Readable, ReadableArgs, MaybeReadable, UpgradableRequired, Writer, Writeable};
 
 use crate::io;
 use crate::prelude::*;
@@ -179,6 +181,7 @@ pub(crate) struct ExternalHTLCClaim {
        pub(crate) htlc: HTLCOutputInCommitment,
        pub(crate) preimage: Option<PaymentPreimage>,
        pub(crate) counterparty_sig: Signature,
+       pub(crate) per_commitment_point: PublicKey,
 }
 
 // Represents the different types of claims for which events are yielded externally to satisfy said
@@ -225,7 +228,7 @@ pub(crate) enum FeerateStrategy {
 /// OnchainTxHandler receives claiming requests, aggregates them if it's sound, broadcast and
 /// do RBF bumping if possible.
 #[derive(Clone)]
-pub struct OnchainTxHandler<ChannelSigner: WriteableEcdsaChannelSigner> {
+pub struct OnchainTxHandler<ChannelSigner: EcdsaChannelSigner> {
        channel_value_satoshis: u64,
        channel_keys_id: [u8; 32],
        destination_script: ScriptBuf,
@@ -281,7 +284,7 @@ pub struct OnchainTxHandler<ChannelSigner: WriteableEcdsaChannelSigner> {
        pub(super) secp_ctx: Secp256k1<secp256k1::All>,
 }
 
-impl<ChannelSigner: WriteableEcdsaChannelSigner> PartialEq for OnchainTxHandler<ChannelSigner> {
+impl<ChannelSigner: EcdsaChannelSigner> PartialEq for OnchainTxHandler<ChannelSigner> {
        fn eq(&self, other: &Self) -> bool {
                // `signer`, `secp_ctx`, and `pending_claim_events` are excluded on purpose.
                self.channel_value_satoshis == other.channel_value_satoshis &&
@@ -300,7 +303,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> PartialEq for OnchainTxHandler<
 const SERIALIZATION_VERSION: u8 = 1;
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
-impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
+impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
        pub(crate) fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
 
@@ -312,12 +315,9 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
 
                self.channel_transaction_parameters.write(writer)?;
 
-               let mut key_data = VecWriter(Vec::new());
-               self.signer.write(&mut key_data)?;
-               assert!(key_data.0.len() < core::usize::MAX);
-               assert!(key_data.0.len() < core::u32::MAX as usize);
-               (key_data.0.len() as u32).write(writer)?;
-               writer.write_all(&key_data.0[..])?;
+               // Write a zero-length signer. The data is no longer deserialized as of version 0.0.113 and
+               // downgrades before version 0.0.113 are no longer supported as of version 0.0.119.
+               0u32.write(writer)?;
 
                writer.write_all(&(self.pending_claim_requests.len() as u64).to_be_bytes())?;
                for (ref ancestor_claim_txid, request) in self.pending_claim_requests.iter() {
@@ -443,7 +443,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP
        }
 }
 
-impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
+impl<ChannelSigner: EcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
        pub(crate) fn new(
                channel_value_satoshis: u64, channel_keys_id: [u8; 32], destination_script: ScriptBuf,
                signer: ChannelSigner, channel_parameters: ChannelTransactionParameters,
@@ -618,7 +618,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
                                assert!(new_feerate != 0);
 
                                let transaction = cached_request.maybe_finalize_malleable_package(
-                                       cur_height, self, output_value, self.destination_script.clone(), logger
+                                       cur_height, self, Amount::from_sat(output_value), self.destination_script.clone(), logger
                                ).unwrap();
                                assert!(predicted_weight >= transaction.0.weight().to_wu());
                                return Some((new_timer, new_feerate, OnchainClaim::Tx(transaction)));
@@ -647,7 +647,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
                                        let package_target_feerate_sat_per_1000_weight = cached_request
                                                .compute_package_feerate(fee_estimator, conf_target, feerate_strategy);
                                        if let Some(input_amount_sat) = output.funding_amount {
-                                               let fee_sat = input_amount_sat - tx.0.output.iter().map(|output| output.value).sum::<u64>();
+                                               let fee_sat = input_amount_sat - tx.0.output.iter().map(|output| output.value.to_sat()).sum::<u64>();
                                                let commitment_tx_feerate_sat_per_1000_weight =
                                                        compute_feerate_sat_per_1000_weight(fee_sat, tx.0.weight().to_wu());
                                                if commitment_tx_feerate_sat_per_1000_weight >= package_target_feerate_sat_per_1000_weight {
@@ -726,7 +726,10 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
                B::Target: BroadcasterInterface,
                F::Target: FeeEstimator,
        {
-               log_debug!(logger, "Updating claims view at height {} with {} claim requests", cur_height, requests.len());
+               if !requests.is_empty() {
+                       log_debug!(logger, "Updating claims view at height {} with {} claim requests", cur_height, requests.len());
+               }
+
                let mut preprocessed_requests = Vec::with_capacity(requests.len());
                let mut aggregated_request = None;
 
@@ -772,6 +775,12 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
 
                // Claim everything up to and including `cur_height`
                let remaining_locked_packages = self.locktimed_packages.split_off(&(cur_height + 1));
+               if !self.locktimed_packages.is_empty() {
+                       log_debug!(logger,
+                               "Updating claims view at height {} with {} locked packages available for claim",
+                               cur_height,
+                               self.locktimed_packages.len());
+               }
                for (pop_height, mut entry) in self.locktimed_packages.iter_mut() {
                        log_trace!(logger, "Restoring delayed claim of package(s) at their timelock at {}.", pop_height);
                        preprocessed_requests.append(&mut entry);
@@ -852,8 +861,15 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
                B::Target: BroadcasterInterface,
                F::Target: FeeEstimator,
        {
-               log_debug!(logger, "Updating claims view at height {} with {} matched transactions in block {}", cur_height, txn_matched.len(), conf_height);
+               let mut have_logged_intro = false;
+               let mut maybe_log_intro = || {
+                       if !have_logged_intro {
+                               log_debug!(logger, "Updating claims view at height {} with {} matched transactions in block {}", cur_height, txn_matched.len(), conf_height);
+                               have_logged_intro = true;
+                       }
+               };
                let mut bump_candidates = new_hash_map();
+               if !txn_matched.is_empty() { maybe_log_intro(); }
                for tx in txn_matched {
                        // Scan all input to verify is one of the outpoint spent is of interest for us
                        let mut claimed_outputs_material = Vec::new();
@@ -946,6 +962,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
                        self.onchain_events_awaiting_threshold_conf.drain(..).collect::<Vec<_>>();
                for entry in onchain_events_awaiting_threshold_conf {
                        if entry.has_reached_confirmation_threshold(cur_height) {
+                               maybe_log_intro();
                                match entry.event {
                                        OnchainEvent::Claim { claim_id } => {
                                                // We may remove a whole set of claim outpoints here, as these one may have
@@ -983,7 +1000,11 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
                }
 
                // Build, bump and rebroadcast tx accordingly
-               log_trace!(logger, "Bumping {} candidates", bump_candidates.len());
+               if !bump_candidates.is_empty() {
+                       maybe_log_intro();
+                       log_trace!(logger, "Bumping {} candidates", bump_candidates.len());
+               }
+
                for (claim_id, request) in bump_candidates.iter() {
                        if let Some((new_timer, new_feerate, bump_claim)) = self.generate_claim(
                                cur_height, &request, &FeerateStrategy::ForceBump, &*fee_estimator, &*logger,
@@ -1212,6 +1233,7 @@ impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner>
                                                htlc: htlc.clone(),
                                                preimage: *preimage,
                                                counterparty_sig: counterparty_htlc_sig,
+                                               per_commitment_point: trusted_tx.per_commitment_point(),
                                        }
                                })
                };