X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannelmanager.rs;h=ee2e94c462bba0130be9113c24f723153d85fe48;hb=761f09b04c7094d9cf6686efe96c2a22526e82ff;hp=8dfd0c8fcaa32538de27b5f255a8b013e3939e26;hpb=6d5c952556aefa8f61c5a2c74ff72f426f5406ac;p=rust-lightning diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 8dfd0c8f..ee2e94c4 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -200,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, }, } @@ -221,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, } } @@ -1106,11 +1109,523 @@ 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 /// -/// Implements [`ChannelMessageHandler`], handling the multi-channel parts and passing things through -/// to individual Channels. +/// [`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), +/// // ... +/// # _ => {}, +/// }); +/// # } +/// ``` +/// +/// # 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 @@ -1131,12 +1646,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 @@ -1146,19 +1665,51 @@ 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 /// [`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: @@ -4523,7 +5074,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, @@ -5740,7 +6294,7 @@ where fn claim_funds_internal(&self, source: HTLCSource, payment_preimage: PaymentPreimage, 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_channel_outpoint: OutPoint, next_channel_id: ChannelId, next_user_channel_id: Option, ) { match source { HTLCSource::OutboundRoute { session_priv, payment_id, path, .. } => { @@ -5759,11 +6313,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 = @@ -5821,7 +6374,7 @@ where BackgroundEvent::MonitorUpdatesComplete { channel_id, .. } => - *channel_id == claiming_channel_id, + *channel_id == prev_channel_id, } }), "{:?}", *background_events); } @@ -5845,12 +6398,14 @@ where "skimmed_fee_msat must always be included in total_fee_earned_msat"); Some(MonitorUpdateCompletionAction::EmitEventAndFreeOtherChannel { event: events::Event::PaymentForwarded { - total_fee_earned_msat, - claim_from_onchain_tx: from_onchain, prev_channel_id: Some(prev_channel_id), next_channel_id: Some(next_channel_id), - outbound_amount_forwarded_msat: forwarded_htlc_value_msat, + 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, }) @@ -6105,73 +6660,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; 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(), } - } - }; - 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 }); + } 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 }); - } - } + 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, @@ -6824,6 +7388,7 @@ where fn internal_update_fulfill_htlc(&self, counterparty_node_id: &PublicKey, msg: &msgs::UpdateFulfillHTLC) -> Result<(), MsgHandleErrInternal> { let funding_txo; + 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) @@ -6853,6 +7418,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( @@ -6864,7 +7430,7 @@ where }; 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 + funding_txo, msg.channel_id, Some(next_user_channel_id), ); Ok(()) @@ -7366,7 +7932,7 @@ where 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), None, true, - false, counterparty_node_id, funding_outpoint, channel_id); + 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 }; @@ -7374,7 +7940,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 => { @@ -7392,7 +7958,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 @@ -7401,7 +7972,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() }) }, }); } @@ -7755,6 +8326,8 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => { .absolute_expiry(absolute_expiry) .path(path); + let _persistence_guard = PersistenceNotifierGuard::notify_on_drop($self); + let expiration = StaleExpiration::AbsoluteTimeout(absolute_expiry); $self.pending_outbound_payments .add_new_awaiting_invoice( @@ -7830,6 +8403,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. /// @@ -7869,6 +8443,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( @@ -7918,8 +8494,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> { @@ -7930,6 +8508,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) @@ -8725,6 +9309,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) } @@ -9229,8 +9816,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" => @@ -9243,34 +9828,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(); @@ -9753,6 +10349,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 @@ -11364,7 +11961,9 @@ where // 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), None, - downstream_closed, true, downstream_node_id, downstream_funding, downstream_channel_id); + 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