X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmonitor.rs;h=d180d3bbdc095501f686e86f5f433a0373210b7e;hb=1107ab06c33bd360bdee7ee64f4b690e753003f6;hp=f4f03abc3e20835258302766882d09e6b539f4eb;hpb=8369541f63eead52552788198fadfa2456b2f462;p=rust-lightning diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index f4f03abc..d180d3bb 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -409,7 +409,6 @@ impl PartialEq for OnchainDetection { struct LocalSignedTx { /// txid of the transaction in tx, just used to make comparison faster txid: Sha256dHash, - tx: LocalCommitmentTransaction, revocation_key: PublicKey, a_htlc_key: PublicKey, b_htlc_key: PublicKey, @@ -439,8 +438,6 @@ pub(crate) enum InputMaterial { locktime: u32, }, LocalHTLC { - witness_script: Script, - sigs: (Signature, Signature), preimage: Option, amount: u64, }, @@ -468,11 +465,8 @@ impl Writeable for InputMaterial { writer.write_all(&byte_utils::be64_to_array(*amount))?; writer.write_all(&byte_utils::be32_to_array(*locktime))?; }, - &InputMaterial::LocalHTLC { ref witness_script, ref sigs, ref preimage, ref amount } => { + &InputMaterial::LocalHTLC { ref preimage, ref amount } => { writer.write_all(&[2; 1])?; - witness_script.write(writer)?; - sigs.0.write(writer)?; - sigs.1.write(writer)?; preimage.write(writer)?; writer.write_all(&byte_utils::be64_to_array(*amount))?; }, @@ -517,16 +511,11 @@ impl Readable for InputMaterial { } }, 2 => { - let witness_script = Readable::read(reader)?; - let their_sig = Readable::read(reader)?; - let our_sig = Readable::read(reader)?; let preimage = Readable::read(reader)?; let amount = Readable::read(reader)?; InputMaterial::LocalHTLC { - witness_script, - sigs: (their_sig, our_sig), preimage, - amount + amount, } }, 3 => { @@ -970,7 +959,7 @@ impl ChannelMonitor { macro_rules! serialize_local_tx { ($local_tx: expr) => { - $local_tx.tx.write(writer)?; + $local_tx.txid.write(writer)?; writer.write_all(&$local_tx.revocation_key.serialize())?; writer.write_all(&$local_tx.a_htlc_key.serialize())?; writer.write_all(&$local_tx.b_htlc_key.serialize())?; @@ -1261,23 +1250,32 @@ impl ChannelMonitor { /// is important that any clones of this channel monitor (including remote clones) by kept /// up-to-date as our local commitment transaction is updated. /// Panics if set_their_to_self_delay has never been called. - pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>) -> Result<(), MonitorUpdateError> { + pub(super) fn provide_latest_local_commitment_tx_info(&mut self, mut commitment_tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>) -> Result<(), MonitorUpdateError> { if self.their_to_self_delay.is_none() { return Err(MonitorUpdateError("Got a local commitment tx info update before we'd set basic information about the channel")); } + let txid = commitment_tx.txid(); + let sequence = commitment_tx.without_valid_witness().input[0].sequence as u64; + let locktime = commitment_tx.without_valid_witness().lock_time as u64; + let mut htlcs = Vec::with_capacity(htlc_outputs.len()); + for htlc in htlc_outputs.clone() { + if let Some(_) = htlc.0.transaction_output_index { + htlcs.push((htlc.0, htlc.1, None)); + } + } + commitment_tx.set_htlc_cache(local_keys.clone(), feerate_per_kw, htlcs); // Returning a monitor error before updating tracking points means in case of using // a concurrent watchtower implementation for same channel, if this one doesn't // reject update as we do, you MAY have the latest local valid commitment tx onchain // for which you want to spend outputs. We're NOT robust again this scenario right // now but we should consider it later. - if let Err(_) = self.onchain_tx_handler.provide_latest_local_tx(commitment_tx.clone(), local_keys.clone(), feerate_per_kw, htlc_outputs.clone()) { + if let Err(_) = self.onchain_tx_handler.provide_latest_local_tx(commitment_tx) { return Err(MonitorUpdateError("Local commitment signed has already been signed, no further update of LOCAL commitment transaction is allowed")); } - self.current_local_commitment_number = 0xffff_ffff_ffff - ((((commitment_tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (commitment_tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor); + self.current_local_commitment_number = 0xffff_ffff_ffff - ((((sequence & 0xffffff) << 3*8) | (locktime as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor); self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take(); self.current_local_signed_commitment_tx = Some(LocalSignedTx { - txid: commitment_tx.txid(), - tx: commitment_tx, + txid, revocation_key: local_keys.revocation_key, a_htlc_key: local_keys.a_htlc_key, b_htlc_key: local_keys.b_htlc_key, @@ -1687,8 +1685,8 @@ impl ChannelMonitor { (claimable_outpoints, Some((htlc_txid, tx.output.clone()))) } - fn broadcast_by_local_state(&self, commitment_tx: &Transaction, local_tx: &LocalSignedTx) -> (Vec, Vec, Option<(Script, SecretKey, Script)>) { - let mut res = Vec::with_capacity(local_tx.htlc_outputs.len()); + fn broadcast_by_local_state(&self, commitment_tx: &Transaction, local_tx: &LocalSignedTx) -> (Vec, Vec, Option<(Script, SecretKey, Script)>) { + let mut claim_requests = Vec::with_capacity(local_tx.htlc_outputs.len()); let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len()); let redeemscript = chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.their_to_self_delay.unwrap(), &local_tx.delayed_payment_key); @@ -1696,40 +1694,23 @@ impl ChannelMonitor { Some((redeemscript.to_v0_p2wsh(), local_delayedkey, redeemscript)) } else { None }; - for &(ref htlc, ref sigs, _) in local_tx.htlc_outputs.iter() { + for &(ref htlc, _, _) in local_tx.htlc_outputs.iter() { if let Some(transaction_output_index) = htlc.transaction_output_index { - if let &Some(ref their_sig) = sigs { - if htlc.offered { - log_trace!(self, "Broadcasting HTLC-Timeout transaction against local commitment transactions"); - let mut htlc_timeout_tx = chan_utils::build_htlc_transaction(&local_tx.txid, local_tx.feerate_per_kw, self.their_to_self_delay.unwrap(), htlc, &local_tx.delayed_payment_key, &local_tx.revocation_key); - self.onchain_detection.keys.sign_htlc_transaction(&mut htlc_timeout_tx, their_sig, &None, htlc, &local_tx.a_htlc_key, &local_tx.b_htlc_key, &local_tx.revocation_key, &local_tx.per_commitment_point, &self.secp_ctx); - - log_trace!(self, "Outpoint {}:{} is being being claimed", htlc_timeout_tx.input[0].previous_output.vout, htlc_timeout_tx.input[0].previous_output.txid); - res.push(htlc_timeout_tx); - } else { - if let Some(payment_preimage) = self.payment_preimages.get(&htlc.payment_hash) { - log_trace!(self, "Broadcasting HTLC-Success transaction against local commitment transactions"); - let mut htlc_success_tx = chan_utils::build_htlc_transaction(&local_tx.txid, local_tx.feerate_per_kw, self.their_to_self_delay.unwrap(), htlc, &local_tx.delayed_payment_key, &local_tx.revocation_key); - self.onchain_detection.keys.sign_htlc_transaction(&mut htlc_success_tx, their_sig, &Some(*payment_preimage), htlc, &local_tx.a_htlc_key, &local_tx.b_htlc_key, &local_tx.revocation_key, &local_tx.per_commitment_point, &self.secp_ctx); - - log_trace!(self, "Outpoint {}:{} is being being claimed", htlc_success_tx.input[0].previous_output.vout, htlc_success_tx.input[0].previous_output.txid); - res.push(htlc_success_tx); - } - } - watch_outputs.push(commitment_tx.output[transaction_output_index as usize].clone()); - } else { panic!("Should have sigs for non-dust local tx outputs!") } + let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) { Some(*preimage) } else { None }; + claim_requests.push(ClaimRequest { absolute_timelock: ::std::u32::MAX, aggregable: false, outpoint: BitcoinOutPoint { txid: local_tx.txid, vout: transaction_output_index as u32 }, witness_data: InputMaterial::LocalHTLC { preimage, amount: htlc.amount_msat / 1000 }}); + watch_outputs.push(commitment_tx.output[transaction_output_index as usize].clone()); } } - (res, watch_outputs, broadcasted_local_revokable_script) + (claim_requests, watch_outputs, broadcasted_local_revokable_script) } /// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet) /// revoked using data in local_claimable_outpoints. /// Should not be used if check_spend_revoked_transaction succeeds. - fn check_spend_local_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec, (Sha256dHash, Vec)) { + fn check_spend_local_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec, (Sha256dHash, Vec)) { let commitment_txid = tx.txid(); - let mut local_txn = Vec::new(); + let mut claim_requests = Vec::new(); let mut watch_outputs = Vec::new(); macro_rules! wait_threshold_conf { @@ -1757,7 +1738,7 @@ impl ChannelMonitor { macro_rules! append_onchain_update { ($updates: expr) => { - local_txn.append(&mut $updates.0); + claim_requests = $updates.0; watch_outputs.append(&mut $updates.1); self.broadcasted_local_revokable_script = $updates.2; } @@ -1804,7 +1785,7 @@ impl ChannelMonitor { } } - (local_txn, (commitment_txid, watch_outputs)) + (claim_requests, (commitment_txid, watch_outputs)) } /// Used by ChannelManager deserialization to broadcast the latest local state if its copy of @@ -1898,14 +1879,11 @@ impl ChannelMonitor { watch_outputs.push(new_outputs); } if new_outpoints.is_empty() { - let (local_txn, new_outputs) = self.check_spend_local_transaction(&tx, height); - for tx in local_txn.iter() { - log_trace!(self, "Broadcast onchain {}", log_tx!(tx)); - broadcaster.broadcast_transaction(tx); - } + let (mut new_outpoints, new_outputs) = self.check_spend_local_transaction(&tx, height); if !new_outputs.1.is_empty() { watch_outputs.push(new_outputs); } + claimable_outpoints.append(&mut new_outpoints); } claimable_outpoints.append(&mut new_outpoints); } @@ -1935,14 +1913,11 @@ impl ChannelMonitor { if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx { if should_broadcast { if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(self.channel_value_satoshis.unwrap()) { - let (txs, new_outputs, _) = self.broadcast_by_local_state(&commitment_tx, cur_local_tx); + let (mut new_outpoints, new_outputs, _) = self.broadcast_by_local_state(&commitment_tx, cur_local_tx); if !new_outputs.is_empty() { watch_outputs.push((cur_local_tx.txid.clone(), new_outputs)); } - for tx in txs { - log_trace!(self, "Broadcast onchain {}", log_tx!(tx)); - broadcaster.broadcast_transaction(&tx); - } + claimable_outpoints.append(&mut new_outpoints); } } } @@ -2393,7 +2368,7 @@ impl ReadableArgs> for (Sha256dH macro_rules! read_local_tx { () => { { - let tx = ::read(reader)?; + let txid = Readable::read(reader)?; let revocation_key = Readable::read(reader)?; let a_htlc_key = Readable::read(reader)?; let b_htlc_key = Readable::read(reader)?; @@ -2414,8 +2389,7 @@ impl ReadableArgs> for (Sha256dH } LocalSignedTx { - txid: tx.txid(), - tx, + txid, revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, per_commitment_point, feerate_per_kw, htlc_outputs: htlcs }