X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fonchaintx.rs;h=2d7d417d255ac77dfecb1791dd24bca42d4166ca;hb=c7ddcd3867757c74d8a3a2997604edf52aa0a536;hp=9e77ac9741ad2caa3eaf75971ab21d7a2b5c05cb;hpb=63c56a4a86cd638ebd1d85c7a227b7c19f2f6765;p=rust-lightning diff --git a/lightning/src/ln/onchaintx.rs b/lightning/src/ln/onchaintx.rs index 9e77ac97..2d7d417d 100644 --- a/lightning/src/ln/onchaintx.rs +++ b/lightning/src/ln/onchaintx.rs @@ -35,6 +35,7 @@ use util::byte_utils; use std::collections::{HashMap, hash_map}; use std::cmp; use std::ops::Deref; +use std::mem::replace; const MAX_ALLOC_SIZE: usize = 64*1024; @@ -241,7 +242,7 @@ impl Writeable for Option>> { /// do RBF bumping if possible. pub struct OnchainTxHandler { destination_script: Script, - holder_commitment: Option, + holder_commitment: HolderCommitmentTransaction, // holder_htlc_sigs and prev_holder_htlc_sigs are in the order as they appear in the commitment // transaction outputs (hence the Option<>s inside the Vec). The first usize is the index in // the set of HTLCs in the HolderCommitmentTransaction. @@ -423,13 +424,13 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler OnchainTxHandler { - pub(crate) fn new(destination_script: Script, keys: ChanSigner, channel_parameters: ChannelTransactionParameters) -> Self { + pub(crate) fn new(destination_script: Script, keys: ChanSigner, channel_parameters: ChannelTransactionParameters, holder_commitment: HolderCommitmentTransaction) -> Self { let key_storage = keys; OnchainTxHandler { destination_script, - holder_commitment: None, + holder_commitment, holder_htlc_sigs: None, prev_holder_commitment: None, prev_holder_htlc_sigs: None, @@ -663,10 +664,10 @@ impl OnchainTxHandler { return None; }, &InputMaterial::Funding { ref funding_redeemscript } => { - let signed_tx = self.get_fully_signed_holder_tx(funding_redeemscript).unwrap(); + let signed_tx = self.get_fully_signed_holder_tx(funding_redeemscript); // Timer set to $NEVER given we can't bump tx without anchor outputs log_trace!(logger, "Going to broadcast Holder Transaction {} claiming funding output {} from {}...", signed_tx.txid(), outp.vout, outp.txid); - return Some((None, self.holder_commitment.as_ref().unwrap().feerate_per_kw(), signed_tx)); + return Some((None, self.holder_commitment.feerate_per_kw(), signed_tx)); } _ => unreachable!() } @@ -904,9 +905,8 @@ impl OnchainTxHandler { } pub(crate) fn provide_latest_holder_tx(&mut self, tx: HolderCommitmentTransaction) { - self.prev_holder_commitment = self.holder_commitment.take(); + self.prev_holder_commitment = Some(replace(&mut self.holder_commitment, tx)); self.holder_htlc_sigs = None; - self.holder_commitment = Some(tx); } // Normally holder HTLCs are signed at the same time as the holder commitment tx. However, @@ -914,15 +914,13 @@ impl OnchainTxHandler { // ChannelMonitor replica, so we handle that case here. fn sign_latest_holder_htlcs(&mut self) { if self.holder_htlc_sigs.is_none() { - if let Some(ref holder_commitment) = self.holder_commitment { - let (_sig, sigs) = self.key_storage.sign_holder_commitment_and_htlcs(holder_commitment, &self.secp_ctx).expect("sign holder commitment"); - self.holder_htlc_sigs = Some(Self::extract_holder_sigs(holder_commitment, sigs)); - } + let (_sig, sigs) = self.key_storage.sign_holder_commitment_and_htlcs(&self.holder_commitment, &self.secp_ctx).expect("sign holder commitment"); + self.holder_htlc_sigs = Some(Self::extract_holder_sigs(&self.holder_commitment, sigs)); } } // Normally only the latest commitment tx and HTLCs need to be signed. However, in some - // configurations we may have updated our holder commtiment but a replica of the ChannelMonitor + // configurations we may have updated our holder commitment but a replica of the ChannelMonitor // broadcast the previous one before we sync with it. We handle that case here. fn sign_prev_holder_htlcs(&mut self) { if self.prev_holder_htlc_sigs.is_none() { @@ -947,43 +945,34 @@ impl OnchainTxHandler { // have empty holder commitment transaction if a ChannelMonitor is asked to force-close just after Channel::get_outbound_funding_created, // before providing a initial commitment transaction. For outbound channel, init ChannelMonitor at Channel::funding_signed, there is nothing // to monitor before. - pub(crate) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Option { - if let Some(ref mut holder_commitment) = self.holder_commitment { - let (sig, htlc_sigs) = self.key_storage.sign_holder_commitment_and_htlcs(holder_commitment, &self.secp_ctx).expect("signing holder commitment"); - self.holder_htlc_sigs = Some(Self::extract_holder_sigs(holder_commitment, htlc_sigs)); - Some(holder_commitment.add_holder_sig(funding_redeemscript, sig)) - } else { - None - } + pub(crate) fn get_fully_signed_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction { + let (sig, htlc_sigs) = self.key_storage.sign_holder_commitment_and_htlcs(&self.holder_commitment, &self.secp_ctx).expect("signing holder commitment"); + self.holder_htlc_sigs = Some(Self::extract_holder_sigs(&self.holder_commitment, htlc_sigs)); + self.holder_commitment.add_holder_sig(funding_redeemscript, sig) } #[cfg(any(test, feature="unsafe_revoked_tx_signing"))] - pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Option { - if let Some(ref mut holder_commitment) = self.holder_commitment { - let (sig, htlc_sigs) = self.key_storage.sign_holder_commitment_and_htlcs(holder_commitment, &self.secp_ctx).expect("sign holder commitment"); - self.holder_htlc_sigs = Some(Self::extract_holder_sigs(holder_commitment, htlc_sigs)); - Some(holder_commitment.add_holder_sig(funding_redeemscript, sig)) - } else { - None - } + pub(crate) fn get_fully_signed_copy_holder_tx(&mut self, funding_redeemscript: &Script) -> Transaction { + let (sig, htlc_sigs) = self.key_storage.unsafe_sign_holder_commitment_and_htlcs(&self.holder_commitment, &self.secp_ctx).expect("sign holder commitment"); + self.holder_htlc_sigs = Some(Self::extract_holder_sigs(&self.holder_commitment, htlc_sigs)); + self.holder_commitment.add_holder_sig(funding_redeemscript, sig) } pub(crate) fn get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option) -> Option { let mut htlc_tx = None; - if self.holder_commitment.is_some() { - let commitment_txid = self.holder_commitment.as_ref().unwrap().trust().txid(); - if commitment_txid == outp.txid { - self.sign_latest_holder_htlcs(); - if let &Some(ref htlc_sigs) = &self.holder_htlc_sigs { - let &(ref htlc_idx, ref htlc_sig) = htlc_sigs[outp.vout as usize].as_ref().unwrap(); - let holder_commitment = self.holder_commitment.as_ref().unwrap(); - let trusted_tx = holder_commitment.trust(); - let counterparty_htlc_sig = holder_commitment.counterparty_htlc_sigs[*htlc_idx]; - htlc_tx = Some(trusted_tx - .get_signed_htlc_tx(&self.channel_transaction_parameters.as_holder_broadcastable(), *htlc_idx, &counterparty_htlc_sig, htlc_sig, preimage)); - } + let commitment_txid = self.holder_commitment.trust().txid(); + // Check if the HTLC spends from the current holder commitment + if commitment_txid == outp.txid { + self.sign_latest_holder_htlcs(); + if let &Some(ref htlc_sigs) = &self.holder_htlc_sigs { + let &(ref htlc_idx, ref htlc_sig) = htlc_sigs[outp.vout as usize].as_ref().unwrap(); + let trusted_tx = self.holder_commitment.trust(); + let counterparty_htlc_sig = self.holder_commitment.counterparty_htlc_sigs[*htlc_idx]; + htlc_tx = Some(trusted_tx + .get_signed_htlc_tx(&self.channel_transaction_parameters.as_holder_broadcastable(), *htlc_idx, &counterparty_htlc_sig, htlc_sig, preimage)); } } + // If the HTLC doesn't spend the current holder commitment, check if it spends the previous one if htlc_tx.is_none() && self.prev_holder_commitment.is_some() { let commitment_txid = self.prev_holder_commitment.as_ref().unwrap().trust().txid(); if commitment_txid == outp.txid {