From 6c78c6da7788eb351a368302c1d32c959b5fc93f Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Mon, 23 Mar 2020 22:17:46 -0400 Subject: [PATCH] Cache remote HTLC inside OnchainTxHandler::RemoteTxCache As we can't predict if any and which revoked commitment tx is going to appear onchain we have by design to cache all htlc information to regenerate htlc script if needed. --- lightning/src/ln/channelmonitor.rs | 9 +++++++- lightning/src/ln/onchaintx.rs | 33 ++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index 75bf6d7c6..a818e0702 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -1186,7 +1186,7 @@ impl ChannelMonitor { log_trace!(self, "New potential remote commitment transaction: {}", encode::serialize_hex(unsigned_commitment_tx)); self.prev_remote_commitment_txid = self.current_remote_commitment_txid.take(); self.current_remote_commitment_txid = Some(new_txid); - self.remote_claimable_outpoints.insert(new_txid, htlc_outputs); + self.remote_claimable_outpoints.insert(new_txid, htlc_outputs.clone()); self.current_remote_commitment_number = commitment_number; //TODO: Merge this into the other per-remote-transaction output storage stuff match self.their_cur_revocation_points { @@ -1207,6 +1207,13 @@ impl ChannelMonitor { self.their_cur_revocation_points = Some((commitment_number, their_revocation_point, None)); } } + let mut htlcs = Vec::with_capacity(htlc_outputs.len()); + for htlc in htlc_outputs { + if htlc.0.transaction_output_index.is_some() { + htlcs.push(htlc.0); + } + } + self.onchain_tx_handler.provide_latest_remote_tx(new_txid, htlcs); } /// Informs this monitor of the latest local (ie broadcastable) commitment transaction. The diff --git a/lightning/src/ln/onchaintx.rs b/lightning/src/ln/onchaintx.rs index c57b11aaf..bdb2b952a 100644 --- a/lightning/src/ln/onchaintx.rs +++ b/lightning/src/ln/onchaintx.rs @@ -17,7 +17,7 @@ use bitcoin::secp256k1::key::PublicKey; use ln::msgs::DecodeError; use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest}; use ln::channelmanager::PaymentPreimage; -use ln::chan_utils::{HTLCType, LocalCommitmentTransaction}; +use ln::chan_utils::{HTLCType, LocalCommitmentTransaction, HTLCOutputInCommitment}; use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT}; use chain::keysinterface::ChannelKeys; use util::logger::Logger; @@ -53,7 +53,8 @@ enum OnchainEvent { /// remote outputs, either justice or preimage/timeout transactions. struct RemoteTxCache { remote_delayed_payment_base_key: PublicKey, - remote_htlc_base_key: PublicKey + remote_htlc_base_key: PublicKey, + per_htlc: HashMap> } /// Higher-level cache structure needed to re-generate bumped claim txn if needed @@ -253,6 +254,14 @@ impl OnchainTxHandler { self.remote_tx_cache.remote_delayed_payment_base_key.write(writer)?; self.remote_tx_cache.remote_htlc_base_key.write(writer)?; + writer.write_all(&byte_utils::be64_to_array(self.remote_tx_cache.per_htlc.len() as u64))?; + for (ref txid, ref htlcs) in self.remote_tx_cache.per_htlc.iter() { + writer.write_all(&txid[..])?; + writer.write_all(&byte_utils::be64_to_array(htlcs.len() as u64))?; + for &ref htlc in htlcs.iter() { + htlc.write(writer)?; + } + } self.remote_csv.write(writer)?; self.key_storage.write(writer)?; @@ -306,9 +315,24 @@ impl ReadableArgs> for OnchainTx let remote_tx_cache = { let remote_delayed_payment_base_key = Readable::read(reader)?; let remote_htlc_base_key = Readable::read(reader)?; + let per_htlc_len: u64 = Readable::read(reader)?; + let mut per_htlc = HashMap::with_capacity(cmp::min(per_htlc_len as usize, MAX_ALLOC_SIZE / 64)); + for _ in 0..per_htlc_len { + let txid: Sha256dHash = Readable::read(reader)?; + let htlcs_count: u64 = Readable::read(reader)?; + let mut htlcs = Vec::with_capacity(cmp::min(htlcs_count as usize, MAX_ALLOC_SIZE / 32)); + for _ in 0..htlcs_count { + let htlc = Readable::read(reader)?; + htlcs.push(htlc); + } + if let Some(_) = per_htlc.insert(txid, htlcs) { + return Err(DecodeError::InvalidValue); + } + } RemoteTxCache { remote_delayed_payment_base_key, remote_htlc_base_key, + per_htlc, } }; let remote_csv = Readable::read(reader)?; @@ -385,6 +409,7 @@ impl OnchainTxHandler { let remote_tx_cache = RemoteTxCache { remote_delayed_payment_base_key, remote_htlc_base_key, + per_htlc: HashMap::new(), }; OnchainTxHandler { @@ -903,6 +928,10 @@ impl OnchainTxHandler { } } + pub(super) fn provide_latest_remote_tx(&mut self, commitment_txid: Sha256dHash, htlcs: Vec) { + self.remote_tx_cache.per_htlc.insert(commitment_txid, htlcs); + } + #[cfg(test)] pub(super) fn get_fully_signed_copy_local_tx(&mut self, funding_redeemscript: &Script) -> Option { if let Some(ref mut local_commitment) = self.local_commitment { -- 2.39.5