X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=0bfd944456ab6851749505350c781e8ec267d27e;hb=refs%2Fheads%2F2023-03-one-less-sig;hp=80cd9cb9d45958629e1789513190a4de63b87e7b;hpb=b76040718f954fa7baae42c7070e3ff6ac8add3c;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index 80cd9cb9..66ab1691 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, SentHTLCId}; +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, WriteableEcdsaChannelSigner, SignerProvider, EntropySource}; +#[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, RequiredWrapper, MaybeReadable, UpgradableRequired, Writer, Writeable, U48}; +use crate::util::byte_utils; +use crate::util::events::Event; +#[cfg(anchors)] +use crate::util::events::{AnchorDescriptor, HTLCDescriptor, 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, LockTestExt}; -/// 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, @@ -265,7 +291,7 @@ struct CounterpartyCommitmentParameters { impl Writeable for CounterpartyCommitmentParameters { fn write(&self, w: &mut W) -> Result<(), io::Error> { - w.write_all(&byte_utils::be64_to_array(0))?; + w.write_all(&(0 as u64).to_be_bytes())?; write_tlv_fields!(w, { (0, self.counterparty_delayed_payment_base_key, required), (2, self.counterparty_htlc_base_key, required), @@ -288,8 +314,8 @@ impl Readable for CounterpartyCommitmentParameters { } } - let mut counterparty_delayed_payment_base_key = OptionDeserWrapper(None); - let mut counterparty_htlc_base_key = OptionDeserWrapper(None); + let mut counterparty_delayed_payment_base_key = RequiredWrapper(None); + let mut counterparty_htlc_base_key = RequiredWrapper(None); let mut on_counterparty_tx_csv: u16 = 0; read_tlv_fields!(r, { (0, counterparty_delayed_payment_base_key, required), @@ -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,19 +450,19 @@ 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; + let mut event = UpgradableRequired(None); read_tlv_fields!(reader, { (0, txid, required), + (1, transaction, option), (2, height, required), - (4, event, ignorable), + (3, block_hash, option), + (4, event, upgradable_required), }); - if let Some(ev) = event { - Ok(Some(Self { txid, height, event: ev })) - } else { - Ok(None) - } + Ok(Some(Self { txid, transaction, height, block_hash, event: _init_tlv_based_struct_field!(event, upgradable_required) })) } } @@ -432,6 +478,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,12 +488,17 @@ 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 { 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, @@ -489,7 +541,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), @@ -555,28 +609,89 @@ 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 + resolving_tx: Option, /// 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), + (3, self.resolving_tx, 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; + let mut resolving_tx = None; + read_tlv_fields!(reader, { + (0, mapped_commitment_tx_output_idx, required), + (1, resolving_txid, option), + (2, payment_preimage, option), + (3, resolving_tx, 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, + resolving_tx, + }) + } +} /// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates /// on-chain transactions to ensure no loss of funds occurs. @@ -594,14 +709,15 @@ impl_writeable_tlv_based!(IrrevocablyResolvedHTLC, { /// the "reorg path" (ie disconnecting blocks until you find a common ancestor from both the /// returned block hash and the the current chain and then reconnecting blocks to get to the /// best chain) upon deserializing the object! -pub struct ChannelMonitor { +pub struct ChannelMonitor { #[cfg(test)] pub(crate) inner: Mutex>, #[cfg(not(test))] inner: Mutex>, } -pub(crate) struct ChannelMonitorImpl { +#[derive(PartialEq)] +pub(crate) struct ChannelMonitorImpl { latest_update_id: u64, commitment_transaction_number_obscure_factor: u64, @@ -641,6 +757,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 @@ -709,12 +827,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 @@ -724,71 +853,24 @@ pub(crate) struct ChannelMonitorImpl { /// The node_id of our counterparty counterparty_node_id: Option, - - secp_ctx: Secp256k1, //TODO: dedup this a bit... } /// Transaction outputs to watch for on-chain spends. pub type TransactionOutputs = (Txid, Vec<(u32, TxOut)>); -#[cfg(any(test, fuzzing, feature = "_test_utils"))] -/// Used only in testing and fuzzing to check serialization roundtrips don't change the underlying -/// object -impl PartialEq for ChannelMonitor { +impl PartialEq for ChannelMonitor where Signer: PartialEq { fn eq(&self, other: &Self) -> bool { - let inner = self.inner.lock().unwrap(); - let other = other.inner.lock().unwrap(); - inner.eq(&other) + // We need some kind of total lockorder. Absent a better idea, we sort by position in + // memory and take locks in that order (assuming that we can't move within memory while a + // lock is held). + let ord = ((self as *const _) as usize) < ((other as *const _) as usize); + let a = if ord { self.inner.unsafe_well_ordered_double_lock_self() } else { other.inner.unsafe_well_ordered_double_lock_self() }; + let b = if ord { other.inner.unsafe_well_ordered_double_lock_self() } else { self.inner.unsafe_well_ordered_double_lock_self() }; + a.eq(&b) } } -#[cfg(any(test, fuzzing, feature = "_test_utils"))] -/// Used only in testing and fuzzing to check serialization roundtrips don't change the underlying -/// object -impl PartialEq for ChannelMonitorImpl { - fn eq(&self, other: &Self) -> bool { - if self.latest_update_id != other.latest_update_id || - self.commitment_transaction_number_obscure_factor != other.commitment_transaction_number_obscure_factor || - self.destination_script != other.destination_script || - self.broadcasted_holder_revokable_script != other.broadcasted_holder_revokable_script || - self.counterparty_payment_script != other.counterparty_payment_script || - self.channel_keys_id != other.channel_keys_id || - self.holder_revocation_basepoint != other.holder_revocation_basepoint || - self.funding_info != other.funding_info || - self.current_counterparty_commitment_txid != other.current_counterparty_commitment_txid || - self.prev_counterparty_commitment_txid != other.prev_counterparty_commitment_txid || - self.counterparty_commitment_params != other.counterparty_commitment_params || - self.funding_redeemscript != other.funding_redeemscript || - self.channel_value_satoshis != other.channel_value_satoshis || - self.their_cur_per_commitment_points != other.their_cur_per_commitment_points || - self.on_holder_tx_csv != other.on_holder_tx_csv || - self.commitment_secrets != other.commitment_secrets || - self.counterparty_claimable_outpoints != other.counterparty_claimable_outpoints || - self.counterparty_commitment_txn_on_chain != other.counterparty_commitment_txn_on_chain || - self.counterparty_hash_commitment_number != other.counterparty_hash_commitment_number || - self.prev_holder_signed_commitment_tx != other.prev_holder_signed_commitment_tx || - self.current_counterparty_commitment_number != other.current_counterparty_commitment_number || - self.current_holder_commitment_number != other.current_holder_commitment_number || - self.current_holder_commitment_tx != other.current_holder_commitment_tx || - self.payment_preimages != other.payment_preimages || - self.pending_monitor_events != other.pending_monitor_events || - self.pending_events.len() != other.pending_events.len() || // We trust events to round-trip properly - self.onchain_events_awaiting_threshold_conf != other.onchain_events_awaiting_threshold_conf || - self.outputs_to_watch != other.outputs_to_watch || - self.lockdown_from_offchain != other.lockdown_from_offchain || - 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.htlcs_resolved_on_chain != other.htlcs_resolved_on_chain - { - false - } else { - true - } - } -} - -impl Writeable for ChannelMonitor { +impl Writeable for ChannelMonitor { fn write(&self, writer: &mut W) -> Result<(), Error> { self.inner.lock().unwrap().write(writer) } @@ -798,7 +880,7 @@ impl Writeable for ChannelMonitor { const SERIALIZATION_VERSION: u8 = 1; const MIN_SERIALIZATION_VERSION: u8 = 1; -impl Writeable for ChannelMonitorImpl { +impl Writeable for ChannelMonitorImpl { fn write(&self, writer: &mut W) -> Result<(), Error> { write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION); @@ -826,7 +908,7 @@ impl Writeable for ChannelMonitorImpl { self.channel_keys_id.write(writer)?; self.holder_revocation_basepoint.write(writer)?; writer.write_all(&self.funding_info.0.txid[..])?; - writer.write_all(&byte_utils::be16_to_array(self.funding_info.0.index))?; + writer.write_all(&self.funding_info.0.index.to_be_bytes())?; self.funding_info.1.write(writer)?; self.current_counterparty_commitment_txid.write(writer)?; self.prev_counterparty_commitment_txid.write(writer)?; @@ -853,24 +935,24 @@ impl Writeable for ChannelMonitorImpl { }, } - writer.write_all(&byte_utils::be16_to_array(self.on_holder_tx_csv))?; + writer.write_all(&self.on_holder_tx_csv.to_be_bytes())?; self.commitment_secrets.write(writer)?; macro_rules! serialize_htlc_in_commitment { ($htlc_output: expr) => { writer.write_all(&[$htlc_output.offered as u8; 1])?; - writer.write_all(&byte_utils::be64_to_array($htlc_output.amount_msat))?; - writer.write_all(&byte_utils::be32_to_array($htlc_output.cltv_expiry))?; + writer.write_all(&$htlc_output.amount_msat.to_be_bytes())?; + writer.write_all(&$htlc_output.cltv_expiry.to_be_bytes())?; writer.write_all(&$htlc_output.payment_hash.0[..])?; $htlc_output.transaction_output_index.write(writer)?; } } - writer.write_all(&byte_utils::be64_to_array(self.counterparty_claimable_outpoints.len() as u64))?; + writer.write_all(&(self.counterparty_claimable_outpoints.len() as u64).to_be_bytes())?; for (ref txid, ref htlc_infos) in self.counterparty_claimable_outpoints.iter() { writer.write_all(&txid[..])?; - writer.write_all(&byte_utils::be64_to_array(htlc_infos.len() as u64))?; + writer.write_all(&(htlc_infos.len() as u64).to_be_bytes())?; for &(ref htlc_output, ref htlc_source) in htlc_infos.iter() { debug_assert!(htlc_source.is_none() || Some(**txid) == self.current_counterparty_commitment_txid || Some(**txid) == self.prev_counterparty_commitment_txid, @@ -880,13 +962,13 @@ impl Writeable for ChannelMonitorImpl { } } - writer.write_all(&byte_utils::be64_to_array(self.counterparty_commitment_txn_on_chain.len() as u64))?; + writer.write_all(&(self.counterparty_commitment_txn_on_chain.len() as u64).to_be_bytes())?; for (ref txid, commitment_number) in self.counterparty_commitment_txn_on_chain.iter() { writer.write_all(&txid[..])?; writer.write_all(&byte_utils::be48_to_array(*commitment_number))?; } - writer.write_all(&byte_utils::be64_to_array(self.counterparty_hash_commitment_number.len() as u64))?; + writer.write_all(&(self.counterparty_hash_commitment_number.len() as u64).to_be_bytes())?; for (ref payment_hash, commitment_number) in self.counterparty_hash_commitment_number.iter() { writer.write_all(&payment_hash.0[..])?; writer.write_all(&byte_utils::be48_to_array(*commitment_number))?; @@ -904,7 +986,7 @@ impl Writeable for ChannelMonitorImpl { writer.write_all(&byte_utils::be48_to_array(self.current_counterparty_commitment_number))?; writer.write_all(&byte_utils::be48_to_array(self.current_holder_commitment_number))?; - writer.write_all(&byte_utils::be64_to_array(self.payment_preimages.len() as u64))?; + writer.write_all(&(self.payment_preimages.len() as u64).to_be_bytes())?; for payment_preimage in self.payment_preimages.values() { writer.write_all(&payment_preimage.0[..])?; } @@ -925,15 +1007,15 @@ impl Writeable for ChannelMonitorImpl { } } - writer.write_all(&byte_utils::be64_to_array(self.pending_events.len() as u64))?; + writer.write_all(&(self.pending_events.len() as u64).to_be_bytes())?; for event in self.pending_events.iter() { event.write(writer)?; } self.best_block.block_hash().write(writer)?; - writer.write_all(&byte_utils::be32_to_array(self.best_block.height()))?; + writer.write_all(&self.best_block.height().to_be_bytes())?; - writer.write_all(&byte_utils::be64_to_array(self.onchain_events_awaiting_threshold_conf.len() as u64))?; + writer.write_all(&(self.onchain_events_awaiting_threshold_conf.len() as u64).to_be_bytes())?; for ref entry in self.onchain_events_awaiting_threshold_conf.iter() { entry.write(writer)?; } @@ -958,13 +1040,23 @@ 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), + (15, self.counterparty_fulfilled_htlcs, required), }); Ok(()) } } -impl ChannelMonitor { +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