X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fchannelmonitor.rs;h=f98c0bcac8c0ef453d281b700272b8ac69dd4d06;hb=e4c44f3c5becabccdb6df4e4b30aaa14671f9705;hp=fc3079271c65059c9c280fa4eb1d24a6cf9ecea1;hpb=397386539d19ea368d1f37566b6b0640b90c9668;p=rust-lightning diff --git a/lightning/src/chain/channelmonitor.rs b/lightning/src/chain/channelmonitor.rs index fc307927..f98c0bca 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, _, _)| { @@ -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), @@ -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,7 +747,7 @@ pub struct ChannelMonitor { #[cfg(test)] pub(crate) inner: Mutex>, #[cfg(not(test))] - inner: Mutex>, + pub(super) inner: Mutex>, } #[derive(PartialEq)] @@ -833,7 +824,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 +1071,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 +1211,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 +1339,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. + /// + /// 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. /// - /// This is called by the [`EventsProvider::process_pending_events`] implementation for - /// [`ChainMonitor`]. + /// An [`EventHandler`] may safely call back to the provider, though this shouldn't be needed in + /// order to handle these events. /// - /// [`EventsProvider::process_pending_events`]: crate::events::EventsProvider::process_pending_events - /// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor + /// [`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. + /// + /// 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 +2589,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 +2611,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 +2630,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 +4120,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 +4165,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,