From: Antoine Riard Date: Sat, 21 Mar 2020 22:52:00 +0000 (-0400) Subject: Cache per-HTLC data in OnchainTxHandler::HTLCTxCache X-Git-Tag: v0.0.12~84^2~7 X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=commitdiff_plain;h=080afeb6ea5746ac076658c723492e3d6d257ceb;p=rust-lightning Cache per-HTLC data in OnchainTxHandler::HTLCTxCache Splitting further parsing from transaction generation, we cache transaction elements needed for local HTLC transaction inside OnchainTxHandler. Duplicated data will be removed from ChannelMonitor in future commits. --- diff --git a/lightning/src/ln/channelmonitor.rs b/lightning/src/ln/channelmonitor.rs index b0b311931..4a89f5002 100644 --- a/lightning/src/ln/channelmonitor.rs +++ b/lightning/src/ln/channelmonitor.rs @@ -1270,7 +1270,7 @@ impl ChannelMonitor { // 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) { + if let Err(_) = self.onchain_tx_handler.provide_latest_local_tx(commitment_tx.clone(), local_keys.clone(), feerate_per_kw, htlc_outputs.clone()) { 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); @@ -1284,7 +1284,7 @@ impl ChannelMonitor { delayed_payment_key: local_keys.a_delayed_payment_key, per_commitment_point: local_keys.per_commitment_point, feerate_per_kw, - htlc_outputs, + htlc_outputs: htlc_outputs, }); Ok(()) } diff --git a/lightning/src/ln/onchaintx.rs b/lightning/src/ln/onchaintx.rs index 43d3ec9a6..406d9f38b 100644 --- a/lightning/src/ln/onchaintx.rs +++ b/lightning/src/ln/onchaintx.rs @@ -10,13 +10,14 @@ use bitcoin::util::bip143; use bitcoin_hashes::sha256d::Hash as Sha256dHash; -use secp256k1::Secp256k1; +use secp256k1::{Secp256k1, Signature}; use secp256k1; use ln::msgs::DecodeError; use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest}; +use ln::channelmanager::HTLCSource; use ln::chan_utils; -use ln::chan_utils::{HTLCType, LocalCommitmentTransaction, TxCreationKeys}; +use ln::chan_utils::{HTLCType, LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment}; use chain::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT}; use chain::keysinterface::ChannelKeys; use util::logger::Logger; @@ -54,6 +55,7 @@ enum OnchainEvent { struct HTLCTxCache { local_keys: TxCreationKeys, feerate_per_kw: u64, + per_htlc: HashMap)> } /// Higher-level cache structure needed to re-generate bumped claim txn if needed @@ -202,6 +204,16 @@ impl OnchainTxHandler { ($cache: expr) => { $cache.local_keys.write(writer)?; $cache.feerate_per_kw.write(writer)?; + writer.write_all(&byte_utils::be64_to_array($cache.per_htlc.len() as u64))?; + for (_, &(ref htlc, ref sig)) in $cache.per_htlc.iter() { + htlc.write(writer)?; + if let &Some(ref their_sig) = sig { + 1u8.write(writer)?; + writer.write_all(&their_sig.serialize_compact())?; + } else { + 0u8.write(writer)?; + } + } } } @@ -268,9 +280,21 @@ impl ReadableArgs> for OnchainTx { let local_keys = Readable::read(reader)?; let feerate_per_kw = Readable::read(reader)?; + let htlcs_count: u64 = Readable::read(reader)?; + let mut per_htlc = HashMap::with_capacity(cmp::min(htlcs_count as usize, MAX_ALLOC_SIZE / 32)); + for _ in 0..htlcs_count { + let htlc: HTLCOutputInCommitment = Readable::read(reader)?; + let sigs = match ::read(reader)? { + 0 => None, + 1 => Some(Readable::read(reader)?), + _ => return Err(DecodeError::InvalidValue), + }; + per_htlc.insert(htlc.transaction_output_index.unwrap(), (htlc, sigs)); + } HTLCTxCache { local_keys, feerate_per_kw, + per_htlc } } } @@ -821,7 +845,7 @@ impl OnchainTxHandler { } } - pub(super) fn provide_latest_local_tx(&mut self, tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64) -> Result<(), ()> { + pub(super) fn provide_latest_local_tx(&mut self, tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>) -> Result<(), ()> { // To prevent any unsafe state discrepancy between offchain and onchain, once local // commitment transaction has been signed due to an event (either block height for // HTLC-timeout or channel force-closure), don't allow any further update of local @@ -833,9 +857,16 @@ impl OnchainTxHandler { self.prev_local_commitment = self.local_commitment.take(); self.local_commitment = Some(tx); self.prev_htlc_cache = self.current_htlc_cache.take(); + let mut per_htlc = HashMap::with_capacity(htlc_outputs.len()); + for htlc in htlc_outputs { + if htlc.0.transaction_output_index.is_some() { // Discard dust HTLC as we will never have to generate onchain tx for them + per_htlc.insert(htlc.0.transaction_output_index.unwrap(), (htlc.0, htlc.1)); + } + } self.current_htlc_cache = Some(HTLCTxCache { local_keys, feerate_per_kw, + per_htlc }); Ok(()) }