X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=bee2bfd012e0ff3efc628b4954883804f5d6a0c7;hb=21804de70c3ff37970ead98e5e72c4fccd14b1fb;hp=f91af7cc66cd3c9a3ea70b07c9cb5aef82bcca86;hpb=a491200f96760315fa420e433d0e60c4e6503a97;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index f91af7cc..bee2bfd0 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -21,7 +21,7 @@ //! ChannelMonitors to get out of the HSM and onto monitoring devices. use bitcoin::blockdata::block::BlockHeader; -use bitcoin::blockdata::transaction::{TxOut,Transaction}; +use bitcoin::blockdata::transaction::{OutPoint as BitcoinOutPoint, TxOut, Transaction}; use bitcoin::blockdata::script::{Script, Builder}; use bitcoin::blockdata::opcodes; @@ -33,33 +33,43 @@ use bitcoin::secp256k1::{Secp256k1, ecdsa::Signature}; use bitcoin::secp256k1::{SecretKey, PublicKey}; 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::channelmanager::HTLCSource; -use chain; -use chain::{BestBlock, WatchedOutput}; -use chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator}; -use chain::transaction::{OutPoint, TransactionData}; -use chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface}; -use chain::onchaintx::OnchainTxHandler; -use chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput}; -use chain::Filter; -use util::logger::Logger; -use util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48, OptionDeserWrapper}; -use util::byte_utils; -use util::events::Event; - -use prelude::*; +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::chain; +use crate::chain::{BestBlock, WatchedOutput}; +use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator}; +use crate::chain::transaction::{OutPoint, TransactionData}; +use crate::chain::keysinterface::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, Sign, KeysInterface}; +#[cfg(anchors)] +use crate::chain::onchaintx::ClaimEvent; +use crate::chain::onchaintx::OnchainTxHandler; +use crate::chain::package::{CounterpartyOfferedHTLCOutput, CounterpartyReceivedHTLCOutput, HolderFundingOutput, HolderHTLCOutput, PackageSolvingData, PackageTemplate, RevokedOutput, RevokedHTLCOutput}; +use crate::chain::Filter; +use crate::util::logger::Logger; +use crate::util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48, OptionDeserWrapper}; +use crate::util::byte_utils; +use crate::util::events::Event; +#[cfg(anchors)] +use crate::util::events::{AnchorDescriptor, BumpTransactionEvent}; + +use crate::prelude::*; use core::{cmp, mem}; -use io::{self, Error}; +use crate::io::{self, Error}; +use core::convert::TryInto; use core::ops::Deref; -use sync::Mutex; +use crate::sync::Mutex; -/// An update generated by the underlying Channel itself which contains some new information the -/// ChannelMonitor should be made aware of. -#[cfg_attr(any(test, fuzzing, feature = "_test_utils"), derive(PartialEq))] +/// 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, Eq))] #[derive(Clone)] #[must_use] pub struct ChannelMonitorUpdate { @@ -69,12 +79,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, } @@ -116,7 +128,7 @@ impl Readable for ChannelMonitorUpdate { } /// An event to be processed by the ChannelManager. -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Eq)] pub enum MonitorEvent { /// A monitor event containing an HTLCUpdate. HTLCEvent(HTLCUpdate), @@ -125,10 +137,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 @@ -140,15 +152,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), }, @@ -161,7 +173,7 @@ impl_writeable_tlv_based_enum_upgradable!(MonitorEvent, /// Simple structure sent back by `chain::Watch` when an HTLC from a forward channel is detected on /// chain. Used to update the corresponding HTLC in the backward channel. Failing to pass the /// preimage claim backward will lead to loss of funds. -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Eq)] pub struct HTLCUpdate { pub(crate) payment_hash: PaymentHash, pub(crate) payment_preimage: Option, @@ -227,7 +239,7 @@ pub const ANTI_REORG_DELAY: u32 = 6; pub(crate) const HTLC_FAIL_BACK_BUFFER: u32 = CLTV_CLAIM_BUFFER + LATENCY_GRACE_PERIOD_BLOCKS; // TODO(devrandom) replace this with HolderCommitmentTransaction -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Eq)] struct HolderSignedTx { /// txid of the transaction in tx, just used to make comparison faster txid: Txid, @@ -254,9 +266,23 @@ impl_writeable_tlv_based!(HolderSignedTx, { (14, htlc_outputs, vec_type) }); +#[cfg(anchors)] +impl HolderSignedTx { + fn non_dust_htlcs(&self) -> Vec { + self.htlc_outputs.iter().filter_map(|(htlc, _, _)| { + if let Some(_) = htlc.transaction_output_index { + Some(htlc.clone()) + } else { + None + } + }) + .collect() + } +} + /// We use this to track static counterparty commitment transaction data and to generate any /// justice or 2nd-stage preimage/timeout transactions. -#[derive(PartialEq)] +#[derive(PartialEq, Eq)] struct CounterpartyCommitmentParameters { counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, @@ -306,15 +332,17 @@ impl Readable for CounterpartyCommitmentParameters { } } -/// An entry for an [`OnchainEvent`], stating the block height when the event was observed and the -/// transaction causing it. +/// An entry for an [`OnchainEvent`], stating the block height and hash when the event was +/// observed, as well as the transaction causing it. /// /// Used to determine when the on-chain event can be considered safe from a chain reorganization. -#[derive(PartialEq)] +#[derive(PartialEq, Eq)] struct OnchainEventEntry { txid: Txid, height: u32, + block_hash: Option, // Added as optional, will be filled in for any entry generated on 0.0.113 or after event: OnchainEvent, + transaction: Option, // Added as optional, but always filled in, in LDK 0.0.110 } impl OnchainEventEntry { @@ -344,9 +372,14 @@ impl OnchainEventEntry { } } +/// The (output index, sats value) for the counterparty's output in a commitment transaction. +/// +/// This was added as an `Option` in 0.0.110. +type CommitmentTxCounterpartyOutputInfo = Option<(u32, u64)>; + /// Upon discovering of some classes of onchain tx by ChannelMonitor, we may have to take actions on it /// once they mature to enough confirmations (ANTI_REORG_DELAY) -#[derive(PartialEq)] +#[derive(PartialEq, Eq)] enum OnchainEvent { /// An outbound HTLC failing after a transaction is confirmed. Used /// * when an outbound HTLC output is spent by us after the HTLC timed out @@ -362,6 +395,8 @@ enum OnchainEvent { /// transaction which appeared on chain. commitment_tx_output_idx: Option, }, + /// An output waiting on [`ANTI_REORG_DELAY`] confirmations before we hand the user the + /// [`SpendableOutputDescriptor`]. MaturingOutput { descriptor: SpendableOutputDescriptor, }, @@ -371,6 +406,12 @@ enum OnchainEvent { /// The CSV delay for the output of the funding spend transaction (implying it is a local /// commitment transaction, and this is the delay on the to_self output). on_local_output_csv: Option, + /// If the funding spend transaction was a known remote commitment transaction, we track + /// the output index and amount of the counterparty's `to_self` output here. + /// + /// This allows us to generate a [`Balance::CounterpartyRevokedOutputClaimable`] for the + /// counterparty output. + commitment_tx_to_counterparty_output: CommitmentTxCounterpartyOutputInfo, }, /// A spend of a commitment transaction HTLC output, set in the cases where *no* `HTLCUpdate` /// is constructed. This is used when @@ -380,6 +421,9 @@ enum OnchainEvent { /// * an inbound HTLC is claimed by us (with a preimage). /// * a revoked-state HTLC transaction was broadcasted, which was claimed by the revocation /// signature. + /// * a revoked-state HTLC transaction was broadcasted, which was claimed by an + /// HTLC-Success/HTLC-Failure transaction (and is still claimable with a revocation + /// signature). HTLCSpendConfirmation { commitment_tx_output_idx: u32, /// If the claim was made by either party with a preimage, this is filled in @@ -395,7 +439,9 @@ impl Writeable for OnchainEventEntry { fn write(&self, writer: &mut W) -> Result<(), io::Error> { write_tlv_fields!(writer, { (0, self.txid, required), + (1, self.transaction, option), (2, self.height, required), + (3, self.block_hash, option), (4, self.event, required), }); Ok(()) @@ -404,16 +450,20 @@ impl Writeable for OnchainEventEntry { impl MaybeReadable for OnchainEventEntry { fn read(reader: &mut R) -> Result, DecodeError> { - let mut txid = Default::default(); + let mut txid = Txid::all_zeros(); + let mut transaction = None; + let mut block_hash = None; let mut height = 0; let mut event = None; read_tlv_fields!(reader, { (0, txid, required), + (1, transaction, option), (2, height, required), + (3, block_hash, option), (4, event, ignorable), }); if let Some(ev) = event { - Ok(Some(Self { txid, height, event: ev })) + Ok(Some(Self { txid, transaction, height, block_hash, event: ev })) } else { Ok(None) } @@ -432,6 +482,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent, }, (3, FundingSpendConfirmation) => { (0, on_local_output_csv, option), + (1, commitment_tx_to_counterparty_output, option), }, (5, HTLCSpendConfirmation) => { (0, commitment_tx_output_idx, required), @@ -441,7 +492,7 @@ impl_writeable_tlv_based_enum_upgradable!(OnchainEvent, ); -#[cfg_attr(any(test, fuzzing, feature = "_test_utils"), derive(PartialEq))] +#[cfg_attr(any(test, fuzzing, feature = "_test_utils"), derive(PartialEq, Eq))] #[derive(Clone)] pub(crate) enum ChannelMonitorUpdateStep { LatestHolderCommitmentTXInfo { @@ -555,28 +606,84 @@ 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. + /// + /// Thus, we're able to claim all outputs in the commitment transaction, one of which has the + /// following amount. + CounterpartyRevokedOutputClaimable { + /// The amount, in satoshis, of the output which we can claim. + /// + /// Note that for outputs from HTLC balances this may be excluding some on-chain fees that + /// were already spent. + claimable_amount_satoshis: u64, + }, } /// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY. -#[derive(PartialEq)] +#[derive(PartialEq, Eq)] 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. + resolving_txid: Option, // Added as optional, but always filled in, in 0.0.110 /// Only set if the HTLC claim was ours using a payment preimage payment_preimage: Option, } -impl_writeable_tlv_based!(IrrevocablyResolvedHTLC, { - (0, commitment_tx_output_idx, required), - (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. @@ -709,12 +816,23 @@ 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 /// spending CSV for revocable outputs). htlcs_resolved_on_chain: Vec, + /// The set of `SpendableOutput` events which we have already passed upstream to be claimed. + /// These are tracked explicitly to ensure that we don't generate the same events redundantly + /// if users duplicatively confirm old transactions. Specifically for transactions claiming a + /// revoked remote outpoint we otherwise have no tracking at all once they've reached + /// [`ANTI_REORG_DELAY`], so we have to track them here. + spendable_txids_confirmed: Vec, + // We simply modify best_block in Channel's block_connected so that serialization is // consistent but hopefully the users' copy handles block_connected in a consistent way. // (we do *not*, however, update them in update_monitor to ensure any local user copies keep @@ -779,6 +897,7 @@ impl PartialEq for ChannelMonitorImpl { self.holder_tx_signed != other.holder_tx_signed || self.funding_spend_seen != other.funding_spend_seen || self.funding_spend_confirmed != other.funding_spend_confirmed || + self.confirmed_commitment_tx_counterparty_output != other.confirmed_commitment_tx_counterparty_output || self.htlcs_resolved_on_chain != other.htlcs_resolved_on_chain { false @@ -958,6 +1077,8 @@ impl Writeable for ChannelMonitorImpl { (5, self.pending_monitor_events, vec_type), (7, self.funding_spend_seen, required), (9, self.counterparty_node_id, option), + (11, self.confirmed_commitment_tx_counterparty_output, option), + (13, self.spendable_txids_confirmed, vec_type), }); Ok(()) @@ -965,6 +1086,13 @@ impl Writeable for ChannelMonitorImpl { } impl ChannelMonitor { + /// For lockorder enforcement purposes, we need to have a single site which constructs the + /// `inner` mutex, otherwise cases where we lock two monitors at the same time (eg in our + /// PartialEq implementation) we may decide a lockorder violation has occurred. + fn from_impl(imp: ChannelMonitorImpl) -> Self { + ChannelMonitor { inner: Mutex::new(imp) } + } + pub(crate) fn new(secp_ctx: Secp256k1, keys: Signer, shutdown_script: Option