From 8369541f63eead52552788198fadfa2456b2f462 Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Mon, 23 Mar 2020 01:30:48 -0400 Subject: [PATCH] Add OnchainTxHandler::get_fully_signed_htlc In case of channel force-closure, access to local commitment transactions and its dependent HTLCs is needed. Instead of using broadcast_by_local_state which registers outpoint to claim and outputs to watch which are going to be discarded in this case, we simply ask OnchainTxHandler to build and sign HTLC transactions through new API. --- lightning/src/ln/channelmonitor.rs | 22 ++++++++++++++++++---- lightning/src/ln/onchaintx.rs | 21 ++++++++++++++++++++- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index 0f6cc826..f4f03abc 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -1819,10 +1819,17 @@ impl ChannelMonitor { pub fn get_latest_local_commitment_txn(&mut self) -> Vec { log_trace!(self, "Getting signed latest local commitment transaction!"); if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(self.channel_value_satoshis.unwrap()) { + let txid = commitment_tx.txid(); let mut res = vec![commitment_tx]; if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx { - let mut htlc_txn = self.broadcast_by_local_state(res.get(0).unwrap(), local_tx).0; - res.append(&mut htlc_txn); + for htlc in local_tx.htlc_outputs.iter() { + if let Some(htlc_index) = htlc.0.transaction_output_index { + let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None }; + if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) { + res.push(htlc_tx); + } + } + } // We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do. // The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation. } @@ -1838,10 +1845,17 @@ impl ChannelMonitor { pub fn unsafe_get_latest_local_commitment_txn(&mut self) -> Vec { log_trace!(self, "Getting signed copy of latest local commitment transaction!"); if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_copy_local_tx(self.channel_value_satoshis.unwrap()) { + let txid = commitment_tx.txid(); let mut res = vec![commitment_tx]; if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx { - let mut htlc_txn = self.broadcast_by_local_state(res.get(0).unwrap(), local_tx).0; - res.append(&mut htlc_txn); + for htlc in local_tx.htlc_outputs.iter() { + if let Some(htlc_index) = htlc.0.transaction_output_index { + let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None }; + if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) { + res.push(htlc_tx); + } + } + } } return res } diff --git a/lightning/src/ln/onchaintx.rs b/lightning/src/ln/onchaintx.rs index fce93554..8cb9bfb3 100644 --- a/lightning/src/ln/onchaintx.rs +++ b/lightning/src/ln/onchaintx.rs @@ -15,7 +15,7 @@ use secp256k1; use ln::msgs::DecodeError; use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest}; -use ln::channelmanager::HTLCSource; +use ln::channelmanager::{HTLCSource, PaymentPreimage}; use ln::chan_utils; use ln::chan_utils::{HTLCType, LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment}; use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT}; @@ -893,4 +893,23 @@ impl OnchainTxHandler { } None } + + pub(super) fn get_fully_signed_htlc_tx(&mut self, txid: Sha256dHash, htlc_index: u32, preimage: Option) -> Option { + //TODO: store preimage in OnchainTxHandler + if let Some(ref local_commitment) = self.local_commitment { + if local_commitment.txid() == txid { + if let Some(ref htlc_cache) = self.current_htlc_cache { + if let Some(htlc) = htlc_cache.per_htlc.get(&htlc_index) { + if !htlc.0.offered && preimage.is_none() { return None; }; // If we don't have preimage for HTLC-Success, don't try to generate + let htlc_secret = if !htlc.0.offered { preimage } else { None }; // If we have a preimage for a HTLC-Timeout, don't use it that's likely a duplicate HTLC hash + let mut htlc_tx = chan_utils::build_htlc_transaction(&txid, htlc_cache.feerate_per_kw, self.local_csv, &htlc.0, &htlc_cache.local_keys.a_delayed_payment_key, &htlc_cache.local_keys.revocation_key); + self.key_storage.sign_htlc_transaction(&mut htlc_tx, htlc.1.as_ref().unwrap(), &htlc_secret, &htlc.0, &htlc_cache.local_keys.a_htlc_key, &htlc_cache.local_keys.b_htlc_key, &htlc_cache.local_keys.revocation_key, &htlc_cache.local_keys.per_commitment_point, &self.secp_ctx); + return Some(htlc_tx); + + } + } + } + } + None + } } -- 2.30.2