UNPKG

lightningdevkit

Version:
1,020 lines (1,019 loc) 98.6 kB
import { Result_RefundMaybeWithDerivedMetadataBuilderBolt12SemanticErrorZ } from '../structs/Result_RefundMaybeWithDerivedMetadataBuilderBolt12SemanticErrorZ.mjs'; import { Refund } from '../structs/Refund.mjs'; import { Option_u64Z } from '../structs/Option_u64Z.mjs'; import { Retry } from '../structs/Retry.mjs'; import { Option_ThirtyTwoBytesZ } from '../structs/Option_ThirtyTwoBytesZ.mjs'; import { RecipientOnionFields } from '../structs/RecipientOnionFields.mjs'; import { Destination } from '../structs/Destination.mjs'; import { HumanReadableName } from '../structs/HumanReadableName.mjs'; import { Offer } from '../structs/Offer.mjs'; import { Bolt12Invoice } from '../structs/Bolt12Invoice.mjs'; import { Result_Bolt12InvoiceBolt12SemanticErrorZ } from '../structs/Result_Bolt12InvoiceBolt12SemanticErrorZ.mjs'; import { Result_ThirtyTwoBytesNoneZ } from '../structs/Result_ThirtyTwoBytesNoneZ.mjs'; import { OutPoint } from '../structs/OutPoint.mjs'; import { Option_u32Z } from '../structs/Option_u32Z.mjs'; import { Result_NoneNoneZ } from '../structs/Result_NoneNoneZ.mjs'; import { ShutdownScript } from '../structs/ShutdownScript.mjs'; import { Option_u16Z } from '../structs/Option_u16Z.mjs'; import { RouteParameters } from '../structs/RouteParameters.mjs'; import { ChannelDetails } from '../structs/ChannelDetails.mjs'; import { Route } from '../structs/Route.mjs'; import { InFlightHtlcs } from '../structs/InFlightHtlcs.mjs'; import { Path } from '../structs/Path.mjs'; import { Logger } from '../structs/Logger.mjs'; import { BestBlock } from '../structs/BestBlock.mjs'; import { ChannelId } from '../structs/ChannelId.mjs'; import { Option_StrZ } from '../structs/Option_StrZ.mjs'; import { Result_NoneBolt12SemanticErrorZ } from '../structs/Result_NoneBolt12SemanticErrorZ.mjs'; import { Result_ChannelIdAPIErrorZ } from '../structs/Result_ChannelIdAPIErrorZ.mjs'; import { RecentPaymentDetails } from '../structs/RecentPaymentDetails.mjs'; import { Result_NoneAPIErrorZ } from '../structs/Result_NoneAPIErrorZ.mjs'; import { Result_NoneRetryableSendFailureZ } from '../structs/Result_NoneRetryableSendFailureZ.mjs'; import { Option_OffersContextZ } from '../structs/Option_OffersContextZ.mjs'; import { Result_NoneBolt12PaymentErrorZ } from '../structs/Result_NoneBolt12PaymentErrorZ.mjs'; import { Result_ThirtyTwoBytesRetryableSendFailureZ } from '../structs/Result_ThirtyTwoBytesRetryableSendFailureZ.mjs'; import { Result_C2Tuple_ThirtyTwoBytesThirtyTwoBytesZProbeSendFailureZ } from '../structs/Result_C2Tuple_ThirtyTwoBytesThirtyTwoBytesZProbeSendFailureZ.mjs'; import { Result_CVec_C2Tuple_ThirtyTwoBytesThirtyTwoBytesZZProbeSendFailureZ } from '../structs/Result_CVec_C2Tuple_ThirtyTwoBytesThirtyTwoBytesZZProbeSendFailureZ.mjs'; import { TwoTuple_ChannelIdPublicKeyZ } from '../structs/TwoTuple_ChannelIdPublicKeyZ.mjs'; import { Option_C2Tuple_PublicKeyChannelIdZZ } from '../structs/Option_C2Tuple_PublicKeyChannelIdZZ.mjs'; import { Result_Bolt11InvoiceSignOrCreationErrorZ } from '../structs/Result_Bolt11InvoiceSignOrCreationErrorZ.mjs'; import { Result_OfferWithDerivedMetadataBuilderBolt12SemanticErrorZ } from '../structs/Result_OfferWithDerivedMetadataBuilderBolt12SemanticErrorZ.mjs'; import { Result_C2Tuple_ThirtyTwoBytesThirtyTwoBytesZNoneZ } from '../structs/Result_C2Tuple_ThirtyTwoBytesThirtyTwoBytesZNoneZ.mjs'; import { Result_ThirtyTwoBytesAPIErrorZ } from '../structs/Result_ThirtyTwoBytesAPIErrorZ.mjs'; import { PhantomRouteHints } from '../structs/PhantomRouteHints.mjs'; import { Watch } from '../structs/Watch.mjs'; import { BroadcasterInterface } from '../structs/BroadcasterInterface.mjs'; import { EntropySource } from '../structs/EntropySource.mjs'; import { NodeSigner } from '../structs/NodeSigner.mjs'; import { SignerProvider } from '../structs/SignerProvider.mjs'; import { FeeEstimator } from '../structs/FeeEstimator.mjs'; import { Router } from '../structs/Router.mjs'; import { MessageRouter } from '../structs/MessageRouter.mjs'; import { ChannelConfig } from '../structs/ChannelConfig.mjs'; import { ChannelTypeFeatures } from '../structs/ChannelTypeFeatures.mjs'; import { InitFeatures } from '../structs/InitFeatures.mjs'; import { ChannelFeatures } from '../structs/ChannelFeatures.mjs'; import { NodeFeatures } from '../structs/NodeFeatures.mjs'; import { Listen } from '../structs/Listen.mjs'; import { Confirm } from '../structs/Confirm.mjs'; import { Future } from '../structs/Future.mjs'; import { ChannelConfigUpdate } from '../structs/ChannelConfigUpdate.mjs'; import { UserConfig } from '../structs/UserConfig.mjs'; import { EventsProvider } from '../structs/EventsProvider.mjs'; import { FailureCode } from '../structs/FailureCode.mjs'; import { ChainParameters } from '../structs/ChainParameters.mjs'; import { Bolt11InvoiceDescription } from '../structs/Bolt11InvoiceDescription.mjs'; import { MessageSendEventsProvider } from '../structs/MessageSendEventsProvider.mjs'; import { ChannelMessageHandler } from '../structs/ChannelMessageHandler.mjs'; import { OffersMessageHandler } from '../structs/OffersMessageHandler.mjs'; import { AsyncPaymentsMessageHandler } from '../structs/AsyncPaymentsMessageHandler.mjs'; import { DNSResolverMessageHandler } from '../structs/DNSResolverMessageHandler.mjs'; import { NodeIdLookUp } from '../structs/NodeIdLookUp.mjs'; import { CommonBase } from './CommonBase.mjs'; /** * 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 * - [`MessageRouter`] for finding message paths when initiating and retrying onion messages * - [`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::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<ChannelMonitor<lightning::sign::InMemorySigner>> { 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<ScoreParams = SP>, * # SP: Sized, * # R: lightning::io::Read, * # >( * # fee_estimator: &dyn lightning::chain::chaininterface::FeeEstimator, * # chain_monitor: &dyn lightning::chain::Watch<lightning::sign::InMemorySigner>, * # tx_broadcaster: &dyn lightning::chain::chaininterface::BroadcasterInterface, * # router: &lightning::routing::router::DefaultRouter<&NetworkGraph<&'a L>, &'a L, &ES, &S>, * # message_router: &lightning::onion_message::messenger::DefaultMessageRouter<&NetworkGraph<&'a L>, &'a L, &ES>, * # 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, message_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, message_router, logger, default_config, channel_monitors.iter().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<T: AChannelManager>(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<T: AChannelManager, W: Wallet>(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); * }, * ... * # _ => {}, * } * Ok(()) * }); * # } * ``` * * ## 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<T: AChannelManager>(channel_manager: T) { * # let channel_manager = channel_manager.get_cm(); * # let error_message = \"Channel force-closed\"; * 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, error_message.to_string() * ) { * Ok(()) => println!(\"Rejecting channel {}\", temporary_channel_id), * Err(e) => println!(\"Error rejecting channel {}: {:?}\", temporary_channel_id, e), * } * return Ok(()); * } * * 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), * } * }, * ... * # _ => {}, * } * Ok(()) * }); * # } * ``` * * ## 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::types::ChannelId; * # use lightning::ln::channelmanager::AChannelManager; * # use lightning::events::{Event, EventsProvider}; * # * # fn example<T: AChannelManager>( * # 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); * }, * ... * # _ => {}, * } * Ok(()) * }); * # } * ``` * * # 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. However, in order to * construct a [`Bolt11Invoice`] that is compatible with [`ChannelManager`], use * [`create_bolt11_invoice`]. This method serves as a convenience for building invoices with the * [`PaymentHash`] and [`PaymentSecret`] returned from [`create_inbound_payment`]. To provide your * own [`PaymentHash`], override the appropriate [`Bolt11InvoiceParameters`], which is equivalent * to using [`create_inbound_payment_for_hash`]. * * [`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, Bolt11InvoiceParameters}; * # * # fn example<T: AChannelManager>(channel_manager: T) { * # let channel_manager = channel_manager.get_cm(); * let params = Bolt11InvoiceParameters { * amount_msats: Some(10_000_000), * invoice_expiry_delta_secs: Some(3600), * ..Default::default() * }; * let invoice = match channel_manager.create_bolt11_invoice(params) { * Ok(invoice) => { * println!(\"Creating invoice with payment hash {}\", invoice.payment_hash()); * invoice * }, * Err(e) => panic!(\"Error creating invoice: {}\", e), * }; * * On the event processing thread * channel_manager.process_pending_events(&|event| { * match event { * Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose { * PaymentPurpose::Bolt11InvoicePayment { payment_preimage: Some(payment_preimage), .. } => { * assert_eq!(payment_hash.0, invoice.payment_hash().as_ref()); * println!(\"Claiming payment {}\", payment_hash); * channel_manager.claim_funds(payment_preimage); * }, * PaymentPurpose::Bolt11InvoicePayment { payment_preimage: None, .. } => { * println!(\"Unknown payment hash: {}\", payment_hash); * }, * PaymentPurpose::SpontaneousPayment(payment_preimage) => { * assert_ne!(payment_hash.0, invoice.payment_hash().as_ref()); * println!(\"Claiming spontaneous payment {}\", payment_hash); * channel_manager.claim_funds(payment_preimage); * }, * ... * # _ => {}, * }, * Event::PaymentClaimed { payment_hash, amount_msat, .. } => { * assert_eq!(payment_hash.0, invoice.payment_hash().as_ref()); * println!(\"Claimed {} msats\", amount_msat); * }, * ... * # _ => {}, * } * Ok(()) * }); * # } * ``` * * For paying an invoice, see the [`bolt11_payment`] module with convenience functions for use with * [`send_payment`]. * * ``` * # use lightning::events::{Event, EventsProvider}; * # use lightning::types::payment::PaymentHash; * # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails}; * # use lightning::ln::outbound_payment::{RecipientOnionFields, Retry}; * # use lightning::routing::router::RouteParameters; * # * # fn example<T: AChannelManager>( * # 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: Some(payment_hash), .. } => * println!(\"Failed paying {}\", payment_hash), * ... * # _ => {}, * } * Ok(()) * }); * # } * ``` * * ## 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<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> { * # let channel_manager = channel_manager.get_cm(); * # let absolute_expiry = None; * let offer = channel_manager * .create_offer_builder(absolute_expiry)? * # ; * # // Needed for compiling for c_bindings * # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into(); * # let offer = builder * .description(\"coffee\".to_string()) * .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::Bolt12OfferPayment { payment_preimage: Some(payment_preimage), .. } => { * println!(\"Claiming payment {}\", payment_hash); * channel_manager.claim_funds(payment_preimage); * }, * PaymentPurpose::Bolt12OfferPayment { payment_preimage: None, .. } => { * println!(\"Unknown payment hash: {}\", payment_hash); * } * # _ => {}, * }, * Event::PaymentClaimed { payment_hash, amount_msat, .. } => { * println!(\"Claimed {} msats\", amount_msat); * }, * ... * # _ => {}, * } * Ok(()) * }); * # Ok(()) * # } * ``` * * Use [`pay_for_offer`] to initiated payment, which sends an [`InvoiceRequest`] for an [`Offer`] * and pays the [`Bolt12Invoice`] response. * * ``` * # use lightning::events::{Event, EventsProvider}; * # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails}; * # use lightning::ln::outbound_payment::Retry; * # use lightning::offers::offer::Offer; * # * # fn example<T: AChannelManager>( * # channel_manager: T, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>, * # payer_note: Option<String>, retry: Retry, max_total_routing_fee_msat: Option<u64> * # ) { * # 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), * ... * # _ => {}, * } * Ok(()) * }); * # } * ``` * * ## 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}; * # use lightning::ln::outbound_payment::Retry; * # use lightning::offers::parse::Bolt12SemanticError; * # * # fn example<T: AChannelManager>( * # channel_manager: T, amount_msats: u64, absolute_expiry: Duration, retry: Retry, * # max_total_routing_fee_msat: Option<u64> * # ) -> Result<(), Bolt12SemanticError> { * # let channel_manager = channel_manager.get_cm(); * let payment_id = PaymentId([42; 32]); * let refund = channel_manager * .create_refund_builder( * 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 * .description(\"coffee\".to_string()) * .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() * ); * * 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(()) * }); * # 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<T: AChannelManager>(channel_manager: T, refund: &Refund) { * # let channel_manager = channel_manager.get_cm(); * let known_payment_hash = match channel_manager.request_refund_payment(refund) { * Ok(invoice) => { * let payment_hash = invoice.payment_hash(); * println!(\"Requesting refund payment {}\", payment_hash); * payment_hash * }, * Err(e) => panic!(\"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::Bolt12RefundPayment { payment_preimage: Some(payment_preimage), .. } => { * assert_eq!(payment_hash, known_payment_hash); * println!(\"Claiming payment {}\", payment_hash); * channel_manager.claim_funds(payment_preimage); * }, * PaymentPurpose::Bolt12RefundPayment { payment_preimage: None, .. } => { * println!(\"Unknown payment hash: {}\", payment_hash); * }, * ... * # _ => {}, * }, * Event::PaymentClaimed { payment_hash, amount_msat, .. } => { * assert_eq!(payment_hash, known_payment_hash); * println!(\"Claimed {} msats\", amount_msat); * }, * ... * # _ => {}, * } * Ok(()) * }); * # } * ``` * * # 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 * serialized). This will result in any channels which have not yet exchanged [`funding_created`] (i.e., * called [`funding_transaction_generated`] for outbound channels) being closed. * * Note that you can be a bit lazier about writing out `ChannelManager` than you can be with * [`ChannelMonitor`]. With [`ChannelMonitor`] you MUST durably write each * [`ChannelMonitorUpdate`] before returning from * [`chain::Watch::watch_channel`]/[`update_channel`] or before completing async writes. With * `ChannelManager`s, writing updates happens out-of-band (and will prevent any other * `ChannelManager` operations from occurring during the serialization process). If the * deserialized version is out-of-date compared to the [`ChannelMonitor`] passed by reference to * [`read`], those channels will be force-closed based on the `ChannelMonitor` state and no funds * will be lost (modulo on-chain transaction fees). * * Note that the deserializer is only implemented for `(`[`BlockHash`]`, `[`ChannelManager`]`)`, which * 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 * many peers with unfunded channels. * * Because it is an indication of trust, inbound channels which we've accepted as 0conf are * 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_bolt11_invoice`]: Self::create_bolt11_invoice * [`create_inbound_payment`]: Self::create_inbound_payment * [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash * [`bolt11_payment`]: crate::ln::bolt11_payment * [`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 * [`read`]: ReadableArgs::read */ export declare class ChannelManager extends CommonBase { /** * Constructs a new `ChannelManager` to hold several channels and route between them. * * The current time or latest block header time can be provided as the `current_timestamp`. * * This is the main \"logic hub\" for all channel-related actions, and implements * [`ChannelMessageHandler`]. * * Non-proportional fees are fixed according to our risk using the provided fee estimator. * * Users need to notify the new `ChannelManager` when a new block is connected or * disconnected using its [`block_connected`] and [`block_disconnected`] methods, starting * from after [`params.best_block.block_hash`]. See [`chain::Listen`] and [`chain::Confirm`] for * more details. * * [`block_connected`]: chain::Listen::block_connected * [`block_disconnected`]: chain::Listen::block_disconnected * [`params.best_block.block_hash`]: chain::BestBlock::block_hash */ static constructor_new(fee_est: FeeEstimator, chain_monitor: Watch, tx_broadcaster: BroadcasterInterface, router: Router, message_router: MessageRouter, logger: Logger, entropy_source: EntropySource, node_signer: NodeSigner, signer_provider: SignerProvider, config: UserConfig, params: ChainParameters, current_timestamp: number): ChannelManager; /** * Gets the current configuration applied to all new channels. */ get_current_default_configuration(): UserConfig; /** * Creates a new outbound channel to the given remote node and with the given value. * * `user_channel_id` will be provided back as in * [`Event::FundingGenerationReady::user_channel_id`] to allow tracking of which events * correspond with which `create_channel` call. Note that the `user_channel_id` defaults to a * randomized value for inbound channels. `user_channel_id` has no meaning inside of LDK, it * is simply copied to events and otherwise ignored. * * Raises [`APIError::APIMisuseError`] when `channel_value_satoshis` > 2**24 or `push_msat` is * greater than `channel_value_satoshis * 1k` or `channel_value_satoshis < 1000`. * * Raises [`APIError::ChannelUnavailable`] if the channel cannot be opened due to failing to * generate a shutdown scriptpubkey or destination script set by * [`SignerProvider::get_shutdown_scriptpubkey`] or [`SignerProvider::get_destination_script`]. * * Note that we do not check if you are currently connected to the given peer. If no * connection is available, the outbound `open_channel` message may fail to send, resulting in * the channel eventually being silently forgotten (dropped on reload). * * If `temporary_channel_id` is specified, it will be used as the temporary channel ID of the * channel. Otherwise, a random one will be generated for you. * * Returns the new Channel's temporary `channel_id`. This ID will appear as * [`Event::FundingGenerationReady::temporary_channel_id`] and in * [`ChannelDetails::channel_id`] until after * [`ChannelManager::funding_transaction_generated`] is called, swapping the Channel's ID for * one derived from the funding transaction's TXID. If the counterparty rejects the channel * immediately, this temporary ID will appear in [`Event::ChannelClosed::channel_id`]. * * [`Event::FundingGenerationReady::user_channel_id`]: events::Event::FundingGenerationReady::user_channel_id * [`Event::FundingGenerationReady::temporary_channel_id`]: events::Event::FundingGenerationReady::temporary_channel_id * [`Event::ChannelClosed::channel_id`]: events::Event::ChannelClosed::channel_id * * Note that temporary_channel_id (or a relevant inner pointer) may be NULL or all-0s to represent None * Note that override_config (or a relevant inner pointer) may be NULL or all-0s to represent None */ create_channel(their_network_key: Uint8Array, channel_value_satoshis: bigint, push_msat: bigint, user_channel_id: bigint, temporary_channel_id: ChannelId | null, override_config: UserConfig | null): Result_ChannelIdAPIErrorZ; /** * Gets the list of open channels, in random order. See [`ChannelDetails`] field documentation for * more information. */ list_channels(): ChannelDetails[]; /** * Gets the list of usable channels, in random order. Useful as an argument to * [`Router::find_route`] to ensure non-announced channels are used. * * These are guaranteed to have their [`ChannelDetails::is_usable`] value set to true, see the * documentation for [`ChannelDetails::is_usable`] for more info on exactly what the criteria * are. */ list_usable_channels(): ChannelDetails[]; /** * Gets the list of channels we have with a given counterparty, in random order. */ list_channels_with_counterparty(counterparty_node_id: Uint8Array): ChannelDetails[]; /** * Returns in an undefined order recent payments that -- if not fulfilled -- have yet to find a * successful path, or have unresolved HTLCs. * * This can be useful for payments that may have been prepared, but ultimately not sent, as a * result of a crash. If such a payment exists, is not listed here, and an * [`Event::PaymentSent`] has not been received, you may consider resending the payment. * * [`Event::PaymentSent`]: events::Event::PaymentSent */ list_recent_payments(): RecentPaymentDetails[]; /** * Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs * will be accepted on the given channel, and after additional timeout/the closing of all * pending HTLCs, the channel will be closed on chain. * * If we are the channel initiator, we will pay between our [`ChannelCloseMinimum`] and * [`ChannelConfig::force_close_avoidance_max_fee_satoshis`] plus our [`NonAnchorChannelFee`] * fee estimate. * If our counterparty is the channel initiator, we will require a channel closing * transaction feerate of at least our [`ChannelCloseMinimum`] feerate or the feerate which * would appear on a force-closure transaction, whichever is lower. We will allow our * counterparty to pay as much fee as they'd like, however. * * May generate a [`SendShutdown`] message event on success, which should be relayed. * * Raises [`APIError::ChannelUnavailable`] if the channel cannot be closed due to failing to * generate a shutdown scriptpubkey or destination script set by * [`SignerProvider::get_shutdown_scriptpubkey`]. A force-closure may be needed to close the * channel. * * [`ChannelConfig::force_close_avoidance_max_fee_satoshis`]: crate::util::config::ChannelConfig::force_close_avoidance_max_fee_satoshis * [`ChannelCloseMinimum`]: crate::chain::chaininterface::ConfirmationTarget::ChannelCloseMinimum * [`NonAnchorChannelFee`]: crate::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee * [`SendShutdown`]: crate::events::MessageSendEvent::SendShutdown */ close_channel(channel_id: ChannelId, counterparty_node_id: Uint8Array): Result_NoneAPIErrorZ; /** * Begins the process of closing a channel. After this call (plus some timeout), no new HTLCs * will be accepted on the given channel, and after additional timeout/the closing of all * pending HTLCs, the channel will be closed on chain. * * `target_feerate_sat_per_1000_weight` has different meanings depending on if we initiated * the channel being closed or not: * If we are the channel initiator, we will pay at least this feerate on the closing * transaction. The upper-bound is set by * [`ChannelConfig::force_close_avoidance_max_fee_satoshis`] plus our [`NonAnchorChannelFee`] * fee estimate (or `target_feerate_sat_per_1000_weight`, if it is greater). * If our counterparty is the channel initiator, we will refuse to accept a channel closure * transaction feerate below `target_feerate_sat_per_1000_weight` (or the feerate which * will appear on a force-closure transaction, whichever is lower). * * The `shutdown_script` provided will be used as the `scriptPubKey` for the closing transaction. * Will fail if a shutdown script has already been set for this channel by * ['ChannelHandshakeConfig::commit_upfront_shutdown_pubkey`]. The given shutdown script must * also be compatible with our and the counterparty's features. * * May generate a [`SendShutdown`] message event on success, which should be relayed. * * Raises [`APIError::ChannelUnavailable`] if the channel cannot be closed due to failing to * generate a shutdown scriptpubkey or destination script set by * [`SignerProvider::get_shutdown_scriptpubkey`]. A force-closure may be needed to close the * channel. * * [`ChannelConfig::force_close_avoidance_max_fee_satoshis`]: crate::util::config::ChannelConfig::force_close_avoidance_max_fee_satoshis * [`NonAnchorChannelFee`]: crate::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee * [`SendShutdown`]: crate::events::MessageSendEvent::SendShutdown * * Note that shutdown_script (or a relevant inner pointer) may be NULL or all-0s to represent None */ close_channel_with_feerate_and_script(channel_id: ChannelId, counterparty_node_id: Uint8Array, target_feerate_sats_per_1000_weight: Option_u32Z, shutdown_script: ShutdownScript | null): Result_NoneAPIErrorZ; /** * Force closes a channel, immediately broadcasting the latest local transaction(s), * rejecting new HTLCs. * * The provided `error_message` is sent to connected peers for closing * channels and should be a human-readable description of what went wrong. * * Fails if `channel_id` is unknown to the manager, or if the `counterparty_node_id` * isn't the counterparty of the corresponding channel. */ force_close_broadcasting_latest_txn(channel_id: ChannelId, counterparty_node_id: Uint8Array, error_message: string): Result_NoneAPIErrorZ; /** * Force closes a channel, rejecting new HTLCs on the given channel but skips broadcasting * the latest local transaction(s). * * The provided `error_message` is sent to connected peers for closing channels and should * be a human-readable description of what went wrong. * * 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 broadcast the latest local transaction(s) via * [`ChannelMonitor::broadcast_latest_holder_commitment_txn`]. */ force_close_without_broadcasting_txn(channel_id: ChannelId, counterparty_node_id: Uint8Array, error_message: string): Result_NoneAPIErrorZ; /** * Force close all channels, immediately broadcasting the latest local commitment transaction * for each to the chain and rejecting new HTLCs on each. * * The provided `error_message` is sent to connected peers for closing channels and should * be a human-readable description of what went wrong. */ force_close_all_channels_broadcasting_latest_txn(error_message: string): void; /** * Force close all channels rejecting new HTLCs on each but without broadcasting the latest * local transaction(s). * * The provided `error_message` is sent to connected peers for closing channels and * should be a human-readable description of what went wrong. */ force_close_all_channels_without_broadcasting_txn(error_message: string): void; /** * Sends a payment along a given route. See [`Self::send_payment`] for more info. * * LDK will not automatically retry this payment, though it may be manually re-sent after an * [`Event::PaymentFailed`] is generated. */ send_payment_with_route(route: Route, payment_hash: Uint8Array, recipient_onion: RecipientOnionFields, payment_id: Uint8Array): Result_NoneRetryableSendFailureZ;