Pass pending_events into pay_internal
[rust-lightning] / lightning / src / chain / onchaintx.rs
index 5bf3a8fd4823369902fba99752ef4b546aebaad3..039fb5ff13a04eb1fd843d061bbd992a0f394935 100644 (file)
@@ -21,7 +21,7 @@ use bitcoin::hash_types::{Txid, BlockHash};
 use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature};
 use bitcoin::secp256k1;
 
-use crate::chain::keysinterface::BaseSign;
+use crate::chain::keysinterface::{ChannelSigner, EntropySource, SignerProvider};
 use crate::ln::msgs::DecodeError;
 use crate::ln::PaymentPreimage;
 #[cfg(anchors)]
@@ -31,7 +31,7 @@ use crate::ln::chan_utils::{ChannelTransactionParameters, HolderCommitmentTransa
 use crate::chain::chaininterface::ConfirmationTarget;
 use crate::chain::chaininterface::{FeeEstimator, BroadcasterInterface, LowerBoundedFeeEstimator};
 use crate::chain::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER};
-use crate::chain::keysinterface::{Sign, KeysInterface};
+use crate::chain::keysinterface::WriteableEcdsaChannelSigner;
 #[cfg(anchors)]
 use crate::chain::package::PackageSolvingData;
 use crate::chain::package::PackageTemplate;
