X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=ce8279234a54f71a201521e9a19545b29e319941;hb=5cddf5e06afeb9b6794308d8fa5e0d1eebb8e705;hp=fc3079271c65059c9c280fa4eb1d24a6cf9ecea1;hpb=397386539d19ea368d1f37566b6b0640b90c9668;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index fc307927..ce827923 100644 --- a/lightning/src/chain/channelmonitor.rs +++ b/lightning/src/chain/channelmonitor.rs @@ -43,17 +43,14 @@ use crate::chain::{BestBlock, WatchedOutput}; use crate::chain::chaininterface::{BroadcasterInterface, FeeEstimator, LowerBoundedFeeEstimator}; use crate::chain::transaction::{OutPoint, TransactionData}; use crate::sign::{SpendableOutputDescriptor, StaticPaymentOutputDescriptor, DelayedPaymentOutputDescriptor, WriteableEcdsaChannelSigner, SignerProvider, EntropySource}; -#[cfg(anchors)] -use crate::chain::onchaintx::ClaimEvent; -use crate::chain::onchaintx::OnchainTxHandler; +use crate::chain::onchaintx::{ClaimEvent, 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::events::Event; -#[cfg(anchors)] -use crate::events::bump_transaction::{AnchorDescriptor, HTLCDescriptor, BumpTransactionEvent}; +use crate::events::{Event, EventHandler}; +use crate::events::bump_transaction::{ChannelDerivationParameters, AnchorDescriptor, HTLCDescriptor, BumpTransactionEvent}; use crate::prelude::*; use core::{cmp, mem}; @@ -265,10 +262,9 @@ impl_writeable_tlv_based!(HolderSignedTx, { (8, delayed_payment_key, required), (10, per_commitment_point, required), (12, feerate_per_kw, required), - (14, htlc_outputs, vec_type) + (14, htlc_outputs, required_vec) }); -#[cfg(anchors)] impl HolderSignedTx { fn non_dust_htlcs(&self) -> Vec { self.htlc_outputs.iter().filter_map(|(htlc, _, _)| { @@ -284,7 +280,7 @@ impl HolderSignedTx { /// We use this to track static counterparty commitment transaction data and to generate any /// justice or 2nd-stage preimage/timeout transactions. -#[derive(PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] struct CounterpartyCommitmentParameters { counterparty_delayed_payment_base_key: PublicKey, counterparty_htlc_base_key: PublicKey, @@ -338,7 +334,7 @@ impl Readable for CounterpartyCommitmentParameters { /// 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, Eq)] +#[derive(Clone, PartialEq, Eq)] struct OnchainEventEntry { txid: Txid, height: u32, @@ -381,7 +377,7 @@ 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, Eq)] +#[derive(Clone, 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 @@ -542,15 +538,15 @@ 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), + (1, claimed_htlcs, optional_vec), + (2, htlc_outputs, required_vec), (4, nondust_htlc_sources, optional_vec), }, (1, LatestCounterpartyCommitmentTXInfo) => { (0, commitment_txid, required), (2, commitment_number, required), (4, their_per_commitment_point, required), - (6, htlc_outputs, vec_type), + (6, htlc_outputs, required_vec), }, (2, PaymentPreimage) => { (0, payment_preimage, required), @@ -686,7 +682,7 @@ impl Balance { } /// An HTLC which has been irrevocably resolved on-chain, and has reached ANTI_REORG_DELAY. -#[derive(PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] struct IrrevocablyResolvedHTLC { commitment_tx_output_idx: Option, /// The txid of the transaction which resolved the HTLC, this may be a commitment (if the HTLC @@ -742,11 +738,6 @@ impl Readable for IrrevocablyResolvedHTLC { /// You MUST ensure that no ChannelMonitors for a given channel anywhere contain out-of-date /// information and are actively monitoring the chain. /// -/// Pending Events or updated HTLCs which have not yet been read out by -/// get_and_clear_pending_monitor_events or get_and_clear_pending_events are serialized to disk and -/// reloaded at deserialize-time. Thus, you must ensure that, when handling events, all events -/// gotten are fully handled before re-serializing the new state. -/// /// Note that the deserializer is only implemented for (BlockHash, ChannelMonitor), which /// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along /// the "reorg path" (ie disconnecting blocks until you find a common ancestor from both the @@ -756,10 +747,17 @@ pub struct ChannelMonitor { #[cfg(test)] pub(crate) inner: Mutex>, #[cfg(not(test))] - inner: Mutex>, + pub(super) inner: Mutex>, } -#[derive(PartialEq)] +impl Clone for ChannelMonitor where Signer: Clone { + fn clone(&self) -> Self { + let inner = self.inner.lock().unwrap().clone(); + ChannelMonitor::from_impl(inner) + } +} + +#[derive(Clone, PartialEq)] pub(crate) struct ChannelMonitorImpl { latest_update_id: u64, commitment_transaction_number_obscure_factor: u64, @@ -833,7 +831,8 @@ pub(crate) struct ChannelMonitorImpl { // we further MUST NOT generate events during block/transaction-disconnection. pending_monitor_events: Vec, - pending_events: Vec, + pub(super) pending_events: Vec, + pub(super) is_processing_pending_events: bool, // Used to track on-chain events (i.e., transactions part of channels confirmed on chain) on // which to take actions once they reach enough confirmations. Each entry includes the @@ -1079,12 +1078,12 @@ impl Writeable for ChannelMonitorImpl Writeable for ChannelMonitorImpl { + loop { + let (pending_events, repeated_events); + if let Some(us) = $self_opt { + let mut inner = us.inner.lock().unwrap(); + if inner.is_processing_pending_events { + break; + } + inner.is_processing_pending_events = true; + + pending_events = inner.pending_events.clone(); + repeated_events = inner.get_repeated_events(); + } else { break; } + let num_events = pending_events.len(); + + for event in pending_events.into_iter().chain(repeated_events.into_iter()) { + $event_to_handle = event; + $handle_event; + } + + if let Some(us) = $self_opt { + let mut inner = us.inner.lock().unwrap(); + inner.pending_events.drain(..num_events); + inner.is_processing_pending_events = false; + if !inner.pending_events.is_empty() { + // If there's more events to process, go ahead and do so. + continue; + } + } + break; + } + } +} +pub(super) use _process_events_body as process_events_body; + 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 @@ -1183,6 +1218,7 @@ impl ChannelMonitor { payment_preimages: HashMap::new(), pending_monitor_events: Vec::new(), pending_events: Vec::new(), + is_processing_pending_events: false, onchain_events_awaiting_threshold_conf: Vec::new(), outputs_to_watch, @@ -1310,16 +1346,41 @@ impl ChannelMonitor { self.inner.lock().unwrap().get_and_clear_pending_monitor_events() } - /// Gets the list of pending events which were generated by previous actions, clearing the list - /// in the process. + /// Processes [`SpendableOutputs`] events produced from each [`ChannelMonitor`] upon maturity. /// - /// This is called by the [`EventsProvider::process_pending_events`] implementation for - /// [`ChainMonitor`]. + /// For channels featuring anchor outputs, this method will also process [`BumpTransaction`] + /// events produced from each [`ChannelMonitor`] while there is a balance to claim onchain + /// within each channel. As the confirmation of a commitment transaction may be critical to the + /// safety of funds, we recommend invoking this every 30 seconds, or lower if running in an + /// environment with spotty connections, like on mobile. + /// + /// An [`EventHandler`] may safely call back to the provider, though this shouldn't be needed in + /// order to handle these events. + /// + /// [`SpendableOutputs`]: crate::events::Event::SpendableOutputs + /// [`BumpTransaction`]: crate::events::Event::BumpTransaction + pub fn process_pending_events(&self, handler: &H) where H::Target: EventHandler { + let mut ev; + process_events_body!(Some(self), ev, handler.handle_event(ev)); + } + + /// Processes any events asynchronously. /// - /// [`EventsProvider::process_pending_events`]: crate::events::EventsProvider::process_pending_events - /// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor + /// See [`Self::process_pending_events`] for more information. + pub async fn process_pending_events_async Future>( + &self, handler: &H + ) { + let mut ev; + process_events_body!(Some(self), ev, { handler(ev).await }); + } + + #[cfg(test)] pub fn get_and_clear_pending_events(&self) -> Vec { - self.inner.lock().unwrap().get_and_clear_pending_events() + let mut ret = Vec::new(); + let mut lck = self.inner.lock().unwrap(); + mem::swap(&mut ret, &mut lck.pending_events); + ret.append(&mut lck.get_repeated_events()); + ret } pub(crate) fn get_min_seen_secret(&self) -> u64 { @@ -2535,11 +2596,13 @@ impl ChannelMonitorImpl { ret } - pub fn get_and_clear_pending_events(&mut self) -> Vec { - let mut ret = Vec::new(); - mem::swap(&mut ret, &mut self.pending_events); - #[cfg(anchors)] - for (claim_id, claim_event) in self.onchain_tx_handler.get_and_clear_pending_claim_events().drain(..) { + /// Gets the set of events that are repeated regularly (e.g. those which RBF bump + /// transactions). We're okay if we lose these on restart as they'll be regenerated for us at + /// some regular interval via [`ChannelMonitor::rebroadcast_pending_claims`]. + pub(super) fn get_repeated_events(&mut self) -> Vec { + let pending_claim_events = self.onchain_tx_handler.get_and_clear_pending_claim_events(); + let mut ret = Vec::with_capacity(pending_claim_events.len()); + for (claim_id, claim_event) in pending_claim_events { match claim_event { ClaimEvent::BumpCommitment { package_target_feerate_sat_per_1000_weight, commitment_tx, anchor_output_idx, @@ -2555,8 +2618,11 @@ impl ChannelMonitorImpl { commitment_tx, commitment_tx_fee_satoshis, anchor_descriptor: AnchorDescriptor { - channel_keys_id: self.channel_keys_id, - channel_value_satoshis: self.channel_value_satoshis, + channel_derivation_parameters: ChannelDerivationParameters { + keys_id: self.channel_keys_id, + value_satoshis: self.channel_value_satoshis, + transaction_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(), + }, outpoint: BitcoinOutPoint { txid: commitment_txid, vout: anchor_output_idx, @@ -2571,11 +2637,16 @@ impl ChannelMonitorImpl { let mut htlc_descriptors = Vec::with_capacity(htlcs.len()); for htlc in htlcs { htlc_descriptors.push(HTLCDescriptor { - channel_keys_id: self.channel_keys_id, - channel_value_satoshis: self.channel_value_satoshis, - channel_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(), + channel_derivation_parameters: ChannelDerivationParameters { + keys_id: self.channel_keys_id, + value_satoshis: self.channel_value_satoshis, + transaction_parameters: self.onchain_tx_handler.channel_transaction_parameters.clone(), + }, commitment_txid: htlc.commitment_txid, per_commitment_number: htlc.per_commitment_number, + per_commitment_point: self.onchain_tx_handler.signer.get_per_commitment_point( + htlc.per_commitment_number, &self.onchain_tx_handler.secp_ctx, + ), htlc: htlc.htlc, preimage: htlc.preimage, counterparty_sig: htlc.counterparty_sig, @@ -4056,12 +4127,12 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP let mut counterparty_fulfilled_htlcs = Some(HashMap::new()); read_tlv_fields!(reader, { (1, funding_spend_confirmed, option), - (3, htlcs_resolved_on_chain, vec_type), - (5, pending_monitor_events, vec_type), + (3, htlcs_resolved_on_chain, optional_vec), + (5, pending_monitor_events, optional_vec), (7, funding_spend_seen, option), (9, counterparty_node_id, option), (11, confirmed_commitment_tx_counterparty_output, option), - (13, spendable_txids_confirmed, vec_type), + (13, spendable_txids_confirmed, optional_vec), (15, counterparty_fulfilled_htlcs, option), }); @@ -4101,6 +4172,7 @@ impl<'a, 'b, ES: EntropySource, SP: SignerProvider> ReadableArgs<(&'a ES, &'b SP payment_preimages, pending_monitor_events: pending_monitor_events.unwrap(), pending_events, + is_processing_pending_events: false, onchain_events_awaiting_threshold_conf, outputs_to_watch,