Skip to content

Commit c2909c2

Browse files
committed
Add a payments section to ChannelManager docs
1 parent 65b381c commit c2909c2

File tree

1 file changed

+129
-0
lines changed

1 file changed

+129
-0
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,126 @@ where
14071407
/// # }
14081408
/// ```
14091409
///
1410+
/// # Payments
1411+
///
1412+
/// [`ChannelManager`] is responsible for sending, forwarding, and receiving payments through its
1413+
/// channels. A payment is typically initiated from a [BOLT 11] invoice or a [BOLT 12] offer, though
1414+
/// spontaneous (i.e., keysend) payments are also possible. Incoming payments don't require
1415+
/// maintaining any additional state as [`ChannelManager`] can reconstruct the [`PaymentPreimage`]
1416+
/// from the [`PaymentSecret`]. Sending payments, however, require tracking in order to retry failed
1417+
/// HTLCs.
1418+
///
1419+
/// After a payment is initiated, it will appear in [`list_recent_payments`] until a short time
1420+
/// after either an [`Event::PaymentSent`] or [`Event::PaymentFailed`] is generated. Failed HTLCs
1421+
/// for a payment will be retried according to the payment's [`Retry`] strategy or until
1422+
/// [`abandon_payment`] is called.
1423+
///
1424+
/// ## BOLT 11 Invoices
1425+
///
1426+
/// The [`lightning-invoice`] crate is useful for creating BOLT 11 invoices. Specifically, use the
1427+
/// functions in its `utils` module for constructing invoices that are compatible with
1428+
/// [`ChannelManager`]. These functions serve as a convenience for building invoices with the
1429+
/// [`PaymentHash`] and [`PaymentSecret`] returned from [`create_inbound_payment`]. To provide your
1430+
/// own [`PaymentHash`], use [`create_inbound_payment_for_hash`] or the corresponding
1431+
/// [`lightning-invoice`] utilities.
1432+
///
1433+
/// [`ChannelManager`] generates an [`Event::PaymentClaimable`] once the full payment has been
1434+
/// received. Call [`claim_funds`] to release the [`PaymentPreimage`], which in turn will result in
1435+
/// an [`Event::PaymentClaimed`].
1436+
///
1437+
/// ```
1438+
/// # use lightning::events::{Event, EventsProvider, PaymentPurpose};
1439+
/// # use lightning::ln::channelmanager::AChannelManager;
1440+
/// #
1441+
/// # fn example<T: AChannelManager>(channel_manager: T) {
1442+
/// # let channel_manager = channel_manager.get_cm();
1443+
/// // Or use utils::create_invoice_from_channelmanager
1444+
/// let known_payment_hash = match channel_manager.create_inbound_payment(
1445+
/// Some(10_000_000), 3600, None
1446+
/// ) {
1447+
/// Ok((payment_hash, _payment_secret)) => {
1448+
/// println!("Creating inbound payment {}", payment_hash);
1449+
/// payment_hash
1450+
/// },
1451+
/// Err(()) => panic!("Error creating inbound payment"),
1452+
/// };
1453+
///
1454+
/// // On the event processing thread
1455+
/// channel_manager.process_pending_events(&|event| match event {
1456+
/// Event::PaymentClaimable { payment_hash, purpose, .. } => match purpose {
1457+
/// PaymentPurpose::InvoicePayment { payment_preimage: Some(payment_preimage), .. } => {
1458+
/// assert_eq!(payment_hash, known_payment_hash);
1459+
/// println!("Claiming payment {}", payment_hash);
1460+
/// channel_manager.claim_funds(payment_preimage);
1461+
/// },
1462+
/// PaymentPurpose::InvoicePayment { payment_preimage: None, .. } => {
1463+
/// println!("Unknown payment hash: {}", payment_hash);
1464+
/// },
1465+
/// PaymentPurpose::SpontaneousPayment(payment_preimage) => {
1466+
/// assert_ne!(payment_hash, known_payment_hash);
1467+
/// println!("Claiming spontaneous payment {}", payment_hash);
1468+
/// channel_manager.claim_funds(payment_preimage);
1469+
/// },
1470+
/// },
1471+
/// Event::PaymentClaimed { payment_hash, amount_msat, .. } => {
1472+
/// assert_eq!(payment_hash, known_payment_hash);
1473+
/// println!("Claimed {} msats", amount_msat);
1474+
/// },
1475+
/// // ...
1476+
/// # _ => {},
1477+
/// });
1478+
/// # }
1479+
/// ```
1480+
///
1481+
/// For paying an invoice, [`lightning-invoice`] provides a `payment` module with convenience
1482+
/// functions for use with [`send_payment`].
1483+
///
1484+
/// ```
1485+
/// # use core::time::Duration;
1486+
/// # use lightning::events::{Event, EventsProvider};
1487+
/// # use lightning::ln::PaymentHash;
1488+
/// # use lightning::ln::channelmanager::{AChannelManager, PaymentId, RecentPaymentDetails, RecipientOnionFields, Retry};
1489+
/// # use lightning::routing::router::RouteParameters;
1490+
/// #
1491+
/// # fn example<T: AChannelManager>(
1492+
/// # channel_manager: T, payment_hash: PaymentHash, recipient_onion: RecipientOnionFields,
1493+
/// # route_params: RouteParameters
1494+
/// # ) {
1495+
/// # let channel_manager = channel_manager.get_cm();
1496+
/// // let (payment_hash, recipient_onion, route_params) =
1497+
/// // payment::payment_parameters_from_invoice(&invoice);
1498+
/// let payment_id = PaymentId([42; 32]);
1499+
/// let retry = Retry::Timeout(Duration::from_secs(60));
1500+
/// match channel_manager.send_payment(
1501+
/// payment_hash, recipient_onion, payment_id, route_params, retry
1502+
/// ) {
1503+
/// Ok(()) => println!("Sending payment with hash {}", payment_hash),
1504+
/// Err(e) => println!("Failed sending payment with hash {}: {:?}", payment_hash, e),
1505+
/// }
1506+
///
1507+
/// let expected_payment_id = payment_id;
1508+
/// let expected_payment_hash = payment_hash;
1509+
/// assert!(
1510+
/// channel_manager.list_recent_payments().iter().find(|details| matches!(
1511+
/// details,
1512+
/// RecentPaymentDetails::Pending {
1513+
/// payment_id: expected_payment_id,
1514+
/// payment_hash: expected_payment_hash,
1515+
/// ..
1516+
/// }
1517+
/// )).is_some()
1518+
/// );
1519+
///
1520+
/// // On the event processing thread
1521+
/// channel_manager.process_pending_events(&|event| match event {
1522+
/// Event::PaymentSent { payment_hash, .. } => println!("Paid {}", payment_hash),
1523+
/// Event::PaymentFailed { payment_hash, .. } => println!("Failed paying {}", payment_hash),
1524+
/// // ...
1525+
/// # _ => {},
1526+
/// });
1527+
/// # }
1528+
/// ```
1529+
///
14101530
/// # Persistence
14111531
///
14121532
/// Implements [`Writeable`] to write out all channel state to disk. Implies [`peer_disconnected`] for
@@ -1473,6 +1593,15 @@ where
14731593
/// [`create_channel`]: Self::create_channel
14741594
/// [`close_channel`]: Self::force_close_broadcasting_latest_txn
14751595
/// [`force_close_broadcasting_latest_txn`]: Self::force_close_broadcasting_latest_txn
1596+
/// [BOLT 11]: https://github.com/lightning/bolts/blob/master/11-payment-encoding.md
1597+
/// [BOLT 12]: https://github.com/rustyrussell/lightning-rfc/blob/guilt/offers/12-offer-encoding.md
1598+
/// [`list_recent_payments`]: Self::list_recent_payments
1599+
/// [`abandon_payment`]: Self::abandon_payment
1600+
/// [`lightning-invoice`]: https://docs.rs/lightning_invoice/latest/lightning_invoice
1601+
/// [`create_inbound_payment`]: Self::create_inbound_payment
1602+
/// [`create_inbound_payment_for_hash`]: Self::create_inbound_payment_for_hash
1603+
/// [`claim_funds`]: Self::claim_funds
1604+
/// [`send_payment`]: Self::send_payment
14761605
/// [`peer_disconnected`]: msgs::ChannelMessageHandler::peer_disconnected
14771606
/// [`funding_created`]: msgs::FundingCreated
14781607
/// [`funding_transaction_generated`]: Self::funding_transaction_generated

0 commit comments

Comments
 (0)