X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=9c559909bc723fdd81b83c15533da71a9ae4b39e;hb=998fffb99bfc83b8ab66d4174d235e597ea4494f;hp=b5fc9996e294ac2ffb4cd6d6e964e64c856439f6;hpb=5bf58f0d33b13bd3d9f88c4f2021fbd77745274a;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index b5fc9996..9c559909 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -44,6 +44,7 @@ use crate::events::{Event, EventHandler, EventsProvider, MessageSendEvent, Messa // construct one themselves. use crate::ln::{inbound_payment, ChannelId, PaymentHash, PaymentPreimage, PaymentSecret}; use crate::ln::channel::{self, Channel, ChannelPhase, ChannelContext, ChannelError, ChannelUpdateStatus, ShutdownResult, UnfundedChannelContext, UpdateFulfillCommitFetch, OutboundV1Channel, InboundV1Channel, WithChannelContext}; +pub use crate::ln::channel::{InboundHTLCDetails, InboundHTLCStateDetails, OutboundHTLCDetails, OutboundHTLCStateDetails}; use crate::ln::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures}; #[cfg(any(feature = "_test_utils", test))] use crate::ln::features::Bolt11InvoiceFeatures; @@ -57,10 +58,11 @@ use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError}; use crate::ln::outbound_payment; use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration}; use crate::ln::wire::Encode; -use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, InvoiceBuilder}; +use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice}; use crate::offers::invoice_error::InvoiceError; +use crate::offers::invoice_request::{DerivedPayerId, InvoiceRequestBuilder}; use crate::offers::merkle::SignError; -use crate::offers::offer::{DerivedMetadata, Offer, OfferBuilder}; +use crate::offers::offer::{Offer, OfferBuilder}; use crate::offers::parse::Bolt12SemanticError; use crate::offers::refund::{Refund, RefundBuilder}; use crate::onion_message::messenger::{Destination, MessageRouter, PendingOnionMessage, new_pending_onion_message}; @@ -76,11 +78,17 @@ use crate::util::logger::{Level, Logger, WithContext}; use crate::util::errors::APIError; #[cfg(not(c_bindings))] use { + crate::offers::offer::DerivedMetadata, crate::routing::router::DefaultRouter, crate::routing::gossip::NetworkGraph, crate::routing::scoring::{ProbabilisticScorer, ProbabilisticScoringFeeParameters}, crate::sign::KeysManager, }; +#[cfg(c_bindings)] +use { + crate::offers::offer::OfferWithDerivedMetadataBuilder, + crate::offers::refund::RefundMaybeWithDerivedMetadataBuilder, +}; use alloc::collections::{btree_map, BTreeMap}; @@ -192,6 +200,8 @@ pub enum PendingHTLCRouting { /// For HTLCs received by LDK, these will ultimately bubble back up as /// [`RecipientOnionFields::custom_tlvs`]. custom_tlvs: Vec<(u64, Vec)>, + /// Set if this HTLC is the final hop in a multi-hop blinded path. + requires_blinded_error: bool, }, } @@ -213,6 +223,7 @@ impl PendingHTLCRouting { match self { Self::Forward { blinded: Some(BlindedForward { failure, .. }), .. } => Some(*failure), Self::Receive { requires_blinded_error: true, .. } => Some(BlindedFailure::FromBlindedNode), + Self::ReceiveKeysend { requires_blinded_error: true, .. } => Some(BlindedFailure::FromBlindedNode), _ => None, } } @@ -903,7 +914,16 @@ impl PeerState where SP::Target: SignerProvider { if require_disconnected && self.is_connected { return false } - self.channel_by_id.iter().filter(|(_, phase)| matches!(phase, ChannelPhase::Funded(_))).count() == 0 + !self.channel_by_id.iter().any(|(_, phase)| + match phase { + ChannelPhase::Funded(_) | ChannelPhase::UnfundedOutboundV1(_) => true, + ChannelPhase::UnfundedInboundV1(_) => false, + #[cfg(dual_funding)] + ChannelPhase::UnfundedOutboundV2(_) => true, + #[cfg(dual_funding)] + ChannelPhase::UnfundedInboundV2(_) => false, + } + ) && self.monitor_update_blocked_actions.is_empty() && self.in_flight_monitor_updates.is_empty() } @@ -975,6 +995,7 @@ pub type SimpleArcChannelManager = ChannelManager< Arc>>, Arc, + Arc, Arc>>, Arc>>>, ProbabilisticScoringFeeParameters, ProbabilisticScorer>>, Arc>, @@ -1005,6 +1026,7 @@ pub type SimpleRefChannelManager<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, M, T, F, L> = &'e DefaultRouter< &'f NetworkGraph<&'g L>, &'g L, + &'c KeysManager, &'h RwLock, &'g L>>, ProbabilisticScoringFeeParameters, ProbabilisticScorer<&'f NetworkGraph<&'g L>, &'g L> @@ -1087,11 +1109,620 @@ where fn get_cm(&self) -> &ChannelManager { self } } -/// Manager which keeps track of a number of channels and sends messages to the appropriate -/// channel, also tracking HTLC preimages and forwarding onion packets appropriately. +/// A lightning node's channel state machine and payment management logic, which facilitates +/// sending, forwarding, and receiving payments through lightning channels. +/// +/// [`ChannelManager`] is parameterized by a number of components to achieve this. +/// - [`chain::Watch`] (typically [`ChainMonitor`]) for on-chain monitoring and enforcement of each +/// channel +/// - [`BroadcasterInterface`] for broadcasting transactions related to opening, funding, and +/// closing channels +/// - [`EntropySource`] for providing random data needed for cryptographic operations +/// - [`NodeSigner`] for cryptographic operations scoped to the node +/// - [`SignerProvider`] for providing signers whose operations are scoped to individual channels +/// - [`FeeEstimator`] to determine transaction fee rates needed to have a transaction mined in a +/// timely manner +/// - [`Router`] for finding payment paths when initiating and retrying payments +/// - [`Logger`] for logging operational information of varying degrees +/// +/// Additionally, it implements the following traits: +/// - [`ChannelMessageHandler`] to handle off-chain channel activity from peers +/// - [`MessageSendEventsProvider`] to similarly send such messages to peers +/// - [`OffersMessageHandler`] for BOLT 12 message handling and sending +/// - [`EventsProvider`] to generate user-actionable [`Event`]s +/// - [`chain::Listen`] and [`chain::Confirm`] for notification of on-chain activity +/// +/// Thus, [`ChannelManager`] is typically used to parameterize a [`MessageHandler`] and an +/// [`OnionMessenger`]. The latter is required to support BOLT 12 functionality. +/// +/// # `ChannelManager` vs `ChannelMonitor` +/// +/// It's important to distinguish between the *off-chain* management and *on-chain* enforcement of +/// lightning channels. [`ChannelManager`] exchanges messages with peers to manage the off-chain +/// state of each channel. During this process, it generates a [`ChannelMonitor`] for each channel +/// and a [`ChannelMonitorUpdate`] for each relevant change, notifying its parameterized +/// [`chain::Watch`] of them. +/// +/// An implementation of [`chain::Watch`], such as [`ChainMonitor`], is responsible for aggregating +/// these [`ChannelMonitor`]s and applying any [`ChannelMonitorUpdate`]s to them. It then monitors +/// for any pertinent on-chain activity, enforcing claims as needed. +/// +/// This division of off-chain management and on-chain enforcement allows for interesting node +/// setups. For instance, on-chain enforcement could be moved to a separate host or have added +/// redundancy, possibly as a watchtower. See [`chain::Watch`] for the relevant interface. +/// +/// # Initialization +/// +/// Use [`ChannelManager::new`] with the most recent [`BlockHash`] when creating a fresh instance. +/// Otherwise, if restarting, construct [`ChannelManagerReadArgs`] with the necessary parameters and +/// references to any deserialized [`ChannelMonitor`]s that were previously persisted. Use this to +/// deserialize the [`ChannelManager`] and feed it any new chain data since it was last online, as +/// detailed in the [`ChannelManagerReadArgs`] documentation. +/// +/// ``` +/// use bitcoin::BlockHash; +/// use bitcoin::network::constants::Network; +/// use lightning::chain::BestBlock; +/// # use lightning::chain::channelmonitor::ChannelMonitor; +/// use lightning::ln::channelmanager::{ChainParameters, ChannelManager, ChannelManagerReadArgs}; +/// # use lightning::routing::gossip::NetworkGraph; +/// use lightning::util::config::UserConfig; +/// use lightning::util::ser::ReadableArgs; +/// +/// # fn read_channel_monitors() -> Vec> { vec![] } +/// # fn example< +/// # 'a, +/// # L: lightning::util::logger::Logger, +/// # ES: lightning::sign::EntropySource, +/// # S: for <'b> lightning::routing::scoring::LockableScore<'b, ScoreLookUp = SL>, +/// # SL: lightning::routing::scoring::ScoreLookUp, +/// # SP: Sized, +/// # R: lightning::io::Read, +/// # >( +/// # fee_estimator: &dyn lightning::chain::chaininterface::FeeEstimator, +/// # chain_monitor: &dyn lightning::chain::Watch, +/// # tx_broadcaster: &dyn lightning::chain::chaininterface::BroadcasterInterface, +/// # router: &lightning::routing::router::DefaultRouter<&NetworkGraph<&'a L>, &'a L, &ES, &S, SP, SL>, +/// # logger: &L, +/// # entropy_source: &ES, +/// # node_signer: &dyn lightning::sign::NodeSigner, +/// # signer_provider: &lightning::sign::DynSignerProvider, +/// # best_block: lightning::chain::BestBlock, +/// # current_timestamp: u32, +/// # mut reader: R, +/// # ) -> Result<(), lightning::ln::msgs::DecodeError> { +/// // Fresh start with no channels +/// let params = ChainParameters { +/// network: Network::Bitcoin, +/// best_block, +/// }; +/// let default_config = UserConfig::default(); +/// let channel_manager = ChannelManager::new( +/// fee_estimator, chain_monitor, tx_broadcaster, router, logger, entropy_source, node_signer, +/// signer_provider, default_config, params, current_timestamp +/// ); +/// +/// // Restart from deserialized data +/// let mut channel_monitors = read_channel_monitors(); +/// let args = ChannelManagerReadArgs::new( +/// entropy_source, node_signer, signer_provider, fee_estimator, chain_monitor, tx_broadcaster, +/// router, logger, default_config, channel_monitors.iter_mut().collect() +/// ); +/// let (block_hash, channel_manager) = +/// <(BlockHash, ChannelManager<_, _, _, _, _, _, _, _>)>::read(&mut reader, args)?; +/// +/// // Update the ChannelManager and ChannelMonitors with the latest chain data +/// // ... +/// +/// // Move the monitors to the ChannelManager's chain::Watch parameter +/// for monitor in channel_monitors { +/// chain_monitor.watch_channel(monitor.get_funding_txo().0, monitor); +/// } +/// # Ok(()) +/// # } +/// ``` +/// +/// # Operation +/// +/// The following is required for [`ChannelManager`] to function properly: +/// - Handle messages from peers using its [`ChannelMessageHandler`] implementation (typically +/// called by [`PeerManager::read_event`] when processing network I/O) +/// - Send messages to peers obtained via its [`MessageSendEventsProvider`] implementation +/// (typically initiated when [`PeerManager::process_events`] is called) +/// - Feed on-chain activity using either its [`chain::Listen`] or [`chain::Confirm`] implementation +/// as documented by those traits +/// - Perform any periodic channel and payment checks by calling [`timer_tick_occurred`] roughly +/// every minute +/// - Persist to disk whenever [`get_and_clear_needs_persistence`] returns `true` using a +/// [`Persister`] such as a [`KVStore`] implementation +/// - Handle [`Event`]s obtained via its [`EventsProvider`] implementation +/// +/// The [`Future`] returned by [`get_event_or_persistence_needed_future`] is useful in determining +/// when the last two requirements need to be checked. +/// +/// The [`lightning-block-sync`] and [`lightning-transaction-sync`] crates provide utilities that +/// simplify feeding in on-chain activity using the [`chain::Listen`] and [`chain::Confirm`] traits, +/// respectively. The remaining requirements can be met using the [`lightning-background-processor`] +/// crate. For languages other than Rust, the availability of similar utilities may vary. +/// +/// # Channels +/// +/// [`ChannelManager`]'s primary function involves managing a channel state. Without channels, +/// payments can't be sent. Use [`list_channels`] or [`list_usable_channels`] for a snapshot of the +/// currently open channels. +/// +/// ``` +/// # use lightning::ln::channelmanager::AChannelManager; +/// # +/// # fn example(channel_manager: T) { +/// # let channel_manager = channel_manager.get_cm(); +/// let channels = channel_manager.list_usable_channels(); +/// for details in channels { +/// println!("{:?}", details); +/// } +/// # } +/// ``` +/// +/// Each channel is identified using a [`ChannelId`], which will change throughout the channel's +/// life cycle. Additionally, channels are assigned a `user_channel_id`, which is given in +/// [`Event`]s associated with the channel and serves as a fixed identifier but is otherwise unused +/// by [`ChannelManager`]. +/// +/// ## Opening Channels +/// +/// To an open a channel with a peer, call [`create_channel`]. This will initiate the process of +/// opening an outbound channel, which requires self-funding when handling +/// [`Event::FundingGenerationReady`]. +/// +/// ``` +/// # use bitcoin::{ScriptBuf, Transaction}; +/// # use bitcoin::secp256k1::PublicKey; +/// # use lightning::ln::channelmanager::AChannelManager; +/// # use lightning::events::{Event, EventsProvider}; +/// # +/// # trait Wallet { +/// # fn create_funding_transaction( +/// # &self, _amount_sats: u64, _output_script: ScriptBuf +/// # ) -> Transaction; +/// # } +/// # +/// # fn example(channel_manager: T, wallet: W, peer_id: PublicKey) { +/// # let channel_manager = channel_manager.get_cm(); +/// let value_sats = 1_000_000; +/// let push_msats = 10_000_000; +/// match channel_manager.create_channel(peer_id, value_sats, push_msats, 42, None, None) { +/// Ok(channel_id) => println!("Opening channel {}", channel_id), +/// Err(e) => println!("Error opening channel: {:?}", e), +/// } +/// +/// // On the event processing thread once the peer has responded +/// channel_manager.process_pending_events(&|event| match event { +/// Event::FundingGenerationReady { +/// temporary_channel_id, counterparty_node_id, channel_value_satoshis, output_script, +/// user_channel_id, .. +/// } => { +/// assert_eq!(user_channel_id, 42); +/// let funding_transaction = wallet.create_funding_transaction( +/// channel_value_satoshis, output_script +/// ); +/// match channel_manager.funding_transaction_generated( +/// &temporary_channel_id, &counterparty_node_id, funding_transaction +/// ) { +/// Ok(()) => println!("Funding channel {}", temporary_channel_id), +/// Err(e) => println!("Error funding channel {}: {:?}", temporary_channel_id, e), +/// } +/// }, +/// Event::ChannelPending { channel_id, user_channel_id, former_temporary_channel_id, .. } => { +/// assert_eq!(user_channel_id, 42); +/// println!( +/// "Channel {} now {} pending (funding transaction has been broadcasted)", channel_id, +/// former_temporary_channel_id.unwrap() +/// ); +/// }, +/// Event::ChannelReady { channel_id, user_channel_id, .. } => { +/// assert_eq!(user_channel_id, 42); +/// println!("Channel {} ready", channel_id); +/// }, +/// // ... +/// # _ => {}, +/// }); +/// # } +/// ``` +/// +/// ## Accepting Channels +/// +/// Inbound channels are initiated by peers and are automatically accepted unless [`ChannelManager`] +/// has [`UserConfig::manually_accept_inbound_channels`] set. In that case, the channel may be +/// either accepted or rejected when handling [`Event::OpenChannelRequest`]. +/// +/// ``` +/// # use bitcoin::secp256k1::PublicKey; +/// # use lightning::ln::channelmanager::AChannelManager; +/// # use lightning::events::{Event, EventsProvider}; +/// # +/// # fn is_trusted(counterparty_node_id: PublicKey) -> bool { +/// # // ... +/// # unimplemented!() +/// # } +/// # +/// # fn example(channel_manager: T) { +/// # let channel_manager = channel_manager.get_cm(); +/// channel_manager.process_pending_events(&|event| match event { +/// Event::OpenChannelRequest { temporary_channel_id, counterparty_node_id, .. } => { +/// if !is_trusted(counterparty_node_id) { +/// match channel_manager.force_close_without_broadcasting_txn( +/// &temporary_channel_id, &counterparty_node_id +/// ) { +/// Ok(()) => println!("Rejecting channel {}", temporary_channel_id), +/// Err(e) => println!("Error rejecting channel {}: {:?}", temporary_channel_id, e), +/// } +/// return; +/// } +/// +/// let user_channel_id = 43; +/// match channel_manager.accept_inbound_channel( +/// &temporary_channel_id, &counterparty_node_id, user_channel_id +/// ) { +/// Ok(()) => println!("Accepting channel {}", temporary_channel_id), +/// Err(e) => println!("Error accepting channel {}: {:?}", temporary_channel_id, e), +/// } +/// }, +/// // ... +/// # _ => {}, +/// }); +/// # } +/// ``` +/// +/// ## Closing Channels +/// +/// There are two ways to close a channel: either cooperatively using [`close_channel`] or +/// unilaterally using [`force_close_broadcasting_latest_txn`]. The former is ideal as it makes for +/// lower fees and immediate access to funds. However, the latter may be necessary if the +/// counterparty isn't behaving properly or has gone offline. [`Event::ChannelClosed`] is generated +/// once the channel has been closed successfully. +/// +/// ``` +/// # use bitcoin::secp256k1::PublicKey; +/// # use lightning::ln::ChannelId; +/// # use lightning::ln::channelmanager::AChannelManager; +/// # use lightning::events::{Event, EventsProvider}; +/// # +/// # fn example( +/// # channel_manager: T, channel_id: ChannelId, counterparty_node_id: PublicKey +/// # ) { +/// # let channel_manager = channel_manager.get_cm(); +/// match channel_manager.close_channel(&channel_id, &counterparty_node_id) { +/// Ok(()) => println!("Closing channel {}", channel_id), +/// Err(e) => println!("Error closing channel {}: {:?}", channel_id, e), +/// } +/// +/// // On the event processing thread +/// channel_manager.process_pending_events(&|event| match event { +/// Event::ChannelClosed { channel_id, user_channel_id, .. } => { +/// assert_eq!(user_channel_id, 42); +/// println!("Channel {} closed", channel_id); +/// }, +/// // ... +/// # _ => {}, +/// }); +/// # } +/// ``` +/// +/// # Payments +/// +/// [`ChannelManager`] is responsible for sending, forwarding, and receiving payments through its +/// channels. A payment is typically initiated from a [BOLT 11] invoice or a [BOLT 12] offer, though +/// spontaneous (i.e., keysend) payments are also possible. Incoming payments don't require +/// maintaining any additional state as [`ChannelManager`] can reconstruct the [`PaymentPreimage`] +/// from the [`PaymentSecret`]. Sending payments, however, require tracking in order to retry failed +/// HTLCs. +/// +/// After a payment is initiated, it will appear in [`list_recent_payments`] until a short time +/// after either an [`Event::PaymentSent`] or [`Event::PaymentFailed`] is handled. Failed HTLCs +/// for a payment will be retried according to the payment's [`Retry`] strategy or until +/// [`abandon_payment`] is called. +/// +/// ## BOLT 11 Invoices +/// +/// The [`lightning-invoice`] crate is useful for creating BOLT 11 invoices. Specifically, use the +/// functions in its `utils` module for constructing invoices that are compatible with +/// [`ChannelManager`]. These functions serve as a convenience for building invoices with the +/// [`PaymentHash`] and [`PaymentSecret`] returned from [`create_inbound_payment`]. To provide your +/// own [`PaymentHash`], use [`create_inbound_payment_for_hash`] or the corresponding functions in +/// the [`lightning-invoice`] `utils` module. +/// +/// [`ChannelManager`] generates an [`Event::PaymentClaimable`] once the full payment has been +/// received. Call [`claim_funds`] to release the [`PaymentPreimage`], which in turn will result in +/// an [`Event::PaymentClaimed`]. +/// +/// ``` +/// # use lightning::events::{Event, EventsProvider, PaymentPurpose}; +/// # use lightning::ln::channelmanager::AChannelManager; +/// # +/// # fn example(channel_manager: T) { +/// # let channel_manager = channel_manager.get_cm(); +/// // Or use utils::create_invoice_from_channelmanager +/// let known_payment_hash = match channel_manager.create_inbound_payment( +/// Some(10_000_000), 3600, None +/// ) { +/// Ok((payment_hash, _payment_secret)) => { +/// println!("Creating inbound payment {}", payment_hash); +/// payment_hash +/// }, +/// Err(()) => panic!("Error creating inbound payment"), +/// }; +/// +/// // On the event processing thread +/// channel_manager.process_pending_events(&|event| match event { +/// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose { +/// PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => { +/// assert_eq!(payment_hash, known_payment_hash); +/// println!("Claiming payment {}", payment_hash); +/// channel_manager.claim_funds(payment_preimage); +/// }, +/// PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => { +/// println!("Unknown payment hash: {}", payment_hash); +/// }, +/// PaymentPurpose::SpontaneousPayment(payment_preimage) => { +/// assert_ne!(payment_hash, known_payment_hash); +/// println!("Claiming spontaneous payment {}", payment_hash); +/// channel_manager.claim_funds(payment_preimage); +/// }, +/// }, +/// Event::PaymentClaimed { payment_hash, amount_msat, .. } => { +/// assert_eq!(payment_hash, known_payment_hash); +/// println!("Claimed {} msats", amount_msat); +/// }, +/// // ... +/// # _ => {}, +/// }); +/// # } +/// ``` +/// +/// For paying an invoice, [`lightning-invoice`] provides a `payment` module with convenience +/// functions for use with [`send_payment`]. +/// +/// ``` +/// # use lightning::events::{Event, EventsProvider}; +/// # use lightning::ln::PaymentHash; +/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry}; +/// # use lightning::routing::router::RouteParameters; +/// # +/// # fn example( +/// # channel_manager: T, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, +/// # route_params: RouteParameters, retry: Retry +/// # ) { +/// # let channel_manager = channel_manager.get_cm(); +/// // let (payment_hash, recipient_onion, route_params) = +/// // payment::payment_parameters_from_invoice(&invoice); +/// let payment_id = PaymentId([42; 32]); +/// match channel_manager.send_payment( +/// payment_hash, recipient_onion, payment_id, route_params, retry +/// ) { +/// Ok(()) => println!("Sending payment with hash {}", payment_hash), +/// Err(e) => println!("Failed sending payment with hash {}: {:?}", payment_hash, e), +/// } +/// +/// let expected_payment_id = payment_id; +/// let expected_payment_hash = payment_hash; +/// assert!( +/// channel_manager.list_recent_payments().iter().find(|details| matches!( +/// details, +/// RecentPaymentDetails::Pending { +/// payment_id: expected_payment_id, +/// payment_hash: expected_payment_hash, +/// .. +/// } +/// )).is_some() +/// ); +/// +/// // On the event processing thread +/// channel_manager.process_pending_events(&|event| match event { +/// Event::PaymentSent { payment_hash, .. } => println!("Paid {}", payment_hash), +/// Event::PaymentFailed { payment_hash, .. } => println!("Failed paying {}", payment_hash), +/// // ... +/// # _ => {}, +/// }); +/// # } +/// ``` +/// +/// ## BOLT 12 Offers +/// +/// The [`offers`] module is useful for creating BOLT 12 offers. An [`Offer`] is a precursor to a +/// [`Bolt12Invoice`], which must first be requested by the payer. The interchange of these messages +/// as defined in the specification is handled by [`ChannelManager`] and its implementation of +/// [`OffersMessageHandler`]. However, this only works with an [`Offer`] created using a builder +/// returned by [`create_offer_builder`]. With this approach, BOLT 12 offers and invoices are +/// stateless just as BOLT 11 invoices are. +/// +/// ``` +/// # use lightning::events::{Event, EventsProvider, PaymentPurpose}; +/// # use lightning::ln::channelmanager::AChannelManager; +/// # use lightning::offers::parse::Bolt12SemanticError; +/// # +/// # fn example(channel_manager: T) -> Result<(), Bolt12SemanticError> { +/// # let channel_manager = channel_manager.get_cm(); +/// let offer = channel_manager +/// .create_offer_builder("coffee".to_string())? +/// # ; +/// # // Needed for compiling for c_bindings +/// # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into(); +/// # let offer = builder +/// .amount_msats(10_000_000) +/// .build()?; +/// let bech32_offer = offer.to_string(); +/// +/// // On the event processing thread +/// channel_manager.process_pending_events(&|event| match event { +/// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose { +/// PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => { +/// println!("Claiming payment {}", payment_hash); +/// channel_manager.claim_funds(payment_preimage); +/// }, +/// PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => { +/// println!("Unknown payment hash: {}", payment_hash); +/// }, +/// // ... +/// # _ => {}, +/// }, +/// Event::PaymentClaimed { payment_hash, amount_msat, .. } => { +/// println!("Claimed {} msats", amount_msat); +/// }, +/// // ... +/// # _ => {}, +/// }); +/// # Ok(()) +/// # } +/// ``` +/// +/// Use [`pay_for_offer`] to initiated payment, which sends an [`InvoiceRequest`] for an [`Offer`] +/// and pays the [`Bolt12Invoice`] response. In addition to success and failure events, +/// [`ChannelManager`] may also generate an [`Event::InvoiceRequestFailed`]. +/// +/// ``` +/// # use lightning::events::{Event, EventsProvider}; +/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry}; +/// # use lightning::offers::offer::Offer; +/// # +/// # fn example( +/// # channel_manager: T, offer: &Offer, quantity: Option, amount_msats: Option, +/// # payer_note: Option, retry: Retry, max_total_routing_fee_msat: Option +/// # ) { +/// # let channel_manager = channel_manager.get_cm(); +/// let payment_id = PaymentId([42; 32]); +/// match channel_manager.pay_for_offer( +/// offer, quantity, amount_msats, payer_note, payment_id, retry, max_total_routing_fee_msat +/// ) { +/// Ok(()) => println!("Requesting invoice for offer"), +/// Err(e) => println!("Unable to request invoice for offer: {:?}", e), +/// } +/// +/// // First the payment will be waiting on an invoice +/// let expected_payment_id = payment_id; +/// assert!( +/// channel_manager.list_recent_payments().iter().find(|details| matches!( +/// details, +/// RecentPaymentDetails::AwaitingInvoice { payment_id: expected_payment_id } +/// )).is_some() +/// ); +/// +/// // Once the invoice is received, a payment will be sent +/// assert!( +/// channel_manager.list_recent_payments().iter().find(|details| matches!( +/// details, +/// RecentPaymentDetails::Pending { payment_id: expected_payment_id, .. } +/// )).is_some() +/// ); +/// +/// // On the event processing thread +/// channel_manager.process_pending_events(&|event| match event { +/// Event::PaymentSent { payment_id: Some(payment_id), .. } => println!("Paid {}", payment_id), +/// Event::PaymentFailed { payment_id, .. } => println!("Failed paying {}", payment_id), +/// Event::InvoiceRequestFailed { payment_id, .. } => println!("Failed paying {}", payment_id), +/// // ... +/// # _ => {}, +/// }); +/// # } +/// ``` +/// +/// ## BOLT 12 Refunds +/// +/// A [`Refund`] is a request for an invoice to be paid. Like *paying* for an [`Offer`], *creating* +/// a [`Refund`] involves maintaining state since it represents a future outbound payment. +/// Therefore, use [`create_refund_builder`] when creating one, otherwise [`ChannelManager`] will +/// refuse to pay any corresponding [`Bolt12Invoice`] that it receives. +/// +/// ``` +/// # use core::time::Duration; +/// # use lightning::events::{Event, EventsProvider}; +/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, Retry}; +/// # use lightning::offers::parse::Bolt12SemanticError; +/// # +/// # fn example( +/// # channel_manager: T, amount_msats: u64, absolute_expiry: Duration, retry: Retry, +/// # max_total_routing_fee_msat: Option +/// # ) -> Result<(), Bolt12SemanticError> { +/// # let channel_manager = channel_manager.get_cm(); +/// let payment_id = PaymentId([42; 32]); +/// let refund = channel_manager +/// .create_refund_builder( +/// "coffee".to_string(), amount_msats, absolute_expiry, payment_id, retry, +/// max_total_routing_fee_msat +/// )? +/// # ; +/// # // Needed for compiling for c_bindings +/// # let builder: lightning::offers::refund::RefundBuilder<_> = refund.into(); +/// # let refund = builder +/// .payer_note("refund for order 1234".to_string()) +/// .build()?; +/// let bech32_refund = refund.to_string(); +/// +/// // First the payment will be waiting on an invoice +/// let expected_payment_id = payment_id; +/// assert!( +/// channel_manager.list_recent_payments().iter().find(|details| matches!( +/// details, +/// RecentPaymentDetails::AwaitingInvoice { payment_id: expected_payment_id } +/// )).is_some() +/// ); /// -/// Implements [`ChannelMessageHandler`], handling the multi-channel parts and passing things through -/// to individual Channels. +/// // Once the invoice is received, a payment will be sent +/// assert!( +/// channel_manager.list_recent_payments().iter().find(|details| matches!( +/// details, +/// RecentPaymentDetails::Pending { payment_id: expected_payment_id, .. } +/// )).is_some() +/// ); +/// +/// // On the event processing thread +/// channel_manager.process_pending_events(&|event| match event { +/// Event::PaymentSent { payment_id: Some(payment_id), .. } => println!("Paid {}", payment_id), +/// Event::PaymentFailed { payment_id, .. } => println!("Failed paying {}", payment_id), +/// // ... +/// # _ => {}, +/// }); +/// # Ok(()) +/// # } +/// ``` +/// +/// Use [`request_refund_payment`] to send a [`Bolt12Invoice`] for receiving the refund. Similar to +/// *creating* an [`Offer`], this is stateless as it represents an inbound payment. +/// +/// ``` +/// # use lightning::events::{Event, EventsProvider, PaymentPurpose}; +/// # use lightning::ln::channelmanager::AChannelManager; +/// # use lightning::offers::refund::Refund; +/// # +/// # fn example(channel_manager: T, refund: &Refund) { +/// # let channel_manager = channel_manager.get_cm(); +/// match channel_manager.request_refund_payment(refund) { +/// Ok(()) => println!("Requesting payment for refund"), +/// Err(e) => println!("Unable to request payment for refund: {:?}", e), +/// } +/// +/// // On the event processing thread +/// channel_manager.process_pending_events(&|event| match event { +/// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose { +/// PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => { +/// println!("Claiming payment {}", payment_hash); +/// channel_manager.claim_funds(payment_preimage); +/// }, +/// PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => { +/// println!("Unknown payment hash: {}", payment_hash); +/// }, +/// // ... +/// # _ => {}, +/// }, +/// Event::PaymentClaimed { payment_hash, amount_msat, .. } => { +/// println!("Claimed {} msats", amount_msat); +/// }, +/// // ... +/// # _ => {}, +/// }); +/// # } +/// ``` +/// +/// # Persistence /// /// Implements [`Writeable`] to write out all channel state to disk. Implies [`peer_disconnected`] for /// all peers during write/read (though does not modify this instance, only the instance being @@ -1112,12 +1743,16 @@ where /// tells you the last block hash which was connected. You should get the best block tip before using the manager. /// See [`chain::Listen`] and [`chain::Confirm`] for more details. /// +/// # `ChannelUpdate` Messages +/// /// Note that `ChannelManager` is responsible for tracking liveness of its channels and generating /// [`ChannelUpdate`] messages informing peers that the channel is temporarily disabled. To avoid /// spam due to quick disconnection/reconnection, updates are not sent until the channel has been /// offline for a full minute. In order to track this, you must call /// [`timer_tick_occurred`] roughly once per minute, though it doesn't have to be perfect. /// +/// # DoS Mitigation +/// /// To avoid trivial DoS issues, `ChannelManager` limits the number of inbound connections and /// inbound channels without confirmed funding transactions. This may result in nodes which we do /// not have a channel with being unable to connect to us or open new channels with us if we have @@ -1127,19 +1762,53 @@ where /// exempted from the count of unfunded channels. Similarly, outbound channels and connections are /// never limited. Please ensure you limit the count of such channels yourself. /// +/// # Type Aliases +/// /// Rather than using a plain `ChannelManager`, it is preferable to use either a [`SimpleArcChannelManager`] /// a [`SimpleRefChannelManager`], for conciseness. See their documentation for more details, but /// essentially you should default to using a [`SimpleRefChannelManager`], and use a /// [`SimpleArcChannelManager`] when you require a `ChannelManager` with a static lifetime, such as when /// you're using lightning-net-tokio. /// +/// [`ChainMonitor`]: crate::chain::chainmonitor::ChainMonitor +/// [`MessageHandler`]: crate::ln::peer_handler::MessageHandler +/// [`OnionMessenger`]: crate::onion_message::messenger::OnionMessenger +/// [`PeerManager::read_event`]: crate::ln::peer_handler::PeerManager::read_event +/// [`PeerManager::process_events`]: crate::ln::peer_handler::PeerManager::process_events +/// [`timer_tick_occurred`]: Self::timer_tick_occurred +/// [`get_and_clear_needs_persistence`]: Self::get_and_clear_needs_persistence +/// [`Persister`]: crate::util::persist::Persister +/// [`KVStore`]: crate::util::persist::KVStore +/// [`get_event_or_persistence_needed_future`]: Self::get_event_or_persistence_needed_future +/// [`lightning-block-sync`]: https://docs.rs/lightning_block_sync/latest/lightning_block_sync +/// [`lightning-transaction-sync`]: https://docs.rs/lightning_transaction_sync/latest/lightning_transaction_sync +/// [`lightning-background-processor`]: https://docs.rs/lightning_background_processor/lightning_background_processor +/// [`list_channels`]: Self::list_channels +/// [`list_usable_channels`]: Self::list_usable_channels +/// [`create_channel`]: Self::create_channel +/// [`close_channel`]: Self::force_close_broadcasting_latest_txn +/// [`force_close_broadcasting_latest_txn`]: Self::force_close_broadcasting_latest_txn +/// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md +/// [BOLT 12]: https://github.com/rustyrussell/lightning-rfc/blob/guilt/offers/12-offer-encoding.md +/// [`list_recent_payments`]: Self::list_recent_payments +/// [`abandon_payment`]: Self::abandon_payment +/// [`lightning-invoice`]: https://docs.rs/lightning_invoice/latest/lightning_invoice +/// [`create_inbound_payment`]: Self::create_inbound_payment +/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash +/// [`claim_funds`]: Self::claim_funds +/// [`send_payment`]: Self::send_payment +/// [`offers`]: crate::offers +/// [`create_offer_builder`]: Self::create_offer_builder +/// [`pay_for_offer`]: Self::pay_for_offer +/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest +/// [`create_refund_builder`]: Self::create_refund_builder +/// [`request_refund_payment`]: Self::request_refund_payment /// [`peer_disconnected`]: msgs::ChannelMessageHandler::peer_disconnected /// [`funding_created`]: msgs::FundingCreated /// [`funding_transaction_generated`]: Self::funding_transaction_generated /// [`BlockHash`]: bitcoin::hash_types::BlockHash /// [`update_channel`]: chain::Watch::update_channel /// [`ChannelUpdate`]: msgs::ChannelUpdate -/// [`timer_tick_occurred`]: Self::timer_tick_occurred /// [`read`]: ReadableArgs::read // // Lock order: @@ -1636,9 +2305,6 @@ pub struct ChannelDetails { pub counterparty: ChannelCounterparty, /// The Channel's funding transaction output, if we've negotiated the funding transaction with /// our counterparty already. - /// - /// Note that, if this has been set, `channel_id` for V1-established channels will be equivalent to - /// `ChannelId::v1_from_funding_outpoint(funding_txo.unwrap())`. pub funding_txo: Option, /// The features which this channel operates with. See individual features for more info. /// @@ -1804,6 +2470,14 @@ pub struct ChannelDetails { /// /// This field is only `None` for `ChannelDetails` objects serialized prior to LDK 0.0.109. pub config: Option, + /// Pending inbound HTLCs. + /// + /// This field is empty for objects serialized with LDK versions prior to 0.0.122. + pub pending_inbound_htlcs: Vec, + /// Pending outbound HTLCs. + /// + /// This field is empty for objects serialized with LDK versions prior to 0.0.122. + pub pending_outbound_htlcs: Vec, } impl ChannelDetails { @@ -1881,6 +2555,8 @@ impl ChannelDetails { inbound_htlc_maximum_msat: context.get_holder_htlc_maximum_msat(), config: Some(context.config()), channel_shutdown_state: Some(context.shutdown_state()), + pending_inbound_htlcs: context.get_pending_inbound_htlc_details(), + pending_outbound_htlcs: context.get_pending_outbound_htlc_details(), } } } @@ -2080,6 +2756,14 @@ macro_rules! convert_chan_phase_err { ChannelPhase::UnfundedInboundV1(channel) => { convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL) }, + #[cfg(dual_funding)] + ChannelPhase::UnfundedOutboundV2(channel) => { + convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL) + }, + #[cfg(dual_funding)] + ChannelPhase::UnfundedInboundV2(channel) => { + convert_chan_phase_err!($self, $err, channel, $channel_id, UNFUNDED_CHANNEL) + }, } }; } @@ -2155,6 +2839,7 @@ macro_rules! emit_channel_pending_event { counterparty_node_id: $channel.context.get_counterparty_node_id(), user_channel_id: $channel.context.get_user_id(), funding_txo: $channel.context.get_funding_txo().unwrap().into_bitcoin_outpoint(), + channel_type: Some($channel.context.get_channel_type().clone()), }, None)); $channel.context.set_channel_pending_event_emitted(); } @@ -2181,7 +2866,7 @@ macro_rules! handle_monitor_update_completion { let logger = WithChannelContext::from(&$self.logger, &$chan.context); let mut updates = $chan.monitor_updating_restored(&&logger, &$self.node_signer, $self.chain_hash, &$self.default_configuration, - $self.best_block.read().unwrap().height()); + $self.best_block.read().unwrap().height); let counterparty_node_id = $chan.context.get_counterparty_node_id(); let channel_update = if updates.channel_ready.is_some() && $chan.context.is_usable() { // We only send a channel_update in the case where we are just now sending a @@ -2296,7 +2981,7 @@ macro_rules! handle_new_monitor_update { handle_new_monitor_update!($self, $update_res, $chan, _internal, handle_monitor_update_completion!($self, $peer_state_lock, $peer_state, $per_peer_state_lock, $chan)) }; - ($self: ident, $funding_txo: expr, $channel_id: expr, $update: expr, $peer_state_lock: expr, $peer_state: expr, $per_peer_state_lock: expr, $chan: expr) => { { + ($self: ident, $funding_txo: expr, $update: expr, $peer_state_lock: expr, $peer_state: expr, $per_peer_state_lock: expr, $chan: expr) => { { let in_flight_updates = $peer_state.in_flight_monitor_updates.entry($funding_txo) .or_insert_with(Vec::new); // During startup, we push monitor updates as background events through to here in @@ -2435,14 +3120,14 @@ where best_block: RwLock::new(params.best_block), - outbound_scid_aliases: Mutex::new(HashSet::new()), - pending_inbound_payments: Mutex::new(HashMap::new()), + outbound_scid_aliases: Mutex::new(new_hash_set()), + pending_inbound_payments: Mutex::new(new_hash_map()), pending_outbound_payments: OutboundPayments::new(), - forward_htlcs: Mutex::new(HashMap::new()), - claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: HashMap::new(), pending_claiming_payments: HashMap::new() }), - pending_intercepted_htlcs: Mutex::new(HashMap::new()), - outpoint_to_peer: Mutex::new(HashMap::new()), - short_to_chan_info: FairRwLock::new(HashMap::new()), + forward_htlcs: Mutex::new(new_hash_map()), + claimable_payments: Mutex::new(ClaimablePayments { claimable_payments: new_hash_map(), pending_claiming_payments: new_hash_map() }), + pending_intercepted_htlcs: Mutex::new(new_hash_map()), + outpoint_to_peer: Mutex::new(new_hash_map()), + short_to_chan_info: FairRwLock::new(new_hash_map()), our_network_pubkey: node_signer.get_node_id(Recipient::Node).unwrap(), secp_ctx, @@ -2454,7 +3139,7 @@ where highest_seen_timestamp: AtomicUsize::new(current_timestamp as usize), - per_peer_state: FairRwLock::new(HashMap::new()), + per_peer_state: FairRwLock::new(new_hash_map()), pending_events: Mutex::new(VecDeque::new()), pending_events_processor: AtomicBool::new(false), @@ -2481,7 +3166,7 @@ where } fn create_and_insert_outbound_scid_alias(&self) -> u64 { - let height = self.best_block.read().unwrap().height(); + let height = self.best_block.read().unwrap().height; let mut outbound_scid_alias = 0; let mut i = 0; loop { @@ -2559,7 +3244,7 @@ where let config = if override_config.is_some() { override_config.as_ref().unwrap() } else { &self.default_configuration }; match OutboundV1Channel::new(&self.fee_estimator, &self.entropy_source, &self.signer_provider, their_network_key, their_features, channel_value_satoshis, push_msat, user_channel_id, config, - self.best_block.read().unwrap().height(), outbound_scid_alias, temporary_channel_id) + self.best_block.read().unwrap().height, outbound_scid_alias, temporary_channel_id) { Ok(res) => res, Err(e) => { @@ -2598,7 +3283,7 @@ where // the same channel. let mut res = Vec::with_capacity(self.short_to_chan_info.read().unwrap().len()); { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let per_peer_state = self.per_peer_state.read().unwrap(); for (_cp_id, peer_state_mutex) in per_peer_state.iter() { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); @@ -2631,7 +3316,7 @@ where // the same channel. let mut res = Vec::with_capacity(self.short_to_chan_info.read().unwrap().len()); { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let per_peer_state = self.per_peer_state.read().unwrap(); for (_cp_id, peer_state_mutex) in per_peer_state.iter() { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); @@ -2661,7 +3346,7 @@ where /// Gets the list of channels we have with a given counterparty, in random order. pub fn list_channels_with_counterparty(&self, counterparty_node_id: &PublicKey) -> Vec { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let per_peer_state = self.per_peer_state.read().unwrap(); if let Some(peer_state_mutex) = per_peer_state.get(counterparty_node_id) { @@ -2753,7 +3438,7 @@ where // Update the monitor with the shutdown script if necessary. if let Some(monitor_update) = monitor_update_opt.take() { - handle_new_monitor_update!(self, funding_txo_opt.unwrap(), *channel_id, monitor_update, + handle_new_monitor_update!(self, funding_txo_opt.unwrap(), monitor_update, peer_state_lock, peer_state, per_peer_state, chan); } } else { @@ -2945,6 +3630,13 @@ where // Unfunded channel has no update (None, chan_phase.context().get_counterparty_node_id()) }, + // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. + #[cfg(dual_funding)] + ChannelPhase::UnfundedOutboundV2(_) | ChannelPhase::UnfundedInboundV2(_) => { + self.finish_close_channel(chan_phase.context_mut().force_shutdown(false, closure_reason)); + // Unfunded channel has no update + (None, chan_phase.context().get_counterparty_node_id()) + }, } } else if peer_state.inbound_channel_request_by_id.remove(channel_id).is_some() { log_error!(logger, "Force-closing channel {}", &channel_id); @@ -3008,8 +3700,8 @@ where /// the latest local transaction(s). Fails if `channel_id` is unknown to the manager, or if the /// `counterparty_node_id` isn't the counterparty of the corresponding channel. /// - /// You can always get the latest local transaction(s) to broadcast from - /// [`ChannelMonitor::get_latest_holder_commitment_txn`]. + /// You can always broadcast the latest local transaction(s) via + /// [`ChannelMonitor::broadcast_latest_holder_commitment_txn`]. pub fn force_close_without_broadcasting_txn(&self, channel_id: &ChannelId, counterparty_node_id: &PublicKey) -> Result<(), APIError> { self.force_close_sending_error(channel_id, counterparty_node_id, false) @@ -3164,7 +3856,7 @@ where None }; - let cur_height = self.best_block.read().unwrap().height() + 1; + let cur_height = self.best_block.read().unwrap().height + 1; if let Err((err_msg, code)) = check_incoming_htlc_cltv( cur_height, outgoing_cltv_value, msg.cltv_expiry @@ -3241,7 +3933,7 @@ where match decoded_hop { onion_utils::Hop::Receive(next_hop_data) => { // OUR PAYMENT! - let current_height: u32 = self.best_block.read().unwrap().height(); + let current_height: u32 = self.best_block.read().unwrap().height; match create_recv_pending_htlc_info(next_hop_data, shared_secret, msg.payment_hash, msg.amount_msat, msg.cltv_expiry, None, allow_underpay, msg.skimmed_fee_msat, current_height, self.default_configuration.accept_mpp_keysend) @@ -3414,7 +4106,7 @@ where }, onion_packet, None, &self.fee_estimator, &&logger); match break_chan_phase_entry!(self, send_res, chan_phase_entry) { Some(monitor_update) => { - match handle_new_monitor_update!(self, funding_txo, channel_id, monitor_update, peer_state_lock, peer_state, per_peer_state, chan) { + match handle_new_monitor_update!(self, funding_txo, monitor_update, peer_state_lock, peer_state, per_peer_state, chan) { false => { // Note that MonitorUpdateInProgress here indicates (per function // docs) that we will resend the commitment update once monitor @@ -3501,7 +4193,7 @@ where /// [`PeerManager::process_events`]: crate::ln::peer_handler::PeerManager::process_events /// [`ChannelMonitorUpdateStatus::InProgress`]: crate::chain::ChannelMonitorUpdateStatus::InProgress pub fn send_payment_with_route(&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId) -> Result<(), PaymentSendFailure> { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); self.pending_outbound_payments .send_payment_with_route(route, payment_hash, recipient_onion, payment_id, @@ -3512,7 +4204,7 @@ where /// Similar to [`ChannelManager::send_payment_with_route`], but will automatically find a route based on /// `route_params` and retry failed payment paths based on `retry_strategy`. pub fn send_payment(&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry) -> Result<(), RetryableSendFailure> { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); self.pending_outbound_payments .send_payment(payment_hash, recipient_onion, payment_id, retry_strategy, route_params, @@ -3523,7 +4215,7 @@ where #[cfg(test)] pub(super) fn test_send_payment_internal(&self, route: &Route, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, keysend_preimage: Option, payment_id: PaymentId, recv_value_msat: Option, onion_session_privs: Vec<[u8; 32]>) -> Result<(), PaymentSendFailure> { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); self.pending_outbound_payments.test_send_payment_internal(route, payment_hash, recipient_onion, keysend_preimage, payment_id, recv_value_msat, onion_session_privs, &self.node_signer, @@ -3532,7 +4224,7 @@ where #[cfg(test)] pub(crate) fn test_add_new_pending_payment(&self, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route: &Route) -> Result, PaymentSendFailure> { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; self.pending_outbound_payments.test_add_new_pending_payment(payment_hash, recipient_onion, payment_id, route, None, &self.entropy_source, best_block_height) } @@ -3542,7 +4234,7 @@ where } pub(super) fn send_payment_for_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError> { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); self.pending_outbound_payments .send_payment_for_bolt12_invoice( @@ -3599,7 +4291,7 @@ where /// /// [`send_payment`]: Self::send_payment pub fn send_spontaneous_payment(&self, route: &Route, payment_preimage: Option, recipient_onion: RecipientOnionFields, payment_id: PaymentId) -> Result { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); self.pending_outbound_payments.send_spontaneous_payment_with_route( route, payment_preimage, recipient_onion, payment_id, &self.entropy_source, @@ -3614,7 +4306,7 @@ where /// /// [`PaymentParameters::for_keysend`]: crate::routing::router::PaymentParameters::for_keysend pub fn send_spontaneous_payment_with_retry(&self, payment_preimage: Option, recipient_onion: RecipientOnionFields, payment_id: PaymentId, route_params: RouteParameters, retry_strategy: Retry) -> Result { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); self.pending_outbound_payments.send_spontaneous_payment(payment_preimage, recipient_onion, payment_id, retry_strategy, route_params, &self.router, self.list_usable_channels(), @@ -3626,7 +4318,7 @@ where /// [`PaymentHash`] of probes based on a static secret and a random [`PaymentId`], which allows /// us to easily discern them from real payments. pub fn send_probe(&self, path: Path) -> Result<(PaymentHash, PaymentId), PaymentSendFailure> { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); self.pending_outbound_payments.send_probe(path, self.probing_cookie_secret, &self.entropy_source, &self.node_signer, best_block_height, @@ -3688,7 +4380,7 @@ where ProbeSendFailure::RouteNotFound })?; - let mut used_liquidity_map = HashMap::with_capacity(first_hops.len()); + let mut used_liquidity_map = hash_map_with_capacity(first_hops.len()); let mut res = Vec::new(); @@ -3904,7 +4596,7 @@ where })); } { - let height = self.best_block.read().unwrap().height(); + let height = self.best_block.read().unwrap().height; // Transactions are evaluated as final by network mempools if their locktime is strictly // lower than the next block height. However, the modules constituting our Lightning // node might not have perfect sync about their blockchain views. Thus, if the wallet @@ -4245,7 +4937,7 @@ where let mut failed_forwards = Vec::new(); let mut phantom_receives: Vec<(u64, OutPoint, ChannelId, u128, Vec<(PendingHTLCInfo, u64)>)> = Vec::new(); { - let mut forward_htlcs = HashMap::new(); + let mut forward_htlcs = new_hash_map(); mem::swap(&mut forward_htlcs, &mut self.forward_htlcs.lock().unwrap()); for (short_chan_id, mut pending_forwards) in forward_htlcs { @@ -4328,7 +5020,7 @@ where }; match next_hop { onion_utils::Hop::Receive(hop_data) => { - let current_height: u32 = self.best_block.read().unwrap().height(); + let current_height: u32 = self.best_block.read().unwrap().height; match create_recv_pending_htlc_info(hop_data, incoming_shared_secret, payment_hash, outgoing_amt_msat, outgoing_cltv_value, Some(phantom_shared_secret), false, None, @@ -4481,7 +5173,10 @@ where (incoming_cltv_expiry, OnionPayload::Invoice { _legacy_hop_data }, Some(payment_data), phantom_shared_secret, onion_fields) }, - PendingHTLCRouting::ReceiveKeysend { payment_data, payment_preimage, payment_metadata, incoming_cltv_expiry, custom_tlvs } => { + PendingHTLCRouting::ReceiveKeysend { + payment_data, payment_preimage, payment_metadata, + incoming_cltv_expiry, custom_tlvs, requires_blinded_error: _ + } => { let onion_fields = RecipientOnionFields { payment_secret: payment_data.as_ref().map(|data| data.payment_secret), payment_metadata, @@ -4525,7 +5220,7 @@ where debug_assert!(!committed_to_claimable); let mut htlc_msat_height_data = $htlc.value.to_be_bytes().to_vec(); htlc_msat_height_data.extend_from_slice( - &self.best_block.read().unwrap().height().to_be_bytes(), + &self.best_block.read().unwrap().height.to_be_bytes(), ); failed_forwards.push((HTLCSource::PreviousHopData(HTLCPreviousHopData { short_channel_id: $htlc.prev_hop.short_channel_id, @@ -4663,7 +5358,7 @@ where } }; if let Some(min_final_cltv_expiry_delta) = min_final_cltv_expiry_delta { - let expected_min_expiry_height = (self.current_best_block().height() + min_final_cltv_expiry_delta as u32) as u64; + let expected_min_expiry_height = (self.current_best_block().height + min_final_cltv_expiry_delta as u32) as u64; if (cltv_expiry as u64) < expected_min_expiry_height { log_trace!(self.logger, "Failing new HTLC with payment_hash {} as its CLTV expiry was too soon (had {}, earliest expected {})", &payment_hash, cltv_expiry, expected_min_expiry_height); @@ -4717,7 +5412,7 @@ where } } - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; self.pending_outbound_payments.check_retry_payments(&self.router, || self.list_usable_channels(), || self.compute_inflight_htlcs(), &self.entropy_source, &self.node_signer, best_block_height, &self.pending_events, &self.logger, |args| self.send_payment_along_path(args)); @@ -4770,7 +5465,7 @@ where hash_map::Entry::Occupied(mut chan_phase) => { if let ChannelPhase::Funded(chan) = chan_phase.get_mut() { updated_chan = true; - handle_new_monitor_update!(self, funding_txo, channel_id, update.clone(), + handle_new_monitor_update!(self, funding_txo, update.clone(), peer_state_lock, peer_state, per_peer_state, chan); } else { debug_assert!(false, "We shouldn't have an update for a non-funded channel"); @@ -4820,10 +5515,6 @@ where // If the feerate has decreased by less than half, don't bother if new_feerate <= chan.context.get_feerate_sat_per_1000_weight() && new_feerate * 2 > chan.context.get_feerate_sat_per_1000_weight() { - if new_feerate != chan.context.get_feerate_sat_per_1000_weight() { - log_trace!(logger, "Channel {} does not qualify for a feerate change from {} to {}.", - chan_id, chan.context.get_feerate_sat_per_1000_weight(), new_feerate); - } return NotifyOption::SkipPersistNoEvents; } if !chan.context.is_live() { @@ -5022,6 +5713,16 @@ where process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context, pending_msg_events, counterparty_node_id) }, + #[cfg(dual_funding)] + ChannelPhase::UnfundedInboundV2(chan) => { + process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context, + pending_msg_events, counterparty_node_id) + }, + #[cfg(dual_funding)] + ChannelPhase::UnfundedOutboundV2(chan) => { + process_unfunded_channel_tick(chan_id, &mut chan.context, &mut chan.unfunded_context, + pending_msg_events, counterparty_node_id) + }, } }); @@ -5182,7 +5883,7 @@ where FailureCode::RequiredNodeFeatureMissing => HTLCFailReason::from_failure_code(failure_code.into()), FailureCode::IncorrectOrUnknownPaymentDetails => { let mut htlc_msat_height_data = htlc.value.to_be_bytes().to_vec(); - htlc_msat_height_data.extend_from_slice(&self.best_block.read().unwrap().height().to_be_bytes()); + htlc_msat_height_data.extend_from_slice(&self.best_block.read().unwrap().height.to_be_bytes()); HTLCFailReason::reason(failure_code.into(), htlc_msat_height_data) }, FailureCode::InvalidOnionPayload(data) => { @@ -5513,7 +6214,7 @@ where if !valid_mpp { for htlc in sources.drain(..) { let mut htlc_msat_height_data = htlc.value.to_be_bytes().to_vec(); - htlc_msat_height_data.extend_from_slice(&self.best_block.read().unwrap().height().to_be_bytes()); + htlc_msat_height_data.extend_from_slice(&self.best_block.read().unwrap().height.to_be_bytes()); let source = HTLCSource::PreviousHopData(htlc.prev_hop); let reason = HTLCFailReason::reason(0x4000 | 15, htlc_msat_height_data); let receiver = HTLCDestination::FailedPayment { payment_hash }; @@ -5574,7 +6275,7 @@ where peer_state.monitor_update_blocked_actions.entry(chan_id).or_insert(Vec::new()).push(action); } if !during_init { - handle_new_monitor_update!(self, prev_hop.outpoint, prev_hop.channel_id, monitor_update, peer_state_lock, + handle_new_monitor_update!(self, prev_hop.outpoint, monitor_update, peer_state_lock, peer_state, per_peer_state, chan); } else { // If we're running during init we cannot update a monitor directly - @@ -5690,9 +6391,9 @@ where } fn claim_funds_internal(&self, source: HTLCSource, payment_preimage: PaymentPreimage, - forwarded_htlc_value_msat: Option, from_onchain: bool, startup_replay: bool, - next_channel_counterparty_node_id: Option, next_channel_outpoint: OutPoint, - next_channel_id: ChannelId, + forwarded_htlc_value_msat: Option, skimmed_fee_msat: Option, from_onchain: bool, + startup_replay: bool, next_channel_counterparty_node_id: Option, + next_channel_outpoint: OutPoint, next_channel_id: ChannelId, next_user_channel_id: Option, ) { match source { HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => { @@ -5711,11 +6412,10 @@ where }, HTLCSource::PreviousHopData(hop_data) => { let prev_channel_id = hop_data.channel_id; + let prev_user_channel_id = hop_data.user_channel_id; let completed_blocker = RAAMonitorUpdateBlockingAction::from_prev_hop_data(&hop_data); #[cfg(debug_assertions)] let claiming_chan_funding_outpoint = hop_data.outpoint; - #[cfg(debug_assertions)] - let claiming_channel_id = hop_data.channel_id; let res = self.claim_funds_from_hop(hop_data, payment_preimage, |htlc_claim_value_msat, definitely_duplicate| { let chan_to_release = @@ -5773,7 +6473,7 @@ where BackgroundEvent::MonitorUpdatesComplete { channel_id, .. } => - *channel_id == claiming_channel_id, + *channel_id == prev_channel_id, } }), "{:?}", *background_events); } @@ -5788,17 +6488,22 @@ where }) } else { None } } else { - let fee_earned_msat = if let Some(forwarded_htlc_value) = forwarded_htlc_value_msat { + let total_fee_earned_msat = if let Some(forwarded_htlc_value) = forwarded_htlc_value_msat { if let Some(claimed_htlc_value) = htlc_claim_value_msat { Some(claimed_htlc_value - forwarded_htlc_value) } else { None } } else { None }; + debug_assert!(skimmed_fee_msat <= total_fee_earned_msat, + "skimmed_fee_msat must always be included in total_fee_earned_msat"); Some(MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel { event: events::Event::PaymentForwarded { - fee_earned_msat, - claim_from_onchain_tx: from_onchain, prev_channel_id: Some(prev_channel_id), next_channel_id: Some(next_channel_id), + prev_user_channel_id, + next_user_channel_id, + total_fee_earned_msat, + skimmed_fee_msat, + claim_from_onchain_tx: from_onchain, outbound_amount_forwarded_msat: forwarded_htlc_value_msat, }, downstream_counterparty_and_funding_outpoint: chan_to_release, @@ -5951,7 +6656,7 @@ where // TODO: Once we can rely on the counterparty_node_id from the // monitor event, this and the outpoint_to_peer map should be removed. let outpoint_to_peer = self.outpoint_to_peer.lock().unwrap(); - match outpoint_to_peer.get(&funding_txo) { + match outpoint_to_peer.get(funding_txo) { Some(cp_id) => cp_id.clone(), None => return, } @@ -5964,7 +6669,7 @@ where peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap(); let peer_state = &mut *peer_state_lock; let channel = - if let Some(ChannelPhase::Funded(chan)) = peer_state.channel_by_id.get_mut(&channel_id) { + if let Some(ChannelPhase::Funded(chan)) = peer_state.channel_by_id.get_mut(channel_id) { chan } else { let update_actions = peer_state.monitor_update_blocked_actions @@ -6054,73 +6759,82 @@ where // happening and return an error. N.B. that we create channel with an outbound SCID of zero so // that we can delay allocating the SCID until after we're sure that the checks below will // succeed. - let mut channel = match peer_state.inbound_channel_request_by_id.remove(temporary_channel_id) { + let res = match peer_state.inbound_channel_request_by_id.remove(temporary_channel_id) { Some(unaccepted_channel) => { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; InboundV1Channel::new(&self.fee_estimator, &self.entropy_source, &self.signer_provider, counterparty_node_id.clone(), &self.channel_type_features(), &peer_state.latest_features, &unaccepted_channel.open_channel_msg, user_channel_id, &self.default_configuration, best_block_height, - &self.logger, accept_0conf).map_err(|e| { - let err_str = e.to_string(); - log_error!(logger, "{}", err_str); - - APIError::ChannelUnavailable { err: err_str } - }) - } + &self.logger, accept_0conf).map_err(|err| MsgHandleErrInternal::from_chan_no_close(err, *temporary_channel_id)) + }, _ => { let err_str = "No such channel awaiting to be accepted.".to_owned(); log_error!(logger, "{}", err_str); - Err(APIError::APIMisuseError { err: err_str }) + return Err(APIError::APIMisuseError { err: err_str }); } - }?; + }; - if accept_0conf { - // This should have been correctly configured by the call to InboundV1Channel::new. - debug_assert!(channel.context.minimum_depth().unwrap() == 0); - } else if channel.context.get_channel_type().requires_zero_conf() { - let send_msg_err_event = events::MessageSendEvent::HandleError { - node_id: channel.context.get_counterparty_node_id(), - action: msgs::ErrorAction::SendErrorMessage{ - msg: msgs::ErrorMessage { channel_id: temporary_channel_id.clone(), data: "No zero confirmation channels accepted".to_owned(), } + match res { + Err(err) => { + mem::drop(peer_state_lock); + mem::drop(per_peer_state); + match handle_error!(self, Result::<(), MsgHandleErrInternal>::Err(err), *counterparty_node_id) { + Ok(_) => unreachable!("`handle_error` only returns Err as we've passed in an Err"), + Err(e) => { + return Err(APIError::ChannelUnavailable { err: e.err }); + }, } - }; - peer_state.pending_msg_events.push(send_msg_err_event); - let err_str = "Please use accept_inbound_channel_from_trusted_peer_0conf to accept channels with zero confirmations.".to_owned(); - log_error!(logger, "{}", err_str); + } + Ok(mut channel) => { + if accept_0conf { + // This should have been correctly configured by the call to InboundV1Channel::new. + debug_assert!(channel.context.minimum_depth().unwrap() == 0); + } else if channel.context.get_channel_type().requires_zero_conf() { + let send_msg_err_event = events::MessageSendEvent::HandleError { + node_id: channel.context.get_counterparty_node_id(), + action: msgs::ErrorAction::SendErrorMessage{ + msg: msgs::ErrorMessage { channel_id: temporary_channel_id.clone(), data: "No zero confirmation channels accepted".to_owned(), } + } + }; + peer_state.pending_msg_events.push(send_msg_err_event); + let err_str = "Please use accept_inbound_channel_from_trusted_peer_0conf to accept channels with zero confirmations.".to_owned(); + log_error!(logger, "{}", err_str); - return Err(APIError::APIMisuseError { err: err_str }); - } else { - // If this peer already has some channels, a new channel won't increase our number of peers - // with unfunded channels, so as long as we aren't over the maximum number of unfunded - // channels per-peer we can accept channels from a peer with existing ones. - if is_only_peer_channel && peers_without_funded_channels >= MAX_UNFUNDED_CHANNEL_PEERS { - let send_msg_err_event = events::MessageSendEvent::HandleError { - node_id: channel.context.get_counterparty_node_id(), - action: msgs::ErrorAction::SendErrorMessage{ - msg: msgs::ErrorMessage { channel_id: temporary_channel_id.clone(), data: "Have too many peers with unfunded channels, not accepting new ones".to_owned(), } + return Err(APIError::APIMisuseError { err: err_str }); + } else { + // If this peer already has some channels, a new channel won't increase our number of peers + // with unfunded channels, so as long as we aren't over the maximum number of unfunded + // channels per-peer we can accept channels from a peer with existing ones. + if is_only_peer_channel && peers_without_funded_channels >= MAX_UNFUNDED_CHANNEL_PEERS { + let send_msg_err_event = events::MessageSendEvent::HandleError { + node_id: channel.context.get_counterparty_node_id(), + action: msgs::ErrorAction::SendErrorMessage{ + msg: msgs::ErrorMessage { channel_id: temporary_channel_id.clone(), data: "Have too many peers with unfunded channels, not accepting new ones".to_owned(), } + } + }; + peer_state.pending_msg_events.push(send_msg_err_event); + let err_str = "Too many peers with unfunded channels, refusing to accept new ones".to_owned(); + log_error!(logger, "{}", err_str); + + return Err(APIError::APIMisuseError { err: err_str }); } - }; - peer_state.pending_msg_events.push(send_msg_err_event); - let err_str = "Too many peers with unfunded channels, refusing to accept new ones".to_owned(); - log_error!(logger, "{}", err_str); + } - return Err(APIError::APIMisuseError { err: err_str }); - } - } + // Now that we know we have a channel, assign an outbound SCID alias. + let outbound_scid_alias = self.create_and_insert_outbound_scid_alias(); + channel.context.set_outbound_scid_alias(outbound_scid_alias); - // Now that we know we have a channel, assign an outbound SCID alias. - let outbound_scid_alias = self.create_and_insert_outbound_scid_alias(); - channel.context.set_outbound_scid_alias(outbound_scid_alias); - - peer_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel { - node_id: channel.context.get_counterparty_node_id(), - msg: channel.accept_inbound_channel(), - }); + peer_state.pending_msg_events.push(events::MessageSendEvent::SendAcceptChannel { + node_id: channel.context.get_counterparty_node_id(), + msg: channel.accept_inbound_channel(), + }); - peer_state.channel_by_id.insert(temporary_channel_id.clone(), ChannelPhase::UnfundedInboundV1(channel)); + peer_state.channel_by_id.insert(temporary_channel_id.clone(), ChannelPhase::UnfundedInboundV1(channel)); - Ok(()) + Ok(()) + }, + } } /// Gets the number of peers which match the given filter and do not have any funded, outbound, @@ -6131,7 +6845,7 @@ where fn peers_without_funded_channels(&self, maybe_count_peer: Filter) -> usize where Filter: Fn(&PeerState) -> bool { let mut peers_without_funded_channels = 0; - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; { let peer_state_lock = self.per_peer_state.read().unwrap(); for (_, peer_mtx) in peer_state_lock.iter() { @@ -6166,9 +6880,25 @@ where num_unfunded_channels += 1; } }, + // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. + #[cfg(dual_funding)] + ChannelPhase::UnfundedInboundV2(chan) => { + // Only inbound V2 channels that are not 0conf and that we do not contribute to will be + // included in the unfunded count. + if chan.context.minimum_depth().unwrap_or(1) != 0 && + chan.dual_funding_context.our_funding_satoshis == 0 { + num_unfunded_channels += 1; + } + }, ChannelPhase::UnfundedOutboundV1(_) => { // Outbound channels don't contribute to the unfunded count in the DoS context. continue; + }, + // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. + #[cfg(dual_funding)] + ChannelPhase::UnfundedOutboundV2(_) => { + // Outbound channels don't contribute to the unfunded count in the DoS context. + continue; } } } @@ -6178,12 +6908,14 @@ where fn internal_open_channel(&self, counterparty_node_id: &PublicKey, msg: &msgs::OpenChannel) -> Result<(), MsgHandleErrInternal> { // Note that the ChannelManager is NOT re-persisted on disk after this, so any changes are // likely to be lost on restart! - if msg.chain_hash != self.chain_hash { - return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash".to_owned(), msg.temporary_channel_id.clone())); + if msg.common_fields.chain_hash != self.chain_hash { + return Err(MsgHandleErrInternal::send_err_msg_no_close("Unknown genesis block hash".to_owned(), + msg.common_fields.temporary_channel_id.clone())); } if !self.default_configuration.accept_inbound_channels { - return Err(MsgHandleErrInternal::send_err_msg_no_close("No inbound channels accepted".to_owned(), msg.temporary_channel_id.clone())); + return Err(MsgHandleErrInternal::send_err_msg_no_close("No inbound channels accepted".to_owned(), + msg.common_fields.temporary_channel_id.clone())); } // Get the number of peers with channels, but without funded ones. We don't care too much @@ -6196,7 +6928,9 @@ where let peer_state_mutex = per_peer_state.get(counterparty_node_id) .ok_or_else(|| { debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id.clone()) + MsgHandleErrInternal::send_err_msg_no_close( + format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), + msg.common_fields.temporary_channel_id.clone()) })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -6210,34 +6944,36 @@ where { return Err(MsgHandleErrInternal::send_err_msg_no_close( "Have too many peers with unfunded channels, not accepting new ones".to_owned(), - msg.temporary_channel_id.clone())); + msg.common_fields.temporary_channel_id.clone())); } - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; if Self::unfunded_channel_count(peer_state, best_block_height) >= MAX_UNFUNDED_CHANS_PER_PEER { return Err(MsgHandleErrInternal::send_err_msg_no_close( format!("Refusing more than {} unfunded channels.", MAX_UNFUNDED_CHANS_PER_PEER), - msg.temporary_channel_id.clone())); + msg.common_fields.temporary_channel_id.clone())); } - let channel_id = msg.temporary_channel_id; + let channel_id = msg.common_fields.temporary_channel_id; let channel_exists = peer_state.has_channel(&channel_id); if channel_exists { - return Err(MsgHandleErrInternal::send_err_msg_no_close("temporary_channel_id collision for the same peer!".to_owned(), msg.temporary_channel_id.clone())); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "temporary_channel_id collision for the same peer!".to_owned(), + msg.common_fields.temporary_channel_id.clone())); } // If we're doing manual acceptance checks on the channel, then defer creation until we're sure we want to accept. if self.default_configuration.manually_accept_inbound_channels { let channel_type = channel::channel_type_from_open_channel( - &msg, &peer_state.latest_features, &self.channel_type_features() + &msg.common_fields, &peer_state.latest_features, &self.channel_type_features() ).map_err(|e| - MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id) + MsgHandleErrInternal::from_chan_no_close(e, msg.common_fields.temporary_channel_id) )?; let mut pending_events = self.pending_events.lock().unwrap(); pending_events.push_back((events::Event::OpenChannelRequest { - temporary_channel_id: msg.temporary_channel_id.clone(), + temporary_channel_id: msg.common_fields.temporary_channel_id.clone(), counterparty_node_id: counterparty_node_id.clone(), - funding_satoshis: msg.funding_satoshis, + funding_satoshis: msg.common_fields.funding_satoshis, push_msat: msg.push_msat, channel_type, }, None)); @@ -6257,17 +6993,21 @@ where &self.default_configuration, best_block_height, &self.logger, /*is_0conf=*/false) { Err(e) => { - return Err(MsgHandleErrInternal::from_chan_no_close(e, msg.temporary_channel_id)); + return Err(MsgHandleErrInternal::from_chan_no_close(e, msg.common_fields.temporary_channel_id)); }, Ok(res) => res }; let channel_type = channel.context.get_channel_type(); if channel_type.requires_zero_conf() { - return Err(MsgHandleErrInternal::send_err_msg_no_close("No zero confirmation channels accepted".to_owned(), msg.temporary_channel_id.clone())); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "No zero confirmation channels accepted".to_owned(), + msg.common_fields.temporary_channel_id.clone())); } if channel_type.requires_anchors_zero_fee_htlc_tx() { - return Err(MsgHandleErrInternal::send_err_msg_no_close("No channels with anchor outputs accepted".to_owned(), msg.temporary_channel_id.clone())); + return Err(MsgHandleErrInternal::send_err_msg_no_close( + "No channels with anchor outputs accepted".to_owned(), + msg.common_fields.temporary_channel_id.clone())); } let outbound_scid_alias = self.create_and_insert_outbound_scid_alias(); @@ -6289,11 +7029,11 @@ where let peer_state_mutex = per_peer_state.get(counterparty_node_id) .ok_or_else(|| { debug_assert!(false); - MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.temporary_channel_id) + MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.common_fields.temporary_channel_id) })?; let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; - match peer_state.channel_by_id.entry(msg.temporary_channel_id) { + match peer_state.channel_by_id.entry(msg.common_fields.temporary_channel_id) { hash_map::Entry::Occupied(mut phase) => { match phase.get_mut() { ChannelPhase::UnfundedOutboundV1(chan) => { @@ -6301,16 +7041,16 @@ where (chan.context.get_value_satoshis(), chan.context.get_funding_redeemscript().to_v0_p2wsh(), chan.context.get_user_id()) }, _ => { - return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got an unexpected accept_channel message from peer with counterparty_node_id {}", counterparty_node_id), msg.temporary_channel_id)); + return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got an unexpected accept_channel message from peer with counterparty_node_id {}", counterparty_node_id), msg.common_fields.temporary_channel_id)); } } }, - hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.temporary_channel_id)) + hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.common_fields.temporary_channel_id)) } }; let mut pending_events = self.pending_events.lock().unwrap(); pending_events.push_back((events::Event::FundingGenerationReady { - temporary_channel_id: msg.temporary_channel_id, + temporary_channel_id: msg.common_fields.temporary_channel_id, counterparty_node_id: *counterparty_node_id, channel_value_satoshis: value, output_script, @@ -6570,7 +7310,7 @@ where } // Update the monitor with the shutdown script if necessary. if let Some(monitor_update) = monitor_update_opt { - handle_new_monitor_update!(self, funding_txo_opt.unwrap(), chan.context.channel_id(), monitor_update, + handle_new_monitor_update!(self, funding_txo_opt.unwrap(), monitor_update, peer_state_lock, peer_state, per_peer_state, chan); } }, @@ -6581,6 +7321,14 @@ where let mut chan = remove_channel_phase!(self, chan_phase_entry); finish_shutdown = Some(chan.context_mut().force_shutdown(false, ClosureReason::CounterpartyCoopClosedUnfundedChannel)); }, + // TODO(dual_funding): Combine this match arm with above. + #[cfg(dual_funding)] + ChannelPhase::UnfundedInboundV2(_) | ChannelPhase::UnfundedOutboundV2(_) => { + let context = phase.context_mut(); + log_error!(self.logger, "Immediately closing unfunded channel {} as peer asked to cooperatively shut it down (which is unnecessary)", &msg.channel_id); + let mut chan = remove_channel_phase!(self, chan_phase_entry); + finish_shutdown = Some(chan.context_mut().force_shutdown(false, ClosureReason::CounterpartyCoopClosedUnfundedChannel)); + }, } } else { return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id)) @@ -6739,7 +7487,8 @@ where fn internal_update_fulfill_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> { let funding_txo; - let (htlc_source, forwarded_htlc_value) = { + let next_user_channel_id; + let (htlc_source, forwarded_htlc_value, skimmed_fee_msat) = { let per_peer_state = self.per_peer_state.read().unwrap(); let peer_state_mutex = per_peer_state.get(counterparty_node_id) .ok_or_else(|| { @@ -6768,6 +7517,7 @@ where // outbound HTLC is claimed. This is guaranteed to all complete before we // process the RAA as messages are processed from single peers serially. funding_txo = chan.context.get_funding_txo().expect("We won't accept a fulfill until funded"); + next_user_channel_id = chan.context.get_user_id(); res } else { return try_chan_phase_entry!(self, Err(ChannelError::Close( @@ -6777,8 +7527,11 @@ where hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!("Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}", counterparty_node_id), msg.channel_id)) } }; - self.claim_funds_internal(htlc_source, msg.payment_preimage.clone(), Some(forwarded_htlc_value), - false, false, Some(*counterparty_node_id), funding_txo, msg.channel_id); + self.claim_funds_internal(htlc_source, msg.payment_preimage.clone(), + Some(forwarded_htlc_value), skimmed_fee_msat, false, false, Some(*counterparty_node_id), + funding_txo, msg.channel_id, Some(next_user_channel_id), + ); + Ok(()) } @@ -6852,7 +7605,7 @@ where let funding_txo = chan.context.get_funding_txo(); let monitor_update_opt = try_chan_phase_entry!(self, chan.commitment_signed(&msg, &&logger), chan_phase_entry); if let Some(monitor_update) = monitor_update_opt { - handle_new_monitor_update!(self, funding_txo.unwrap(), chan.context.channel_id(), monitor_update, peer_state_lock, + handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock, peer_state, per_peer_state, chan); } Ok(()) @@ -7031,7 +7784,7 @@ where if let Some(monitor_update) = monitor_update_opt { let funding_txo = funding_txo_opt .expect("Funding outpoint must have been set for RAA handling to succeed"); - handle_new_monitor_update!(self, funding_txo, chan.context.channel_id(), monitor_update, + handle_new_monitor_update!(self, funding_txo, monitor_update, peer_state_lock, peer_state, per_peer_state, chan); } htlcs_to_fail @@ -7089,7 +7842,7 @@ where peer_state.pending_msg_events.push(events::MessageSendEvent::BroadcastChannelAnnouncement { msg: try_chan_phase_entry!(self, chan.announcement_signatures( - &self.node_signer, self.chain_hash, self.best_block.read().unwrap().height(), + &self.node_signer, self.chain_hash, self.best_block.read().unwrap().height, msg, &self.default_configuration ), chan_phase_entry), // Note that announcement_signatures fails if the channel cannot be announced, @@ -7276,7 +8029,9 @@ where let logger = WithContext::from(&self.logger, counterparty_node_id, Some(channel_id)); if let Some(preimage) = htlc_update.payment_preimage { log_trace!(logger, "Claiming HTLC with preimage {} from our monitor", preimage); - self.claim_funds_internal(htlc_update.source, preimage, htlc_update.htlc_value_satoshis.map(|v| v * 1000), true, false, counterparty_node_id, funding_outpoint, channel_id); + self.claim_funds_internal(htlc_update.source, preimage, + htlc_update.htlc_value_satoshis.map(|v| v * 1000), None, true, + false, counterparty_node_id, funding_outpoint, channel_id, None); } else { log_trace!(logger, "Failing HTLC with hash {} from our monitor", &htlc_update.payment_hash); let receiver = HTLCDestination::NextHopChannel { node_id: counterparty_node_id, channel_id }; @@ -7284,7 +8039,7 @@ where self.fail_htlc_backwards_internal(&htlc_update.source, &htlc_update.payment_hash, &reason, receiver); } }, - MonitorEvent::HolderForceClosed(_funding_outpoint) => { + MonitorEvent::HolderForceClosed(_) | MonitorEvent::HolderForceClosedWithInfo { .. } => { let counterparty_node_id_opt = match counterparty_node_id { Some(cp_id) => Some(cp_id), None => { @@ -7302,7 +8057,12 @@ where let pending_msg_events = &mut peer_state.pending_msg_events; if let hash_map::Entry::Occupied(chan_phase_entry) = peer_state.channel_by_id.entry(channel_id) { if let ChannelPhase::Funded(mut chan) = remove_channel_phase!(self, chan_phase_entry) { - failed_channels.push(chan.context.force_shutdown(false, ClosureReason::HolderForceClosed)); + let reason = if let MonitorEvent::HolderForceClosedWithInfo { reason, .. } = monitor_event { + reason + } else { + ClosureReason::HolderForceClosed + }; + failed_channels.push(chan.context.force_shutdown(false, reason.clone())); if let Ok(update) = self.get_channel_update_for_broadcast(&chan) { pending_msg_events.push(events::MessageSendEvent::BroadcastChannelUpdate { msg: update @@ -7311,7 +8071,7 @@ where pending_msg_events.push(events::MessageSendEvent::HandleError { node_id: chan.context.get_counterparty_node_id(), action: msgs::ErrorAction::DisconnectPeer { - msg: Some(msgs::ErrorMessage { channel_id: chan.context.channel_id(), data: "Channel force-closed".to_owned() }) + msg: Some(msgs::ErrorMessage { channel_id: chan.context.channel_id(), data: reason.to_string() }) }, }); } @@ -7372,7 +8132,7 @@ where if let Some(monitor_update) = monitor_opt { has_monitor_update = true; - handle_new_monitor_update!(self, funding_txo.unwrap(), chan.context.channel_id(), monitor_update, + handle_new_monitor_update!(self, funding_txo.unwrap(), monitor_update, peer_state_lock, peer_state, per_peer_state, chan); continue 'peer_loop; } @@ -7550,7 +8310,9 @@ where self.finish_close_channel(failure); } } +} +macro_rules! create_offer_builder { ($self: ident, $builder: ty) => { /// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the /// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer will /// not have an expiration unless otherwise set on the builder. @@ -7579,23 +8341,25 @@ where /// [`Offer`]: crate::offers::offer::Offer /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest pub fn create_offer_builder( - &self, description: String - ) -> Result, Bolt12SemanticError> { - let node_id = self.get_our_node_id(); - let expanded_key = &self.inbound_payment_key; - let entropy = &*self.entropy_source; - let secp_ctx = &self.secp_ctx; - - let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; + &$self, description: String + ) -> Result<$builder, Bolt12SemanticError> { + let node_id = $self.get_our_node_id(); + let expanded_key = &$self.inbound_payment_key; + let entropy = &*$self.entropy_source; + let secp_ctx = &$self.secp_ctx; + + let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; let builder = OfferBuilder::deriving_signing_pubkey( description, node_id, expanded_key, entropy, secp_ctx ) - .chain_hash(self.chain_hash) + .chain_hash($self.chain_hash) .path(path); - Ok(builder) + Ok(builder.into()) } +} } +macro_rules! create_refund_builder { ($self: ident, $builder: ty) => { /// Creates a [`RefundBuilder`] such that the [`Refund`] it builds is recognized by the /// [`ChannelManager`] when handling [`Bolt12Invoice`] messages for the refund. /// @@ -7645,31 +8409,55 @@ where /// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths /// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments pub fn create_refund_builder( - &self, description: String, amount_msats: u64, absolute_expiry: Duration, + &$self, description: String, amount_msats: u64, absolute_expiry: Duration, payment_id: PaymentId, retry_strategy: Retry, max_total_routing_fee_msat: Option - ) -> Result, Bolt12SemanticError> { - let node_id = self.get_our_node_id(); - let expanded_key = &self.inbound_payment_key; - let entropy = &*self.entropy_source; - let secp_ctx = &self.secp_ctx; + ) -> Result<$builder, Bolt12SemanticError> { + let node_id = $self.get_our_node_id(); + let expanded_key = &$self.inbound_payment_key; + let entropy = &*$self.entropy_source; + let secp_ctx = &$self.secp_ctx; - let path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; + let path = $self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; let builder = RefundBuilder::deriving_payer_id( description, node_id, expanded_key, entropy, secp_ctx, amount_msats, payment_id )? - .chain_hash(self.chain_hash) + .chain_hash($self.chain_hash) .absolute_expiry(absolute_expiry) .path(path); + let _persistence_guard = PersistenceNotifierGuard::notify_on_drop($self); + let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry); - self.pending_outbound_payments + $self.pending_outbound_payments .add_new_awaiting_invoice( payment_id, expiration, retry_strategy, max_total_routing_fee_msat, ) .map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?; - Ok(builder) + Ok(builder.into()) } +} } + +impl ChannelManager +where + M::Target: chain::Watch<::EcdsaSigner>, + T::Target: BroadcasterInterface, + ES::Target: EntropySource, + NS::Target: NodeSigner, + SP::Target: SignerProvider, + F::Target: FeeEstimator, + R::Target: Router, + L::Target: Logger, +{ + #[cfg(not(c_bindings))] + create_offer_builder!(self, OfferBuilder); + #[cfg(not(c_bindings))] + create_refund_builder!(self, RefundBuilder); + + #[cfg(c_bindings)] + create_offer_builder!(self, OfferWithDerivedMetadataBuilder); + #[cfg(c_bindings)] + create_refund_builder!(self, RefundMaybeWithDerivedMetadataBuilder); /// Pays for an [`Offer`] using the given parameters by creating an [`InvoiceRequest`] and /// enqueuing it to be sent via an onion message. [`ChannelManager`] will pay the actual @@ -7714,6 +8502,7 @@ where /// Errors if: /// - a duplicate `payment_id` is provided given the caveats in the aforementioned link, /// - the provided parameters are invalid for the offer, + /// - the offer is for an unsupported chain, or /// - the parameterized [`Router`] is unable to create a blinded reply path for the invoice /// request. /// @@ -7733,9 +8522,11 @@ where let entropy = &*self.entropy_source; let secp_ctx = &self.secp_ctx; - let builder = offer + let builder: InvoiceRequestBuilder = offer .request_invoice_deriving_payer_id(expanded_key, entropy, secp_ctx, payment_id)? - .chain_hash(self.chain_hash)?; + .into(); + let builder = builder.chain_hash(self.chain_hash)?; + let builder = match quantity { None => builder, Some(quantity) => builder.quantity(quantity)?, @@ -7751,6 +8542,8 @@ where let invoice_request = builder.build_and_sign()?; let reply_path = self.create_blinded_path().map_err(|_| Bolt12SemanticError::MissingPaths)?; + let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); + let expiration = StaleExpiration::TimerTicks(1); self.pending_outbound_payments .add_new_awaiting_invoice( @@ -7800,8 +8593,10 @@ where /// /// # Errors /// - /// Errors if the parameterized [`Router`] is unable to create a blinded payment path or reply - /// path for the invoice. + /// Errors if: + /// - the refund is for an unsupported chain, or + /// - the parameterized [`Router`] is unable to create a blinded payment path or reply path for + /// the invoice. /// /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice pub fn request_refund_payment(&self, refund: &Refund) -> Result<(), Bolt12SemanticError> { @@ -7812,6 +8607,12 @@ where let amount_msats = refund.amount_msats(); let relative_expiry = DEFAULT_RELATIVE_EXPIRY.as_secs() as u32; + if refund.chain() != self.chain_hash { + return Err(Bolt12SemanticError::UnsupportedChain); + } + + let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); + match self.create_inbound_payment(Some(amount_msats), relative_expiry, None) { Ok((payment_hash, payment_secret)) => { let payment_paths = self.create_blinded_payment_paths(amount_msats, payment_secret) @@ -7829,6 +8630,7 @@ where let builder = refund.respond_using_derived_keys_no_std( payment_paths, payment_hash, created_at, expanded_key, entropy )?; + let builder: InvoiceBuilder = builder.into(); let invoice = builder.allow_mpp().build_and_sign(secp_ctx)?; let reply_path = self.create_blinded_path() .map_err(|_| Bolt12SemanticError::MissingPaths)?; @@ -7963,7 +8765,6 @@ where /// Errors if the `MessageRouter` errors or returns an empty `Vec`. fn create_blinded_path(&self) -> Result { let recipient = self.get_our_node_id(); - let entropy_source = self.entropy_source.deref(); let secp_ctx = &self.secp_ctx; let peers = self.per_peer_state.read().unwrap() @@ -7973,7 +8774,7 @@ where .collect::>(); self.router - .create_blinded_paths(recipient, peers, entropy_source, secp_ctx) + .create_blinded_paths(recipient, peers, secp_ctx) .and_then(|paths| paths.into_iter().next().ok_or(())) } @@ -7982,12 +8783,11 @@ where fn create_blinded_payment_paths( &self, amount_msats: u64, payment_secret: PaymentSecret ) -> Result, ()> { - let entropy_source = self.entropy_source.deref(); let secp_ctx = &self.secp_ctx; let first_hops = self.list_usable_channels(); let payee_node_id = self.get_our_node_id(); - let max_cltv_expiry = self.best_block.read().unwrap().height() + CLTV_FAR_FAR_AWAY + let max_cltv_expiry = self.best_block.read().unwrap().height + CLTV_FAR_FAR_AWAY + LATENCY_GRACE_PERIOD_BLOCKS; let payee_tlvs = ReceiveTlvs { payment_secret, @@ -7997,7 +8797,7 @@ where }, }; self.router.create_blinded_payment_paths( - payee_node_id, first_hops, payee_tlvs, amount_msats, entropy_source, secp_ctx + payee_node_id, first_hops, payee_tlvs, amount_msats, secp_ctx ) } @@ -8006,7 +8806,7 @@ where /// /// [phantom node payments]: crate::sign::PhantomKeysManager pub fn get_phantom_scid(&self) -> u64 { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let short_to_chan_info = self.short_to_chan_info.read().unwrap(); loop { let scid_candidate = fake_scid::Namespace::Phantom.get_fake_scid(best_block_height, &self.chain_hash, &self.fake_scid_rand_bytes, &self.entropy_source); @@ -8036,7 +8836,7 @@ where /// Note that this method is not guaranteed to return unique values, you may need to call it a few /// times to get a unique scid. pub fn get_intercept_scid(&self) -> u64 { - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; let short_to_chan_info = self.short_to_chan_info.read().unwrap(); loop { let scid_candidate = fake_scid::Namespace::Intercept.get_fake_scid(best_block_height, &self.chain_hash, &self.fake_scid_rand_bytes, &self.entropy_source); @@ -8141,7 +8941,7 @@ where if let Some((monitor_update, further_update_exists)) = chan.unblock_next_blocked_monitor_update() { log_debug!(logger, "Unlocking monitor updating for channel {} and updating monitor", channel_id); - handle_new_monitor_update!(self, channel_funding_outpoint, channel_id, monitor_update, + handle_new_monitor_update!(self, channel_funding_outpoint, monitor_update, peer_state_lck, peer_state, per_peer_state, chan); if further_update_exists { // If there are more `ChannelMonitorUpdate`s to process, restart at the @@ -8284,9 +9084,9 @@ where fn filtered_block_connected(&self, header: &Header, txdata: &TransactionData, height: u32) { { let best_block = self.best_block.read().unwrap(); - assert_eq!(best_block.block_hash(), header.prev_blockhash, + assert_eq!(best_block.block_hash, header.prev_blockhash, "Blocks must be connected in chain-order - the connected header must build on the last connected header"); - assert_eq!(best_block.height(), height - 1, + assert_eq!(best_block.height, height - 1, "Blocks must be connected in chain-order - the connected block height must be one greater than the previous height"); } @@ -8301,9 +9101,9 @@ where let new_height = height - 1; { let mut best_block = self.best_block.write().unwrap(); - assert_eq!(best_block.block_hash(), header.block_hash(), + assert_eq!(best_block.block_hash, header.block_hash(), "Blocks must be disconnected in chain-order - the disconnected header must be the last connected header"); - assert_eq!(best_block.height(), height, + assert_eq!(best_block.height, height, "Blocks must be disconnected in chain-order - the disconnected block must have the correct height"); *best_block = BestBlock::new(header.prev_blockhash, new_height) } @@ -8337,7 +9137,7 @@ where self.do_chain_event(Some(height), |channel| channel.transactions_confirmed(&block_hash, height, txdata, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context)) .map(|(a, b)| (a, Vec::new(), b))); - let last_best_block_height = self.best_block.read().unwrap().height(); + let last_best_block_height = self.best_block.read().unwrap().height; if height < last_best_block_height { let timestamp = self.highest_seen_timestamp.load(Ordering::Acquire); self.do_chain_event(Some(last_best_block_height), |channel| channel.best_block_updated(last_best_block_height, timestamp as u32, self.chain_hash, &self.node_signer, &self.default_configuration, &&WithChannelContext::from(&self.logger, &channel.context))); @@ -8445,6 +9245,9 @@ where match phase { // Retain unfunded channels. ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => true, + // TODO(dual_funding): Combine this match arm with above. + #[cfg(dual_funding)] + ChannelPhase::UnfundedOutboundV2(_) | ChannelPhase::UnfundedInboundV2(_) => true, ChannelPhase::Funded(channel) => { let res = f(channel); if let Ok((channel_ready_opt, mut timed_out_pending_htlcs, announcement_sigs)) = res { @@ -8605,6 +9408,9 @@ where } /// Returns true if this [`ChannelManager`] needs to be persisted. + /// + /// See [`Self::get_event_or_persistence_needed_future`] for retrieving a [`Future`] that + /// indicates this should be checked. pub fn get_and_clear_needs_persistence(&self) -> bool { self.needs_persist_flag.swap(false, Ordering::AcqRel) } @@ -8694,7 +9500,7 @@ where fn handle_open_channel_v2(&self, counterparty_node_id: &PublicKey, msg: &msgs::OpenChannelV2) { let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( "Dual-funded channels not supported".to_owned(), - msg.temporary_channel_id.clone())), *counterparty_node_id); + msg.common_fields.temporary_channel_id.clone())), *counterparty_node_id); } fn handle_accept_channel(&self, counterparty_node_id: &PublicKey, msg: &msgs::AcceptChannel) { @@ -8710,7 +9516,7 @@ where fn handle_accept_channel_v2(&self, counterparty_node_id: &PublicKey, msg: &msgs::AcceptChannelV2) { let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close( "Dual-funded channels not supported".to_owned(), - msg.temporary_channel_id.clone())), *counterparty_node_id); + msg.common_fields.temporary_channel_id.clone())), *counterparty_node_id); } fn handle_funding_created(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingCreated) { @@ -8905,13 +9711,23 @@ where } &mut chan.context }, - // Unfunded channels will always be removed. - ChannelPhase::UnfundedOutboundV1(chan) => { - &mut chan.context + // We retain UnfundedOutboundV1 channel for some time in case + // peer unexpectedly disconnects, and intends to reconnect again. + ChannelPhase::UnfundedOutboundV1(_) => { + return true; }, + // Unfunded inbound channels will always be removed. ChannelPhase::UnfundedInboundV1(chan) => { &mut chan.context }, + #[cfg(dual_funding)] + ChannelPhase::UnfundedOutboundV2(chan) => { + &mut chan.context + }, + #[cfg(dual_funding)] + ChannelPhase::UnfundedInboundV2(chan) => { + &mut chan.context + }, }; // Clean up for removal. update_maps_on_chan_removal!(self, &context); @@ -9010,8 +9826,8 @@ where return NotifyOption::SkipPersistNoEvents; } e.insert(Mutex::new(PeerState { - channel_by_id: HashMap::new(), - inbound_channel_request_by_id: HashMap::new(), + channel_by_id: new_hash_map(), + inbound_channel_request_by_id: new_hash_map(), latest_features: init_msg.features.clone(), pending_msg_events: Vec::new(), in_flight_monitor_updates: BTreeMap::new(), @@ -9024,7 +9840,7 @@ where let mut peer_state = e.get().lock().unwrap(); peer_state.latest_features = init_msg.features.clone(); - let best_block_height = self.best_block.read().unwrap().height(); + let best_block_height = self.best_block.read().unwrap().height; if inbound_peer_limited && Self::unfunded_channel_count(&*peer_state, best_block_height) == peer_state.channel_by_id.len() @@ -9047,15 +9863,49 @@ where let peer_state = &mut *peer_state_lock; let pending_msg_events = &mut peer_state.pending_msg_events; - peer_state.channel_by_id.iter_mut().filter_map(|(_, phase)| - if let ChannelPhase::Funded(chan) = phase { Some(chan) } else { None } - ).for_each(|chan| { - let logger = WithChannelContext::from(&self.logger, &chan.context); - pending_msg_events.push(events::MessageSendEvent::SendChannelReestablish { - node_id: chan.context.get_counterparty_node_id(), - msg: chan.get_channel_reestablish(&&logger), - }); - }); + for (_, phase) in peer_state.channel_by_id.iter_mut() { + match phase { + ChannelPhase::Funded(chan) => { + let logger = WithChannelContext::from(&self.logger, &chan.context); + pending_msg_events.push(events::MessageSendEvent::SendChannelReestablish { + node_id: chan.context.get_counterparty_node_id(), + msg: chan.get_channel_reestablish(&&logger), + }); + } + + ChannelPhase::UnfundedOutboundV1(chan) => { + pending_msg_events.push(events::MessageSendEvent::SendOpenChannel { + node_id: chan.context.get_counterparty_node_id(), + msg: chan.get_open_channel(self.chain_hash), + }); + } + + // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. + #[cfg(dual_funding)] + ChannelPhase::UnfundedOutboundV2(chan) => { + pending_msg_events.push(events::MessageSendEvent::SendOpenChannelV2 { + node_id: chan.context.get_counterparty_node_id(), + msg: chan.get_open_channel_v2(self.chain_hash), + }); + }, + + ChannelPhase::UnfundedInboundV1(_) => { + // Since unfunded inbound channel maps are cleared upon disconnecting a peer, + // they are not persisted and won't be recovered after a crash. + // Therefore, they shouldn't exist at this point. + debug_assert!(false); + } + + // TODO(dual_funding): Combine this match arm with above once #[cfg(dual_funding)] is removed. + #[cfg(dual_funding)] + ChannelPhase::UnfundedInboundV2(channel) => { + // Since unfunded inbound channel maps are cleared upon disconnecting a peer, + // they are not persisted and won't be recovered after a crash. + // Therefore, they shouldn't exist at this point. + debug_assert!(false); + }, + } + } } return NotifyOption::SkipPersistHandleEvents; @@ -9065,8 +9915,6 @@ where } fn handle_error(&self, counterparty_node_id: &PublicKey, msg: &msgs::ErrorMessage) { - let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); - match &msg.data as &str { "cannot co-op close channel w/ active htlcs"| "link failed to shutdown" => @@ -9079,34 +9927,45 @@ where // We're not going to bother handling this in a sensible way, instead simply // repeating the Shutdown message on repeat until morale improves. if !msg.channel_id.is_zero() { - let per_peer_state = self.per_peer_state.read().unwrap(); - let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id); - if peer_state_mutex_opt.is_none() { return; } - let mut peer_state = peer_state_mutex_opt.unwrap().lock().unwrap(); - if let Some(ChannelPhase::Funded(chan)) = peer_state.channel_by_id.get(&msg.channel_id) { - if let Some(msg) = chan.get_outbound_shutdown() { - peer_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown { - node_id: *counterparty_node_id, - msg, - }); - } - peer_state.pending_msg_events.push(events::MessageSendEvent::HandleError { - node_id: *counterparty_node_id, - action: msgs::ErrorAction::SendWarningMessage { - msg: msgs::WarningMessage { - channel_id: msg.channel_id, - data: "You appear to be exhibiting LND bug 6039, we'll keep sending you shutdown messages until you handle them correctly".to_owned() - }, - log_level: Level::Trace, + PersistenceNotifierGuard::optionally_notify( + self, + || -> NotifyOption { + let per_peer_state = self.per_peer_state.read().unwrap(); + let peer_state_mutex_opt = per_peer_state.get(counterparty_node_id); + if peer_state_mutex_opt.is_none() { return NotifyOption::SkipPersistNoEvents; } + let mut peer_state = peer_state_mutex_opt.unwrap().lock().unwrap(); + if let Some(ChannelPhase::Funded(chan)) = peer_state.channel_by_id.get(&msg.channel_id) { + if let Some(msg) = chan.get_outbound_shutdown() { + peer_state.pending_msg_events.push(events::MessageSendEvent::SendShutdown { + node_id: *counterparty_node_id, + msg, + }); + } + peer_state.pending_msg_events.push(events::MessageSendEvent::HandleError { + node_id: *counterparty_node_id, + action: msgs::ErrorAction::SendWarningMessage { + msg: msgs::WarningMessage { + channel_id: msg.channel_id, + data: "You appear to be exhibiting LND bug 6039, we'll keep sending you shutdown messages until you handle them correctly".to_owned() + }, + log_level: Level::Trace, + } + }); + // This can happen in a fairly tight loop, so we absolutely cannot trigger + // a `ChannelManager` write here. + return NotifyOption::SkipPersistHandleEvents; } - }); - } + NotifyOption::SkipPersistNoEvents + } + ); } return; } _ => {} } + let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); + if msg.channel_id.is_zero() { let channel_ids: Vec = { let per_peer_state = self.per_peer_state.read().unwrap(); @@ -9131,14 +9990,29 @@ where if peer_state_mutex_opt.is_none() { return; } let mut peer_state_lock = peer_state_mutex_opt.unwrap().lock().unwrap(); let peer_state = &mut *peer_state_lock; - if let Some(ChannelPhase::UnfundedOutboundV1(chan)) = peer_state.channel_by_id.get_mut(&msg.channel_id) { - if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) { - peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel { - node_id: *counterparty_node_id, - msg, - }); - return; - } + match peer_state.channel_by_id.get_mut(&msg.channel_id) { + Some(ChannelPhase::UnfundedOutboundV1(ref mut chan)) => { + if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) { + peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannel { + node_id: *counterparty_node_id, + msg, + }); + return; + } + }, + #[cfg(dual_funding)] + Some(ChannelPhase::UnfundedOutboundV2(ref mut chan)) => { + if let Ok(msg) = chan.maybe_handle_error_without_close(self.chain_hash, &self.fee_estimator) { + peer_state.pending_msg_events.push(events::MessageSendEvent::SendOpenChannelV2 { + node_id: *counterparty_node_id, + msg, + }); + return; + } + }, + None | Some(ChannelPhase::UnfundedInboundV1(_) | ChannelPhase::Funded(_)) => (), + #[cfg(dual_funding)] + Some(ChannelPhase::UnfundedInboundV2(_)) => (), } } @@ -9281,6 +10155,8 @@ where let builder = invoice_request.respond_using_derived_keys_no_std( payment_paths, payment_hash, created_at ); + let builder: Result, _> = + builder.map(|b| b.into()); match builder.and_then(|b| b.allow_mpp().build_and_sign(secp_ctx)) { Ok(invoice) => Some(OffersMessage::Invoice(invoice)), Err(error) => Some(OffersMessage::InvoiceError(error.into())), @@ -9292,18 +10168,25 @@ where let builder = invoice_request.respond_with_no_std( payment_paths, payment_hash, created_at ); + let builder: Result, _> = + builder.map(|b| b.into()); let response = builder.and_then(|builder| builder.allow_mpp().build()) .map_err(|e| OffersMessage::InvoiceError(e.into())) - .and_then(|invoice| - match invoice.sign(|invoice| self.node_signer.sign_bolt12_invoice(invoice)) { + .and_then(|invoice| { + #[cfg(c_bindings)] + let mut invoice = invoice; + match invoice.sign(|invoice: &UnsignedBolt12Invoice| + self.node_signer.sign_bolt12_invoice(invoice) + ) { Ok(invoice) => Ok(OffersMessage::Invoice(invoice)), - Err(SignError::Signing(())) => Err(OffersMessage::InvoiceError( + Err(SignError::Signing) => Err(OffersMessage::InvoiceError( InvoiceError::from_string("Failed signing invoice".to_string()) )), Err(SignError::Verification(_)) => Err(OffersMessage::InvoiceError( InvoiceError::from_string("Failed invoice signature verification".to_string()) )), - }); + } + }); match response { Ok(invoice) => Some(invoice), Err(error) => Some(error), @@ -9454,6 +10337,8 @@ impl Writeable for ChannelDetails { (37, user_channel_id_high_opt, option), (39, self.feerate_sat_per_1000_weight, option), (41, self.channel_shutdown_state, option), + (43, self.pending_inbound_htlcs, optional_vec), + (45, self.pending_outbound_htlcs, optional_vec), }); Ok(()) } @@ -9492,6 +10377,8 @@ impl Readable for ChannelDetails { (37, user_channel_id_high_opt, option), (39, feerate_sat_per_1000_weight, option), (41, channel_shutdown_state, option), + (43, pending_inbound_htlcs, optional_vec), + (45, pending_outbound_htlcs, optional_vec), }); // `user_channel_id` used to be a single u64 value. In order to remain backwards compatible with @@ -9528,6 +10415,8 @@ impl Readable for ChannelDetails { inbound_htlc_maximum_msat, feerate_sat_per_1000_weight, channel_shutdown_state, + pending_inbound_htlcs: pending_inbound_htlcs.unwrap_or(Vec::new()), + pending_outbound_htlcs: pending_outbound_htlcs.unwrap_or(Vec::new()), }) } } @@ -9559,6 +10448,7 @@ impl_writeable_tlv_based_enum!(PendingHTLCRouting, }, (2, ReceiveKeysend) => { (0, payment_preimage, required), + (1, requires_blinded_error, (default_value, false)), (2, incoming_cltv_expiry, required), (3, payment_metadata, option), (4, payment_data, option), // Added in 0.0.116 @@ -9816,7 +10706,7 @@ impl_writeable_tlv_based!(PendingAddHTLCInfo, { (2, prev_short_channel_id, required), (4, prev_htlc_id, required), (6, prev_funding_outpoint, required), - // Note that by the time we get past the required read for type 2 above, prev_funding_outpoint will be + // Note that by the time we get past the required read for type 6 above, prev_funding_outpoint will be // filled in, so we can safely unwrap it here. (7, prev_channel_id, (default_value, ChannelId::v1_from_funding_outpoint(prev_funding_outpoint.0.unwrap()))), }); @@ -9911,8 +10801,8 @@ where self.chain_hash.write(writer)?; { let best_block = self.best_block.read().unwrap(); - best_block.height().write(writer)?; - best_block.block_hash().write(writer)?; + best_block.height.write(writer)?; + best_block.block_hash.write(writer)?; } let mut serializable_peer_count: u64 = 0; @@ -10062,7 +10952,7 @@ where } // Encode without retry info for 0.0.101 compatibility. - let mut pending_outbound_payments_no_retry: HashMap> = HashMap::new(); + let mut pending_outbound_payments_no_retry: HashMap> = new_hash_map(); for (id, outbound) in pending_outbound_payments.iter() { match outbound { PendingOutboundPayment::Legacy { session_privs } | @@ -10090,7 +10980,7 @@ where for ((counterparty_id, _), peer_state) in per_peer_state.iter().zip(peer_states.iter()) { for (funding_outpoint, updates) in peer_state.in_flight_monitor_updates.iter() { if !updates.is_empty() { - if in_flight_monitor_updates.is_none() { in_flight_monitor_updates = Some(HashMap::new()); } + if in_flight_monitor_updates.is_none() { in_flight_monitor_updates = Some(new_hash_map()); } in_flight_monitor_updates.as_mut().unwrap().insert((counterparty_id, funding_outpoint), updates); } } @@ -10279,7 +11169,9 @@ where mut channel_monitors: Vec<&'a mut ChannelMonitor<::EcdsaSigner>>) -> Self { Self { entropy_source, node_signer, signer_provider, fee_estimator, chain_monitor, tx_broadcaster, router, logger, default_config, - channel_monitors: channel_monitors.drain(..).map(|monitor| { (monitor.get_funding_txo().0, monitor) }).collect() + channel_monitors: hash_map_from_iter( + channel_monitors.drain(..).map(|monitor| { (monitor.get_funding_txo().0, monitor) }) + ), } } } @@ -10326,13 +11218,13 @@ where let mut failed_htlcs = Vec::new(); let channel_count: u64 = Readable::read(reader)?; - let mut funding_txo_set = HashSet::with_capacity(cmp::min(channel_count as usize, 128)); - let mut funded_peer_channels: HashMap>> = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); - let mut outpoint_to_peer = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); - let mut short_to_chan_info = HashMap::with_capacity(cmp::min(channel_count as usize, 128)); + let mut funding_txo_set = hash_set_with_capacity(cmp::min(channel_count as usize, 128)); + let mut funded_peer_channels: HashMap>> = hash_map_with_capacity(cmp::min(channel_count as usize, 128)); + let mut outpoint_to_peer = hash_map_with_capacity(cmp::min(channel_count as usize, 128)); + let mut short_to_chan_info = hash_map_with_capacity(cmp::min(channel_count as usize, 128)); let mut channel_closures = VecDeque::new(); let mut close_background_events = Vec::new(); - let mut funding_txo_to_channel_id = HashMap::with_capacity(channel_count as usize); + let mut funding_txo_to_channel_id = hash_map_with_capacity(channel_count as usize); for _ in 0..channel_count { let mut channel: Channel = Channel::read(reader, ( &args.entropy_source, &args.signer_provider, best_block_height, &provided_channel_type_features(&args.default_config) @@ -10418,7 +11310,7 @@ where by_id_map.insert(channel.context.channel_id(), ChannelPhase::Funded(channel)); }, hash_map::Entry::Vacant(entry) => { - let mut by_id_map = HashMap::new(); + let mut by_id_map = new_hash_map(); by_id_map.insert(channel.context.channel_id(), ChannelPhase::Funded(channel)); entry.insert(by_id_map); } @@ -10465,7 +11357,7 @@ where const MAX_ALLOC_SIZE: usize = 1024 * 64; let forward_htlcs_count: u64 = Readable::read(reader)?; - let mut forward_htlcs = HashMap::with_capacity(cmp::min(forward_htlcs_count as usize, 128)); + let mut forward_htlcs = hash_map_with_capacity(cmp::min(forward_htlcs_count as usize, 128)); for _ in 0..forward_htlcs_count { let short_channel_id = Readable::read(reader)?; let pending_forwards_count: u64 = Readable::read(reader)?; @@ -10491,7 +11383,7 @@ where let peer_state_from_chans = |channel_by_id| { PeerState { channel_by_id, - inbound_channel_request_by_id: HashMap::new(), + inbound_channel_request_by_id: new_hash_map(), latest_features: InitFeatures::empty(), pending_msg_events: Vec::new(), in_flight_monitor_updates: BTreeMap::new(), @@ -10502,10 +11394,10 @@ where }; let peer_count: u64 = Readable::read(reader)?; - let mut per_peer_state = HashMap::with_capacity(cmp::min(peer_count as usize, MAX_ALLOC_SIZE/mem::size_of::<(PublicKey, Mutex>)>())); + let mut per_peer_state = hash_map_with_capacity(cmp::min(peer_count as usize, MAX_ALLOC_SIZE/mem::size_of::<(PublicKey, Mutex>)>())); for _ in 0..peer_count { let peer_pubkey = Readable::read(reader)?; - let peer_chans = funded_peer_channels.remove(&peer_pubkey).unwrap_or(HashMap::new()); + let peer_chans = funded_peer_channels.remove(&peer_pubkey).unwrap_or(new_hash_map()); let mut peer_state = peer_state_from_chans(peer_chans); peer_state.latest_features = Readable::read(reader)?; per_peer_state.insert(peer_pubkey, Mutex::new(peer_state)); @@ -10539,7 +11431,7 @@ where let highest_seen_timestamp: u32 = Readable::read(reader)?; let pending_inbound_payment_count: u64 = Readable::read(reader)?; - let mut pending_inbound_payments: HashMap = HashMap::with_capacity(cmp::min(pending_inbound_payment_count as usize, MAX_ALLOC_SIZE/(3*32))); + let mut pending_inbound_payments: HashMap = hash_map_with_capacity(cmp::min(pending_inbound_payment_count as usize, MAX_ALLOC_SIZE/(3*32))); for _ in 0..pending_inbound_payment_count { if pending_inbound_payments.insert(Readable::read(reader)?, Readable::read(reader)?).is_some() { return Err(DecodeError::InvalidValue); @@ -10548,11 +11440,11 @@ where let pending_outbound_payments_count_compat: u64 = Readable::read(reader)?; let mut pending_outbound_payments_compat: HashMap = - HashMap::with_capacity(cmp::min(pending_outbound_payments_count_compat as usize, MAX_ALLOC_SIZE/32)); + hash_map_with_capacity(cmp::min(pending_outbound_payments_count_compat as usize, MAX_ALLOC_SIZE/32)); for _ in 0..pending_outbound_payments_count_compat { let session_priv = Readable::read(reader)?; let payment = PendingOutboundPayment::Legacy { - session_privs: [session_priv].iter().cloned().collect() + session_privs: hash_set_from_iter([session_priv]), }; if pending_outbound_payments_compat.insert(PaymentId(session_priv), payment).is_some() { return Err(DecodeError::InvalidValue) @@ -10562,13 +11454,13 @@ where // pending_outbound_payments_no_retry is for compatibility with 0.0.101 clients. let mut pending_outbound_payments_no_retry: Option>> = None; let mut pending_outbound_payments = None; - let mut pending_intercepted_htlcs: Option> = Some(HashMap::new()); + let mut pending_intercepted_htlcs: Option> = Some(new_hash_map()); let mut received_network_pubkey: Option = None; let mut fake_scid_rand_bytes: Option<[u8; 32]> = None; let mut probing_cookie_secret: Option<[u8; 32]> = None; let mut claimable_htlc_purposes = None; let mut claimable_htlc_onion_fields = None; - let mut pending_claiming_payments = Some(HashMap::new()); + let mut pending_claiming_payments = Some(new_hash_map()); let mut monitor_update_blocked_actions_per_peer: Option>)>> = Some(Vec::new()); let mut events_override = None; let mut in_flight_monitor_updates: Option>> = None; @@ -10605,7 +11497,7 @@ where if pending_outbound_payments.is_none() && pending_outbound_payments_no_retry.is_none() { pending_outbound_payments = Some(pending_outbound_payments_compat); } else if pending_outbound_payments.is_none() { - let mut outbounds = HashMap::new(); + let mut outbounds = new_hash_map(); for (id, session_privs) in pending_outbound_payments_no_retry.unwrap().drain() { outbounds.insert(id, PendingOutboundPayment::Legacy { session_privs }); } @@ -10714,7 +11606,7 @@ where // still open, we need to replay any monitor updates that are for closed channels, // creating the neccessary peer_state entries as we go. let peer_state_mutex = per_peer_state.entry(counterparty_id).or_insert_with(|| { - Mutex::new(peer_state_from_chans(HashMap::new())) + Mutex::new(peer_state_from_chans(new_hash_map())) }); let mut peer_state = peer_state_mutex.lock().unwrap(); handle_in_flight_updates!(counterparty_id, chan_in_flight_updates, @@ -10775,7 +11667,7 @@ where retry_strategy: None, attempts: PaymentAttempts::new(), payment_params: None, - session_privs: [session_priv_bytes].iter().map(|a| *a).collect(), + session_privs: hash_set_from_iter([session_priv_bytes]), payment_hash: htlc.payment_hash, payment_secret: None, // only used for retries, and we'll never retry on startup payment_metadata: None, // only used for retries, and we'll never retry on startup @@ -10900,7 +11792,7 @@ where let inbound_pmt_key_material = args.node_signer.get_inbound_payment_key_material(); let expanded_inbound_key = inbound_payment::ExpandedKey::new(&inbound_pmt_key_material); - let mut claimable_payments = HashMap::with_capacity(claimable_htlcs_list.len()); + let mut claimable_payments = hash_map_with_capacity(claimable_htlcs_list.len()); if let Some(purposes) = claimable_htlc_purposes { if purposes.len() != claimable_htlcs_list.len() { return Err(DecodeError::InvalidValue); @@ -10973,7 +11865,7 @@ where } } - let mut outbound_scid_aliases = HashSet::new(); + let mut outbound_scid_aliases = new_hash_set(); for (_peer_node_id, peer_state_mutex) in per_peer_state.iter_mut() { let mut peer_state_lock = peer_state_mutex.lock().unwrap(); let peer_state = &mut *peer_state_lock; @@ -11078,13 +11970,12 @@ where downstream_counterparty_and_funding_outpoint: Some((blocked_node_id, _blocked_channel_outpoint, blocked_channel_id, blocking_action)), .. } = action { - if let Some(blocked_peer_state) = per_peer_state.get(&blocked_node_id) { - let channel_id = blocked_channel_id; + if let Some(blocked_peer_state) = per_peer_state.get(blocked_node_id) { log_trace!(logger, "Holding the next revoke_and_ack from {} until the preimage is durably persisted in the inbound edge's ChannelMonitor", - channel_id); + blocked_channel_id); blocked_peer_state.lock().unwrap().actions_blocking_raa_monitor_updates - .entry(*channel_id) + .entry(*blocked_channel_id) .or_insert_with(Vec::new).push(blocking_action.clone()); } else { // If the channel we were blocking has closed, we don't need to @@ -11168,8 +12059,10 @@ where // We use `downstream_closed` in place of `from_onchain` here just as a guess - we // don't remember in the `ChannelMonitor` where we got a preimage from, but if the // channel is closed we just assume that it probably came from an on-chain claim. - channel_manager.claim_funds_internal(source, preimage, Some(downstream_value), - downstream_closed, true, downstream_node_id, downstream_funding, downstream_channel_id); + channel_manager.claim_funds_internal(source, preimage, Some(downstream_value), None, + downstream_closed, true, downstream_node_id, downstream_funding, + downstream_channel_id, None + ); } //TODO: Broadcast channel update for closed channels, but only after we've made a @@ -11856,8 +12749,8 @@ mod tests { } let (_nodes_1_update, _none) = get_closing_signed_broadcast!(nodes[1].node, nodes[0].node.get_our_node_id()); - check_closed_event!(nodes[0], 1, ClosureReason::CooperativeClosure, [nodes[1].node.get_our_node_id()], 1000000); - check_closed_event!(nodes[1], 1, ClosureReason::CooperativeClosure, [nodes[0].node.get_our_node_id()], 1000000); + check_closed_event!(nodes[0], 1, ClosureReason::LocallyInitiatedCooperativeClosure, [nodes[1].node.get_our_node_id()], 1000000); + check_closed_event!(nodes[1], 1, ClosureReason::CounterpartyInitiatedCooperativeClosure, [nodes[0].node.get_our_node_id()], 1000000); } fn check_not_connected_to_peer_error(res_err: Result, expected_public_key: PublicKey) { @@ -11989,14 +12882,15 @@ mod tests { check_added_monitors!(nodes[0], 1); expect_channel_pending_event(&nodes[0], &nodes[1].node.get_our_node_id()); } - open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); } // A MAX_UNFUNDED_CHANS_PER_PEER + 1 channel will be summarily rejected - open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source( + &nodes[0].keys_manager); nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg); assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, - open_channel_msg.temporary_channel_id); + open_channel_msg.common_fields.temporary_channel_id); // Further, because all of our channels with nodes[0] are inbound, and none of them funded, // it doesn't count as a "protected" peer, i.e. it counts towards the MAX_NO_CHANNEL_PEERS @@ -12044,11 +12938,11 @@ mod tests { for i in 0..super::MAX_UNFUNDED_CHANNEL_PEERS - 1 { nodes[1].node.handle_open_channel(&peer_pks[i], &open_channel_msg); get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, peer_pks[i]); - open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); } nodes[1].node.handle_open_channel(&last_random_pk, &open_channel_msg); assert_eq!(get_err_msg(&nodes[1], &last_random_pk).channel_id, - open_channel_msg.temporary_channel_id); + open_channel_msg.common_fields.temporary_channel_id); // Of course, however, outbound channels are always allowed nodes[1].node.create_channel(last_random_pk, 100_000, 0, 42, None, None).unwrap(); @@ -12084,14 +12978,14 @@ mod tests { for _ in 0..super::MAX_UNFUNDED_CHANS_PER_PEER { nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg); get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, nodes[0].node.get_our_node_id()); - open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); } // Once we have MAX_UNFUNDED_CHANS_PER_PEER unfunded channels, new inbound channels will be // rejected. nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg); assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, - open_channel_msg.temporary_channel_id); + open_channel_msg.common_fields.temporary_channel_id); // but we can still open an outbound channel. nodes[1].node.create_channel(nodes[0].node.get_our_node_id(), 100_000, 0, 42, None, None).unwrap(); @@ -12100,7 +12994,7 @@ mod tests { // but even with such an outbound channel, additional inbound channels will still fail. nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg); assert_eq!(get_err_msg(&nodes[1], &nodes[0].node.get_our_node_id()).channel_id, - open_channel_msg.temporary_channel_id); + open_channel_msg.common_fields.temporary_channel_id); } #[test] @@ -12136,7 +13030,7 @@ mod tests { _ => panic!("Unexpected event"), } get_event_msg!(nodes[1], MessageSendEvent::SendAcceptChannel, random_pk); - open_channel_msg.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); + open_channel_msg.common_fields.temporary_channel_id = ChannelId::temporary_from_entropy_source(&nodes[0].keys_manager); } // If we try to accept a channel from another peer non-0conf it will fail. @@ -12158,7 +13052,7 @@ mod tests { _ => panic!("Unexpected event"), } assert_eq!(get_err_msg(&nodes[1], &last_random_pk).channel_id, - open_channel_msg.temporary_channel_id); + open_channel_msg.common_fields.temporary_channel_id); // ...however if we accept the same channel 0conf it should work just fine. nodes[1].node.handle_open_channel(&last_random_pk, &open_channel_msg); @@ -12192,7 +13086,7 @@ mod tests { }; // Check that if the amount we received + the penultimate hop extra fee is less than the sender // intended amount, we fail the payment. - let current_height: u32 = node[0].node.best_block.read().unwrap().height(); + let current_height: u32 = node[0].node.best_block.read().unwrap().height; if let Err(crate::ln::channelmanager::InboundHTLCErr { err_code, .. }) = create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]), sender_intended_amt_msat - extra_fee_msat - 1, 42, None, true, Some(extra_fee_msat), @@ -12212,7 +13106,7 @@ mod tests { }), custom_tlvs: Vec::new(), }; - let current_height: u32 = node[0].node.best_block.read().unwrap().height(); + let current_height: u32 = node[0].node.best_block.read().unwrap().height; assert!(create_recv_pending_htlc_info(hop_data, [0; 32], PaymentHash([0; 32]), sender_intended_amt_msat - extra_fee_msat, 42, None, true, Some(extra_fee_msat), current_height, node[0].node.default_configuration.accept_mpp_keysend).is_ok()); @@ -12225,7 +13119,7 @@ mod tests { let node_chanmgr = create_node_chanmgrs(1, &node_cfg, &[None]); let node = create_network(1, &node_cfg, &node_chanmgr); - let current_height: u32 = node[0].node.best_block.read().unwrap().height(); + let current_height: u32 = node[0].node.best_block.read().unwrap().height; let result = create_recv_pending_htlc_info(msgs::InboundOnionPayload::Receive { sender_intended_htlc_amt_msat: 100, cltv_expiry_height: 22, @@ -12303,7 +13197,7 @@ mod tests { nodes[0].node.create_channel(nodes[1].node.get_our_node_id(), 100_000, 0, 0, None, None).unwrap(); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); - assert!(open_channel_msg.channel_type.as_ref().unwrap().supports_anchors_zero_fee_htlc_tx()); + assert!(open_channel_msg.common_fields.channel_type.as_ref().unwrap().supports_anchors_zero_fee_htlc_tx()); nodes[1].node.handle_open_channel(&nodes[0].node.get_our_node_id(), &open_channel_msg); let events = nodes[1].node.get_and_clear_pending_events(); @@ -12318,7 +13212,7 @@ mod tests { nodes[0].node.handle_error(&nodes[1].node.get_our_node_id(), &error_msg); let open_channel_msg = get_event_msg!(nodes[0], MessageSendEvent::SendOpenChannel, nodes[1].node.get_our_node_id()); - assert!(!open_channel_msg.channel_type.unwrap().supports_anchors_zero_fee_htlc_tx()); + assert!(!open_channel_msg.common_fields.channel_type.unwrap().supports_anchors_zero_fee_htlc_tx()); // Since nodes[1] should not have accepted the channel, it should // not have generated any events. @@ -12507,7 +13401,7 @@ mod tests { let (scid_1, scid_2) = (42, 43); - let mut forward_htlcs = HashMap::new(); + let mut forward_htlcs = new_hash_map(); forward_htlcs.insert(scid_1, dummy_htlcs_1.clone()); forward_htlcs.insert(scid_2, dummy_htlcs_2.clone()); @@ -12651,7 +13545,7 @@ pub mod bench { assert_eq!(&tx_broadcaster.txn_broadcasted.lock().unwrap()[..], &[tx.clone()]); - let block = create_dummy_block(BestBlock::from_network(network).block_hash(), 42, vec![tx]); + let block = create_dummy_block(BestBlock::from_network(network).block_hash, 42, vec![tx]); Listen::block_connected(&node_a, &block, 1); Listen::block_connected(&node_b, &block, 1);