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.
This commit is contained in:
Antoine Riard 2020-03-23 22:17:46 -04:00
parent 6b1afcc313
commit 275814cc1d
2 changed files with 39 additions and 3 deletions

View file

@ -1193,7 +1193,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
log_trace!(logger, "New potential remote commitment transaction: {}", encode::serialize_hex(unsigned_commitment_tx)); 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.prev_remote_commitment_txid = self.current_remote_commitment_txid.take();
self.current_remote_commitment_txid = Some(new_txid); 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; self.current_remote_commitment_number = commitment_number;
//TODO: Merge this into the other per-remote-transaction output storage stuff //TODO: Merge this into the other per-remote-transaction output storage stuff
match self.their_cur_revocation_points { 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)); 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 /// Informs this monitor of the latest local (ie broadcastable) commitment transaction. The

View file

@ -17,7 +17,7 @@ use bitcoin::secp256k1::key::PublicKey;
use ln::msgs::DecodeError; use ln::msgs::DecodeError;
use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest}; use ln::channelmonitor::{ANTI_REORG_DELAY, CLTV_SHARED_CLAIM_BUFFER, InputMaterial, ClaimRequest};
use ln::channelmanager::PaymentPreimage; 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::chaininterface::{FeeEstimator, BroadcasterInterface, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
use chain::keysinterface::ChannelKeys; use chain::keysinterface::ChannelKeys;
use util::logger::Logger; use util::logger::Logger;
@ -52,7 +52,8 @@ enum OnchainEvent {
/// remote outputs, either justice or preimage/timeout transactions. /// remote outputs, either justice or preimage/timeout transactions.
struct RemoteTxCache { struct RemoteTxCache {
remote_delayed_payment_base_key: PublicKey, 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 /// 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_delayed_payment_base_key.write(writer)?;
self.remote_tx_cache.remote_htlc_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.remote_csv.write(writer)?;
self.key_storage.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_tx_cache = {
let remote_delayed_payment_base_key = Readable::read(reader)?; let remote_delayed_payment_base_key = Readable::read(reader)?;
let remote_htlc_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 { RemoteTxCache {
remote_delayed_payment_base_key, remote_delayed_payment_base_key,
remote_htlc_base_key, remote_htlc_base_key,
per_htlc,
} }
}; };
let remote_csv = Readable::read(reader)?; let remote_csv = Readable::read(reader)?;
@ -382,6 +406,7 @@ impl<ChanSigner: ChannelKeys> OnchainTxHandler<ChanSigner> {
let remote_tx_cache = RemoteTxCache { let remote_tx_cache = RemoteTxCache {
remote_delayed_payment_base_key, remote_delayed_payment_base_key,
remote_htlc_base_key, remote_htlc_base_key,
per_htlc: HashMap::new(),
}; };
OnchainTxHandler { 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)] #[cfg(test)]
pub(super) fn get_fully_signed_copy_local_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> { 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 { if let Some(ref mut local_commitment) = self.local_commitment {