@@ -79,7 +79,7 @@ enum OnchainEvent {
        /// Outpoint under claim process by our own tx, once this one get enough confirmations, we remove it from
        /// bump-txn candidate buffer.
        Claim {
-               claim_request: Txid,
+               package_id: PackageID,
        },
        /// Claim tx aggregate multiple claimable outpoints. One of the outpoint may be claimed by a counterparty party tx.
        /// In this case, we need to drop the outpoint and regenerate a new claim tx. By safety, we keep tracking
@@ -123,7 +123,7 @@ impl MaybeReadable for OnchainEventEntry {
 
 impl_writeable_tlv_based_enum_upgradable!(OnchainEvent,
        (0, Claim) => {
-               (0, claim_request, required),
+               (0, package_id, required),
        },
        (1, ContentiousOutpoint) => {
                (0, package, required),
@@ -219,7 +219,8 @@ type PackageID = [u8; 32];
 
 /// OnchainTxHandler receives claiming requests, aggregates them if it's sound, broadcast and
 /// do RBF bumping if possible.
-pub struct OnchainTxHandler<ChannelSigner: Sign> {
+#[derive(PartialEq)]
+pub struct OnchainTxHandler<ChannelSigner: WriteableEcdsaChannelSigner> {
        destination_script: Script,
        holder_commitment: HolderCommitmentTransaction,
        // holder_htlc_sigs and prev_holder_htlc_sigs are in the order as they appear in the commitment
@@ -271,7 +272,7 @@ pub struct OnchainTxHandler<ChannelSigner: Sign> {
 const SERIALIZATION_VERSION: u8 = 1;
 const MIN_SERIALIZATION_VERSION: u8 = 1;
 
-impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
+impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
        pub(crate) fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
                write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
 
@@ -322,11 +323,12 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
        }
 }
 
-impl<'a, K: KeysInterface> ReadableArgs<(&'a K, u64, [u8; 32])> for OnchainTxHandler<K::Signer> {
-       fn read<R: io::Read>(reader: &mut R, args: (&'a K, u64, [u8; 32])) -> Result<Self, DecodeError> {
-               let keys_manager = args.0;
-               let channel_value_satoshis = args.1;
-               let channel_keys_id = args.2;
+impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP, u64, [u8; 32])> for OnchainTxHandler<SP::Signer> {
+       fn read<R: io::Read>(reader: &mut R, args: (&'a ES, &'b SP, u64, [u8; 32])) -> Result<Self, DecodeError> {
+               let entropy_source = args.0;
+               let signer_provider = args.1;
+               let channel_value_satoshis = args.2;
+               let channel_keys_id = args.3;
 
                let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
 
@@ -352,7 +354,7 @@ impl<'a, K: KeysInterface> ReadableArgs<(&'a K, u64, [u8; 32])> for OnchainTxHan
                        bytes_read += bytes_to_read;
                }
 
-               let mut signer = keys_manager.derive_channel_signer(channel_value_satoshis, channel_keys_id);
+               let mut signer = signer_provider.derive_channel_signer(channel_value_satoshis, channel_keys_id);
                signer.provide_channel_parameters(&channel_parameters);
 
                let pending_claim_requests_len: u64 = Readable::read(reader)?;
@@ -393,7 +395,7 @@ impl<'a, K: KeysInterface> ReadableArgs<(&'a K, u64, [u8; 32])> for OnchainTxHan
                read_tlv_fields!(reader, {});
 
                let mut secp_ctx = Secp256k1::new();
-               secp_ctx.seeded_randomize(&keys_manager.get_secure_random_bytes());
+               secp_ctx.seeded_randomize(&entropy_source.get_secure_random_bytes());
 
                Ok(OnchainTxHandler {
                        destination_script,
@@ -414,7 +416,7 @@ impl<'a, K: KeysInterface> ReadableArgs<(&'a K, u64, [u8; 32])> for OnchainTxHan
        }
 }
 
-impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
+impl<ChannelSigner: WriteableEcdsaChannelSigner> OnchainTxHandler<ChannelSigner> {
        pub(crate) fn new(destination_script: Script, signer: ChannelSigner, channel_parameters: ChannelTransactionParameters, holder_commitment: HolderCommitmentTransaction, secp_ctx: Secp256k1<secp256k1::All>) -> Self {
                OnchainTxHandler {
                        destination_script,
@@ -475,13 +477,13 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                // remove it once it reaches the confirmation threshold, or to generate a new claim if the
                // transaction is reorged out.
                let mut all_inputs_have_confirmed_spend = true;
-               for outpoint in &request_outpoints {
-                       if let Some(first_claim_txid_height) = self.claimable_outpoints.get(outpoint) {
+               for outpoint in request_outpoints.iter() {
+                       if let Some(first_claim_txid_height) = self.claimable_outpoints.get(*outpoint) {
                                // We check for outpoint spends within claims individually rather than as a set
                                // since requests can have outpoints split off.
                                if !self.onchain_events_awaiting_threshold_conf.iter()
-                                       .any(|event_entry| if let OnchainEvent::Claim { claim_request } = event_entry.event {
-                                               first_claim_txid_height.0 == claim_request.into_inner()
+                                       .any(|event_entry| if let OnchainEvent::Claim { package_id } = event_entry.event {
+                                               first_claim_txid_height.0 == package_id
                                        } else {
                                                // The onchain event is not a claim, keep seeking until we find one.
                                                false
@@ -733,31 +735,13 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                                                // outpoints to know if transaction is the original claim or a bumped one issued
                                                // by us.
                                                let mut are_sets_equal = true;
-                                               if !request.requires_external_funding() || !request.is_malleable() {
-                                                       // If the claim does not require external funds to be allocated through
-                                                       // additional inputs we can simply check the inputs in order as they
-                                                       // cannot change under us.
-                                                       if request.outpoints().len() != tx.input.len() {
+                                               let mut tx_inputs = tx.input.iter().map(|input| &input.previous_output).collect::<Vec<_>>();
+                                               tx_inputs.sort_unstable();
+                                               for request_input in request.outpoints() {
+                                                       if tx_inputs.binary_search(&request_input).is_err() {
                                                                are_sets_equal = false;
-                                                       } else {
-                                                               for (claim_inp, tx_inp) in request.outpoints().iter().zip(tx.input.iter()) {
-                                                                       if **claim_inp != tx_inp.previous_output {
-                                                                               are_sets_equal = false;
-                                                                       }
-                                                               }
-                                                       }
-                                               } else {
-                                                       // Otherwise, we'll do a linear search for each input (we don't expect
-                                                       // large input sets to exist) to ensure the request's input set is fully
-                                                       // spent to be resilient against the external claim reordering inputs.
-                                                       let mut spends_all_inputs = true;
-                                                       for request_input in request.outpoints() {
-                                                               if tx.input.iter().find(|input| input.previous_output == *request_input).is_none() {
-                                                                       spends_all_inputs = false;
-                                                                       break;
-                                                               }
+                                                               break;
                                                        }
-                                                       are_sets_equal = spends_all_inputs;
                                                }
 
                                                macro_rules! clean_claim_request_after_safety_delay {
@@ -766,7 +750,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                                                                        txid: tx.txid(),
                                                                        height: conf_height,
                                                                        block_hash: Some(conf_hash),
-                                                                       event: OnchainEvent::Claim { claim_request: Txid::from_inner(first_claim_txid_height.0) }
+                                                                       event: OnchainEvent::Claim { package_id: first_claim_txid_height.0 }
                                                                };
                                                                if !self.onchain_events_awaiting_threshold_conf.contains(&entry) {
                                                                        self.onchain_events_awaiting_threshold_conf.push(entry);
@@ -821,14 +805,14 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                for entry in onchain_events_awaiting_threshold_conf {
                        if entry.has_reached_confirmation_threshold(cur_height) {
                                match entry.event {
-                                       OnchainEvent::Claim { claim_request } => {
-                                               let package_id = claim_request.into_inner();
+                                       OnchainEvent::Claim { package_id } => {
                                                // We may remove a whole set of claim outpoints here, as these one may have
                                                // been aggregated in a single tx and claimed so atomically
                                                if let Some(request) = self.pending_claim_requests.remove(&package_id) {
                                                        for outpoint in request.outpoints() {
-                                                               log_debug!(logger, "Removing claim tracking for {} due to maturation of claim tx {}.", outpoint, claim_request);
-                                                               self.claimable_outpoints.remove(&outpoint);
+                                                               log_debug!(logger, "Removing claim tracking for {} due to maturation of claim package {}.",
+                                                                       outpoint, log_bytes!(package_id));
+                                                               self.claimable_outpoints.remove(outpoint);
                                                                #[cfg(anchors)]
                                                                self.pending_claim_events.remove(&package_id);
                                                        }
@@ -837,7 +821,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                                        OnchainEvent::ContentiousOutpoint { package } => {
                                                log_debug!(logger, "Removing claim tracking due to maturation of claim tx for outpoints:");
                                                log_debug!(logger, " {:?}", package.outpoints());
-                                               self.claimable_outpoints.remove(&package.outpoints()[0]);
+                                               self.claimable_outpoints.remove(package.outpoints()[0]);
                                        }
                                }
                        } else {
@@ -915,7 +899,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
                                //- resurect outpoint back in its claimable set and regenerate tx
                                match entry.event {
                                        OnchainEvent::ContentiousOutpoint { package } => {
-                                               if let Some(ancestor_claimable_txid) = self.claimable_outpoints.get(&package.outpoints()[0]) {
+                                               if let Some(ancestor_claimable_txid) = self.claimable_outpoints.get(package.outpoints()[0]) {
                                                        if let Some(request) = self.pending_claim_requests.get_mut(&ancestor_claimable_txid.0) {
                                                                request.merge_package(package);
                                                                // Using a HashMap guarantee us than if we have multiple outpoints getting
@@ -1065,7 +1049,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
 
        #[cfg(anchors)]
        pub(crate) fn generate_external_htlc_claim(
-               &mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>
+               &self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>
        ) -> Option<ExternalHTLCClaim> {
                let find_htlc = |holder_commitment: &HolderCommitmentTransaction| -> Option<ExternalHTLCClaim> {
                        let trusted_tx = holder_commitment.trust();