Cache remote HTLC inside OnchainTxHandler::RemoteTxCache
authorAntoine Riard <ariard@student.42.fr>
Tue, 24 Mar 2020 02:17:46 +0000 (22:17 -0400)
committerAntoine Riard <ariard@student.42.fr>
Mon, 18 May 2020 08:39:26 +0000 (04:39 -0400)
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
lightning/src/ln/onchaintx.rs

index 6f00392c214c67002e08110930e945976ca342d9..19db34a700b2b2926c8768c653cc93f6ab4a5fcd 100644 (file)
@@ -1193,7 +1193,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                log_trace!(logger, "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 {
@@ -1214,6 +1214,13 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
                                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
index eb30f155cfe3c683fa424fb0c0cce266bfc94aae..7e84132e481b3c11799d4b6e8f27c0f281bb8a20 100644 (file)
@@ -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;
@@ -52,7 +52,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<Sha256dHash, Vec<(HTLCOutputInCommitment)>>
 }
 
 /// Higher-level cache structure needed to re-generate bumped claim txn if needed
@@ -251,6 +252,14 @@ impl<ChanSigner: ChannelKeys + Writeable> OnchainTxHandler<ChanSigner> {
 
                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)?;
@@ -304,9 +313,24 @@ impl<ChanSigner: ChannelKeys + Readable> Readable for OnchainTxHandler<ChanSigne
                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)?;
@@ -382,6 +406,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
                let remote_tx_cache = RemoteTxCache {
                        remote_delayed_payment_base_key,
                        remote_htlc_base_key,
+                       per_htlc: HashMap::new(),
                };
 
                OnchainTxHandler {
@@ -902,6 +927,10 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
                }
        }
 
+       pub(super) fn provide_latest_remote_tx(&mut self, commitment_txid: Sha256dHash, htlcs: Vec<HTLCOutputInCommitment>) {
+               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<Transaction> {
                if let Some(ref mut local_commitment) = self.local_commitment {