X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fonchaintx.rs;h=039fb5ff13a04eb1fd843d061bbd992a0f394935;hb=56a01de61d0eab8c3d343b51e1a500098baa5aea;hp=5bf3a8fd4823369902fba99752ef4b546aebaad3;hpb=d9d4611e65c64001d5ac3b46a1c0288965ee4378;p=rust-lightning diff --git a/lightning/src/chain/onchaintx.rs b/lightning/src/chain/onchaintx.rs index 5bf3a8fd..039fb5ff 100644 --- a/lightning/src/chain/onchaintx.rs +++ b/lightning/src/chain/onchaintx.rs @@ -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 { +#[derive(PartialEq)] +pub struct OnchainTxHandler { 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 { const SERIALIZATION_VERSION: u8 = 1; const MIN_SERIALIZATION_VERSION: u8 = 1; -impl OnchainTxHandler { +impl OnchainTxHandler { pub(crate) fn write(&self, writer: &mut W) -> Result<(), io::Error> { write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION); @@ -322,11 +323,12 @@ impl OnchainTxHandler { } } -impl<'a, K: KeysInterface> ReadableArgs<(&'a K, u64, [u8; 32])> for OnchainTxHandler { - fn read(reader: &mut R, args: (&'a K, u64, [u8; 32])) -> Result { - 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 { + fn read(reader: &mut R, args: (&'a ES, &'b SP, u64, [u8; 32])) -> Result { + 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 OnchainTxHandler { +impl OnchainTxHandler { pub(crate) fn new(destination_script: Script, signer: ChannelSigner, channel_parameters: ChannelTransactionParameters, holder_commitment: HolderCommitmentTransaction, secp_ctx: Secp256k1) -> Self { OnchainTxHandler { destination_script, @@ -475,13 +477,13 @@ impl OnchainTxHandler { // 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 OnchainTxHandler { // 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::>(); + 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 OnchainTxHandler { 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 OnchainTxHandler { 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 OnchainTxHandler { 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 OnchainTxHandler { //- 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 OnchainTxHandler { #[cfg(anchors)] pub(crate) fn generate_external_htlc_claim( - &mut self, outp: &::bitcoin::OutPoint, preimage: &Option + &self, outp: &::bitcoin::OutPoint, preimage: &Option ) -> Option { let find_htlc = |holder_commitment: &HolderCommitmentTransaction| -> Option { let trusted_tx = holder_commitment.trust();