X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=8f8cbdf448adb80d7fa50ee279c86862c1d0abd6;hb=7544030bb63fee6484fc178bb2ac8f382fe3b5b1;hp=500f2b521dd404bdb5c53b06332c37fb5064a4c2;hpb=d8651e3dd57673792344d6aff65eb79fc9f2340b;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 500f2b52..8f8cbdf4 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -37,7 +37,7 @@ use bitcoin::secp256k1; use ln::{PaymentHash, PaymentPreimage}; use ln::msgs::DecodeError; use ln::chan_utils; -use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCType, ChannelTransactionParameters, HolderCommitmentTransaction}; +use ln::chan_utils::{CounterpartyCommitmentSecrets, HTLCOutputInCommitment, HTLCClaim, ChannelTransactionParameters, HolderCommitmentTransaction}; use ln::channelmanager::HTLCSource; use chain; use chain::{BestBlock, WatchedOutput}; @@ -59,8 +59,13 @@ use core::convert::TryInto; use core::ops::Deref; use sync::Mutex; -/// An update generated by the underlying Channel itself which contains some new information the -/// ChannelMonitor should be made aware of. +/// An update generated by the underlying channel itself which contains some new information the +/// [`ChannelMonitor`] should be made aware of. +/// +/// Because this represents only a small number of updates to the underlying state, it is generally +/// 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))] #[derive(Clone)] #[must_use] @@ -71,12 +76,14 @@ pub struct ChannelMonitorUpdate { /// increasing and increase by one for each new update, with one exception specified below. /// /// This sequence number is also used to track up to which points updates which returned - /// ChannelMonitorUpdateErr::TemporaryFailure have been applied to all copies of a given + /// [`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. + /// + /// [`ChannelMonitorUpdateStatus::InProgress`]: super::ChannelMonitorUpdateStatus::InProgress pub update_id: u64, } @@ -127,10 +134,10 @@ pub enum MonitorEvent { CommitmentTxConfirmed(OutPoint), /// Indicates a [`ChannelMonitor`] update has completed. See - /// [`ChannelMonitorUpdateErr::TemporaryFailure`] for more information on how this is used. + /// [`ChannelMonitorUpdateStatus::InProgress`] for more information on how this is used. /// - /// [`ChannelMonitorUpdateErr::TemporaryFailure`]: super::ChannelMonitorUpdateErr::TemporaryFailure - UpdateCompleted { + /// [`ChannelMonitorUpdateStatus::InProgress`]: super::ChannelMonitorUpdateStatus::InProgress + Completed { /// The funding outpoint of the [`ChannelMonitor`] that was updated funding_txo: OutPoint, /// The Update ID from [`ChannelMonitorUpdate::update_id`] which was applied or @@ -142,15 +149,15 @@ pub enum MonitorEvent { }, /// Indicates a [`ChannelMonitor`] update has failed. See - /// [`ChannelMonitorUpdateErr::PermanentFailure`] for more information on how this is used. + /// [`ChannelMonitorUpdateStatus::PermanentFailure`] for more information on how this is used. /// - /// [`ChannelMonitorUpdateErr::PermanentFailure`]: super::ChannelMonitorUpdateErr::PermanentFailure + /// [`ChannelMonitorUpdateStatus::PermanentFailure`]: super::ChannelMonitorUpdateStatus::PermanentFailure UpdateFailed(OutPoint), } impl_writeable_tlv_based_enum_upgradable!(MonitorEvent, - // Note that UpdateCompleted and UpdateFailed are currently never serialized to disk as they are + // Note that Completed and UpdateFailed are currently never serialized to disk as they are // generated only in ChainMonitor - (0, UpdateCompleted) => { + (0, Completed) => { (0, funding_txo, required), (2, monitor_update_id, required), }, @@ -578,14 +585,25 @@ pub enum Balance { /// HTLCs which we sent to our counterparty which are claimable after a timeout (less on-chain /// fees) if the counterparty does not know the preimage for the HTLCs. These are somewhat /// likely to be claimed by our counterparty before we do. - MaybeClaimableHTLCAwaitingTimeout { - /// The amount available to claim, in satoshis, excluding the on-chain fees which will be - /// required to do so. + MaybeTimeoutClaimableHTLC { + /// The amount potentially available to claim, in satoshis, excluding the on-chain fees + /// which will be required to do so. claimable_amount_satoshis: u64, /// The height at which we will be able to claim the balance if our counterparty has not /// done so. claimable_height: u32, }, + /// HTLCs which we received from our counterparty which are claimable with a preimage which we + /// do not currently have. This will only be claimable if we receive the preimage from the node + /// to which we forwarded this HTLC before the timeout. + MaybePreimageClaimableHTLC { + /// The amount potentially available to claim, in satoshis, excluding the on-chain fees + /// which will be required to do so. + claimable_amount_satoshis: u64, + /// The height at which our counterparty will be able to claim the balance if we have not + /// yet received the preimage and claimed it ourselves. + expiry_height: u32, + }, /// The channel has been closed, and our counterparty broadcasted a revoked commitment /// transaction. /// @@ -603,7 +621,7 @@ pub enum Balance { /// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY. #[derive(PartialEq)] struct IrrevocablyResolvedHTLC { - commitment_tx_output_idx: u32, + commitment_tx_output_idx: Option, /// The txid of the transaction which resolved the HTLC, this may be a commitment (if the HTLC /// was not present in the confirmed commitment transaction), HTLC-Success, or HTLC-Timeout /// transaction. @@ -612,11 +630,39 @@ struct IrrevocablyResolvedHTLC { payment_preimage: Option, } -impl_writeable_tlv_based!(IrrevocablyResolvedHTLC, { - (0, commitment_tx_output_idx, required), - (1, resolving_txid, option), - (2, payment_preimage, option), -}); +// In LDK versions prior to 0.0.111 commitment_tx_output_idx was not Option-al and +// IrrevocablyResolvedHTLC objects only existed for non-dust HTLCs. This was a bug, but to maintain +// backwards compatibility we must ensure we always write out a commitment_tx_output_idx field, +// using `u32::max_value()` as a sentinal to indicate the HTLC was dust. +impl Writeable for IrrevocablyResolvedHTLC { + fn write(&self, writer: &mut W) -> Result<(), io::Error> { + let mapped_commitment_tx_output_idx = self.commitment_tx_output_idx.unwrap_or(u32::max_value()); + write_tlv_fields!(writer, { + (0, mapped_commitment_tx_output_idx, required), + (1, self.resolving_txid, option), + (2, self.payment_preimage, option), + }); + Ok(()) + } +} + +impl Readable for IrrevocablyResolvedHTLC { + fn read(reader: &mut R) -> Result { + let mut mapped_commitment_tx_output_idx = 0; + let mut resolving_txid = None; + let mut payment_preimage = None; + read_tlv_fields!(reader, { + (0, mapped_commitment_tx_output_idx, required), + (1, resolving_txid, option), + (2, payment_preimage, option), + }); + Ok(Self { + commitment_tx_output_idx: if mapped_commitment_tx_output_idx == u32::max_value() { None } else { Some(mapped_commitment_tx_output_idx) }, + resolving_txid, + payment_preimage, + }) + } +} /// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates /// on-chain transactions to ensure no loss of funds occurs. @@ -749,7 +795,10 @@ pub(crate) struct ChannelMonitorImpl { // of block connection between ChannelMonitors and the ChannelManager. funding_spend_seen: bool, + /// Set to `Some` of the confirmed transaction spending the funding input of the channel after + /// reaching `ANTI_REORG_DELAY` confirmations. funding_spend_confirmed: Option, + confirmed_commitment_tx_counterparty_output: CommitmentTxCounterpartyOutputInfo, /// The set of HTLCs which have been either claimed or failed on chain and have reached /// the requisite confirmations on the claim/fail transaction (either ANTI_REORG_DELAY or the @@ -1267,14 +1316,20 @@ impl ChannelMonitor { } /// Used by ChannelManager deserialization to broadcast the latest holder state if its copy of - /// the Channel was out-of-date. You may use it to get a broadcastable holder toxic tx in case of - /// fallen-behind, i.e when receiving a channel_reestablish with a proof that our counterparty side knows - /// a higher revocation secret than the holder commitment number we are aware of. Broadcasting these - /// transactions are UNSAFE, as they allow counterparty side to punish you. Nevertheless you may want to - /// broadcast them if counterparty don't close channel with his higher commitment transaction after a - /// substantial amount of time (a month or even a year) to get back funds. Best may be to contact - /// out-of-band the other node operator to coordinate with him if option is available to you. - /// In any-case, choice is up to the user. + /// the Channel was out-of-date. + /// + /// You may also use this to broadcast the latest local commitment transaction, either because + /// a monitor update failed with [`ChannelMonitorUpdateStatus::PermanentFailure`] or because we've + /// fallen behind (i.e. we've received proof that our counterparty side knows a revocation + /// secret we gave them that they shouldn't know). + /// + /// Broadcasting these transactions in the second case is UNSAFE, as they allow counterparty + /// side to punish you. Nevertheless you may want to broadcast them if counterparty doesn't + /// close channel with their commitment transaction after a substantial amount of time. Best + /// may be to contact the other node operator out-of-band to coordinate other options available + /// to you. In any-case, the choice is up to you. + /// + /// [`ChannelMonitorUpdateStatus::PermanentFailure`]: super::ChannelMonitorUpdateStatus::PermanentFailure pub fn get_latest_holder_commitment_txn(&self, logger: &L) -> Vec where L::Target: Logger { self.inner.lock().unwrap().get_latest_holder_commitment_txn(logger) @@ -1469,7 +1524,7 @@ impl ChannelMonitorImpl { } } let htlc_resolved = self.htlcs_resolved_on_chain.iter() - .find(|v| if v.commitment_tx_output_idx == htlc_commitment_tx_output_idx { + .find(|v| if v.commitment_tx_output_idx == Some(htlc_commitment_tx_output_idx) { debug_assert!(htlc_spend_txid_opt.is_none()); htlc_spend_txid_opt = v.resolving_txid; true @@ -1542,7 +1597,7 @@ impl ChannelMonitorImpl { confirmation_height: conf_thresh, }); } else { - return Some(Balance::MaybeClaimableHTLCAwaitingTimeout { + return Some(Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: htlc.amount_msat / 1000, claimable_height: htlc.cltv_expiry, }); @@ -1565,6 +1620,11 @@ impl ChannelMonitorImpl { timeout_height: htlc.cltv_expiry, }); } + } else if htlc_resolved.is_none() { + return Some(Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: htlc.amount_msat / 1000, + expiry_height: htlc.cltv_expiry, + }); } None } @@ -1581,7 +1641,7 @@ impl ChannelMonitor { /// confirmations on the claim transaction. /// /// Note that for `ChannelMonitors` which track a channel which went on-chain with versions of - /// LDK prior to 0.0.108, balances may not be fully captured if our counterparty broadcasted + /// LDK prior to 0.0.111, balances may not be fully captured if our counterparty broadcasted /// a revoked state. /// /// See [`Balance`] for additional details on the types of claimable balances which @@ -1722,12 +1782,19 @@ impl ChannelMonitor { for (htlc, _, _) in us.current_holder_commitment_tx.htlc_outputs.iter() { if htlc.transaction_output_index.is_none() { continue; } if htlc.offered { - res.push(Balance::MaybeClaimableHTLCAwaitingTimeout { + res.push(Balance::MaybeTimeoutClaimableHTLC { claimable_amount_satoshis: htlc.amount_msat / 1000, claimable_height: htlc.cltv_expiry, }); } else if us.payment_preimages.get(&htlc.payment_hash).is_some() { claimable_inbound_htlc_value_sat += htlc.amount_msat / 1000; + } else { + // As long as the HTLC is still in our latest commitment state, treat + // it as potentially claimable, even if it has long-since expired. + res.push(Balance::MaybePreimageClaimableHTLC { + claimable_amount_satoshis: htlc.amount_msat / 1000, + expiry_height: htlc.cltv_expiry, + }); } } res.push(Balance::ClaimableOnChannelClose { @@ -1747,7 +1814,7 @@ impl ChannelMonitor { macro_rules! walk_htlcs { ($holder_commitment: expr, $htlc_iter: expr) => { for (htlc, source) in $htlc_iter { - if us.htlcs_resolved_on_chain.iter().any(|v| Some(v.commitment_tx_output_idx) == htlc.transaction_output_index) { + if us.htlcs_resolved_on_chain.iter().any(|v| v.commitment_tx_output_idx == htlc.transaction_output_index) { // We should assert that funding_spend_confirmed is_some() here, but we // have some unit tests which violate HTLC transaction CSVs entirely and // would fail. @@ -2189,7 +2256,9 @@ impl ChannelMonitorImpl { if *should_broadcast { self.broadcast_latest_holder_commitment_txn(broadcaster, logger); } else if !self.holder_tx_signed { - log_error!(logger, "You have a toxic holder commitment transaction avaible in channel monitor, read comment in ChannelMonitor::get_latest_holder_commitment_txn to be informed of manual action to take"); + log_error!(logger, "WARNING: You have a potentially-unsafe holder commitment transaction available to broadcast"); + log_error!(logger, " in channel monitor for channel {}!", log_bytes!(self.funding_info.0.to_channel_id())); + log_error!(logger, " Read the docs for ChannelMonitor::get_latest_holder_commitment_txn and take manual action!"); } else { // If we generated a MonitorEvent::CommitmentTxConfirmed, the ChannelManager // will still give us a ChannelForceClosed event with !should_broadcast, but we @@ -2594,6 +2663,11 @@ impl ChannelMonitorImpl { let commitment_tx = self.onchain_tx_handler.get_fully_signed_holder_tx(&self.funding_redeemscript); let txid = commitment_tx.txid(); let mut holder_transactions = vec![commitment_tx]; + // When anchor outputs are present, the HTLC transactions are only valid once the commitment + // transaction confirms. + if self.onchain_tx_handler.opt_anchors() { + return holder_transactions; + } for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() { if let Some(vout) = htlc.0.transaction_output_index { let preimage = if !htlc.0.offered { @@ -2627,6 +2701,11 @@ impl ChannelMonitorImpl { let commitment_tx = self.onchain_tx_handler.get_fully_signed_copy_holder_tx(&self.funding_redeemscript); let txid = commitment_tx.txid(); let mut holder_transactions = vec![commitment_tx]; + // When anchor outputs are present, the HTLC transactions are only final once the commitment + // transaction confirms due to the CSV 1 encumberance. + if self.onchain_tx_handler.opt_anchors() { + return holder_transactions; + } for htlc in self.current_holder_commitment_tx.htlc_outputs.iter() { if let Some(vout) = htlc.0.transaction_output_index { let preimage = if !htlc.0.offered { @@ -2874,12 +2953,10 @@ impl ChannelMonitorImpl { source: source.clone(), htlc_value_satoshis, })); - if let Some(idx) = commitment_tx_output_idx { - self.htlcs_resolved_on_chain.push(IrrevocablyResolvedHTLC { - commitment_tx_output_idx: idx, resolving_txid: Some(entry.txid), - payment_preimage: None, - }); - } + self.htlcs_resolved_on_chain.push(IrrevocablyResolvedHTLC { + commitment_tx_output_idx, resolving_txid: Some(entry.txid), + payment_preimage: None, + }); }, OnchainEvent::MaturingOutput { descriptor } => { log_debug!(logger, "Descriptor {} has got enough confirmations to be passed upstream", log_spendable!(descriptor)); @@ -2889,7 +2966,7 @@ impl ChannelMonitorImpl { }, OnchainEvent::HTLCSpendConfirmation { commitment_tx_output_idx, preimage, .. } => { self.htlcs_resolved_on_chain.push(IrrevocablyResolvedHTLC { - commitment_tx_output_idx, resolving_txid: Some(entry.txid), + commitment_tx_output_idx: Some(commitment_tx_output_idx), resolving_txid: Some(entry.txid), payment_preimage: preimage, }); }, @@ -3014,6 +3091,16 @@ impl ChannelMonitorImpl { } fn should_broadcast_holder_commitment_txn(&self, logger: &L) -> bool where L::Target: Logger { + // There's no need to broadcast our commitment transaction if we've seen one confirmed (even + // with 1 confirmation) as it'll be rejected as duplicate/conflicting. + if self.funding_spend_confirmed.is_some() || + self.onchain_events_awaiting_threshold_conf.iter().find(|event| match event.event { + OnchainEvent::FundingSpendConfirmation { .. } => true, + _ => false, + }).is_some() + { + return false; + } // We need to consider all HTLCs which are: // * in any unrevoked counterparty commitment transaction, as they could broadcast said // transactions and we'd end up in a race, or @@ -3082,25 +3169,17 @@ impl ChannelMonitorImpl { fn is_resolving_htlc_output(&mut self, tx: &Transaction, height: u32, logger: &L) where L::Target: Logger { 'outer_loop: for input in &tx.input { let mut payment_data = None; - let witness_items = input.witness.len(); - let htlctype = input.witness.last().map(|w| w.len()).and_then(HTLCType::scriptlen_to_htlctype); - let prev_last_witness_len = input.witness.second_to_last().map(|w| w.len()).unwrap_or(0); - let revocation_sig_claim = (witness_items == 3 && htlctype == Some(HTLCType::OfferedHTLC) && prev_last_witness_len == 33) - || (witness_items == 3 && htlctype == Some(HTLCType::AcceptedHTLC) && prev_last_witness_len == 33); - let accepted_preimage_claim = witness_items == 5 && htlctype == Some(HTLCType::AcceptedHTLC) - && input.witness.second_to_last().unwrap().len() == 32; + let htlc_claim = HTLCClaim::from_witness(&input.witness); + let revocation_sig_claim = htlc_claim == Some(HTLCClaim::Revocation); + let accepted_preimage_claim = htlc_claim == Some(HTLCClaim::AcceptedPreimage); #[cfg(not(fuzzing))] - let accepted_timeout_claim = witness_items == 3 && htlctype == Some(HTLCType::AcceptedHTLC) && !revocation_sig_claim; - let offered_preimage_claim = witness_items == 3 && htlctype == Some(HTLCType::OfferedHTLC) && - !revocation_sig_claim && input.witness.second_to_last().unwrap().len() == 32; - + let accepted_timeout_claim = htlc_claim == Some(HTLCClaim::AcceptedTimeout); + let offered_preimage_claim = htlc_claim == Some(HTLCClaim::OfferedPreimage); #[cfg(not(fuzzing))] - let offered_timeout_claim = witness_items == 5 && htlctype == Some(HTLCType::OfferedHTLC); + let offered_timeout_claim = htlc_claim == Some(HTLCClaim::OfferedTimeout); let mut payment_preimage = PaymentPreimage([0; 32]); - if accepted_preimage_claim { - payment_preimage.0.copy_from_slice(input.witness.second_to_last().unwrap()); - } else if offered_preimage_claim { + if offered_preimage_claim || accepted_preimage_claim { payment_preimage.0.copy_from_slice(input.witness.second_to_last().unwrap()); } @@ -3698,8 +3777,7 @@ mod tests { use ln::{PaymentPreimage, PaymentHash}; use ln::chan_utils; use ln::chan_utils::{HTLCOutputInCommitment, ChannelPublicKeys, ChannelTransactionParameters, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; - use ln::channelmanager::PaymentSendFailure; - use ln::features::InitFeatures; + use ln::channelmanager::{self, PaymentSendFailure}; use ln::functional_test_utils::*; use ln::script::ShutdownScript; use util::errors::APIError; @@ -3728,9 +3806,9 @@ mod tests { let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let nodes = create_network(3, &node_cfgs, &node_chanmgrs); let channel = create_announced_chan_between_nodes( - &nodes, 0, 1, InitFeatures::known(), InitFeatures::known()); + &nodes, 0, 1, channelmanager::provided_init_features(), channelmanager::provided_init_features()); create_announced_chan_between_nodes( - &nodes, 1, 2, InitFeatures::known(), InitFeatures::known()); + &nodes, 1, 2, channelmanager::provided_init_features(), channelmanager::provided_init_features()); // Rebalance somewhat send_payment(&nodes[0], &[&nodes[1]], 10_000_000);