X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=cbb07305b1caa12b34a737721f1b09412450421b;hb=ba1349982ba28657c9e2d03a5b02c3ecc054b5cc;hp=a664c7c794efe019dd82e909c132c1fd839b9ccf;hpb=0b1a64f12d3dcad46110413cab0cbdfe73979702;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index a664c7c7..cbb07305 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -37,7 +37,7 @@ use crate::ln::{PaymentHash, PaymentPreimage}; use crate::ln::msgs::DecodeError; use crate::ln::chan_utils; use crate::ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction}; -use crate::ln::channelmanager::HTLCSource; +use crate::ln::channelmanager::{HTLCSource, SentHTLCId}; use crate::chain; use crate::chain::{BestBlock, WatchedOutput}; use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator}; @@ -51,9 +51,9 @@ use crate::chain::Filter; use crate::util::logger::Logger; use crate::util::ser::{Readable, ReadableArgs, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48}; use crate::util::byte_utils; -use crate::util::events::Event; +use crate::events::Event; #[cfg(anchors)] -use crate::util::events::{AnchorDescriptor, HTLCDescriptor, BumpTransactionEvent}; +use crate::events::bump_transaction::{AnchorDescriptor, HTLCDescriptor, BumpTransactionEvent}; use crate::prelude::*; use core::{cmp, mem}; @@ -69,34 +69,36 @@ use crate::sync::{Mutex, LockTestExt}; /// much smaller than a full [`ChannelMonitor`]. However, for large single commitment transaction /// updates (e.g. ones during which there are hundreds of HTLCs pending on the commitment /// transaction), a single update may reach upwards of 1 MiB in serialized size. -#[cfg_attr(any(test, fuzzing, feature = "_test_utils"), derive(PartialEq, Eq))] -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq)] #[must_use] pub struct ChannelMonitorUpdate { pub(crate) updates: Vec, /// The sequence number of this update. Updates *must* be replayed in-order according to this /// sequence number (and updates may panic if they are not). The update_id values are strictly - /// increasing and increase by one for each new update, with one exception specified below. + /// increasing and increase by one for each new update, with two exceptions specified below. /// /// This sequence number is also used to track up to which points updates which returned /// [`ChannelMonitorUpdateStatus::InProgress`] have been applied to all copies of a given /// ChannelMonitor when ChannelManager::channel_monitor_updated is called. /// - /// The only instance where update_id values are not strictly increasing is the case where we - /// allow post-force-close updates with a special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. See - /// its docs for more details. + /// The only instances we allow where update_id values are not strictly increasing have a + /// special update ID of [`CLOSED_CHANNEL_UPDATE_ID`]. This update ID is used for updates that + /// will force close the channel by broadcasting the latest commitment transaction or + /// special post-force-close updates, like providing preimages necessary to claim outputs on the + /// broadcast commitment transaction. See its docs for more details. /// /// [`ChannelMonitorUpdateStatus::InProgress`]: super::ChannelMonitorUpdateStatus::InProgress pub update_id: u64, } -/// If: -/// (1) a channel has been force closed and -/// (2) we receive a preimage from a forward link that allows us to spend an HTLC output on -/// this channel's (the backward link's) broadcasted commitment transaction -/// then we allow the `ChannelManager` to send a `ChannelMonitorUpdate` with this update ID, -/// with the update providing said payment preimage. No other update types are allowed after -/// force-close. +/// The update ID used for a [`ChannelMonitorUpdate`] that is either: +/// +/// (1) attempting to force close the channel by broadcasting our latest commitment transaction or +/// (2) providing a preimage (after the channel has been force closed) from a forward link that +/// allows us to spend an HTLC output on this channel's (the backward link's) broadcasted +/// commitment transaction. +/// +/// No other [`ChannelMonitorUpdate`]s are allowed after force-close. pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX; impl Writeable for ChannelMonitorUpdate { @@ -488,12 +490,16 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent, ); -#[cfg_attr(any(test, fuzzing, feature = "_test_utils"), derive(PartialEq, Eq))] -#[derive(Clone)] +#[derive(Clone, PartialEq, Eq)] pub(crate) enum ChannelMonitorUpdateStep { LatestHolderCommitmentTXInfo { commitment_tx: HolderCommitmentTransaction, + /// Note that LDK after 0.0.115 supports this only containing dust HTLCs (implying the + /// `Signature` field is never filled in). At that point, non-dust HTLCs are implied by the + /// HTLC fields in `commitment_tx` and the sources passed via `nondust_htlc_sources`. htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, + claimed_htlcs: Vec<(SentHTLCId, PaymentPreimage)>, + nondust_htlc_sources: Vec, }, LatestCounterpartyCommitmentTXInfo { commitment_txid: Txid, @@ -536,7 +542,9 @@ impl ChannelMonitorUpdateStep { impl_writeable_tlv_based_enum_upgradable!(ChannelMonitorUpdateStep, (0, LatestHolderCommitmentTXInfo) => { (0, commitment_tx, required), + (1, claimed_htlcs, vec_type), (2, htlc_outputs, vec_type), + (4, nondust_htlc_sources, optional_vec), }, (1, LatestCounterpartyCommitmentTXInfo) => { (0, commitment_txid, required), @@ -750,6 +758,8 @@ pub(crate) struct ChannelMonitorImpl { /// Serialized to disk but should generally not be sent to Watchtowers. counterparty_hash_commitment_number: HashMap, + counterparty_fulfilled_htlcs: HashMap, + // We store two holder commitment transactions to avoid any race conditions where we may update // some monitors (potentially on watchtowers) but then fail to update others, resulting in the // various monitors for one channel being out of sync, and us broadcasting a holder @@ -1033,6 +1043,7 @@ impl Writeable for ChannelMonitorImpl ChannelMonitor { counterparty_claimable_outpoints: HashMap::new(), counterparty_commitment_txn_on_chain: HashMap::new(), counterparty_hash_commitment_number: HashMap::new(), + counterparty_fulfilled_htlcs: HashMap::new(), prev_holder_signed_commitment_tx: None, current_holder_commitment_tx: holder_commitment_tx, @@ -1174,7 +1186,7 @@ impl ChannelMonitor { &self, holder_commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, ) -> Result<(), ()> { - self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs).map_err(|_| ()) + self.inner.lock().unwrap().provide_latest_holder_commitment_tx(holder_commitment_tx, htlc_outputs, &Vec::new(), Vec::new()).map_err(|_| ()) } /// This is used to provide payment preimage(s) out-of-band during startup without updating the @@ -1195,17 +1207,6 @@ impl ChannelMonitor { payment_hash, payment_preimage, broadcaster, fee_estimator, logger) } - pub(crate) fn broadcast_latest_holder_commitment_txn( - &self, - broadcaster: &B, - logger: &L, - ) where - B::Target: BroadcasterInterface, - L::Target: Logger, - { - self.inner.lock().unwrap().broadcast_latest_holder_commitment_txn(broadcaster, logger); - } - /// Updates a ChannelMonitor on the basis of some new information provided by the Channel /// itself. /// @@ -1273,7 +1274,7 @@ impl ChannelMonitor { /// This is called by the [`EventsProvider::process_pending_events`] implementation for /// [`ChainMonitor`]. /// - /// [`EventsProvider::process_pending_events`]: crate::util::events::EventsProvider::process_pending_events + /// [`EventsProvider::process_pending_events`]: crate::events::EventsProvider::process_pending_events /// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor pub fn get_and_clear_pending_events(&self) -> Vec { self.inner.lock().unwrap().get_and_clear_pending_events() @@ -1810,9 +1811,10 @@ impl ChannelMonitor { /// `ChannelMonitor`. This is used to determine if an HTLC was removed from the channel prior /// to the `ChannelManager` having been persisted. /// - /// This is similar to [`Self::get_pending_outbound_htlcs`] except it includes HTLCs which were - /// resolved by this `ChannelMonitor`. - pub(crate) fn get_all_current_outbound_htlcs(&self) -> HashMap { + /// This is similar to [`Self::get_pending_or_resolved_outbound_htlcs`] except it includes + /// HTLCs which were resolved on-chain (i.e. where the final HTLC resolution was done by an + /// event from this `ChannelMonitor`). + pub(crate) fn get_all_current_outbound_htlcs(&self) -> HashMap)> { let mut res = HashMap::new(); // Just examine the available counterparty commitment transactions. See docs on // `fail_unbroadcast_htlcs`, below, for justification. @@ -1822,7 +1824,8 @@ impl ChannelMonitor { if let Some(ref latest_outpoints) = us.counterparty_claimable_outpoints.get($txid) { for &(ref htlc, ref source_option) in latest_outpoints.iter() { if let &Some(ref source) = source_option { - res.insert((**source).clone(), htlc.clone()); + res.insert((**source).clone(), (htlc.clone(), + us.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).cloned())); } } } @@ -1837,9 +1840,14 @@ impl ChannelMonitor { res } - /// Gets the set of outbound HTLCs which are pending resolution in this channel. + /// Gets the set of outbound HTLCs which are pending resolution in this channel or which were + /// resolved with a preimage from our counterparty. + /// /// This is used to reconstruct pending outbound payments on restart in the ChannelManager. - pub(crate) fn get_pending_outbound_htlcs(&self) -> HashMap { + /// + /// Currently, the preimage is unused, however if it is present in the relevant internal state + /// an HTLC is always included even if it has been resolved. + pub(crate) fn get_pending_or_resolved_outbound_htlcs(&self) -> HashMap)> { let us = self.inner.lock().unwrap(); // We're only concerned with the confirmation count of HTLC transactions, and don't // actually care how many confirmations a commitment transaction may or may not have. Thus, @@ -1887,8 +1895,10 @@ impl ChannelMonitor { Some(commitment_tx_output_idx) == htlc.transaction_output_index } else { false } }); - if !htlc_update_confd { - res.insert(source.clone(), htlc.clone()); + let counterparty_resolved_preimage_opt = + us.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).cloned(); + if !htlc_update_confd || counterparty_resolved_preimage_opt.is_some() { + res.insert(source.clone(), (htlc.clone(), counterparty_resolved_preimage_opt)); } } } @@ -1970,6 +1980,9 @@ macro_rules! fail_unbroadcast_htlcs { } } if matched_htlc { continue; } + if $self.counterparty_fulfilled_htlcs.get(&SentHTLCId::from_source(source)).is_some() { + continue; + } $self.onchain_events_awaiting_threshold_conf.retain(|ref entry| { if entry.height != $commitment_tx_conf_height { return true; } match entry.event { @@ -2041,8 +2054,23 @@ impl ChannelMonitorImpl { // Prune HTLCs from the previous counterparty commitment tx so we don't generate failure/fulfill // events for now-revoked/fulfilled HTLCs. if let Some(txid) = self.prev_counterparty_commitment_txid.take() { - for &mut (_, ref mut source) in self.counterparty_claimable_outpoints.get_mut(&txid).unwrap() { - *source = None; + if self.current_counterparty_commitment_txid.unwrap() != txid { + let cur_claimables = self.counterparty_claimable_outpoints.get( + &self.current_counterparty_commitment_txid.unwrap()).unwrap(); + for (_, ref source_opt) in self.counterparty_claimable_outpoints.get(&txid).unwrap() { + if let Some(source) = source_opt { + if !cur_claimables.iter() + .any(|(_, cur_source_opt)| cur_source_opt == source_opt) + { + self.counterparty_fulfilled_htlcs.remove(&SentHTLCId::from_source(source)); + } + } + } + for &mut (_, ref mut source_opt) in self.counterparty_claimable_outpoints.get_mut(&txid).unwrap() { + *source_opt = None; + } + } else { + assert!(cfg!(fuzzing), "Commitment txids are unique outside of fuzzing, where hashes can collide"); } } @@ -2127,28 +2155,83 @@ impl ChannelMonitorImpl { /// is important that any clones of this channel monitor (including remote clones) by kept /// up-to-date as our holder commitment transaction is updated. /// Panics if set_on_holder_tx_csv has never been called. - fn provide_latest_holder_commitment_tx(&mut self, holder_commitment_tx: HolderCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>) -> Result<(), &'static str> { - // block for Rust 1.34 compat - let mut new_holder_commitment_tx = { - let trusted_tx = holder_commitment_tx.trust(); - let txid = trusted_tx.txid(); - let tx_keys = trusted_tx.keys(); - self.current_holder_commitment_number = trusted_tx.commitment_number(); - HolderSignedTx { - txid, - revocation_key: tx_keys.revocation_key, - a_htlc_key: tx_keys.broadcaster_htlc_key, - b_htlc_key: tx_keys.countersignatory_htlc_key, - delayed_payment_key: tx_keys.broadcaster_delayed_payment_key, - per_commitment_point: tx_keys.per_commitment_point, - htlc_outputs, - to_self_value_sat: holder_commitment_tx.to_broadcaster_value_sat(), - feerate_per_kw: trusted_tx.feerate_per_kw(), + fn provide_latest_holder_commitment_tx(&mut self, holder_commitment_tx: HolderCommitmentTransaction, mut htlc_outputs: Vec<(HTLCOutputInCommitment, Option, Option)>, claimed_htlcs: &[(SentHTLCId, PaymentPreimage)], nondust_htlc_sources: Vec) -> Result<(), &'static str> { + if htlc_outputs.iter().any(|(_, s, _)| s.is_some()) { + // If we have non-dust HTLCs in htlc_outputs, ensure they match the HTLCs in the + // `holder_commitment_tx`. In the future, we'll no longer provide the redundant data + // and just pass in source data via `nondust_htlc_sources`. + debug_assert_eq!(htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).count(), holder_commitment_tx.trust().htlcs().len()); + for (a, b) in htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).map(|(h, _, _)| h).zip(holder_commitment_tx.trust().htlcs().iter()) { + debug_assert_eq!(a, b); + } + debug_assert_eq!(htlc_outputs.iter().filter(|(_, s, _)| s.is_some()).count(), holder_commitment_tx.counterparty_htlc_sigs.len()); + for (a, b) in htlc_outputs.iter().filter_map(|(_, s, _)| s.as_ref()).zip(holder_commitment_tx.counterparty_htlc_sigs.iter()) { + debug_assert_eq!(a, b); + } + debug_assert!(nondust_htlc_sources.is_empty()); + } else { + // If we don't have any non-dust HTLCs in htlc_outputs, assume they were all passed via + // `nondust_htlc_sources`, building up the final htlc_outputs by combining + // `nondust_htlc_sources` and the `holder_commitment_tx` + #[cfg(debug_assertions)] { + let mut prev = -1; + for htlc in holder_commitment_tx.trust().htlcs().iter() { + assert!(htlc.transaction_output_index.unwrap() as i32 > prev); + prev = htlc.transaction_output_index.unwrap() as i32; + } } + debug_assert!(htlc_outputs.iter().all(|(htlc, _, _)| htlc.transaction_output_index.is_none())); + debug_assert!(htlc_outputs.iter().all(|(_, sig_opt, _)| sig_opt.is_none())); + debug_assert_eq!(holder_commitment_tx.trust().htlcs().len(), holder_commitment_tx.counterparty_htlc_sigs.len()); + + let mut sources_iter = nondust_htlc_sources.into_iter(); + + for (htlc, counterparty_sig) in holder_commitment_tx.trust().htlcs().iter() + .zip(holder_commitment_tx.counterparty_htlc_sigs.iter()) + { + if htlc.offered { + let source = sources_iter.next().expect("Non-dust HTLC sources didn't match commitment tx"); + #[cfg(debug_assertions)] { + assert!(source.possibly_matches_output(htlc)); + } + htlc_outputs.push((htlc.clone(), Some(counterparty_sig.clone()), Some(source))); + } else { + htlc_outputs.push((htlc.clone(), Some(counterparty_sig.clone()), None)); + } + } + debug_assert!(sources_iter.next().is_none()); + } + + let trusted_tx = holder_commitment_tx.trust(); + let txid = trusted_tx.txid(); + let tx_keys = trusted_tx.keys(); + self.current_holder_commitment_number = trusted_tx.commitment_number(); + let mut new_holder_commitment_tx = HolderSignedTx { + txid, + revocation_key: tx_keys.revocation_key, + a_htlc_key: tx_keys.broadcaster_htlc_key, + b_htlc_key: tx_keys.countersignatory_htlc_key, + delayed_payment_key: tx_keys.broadcaster_delayed_payment_key, + per_commitment_point: tx_keys.per_commitment_point, + htlc_outputs, + to_self_value_sat: holder_commitment_tx.to_broadcaster_value_sat(), + feerate_per_kw: trusted_tx.feerate_per_kw(), }; self.onchain_tx_handler.provide_latest_holder_tx(holder_commitment_tx); mem::swap(&mut new_holder_commitment_tx, &mut self.current_holder_commitment_tx); self.prev_holder_signed_commitment_tx = Some(new_holder_commitment_tx); + for (claimed_htlc_id, claimed_preimage) in claimed_htlcs { + #[cfg(debug_assertions)] { + let cur_counterparty_htlcs = self.counterparty_claimable_outpoints.get( + &self.current_counterparty_commitment_txid.unwrap()).unwrap(); + assert!(cur_counterparty_htlcs.iter().any(|(_, source_opt)| { + if let Some(source) = source_opt { + SentHTLCId::from_source(source) == *claimed_htlc_id + } else { false } + })); + } + self.counterparty_fulfilled_htlcs.insert(*claimed_htlc_id, *claimed_preimage); + } if self.holder_tx_signed { return Err("Latest holder commitment signed has already been signed, update is rejected"); } @@ -2223,14 +2306,22 @@ impl ChannelMonitorImpl { { log_info!(logger, "Applying update to monitor {}, bringing update_id from {} to {} with {} changes.", log_funding_info!(self), self.latest_update_id, updates.update_id, updates.updates.len()); - // ChannelMonitor updates may be applied after force close if we receive a - // preimage for a broadcasted commitment transaction HTLC output that we'd - // like to claim on-chain. If this is the case, we no longer have guaranteed - // access to the monitor's update ID, so we use a sentinel value instead. + // ChannelMonitor updates may be applied after force close if we receive a preimage for a + // broadcasted commitment transaction HTLC output that we'd like to claim on-chain. If this + // is the case, we no longer have guaranteed access to the monitor's update ID, so we use a + // sentinel value instead. + // + // The `ChannelManager` may also queue redundant `ChannelForceClosed` updates if it still + // thinks the channel needs to have its commitment transaction broadcast, so we'll allow + // them as well. if updates.update_id == CLOSED_CHANNEL_UPDATE_ID { assert_eq!(updates.updates.len(), 1); match updates.updates[0] { - ChannelMonitorUpdateStep::PaymentPreimage { .. } => {}, + ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {}, + // We should have already seen a `ChannelForceClosed` update if we're trying to + // provide a preimage at this point. + ChannelMonitorUpdateStep::PaymentPreimage { .. } => + debug_assert_eq!(self.latest_update_id, CLOSED_CHANNEL_UPDATE_ID), _ => { log_error!(logger, "Attempted to apply post-force-close ChannelMonitorUpdate of type {}", updates.updates[0].variant_name()); panic!("Attempted to apply post-force-close ChannelMonitorUpdate that wasn't providing a payment preimage"); @@ -2243,10 +2334,10 @@ impl ChannelMonitorImpl { let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&*fee_estimator); for update in updates.updates.iter() { match update { - ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs } => { + ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, claimed_htlcs, nondust_htlc_sources } => { log_trace!(logger, "Updating ChannelMonitor with latest holder commitment transaction info"); if self.lockdown_from_offchain { panic!(); } - if let Err(e) = self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone()) { + if let Err(e) = self.provide_latest_holder_commitment_tx(commitment_tx.clone(), htlc_outputs.clone(), &claimed_htlcs, nondust_htlc_sources.clone()) { log_error!(logger, "Providing latest holder commitment transaction failed/was refused:"); log_error!(logger, " {}", e); ret = Err(()); @@ -2322,6 +2413,13 @@ impl ChannelMonitorImpl { }, } } + + // If the updates succeeded and we were in an already closed channel state, then there's no + // need to refuse any updates we expect to receive afer seeing a confirmed commitment. + if ret.is_ok() && updates.update_id == CLOSED_CHANNEL_UPDATE_ID && self.latest_update_id == updates.update_id { + return Ok(()); + } + self.latest_update_id = updates.update_id; if ret.is_ok() && self.funding_spend_seen { @@ -2384,7 +2482,7 @@ impl ChannelMonitorImpl { })); }, ClaimEvent::BumpHTLC { - target_feerate_sat_per_1000_weight, htlcs, + target_feerate_sat_per_1000_weight, htlcs, tx_lock_time, } => { let mut htlc_descriptors = Vec::with_capacity(htlcs.len()); for htlc in htlcs { @@ -2402,6 +2500,7 @@ impl ChannelMonitorImpl { ret.push(Event::BumpTransaction(BumpTransactionEvent::HTLCResolution { target_feerate_sat_per_1000_weight, htlc_descriptors, + tx_lock_time, })); } } @@ -3626,8 +3725,9 @@ where } } -impl chain::Confirm for (ChannelMonitor, T, F, L) +impl chain::Confirm for (M, T, F, L) where + M: Deref>, T::Target: BroadcasterInterface, F::Target: FeeEstimator, L::Target: Logger, @@ -3868,6 +3968,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let mut counterparty_node_id = None; let mut confirmed_commitment_tx_counterparty_output = None; let mut spendable_txids_confirmed = Some(Vec::new()); + let mut counterparty_fulfilled_htlcs = Some(HashMap::new()); read_tlv_fields!(reader, { (1, funding_spend_confirmed, option), (3, htlcs_resolved_on_chain, vec_type), @@ -3876,6 +3977,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP (9, counterparty_node_id, option), (11, confirmed_commitment_tx_counterparty_output, option), (13, spendable_txids_confirmed, vec_type), + (15, counterparty_fulfilled_htlcs, option), }); Ok((best_block.block_hash(), ChannelMonitor::from_impl(ChannelMonitorImpl { @@ -3904,6 +4006,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP counterparty_claimable_outpoints, counterparty_commitment_txn_on_chain, counterparty_hash_commitment_number, + counterparty_fulfilled_htlcs: counterparty_fulfilled_htlcs.unwrap(), prev_holder_signed_commitment_tx, current_holder_commitment_tx, @@ -3960,6 +4063,7 @@ mod tests { use crate::chain::package::{weight_offered_htlc, weight_received_htlc, weight_revoked_offered_htlc, weight_revoked_received_htlc, WEIGHT_REVOKED_OUTPUT}; use crate::chain::transaction::OutPoint; use crate::chain::keysinterface::InMemorySigner; + use crate::events::ClosureReason; use crate::ln::{PaymentPreimage, PaymentHash}; use crate::ln::chan_utils; use crate::ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; @@ -3967,7 +4071,6 @@ mod tests { use crate::ln::functional_test_utils::*; use crate::ln::script::ShutdownScript; use crate::util::errors::APIError; - use crate::util::events::{ClosureReason, MessageSendEventsProvider}; use crate::util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator}; use crate::util::ser::{ReadableArgs, Writeable}; use crate::sync::{Arc, Mutex}; @@ -4077,7 +4180,6 @@ mod tests { let fee_estimator = TestFeeEstimator { sat_per_kw: Mutex::new(253) }; let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); - let dummy_tx = Transaction { version: 0, lock_time: PackedLockTime::ZERO, input: Vec::new(), output: Vec::new() }; let mut preimages = Vec::new(); { @@ -4088,7 +4190,7 @@ mod tests { } } - macro_rules! preimages_slice_to_htlc_outputs { + macro_rules! preimages_slice_to_htlcs { ($preimages_slice: expr) => { { let mut res = Vec::new(); @@ -4099,21 +4201,20 @@ mod tests { cltv_expiry: 0, payment_hash: preimage.1.clone(), transaction_output_index: Some(idx as u32), - }, None)); + }, ())); } res } } } - macro_rules! preimages_to_holder_htlcs { + macro_rules! preimages_slice_to_htlc_outputs { ($preimages_slice: expr) => { - { - let mut inp = preimages_slice_to_htlc_outputs!($preimages_slice); - let res: Vec<_> = inp.drain(..).map(|e| { (e.0, None, e.1) }).collect(); - res - } + preimages_slice_to_htlcs!($preimages_slice).into_iter().map(|(htlc, _)| (htlc, None)).collect() } } + let dummy_sig = crate::util::crypto::sign(&secp_ctx, + &bitcoin::secp256k1::Message::from_slice(&[42; 32]).unwrap(), + &SecretKey::from_slice(&[42; 32]).unwrap()); macro_rules! test_preimages_exist { ($preimages_slice: expr, $monitor: expr) => { @@ -4160,18 +4261,19 @@ mod tests { let shutdown_pubkey = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()); let best_block = BestBlock::from_network(Network::Testnet); let monitor = ChannelMonitor::new(Secp256k1::new(), keys, - Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &Script::new(), - (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()), - &channel_parameters, - Script::new(), 46, 0, - HolderCommitmentTransaction::dummy(), best_block, dummy_key); - - monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..10])).unwrap(); - let dummy_txid = dummy_tx.txid(); - monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key, &logger); - monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key, &logger); - monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger); - monitor.provide_latest_counterparty_commitment_tx(dummy_txid, preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger); + Some(ShutdownScript::new_p2wpkh_from_pubkey(shutdown_pubkey).into_inner()), 0, &Script::new(), + (OutPoint { txid: Txid::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()), + &channel_parameters, Script::new(), 46, 0, HolderCommitmentTransaction::dummy(&mut Vec::new()), + best_block, dummy_key); + + let mut htlcs = preimages_slice_to_htlcs!(preimages[0..10]); + let dummy_commitment_tx = HolderCommitmentTransaction::dummy(&mut htlcs); + monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(), + htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect()).unwrap(); + monitor.provide_latest_counterparty_commitment_tx(Txid::from_inner(Sha256::hash(b"1").into_inner()), + preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key, &logger); + monitor.provide_latest_counterparty_commitment_tx(Txid::from_inner(Sha256::hash(b"2").into_inner()), + preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key, &logger); for &(ref preimage, ref hash) in preimages.iter() { let bounded_fee_estimator = LowerBoundedFeeEstimator::new(&fee_estimator); monitor.provide_payment_preimage(hash, preimage, &broadcaster, &bounded_fee_estimator, &logger); @@ -4185,6 +4287,9 @@ mod tests { test_preimages_exist!(&preimages[0..10], monitor); test_preimages_exist!(&preimages[15..20], monitor); + monitor.provide_latest_counterparty_commitment_tx(Txid::from_inner(Sha256::hash(b"3").into_inner()), + preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger); + // Now provide a further secret, pruning preimages 15-17 secret[0..32].clone_from_slice(&hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); monitor.provide_secret(281474976710654, secret.clone()).unwrap(); @@ -4192,9 +4297,15 @@ mod tests { test_preimages_exist!(&preimages[0..10], monitor); test_preimages_exist!(&preimages[17..20], monitor); + monitor.provide_latest_counterparty_commitment_tx(Txid::from_inner(Sha256::hash(b"4").into_inner()), + preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger); + // Now update holder commitment tx info, pruning only element 18 as we still care about the // previous commitment tx's preimages too - monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..5])).unwrap(); + let mut htlcs = preimages_slice_to_htlcs!(preimages[0..5]); + let dummy_commitment_tx = HolderCommitmentTransaction::dummy(&mut htlcs); + monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx.clone(), + htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect()).unwrap(); secret[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); monitor.provide_secret(281474976710653, secret.clone()).unwrap(); assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 12); @@ -4202,7 +4313,10 @@ mod tests { test_preimages_exist!(&preimages[18..20], monitor); // But if we do it again, we'll prune 5-10 - monitor.provide_latest_holder_commitment_tx(HolderCommitmentTransaction::dummy(), preimages_to_holder_htlcs!(preimages[0..3])).unwrap(); + let mut htlcs = preimages_slice_to_htlcs!(preimages[0..3]); + let dummy_commitment_tx = HolderCommitmentTransaction::dummy(&mut htlcs); + monitor.provide_latest_holder_commitment_tx(dummy_commitment_tx, + htlcs.into_iter().map(|(htlc, _)| (htlc, Some(dummy_sig), None)).collect()).unwrap(); secret[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); monitor.provide_secret(281474976710652, secret.clone()).unwrap(); assert_eq!(monitor.inner.lock().unwrap().payment_preimages.len(), 5);