diff --git a/fuzz/src/full_stack.rs b/fuzz/src/full_stack.rs index 4591888e3f0..10328cdce81 100644 --- a/fuzz/src/full_stack.rs +++ b/fuzz/src/full_stack.rs @@ -870,7 +870,7 @@ mod tests { // our network key ext_from_hex("0100000000000000000000000000000000000000000000000000000000000000", &mut test); // config - ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff0001000000", &mut test); + ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff000100000000", &mut test); // new outbound connection with id 0 ext_from_hex("00", &mut test); @@ -1383,7 +1383,7 @@ mod tests { // our network key ext_from_hex("0100000000000000000000000000000000000000000000000000000000000000", &mut test); // config - ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff0001000000", &mut test); + ext_from_hex("0000000000900000000000000000640001000000000001ffff0000000000000000ffffffffffffffffffffffffffffffff0000000000000000ffffffffffffffff000000ffffffff00ffff1a000400010000020400000000040200000a08ffffffffffffffff000100000000", &mut test); // new outbound connection with id 0 ext_from_hex("00", &mut test); diff --git a/lightning/src/events/mod.rs b/lightning/src/events/mod.rs index f054a50ceb8..6212cfec5f0 100644 --- a/lightning/src/events/mod.rs +++ b/lightning/src/events/mod.rs @@ -19,18 +19,20 @@ pub mod bump_transaction; pub use bump_transaction::BumpTransactionEvent; use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext, PaymentContextRef}; -use crate::sign::SpendableOutputDescriptor; +use crate::chain::transaction; use crate::ln::channelmanager::{InterceptId, PaymentId, RecipientOnionFields}; use crate::ln::channel::FUNDING_CONF_DEADLINE_BLOCKS; use crate::ln::features::ChannelTypeFeatures; use crate::ln::msgs; use crate::ln::types::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret}; -use crate::chain::transaction; +use crate::offers::invoice::Bolt12Invoice; +use crate::onion_message::messenger::Responder; use crate::routing::gossip::NetworkUpdate; +use crate::routing::router::{BlindedTail, Path, RouteHop, RouteParameters}; +use crate::sign::SpendableOutputDescriptor; use crate::util::errors::APIError; use crate::util::ser::{BigSize, FixedLengthReader, Writeable, Writer, MaybeReadable, Readable, RequiredWrapper, UpgradableRequired, WithoutLength}; use crate::util::string::UntrustedString; -use crate::routing::router::{BlindedTail, Path, RouteHop, RouteParameters}; use bitcoin::{Transaction, OutPoint}; use bitcoin::blockdata::locktime::absolute::LockTime; @@ -715,6 +717,31 @@ pub enum Event { /// The `payment_id` to have been associated with payment for the requested invoice. payment_id: PaymentId, }, + /// Indicates a [`Bolt12Invoice`] in response to an [`InvoiceRequest`] or a [`Refund`] was + /// received. + /// + /// This event will only be generated if [`UserConfig::manually_handle_bolt12_invoices`] is set. + /// Use [`ChannelManager::send_payment_for_bolt12_invoice`] to pay the invoice or + /// [`ChannelManager::abandon_payment`] to abandon the associated payment. See those docs for + /// further details. + /// + /// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest + /// [`Refund`]: crate::offers::refund::Refund + /// [`UserConfig::manually_handle_bolt12_invoices`]: crate::util::config::UserConfig::manually_handle_bolt12_invoices + /// [`ChannelManager::send_payment_for_bolt12_invoice`]: crate::ln::channelmanager::ChannelManager::send_payment_for_bolt12_invoice + /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment + InvoiceReceived { + /// The `payment_id` associated with payment for the invoice. + payment_id: PaymentId, + /// The invoice to pay. + invoice: Bolt12Invoice, + /// A responder for replying with an [`InvoiceError`] if needed. + /// + /// `None` if the invoice wasn't sent with a reply path. + /// + /// [`InvoiceError`]: crate::offers::invoice_error::InvoiceError + responder: Option, + }, /// Indicates an outbound payment we made succeeded (i.e. it made it all the way to its target /// and we got back the payment preimage for it). /// @@ -1471,7 +1498,15 @@ impl Writeable for Event { write_tlv_fields!(writer, { (0, peer_node_id, required), }); - } + }, + &Event::InvoiceReceived { ref payment_id, ref invoice, ref responder } => { + 41u8.write(writer)?; + write_tlv_fields!(writer, { + (0, payment_id, required), + (2, invoice, required), + (4, responder, option), + }) + }, // Note that, going forward, all new events must only write data inside of // `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write // data via `write_tlv_fields`. @@ -1908,6 +1943,21 @@ impl MaybeReadable for Event { }; f() }, + 41u8 => { + let mut f = || { + _init_and_read_len_prefixed_tlv_fields!(reader, { + (0, payment_id, required), + (2, invoice, required), + (4, responder, option), + }); + Ok(Some(Event::InvoiceReceived { + payment_id: payment_id.0.unwrap(), + invoice: invoice.0.unwrap(), + responder, + })) + }; + f() + }, // Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue. // Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt // reads. diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index 80b98b2b6f5..ba07cd606b8 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -58,7 +58,7 @@ use crate::ln::onion_utils::{HTLCFailReason, INVALID_ONION_BLINDING}; use crate::ln::msgs::{ChannelMessageHandler, DecodeError, LightningError}; #[cfg(test)] use crate::ln::outbound_payment; -use crate::ln::outbound_payment::{Bolt12PaymentError, OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration}; +use crate::ln::outbound_payment::{OutboundPayments, PaymentAttempts, PendingOutboundPayment, SendAlongPathArgs, StaleExpiration}; use crate::ln::wire::Encode; use crate::offers::invoice::{BlindedPayInfo, Bolt12Invoice, DEFAULT_RELATIVE_EXPIRY, DerivedSigningPubkey, ExplicitSigningPubkey, InvoiceBuilder, UnsignedBolt12Invoice}; use crate::offers::invoice_error::InvoiceError; @@ -105,7 +105,7 @@ use core::time::Duration; use core::ops::Deref; // Re-export this for use in the public API. -pub use crate::ln::outbound_payment::{PaymentSendFailure, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields}; +pub use crate::ln::outbound_payment::{Bolt12PaymentError, PaymentSendFailure, ProbeSendFailure, Retry, RetryableSendFailure, RecipientOnionFields}; use crate::ln::script::ShutdownScript; // We hold various information about HTLC relay in the HTLC objects in Channel itself: @@ -3996,7 +3996,36 @@ where self.pending_outbound_payments.test_set_payment_metadata(payment_id, new_payment_metadata); } - pub(super) fn send_payment_for_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError> { + /// Pays the [`Bolt12Invoice`] associated with the `payment_id` encoded in its `payer_metadata`. + /// + /// The invoice's `payer_metadata` is used to authenticate that the invoice was indeed requested + /// before attempting a payment. [`Bolt12PaymentError::UnexpectedInvoice`] is returned if this + /// fails or if the encoded `payment_id` is not recognized. The latter may happen once the + /// payment is no longer tracked because the payment was attempted after: + /// - an invoice for the `payment_id` was already paid, + /// - one full [timer tick] has elapsed since initially requesting the invoice when paying an + /// offer, or + /// - the refund corresponding to the invoice has already expired. + /// + /// To retry the payment, request another invoice using a new `payment_id`. + /// + /// Attempting to pay the same invoice twice while the first payment is still pending will + /// result in a [`Bolt12PaymentError::DuplicateInvoice`]. + /// + /// Otherwise, either [`Event::PaymentSent`] or [`Event::PaymentFailed`] are used to indicate + /// whether or not the payment was successful. + /// + /// [timer tick]: Self::timer_tick_occurred + pub fn send_payment_for_bolt12_invoice(&self, invoice: &Bolt12Invoice) -> Result<(), Bolt12PaymentError> { + let secp_ctx = &self.secp_ctx; + let expanded_key = &self.inbound_payment_key; + match invoice.verify(expanded_key, secp_ctx) { + Ok(payment_id) => self.send_payment_for_verified_bolt12_invoice(invoice, payment_id), + Err(()) => Err(Bolt12PaymentError::UnexpectedInvoice), + } + } + + fn send_payment_for_verified_bolt12_invoice(&self, invoice: &Bolt12Invoice, payment_id: PaymentId) -> Result<(), Bolt12PaymentError> { let best_block_height = self.best_block.read().unwrap().height; let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self); self.pending_outbound_payments @@ -10272,42 +10301,45 @@ where }; match response { - Ok(invoice) => return responder.respond(OffersMessage::Invoice(invoice)), - Err(error) => return responder.respond(OffersMessage::InvoiceError(error.into())), + Ok(invoice) => responder.respond(OffersMessage::Invoice(invoice)), + Err(error) => responder.respond(OffersMessage::InvoiceError(error.into())), } }, OffersMessage::Invoice(invoice) => { - let response = invoice - .verify(expanded_key, secp_ctx) - .map_err(|()| InvoiceError::from_string("Unrecognized invoice".to_owned())) - .and_then(|payment_id| { + let result = match invoice.verify(expanded_key, secp_ctx) { + Ok(payment_id) => { let features = self.bolt12_invoice_features(); if invoice.invoice_features().requires_unknown_bits_from(&features) { Err(InvoiceError::from(Bolt12SemanticError::UnknownRequiredFeatures)) + } else if self.default_configuration.manually_handle_bolt12_invoices { + let event = Event::InvoiceReceived { payment_id, invoice, responder }; + self.pending_events.lock().unwrap().push_back((event, None)); + return ResponseInstruction::NoResponse; } else { - self.send_payment_for_bolt12_invoice(&invoice, payment_id) + self.send_payment_for_verified_bolt12_invoice(&invoice, payment_id) .map_err(|e| { log_trace!(self.logger, "Failed paying invoice: {:?}", e); InvoiceError::from_string(format!("{:?}", e)) }) } - }); + }, + Err(()) => Err(InvoiceError::from_string("Unrecognized invoice".to_owned())), + }; - match (responder, response) { - (Some(responder), Err(e)) => responder.respond(OffersMessage::InvoiceError(e)), - (None, Err(_)) => { - log_trace!( - self.logger, - "A response was generated, but there is no reply_path specified for sending the response." - ); - return ResponseInstruction::NoResponse; - } - _ => return ResponseInstruction::NoResponse, + match result { + Ok(()) => ResponseInstruction::NoResponse, + Err(e) => match responder { + Some(responder) => responder.respond(OffersMessage::InvoiceError(e)), + None => { + log_trace!(self.logger, "No reply path for sending invoice error: {:?}", e); + ResponseInstruction::NoResponse + }, + }, } }, OffersMessage::InvoiceError(invoice_error) => { log_trace!(self.logger, "Received invoice_error: {}", invoice_error); - return ResponseInstruction::NoResponse; + ResponseInstruction::NoResponse }, } } diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index c7fb5f8fd59..eca43afee8a 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -46,9 +46,10 @@ use core::time::Duration; use crate::blinded_path::{BlindedPath, IntroductionNode}; use crate::blinded_path::payment::{Bolt12OfferContext, Bolt12RefundContext, PaymentContext}; use crate::events::{Event, MessageSendEventsProvider, PaymentPurpose}; -use crate::ln::channelmanager::{MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, Retry, self}; +use crate::ln::channelmanager::{Bolt12PaymentError, MAX_SHORT_LIVED_RELATIVE_EXPIRY, PaymentId, RecentPaymentDetails, Retry, self}; use crate::ln::functional_test_utils::*; use crate::ln::msgs::{ChannelMessageHandler, Init, NodeAnnouncement, OnionMessage, OnionMessageHandler, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, UnsignedNodeAnnouncement}; +use crate::ln::outbound_payment::IDEMPOTENCY_TIMEOUT_TICKS; use crate::offers::invoice::Bolt12Invoice; use crate::offers::invoice_error::InvoiceError; use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestFields}; @@ -865,6 +866,90 @@ fn pays_for_refund_without_blinded_paths() { expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id); } +/// Checks that a deferred invoice can be paid asynchronously from an Event::InvoiceReceived. +#[test] +fn pays_bolt12_invoice_asynchronously() { + let mut manually_pay_cfg = test_default_channel_config(); + manually_pay_cfg.manually_handle_bolt12_invoices = true; + + let chanmon_cfgs = create_chanmon_cfgs(2); + let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); + let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, Some(manually_pay_cfg)]); + let nodes = create_network(2, &node_cfgs, &node_chanmgrs); + + create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000); + + let alice = &nodes[0]; + let alice_id = alice.node.get_our_node_id(); + let bob = &nodes[1]; + let bob_id = bob.node.get_our_node_id(); + + let offer = alice.node + .create_offer_builder(None).unwrap() + .amount_msats(10_000_000) + .build().unwrap(); + + let payment_id = PaymentId([1; 32]); + bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None).unwrap(); + expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id); + + let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); + alice.onion_messenger.handle_onion_message(&bob_id, &onion_message); + + let (invoice_request, _) = extract_invoice_request(alice, &onion_message); + let payment_context = PaymentContext::Bolt12Offer(Bolt12OfferContext { + offer_id: offer.id(), + invoice_request: InvoiceRequestFields { + payer_id: invoice_request.payer_id(), + quantity: None, + payer_note_truncated: None, + }, + }); + + let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap(); + bob.onion_messenger.handle_onion_message(&alice_id, &onion_message); + + let invoice = match get_event!(bob, Event::InvoiceReceived) { + Event::InvoiceReceived { payment_id: actual_payment_id, invoice, .. } => { + assert_eq!(actual_payment_id, payment_id); + invoice + }, + _ => panic!("No Event::InvoiceReceived"), + }; + assert_eq!(invoice.amount_msats(), 10_000_000); + assert_ne!(invoice.signing_pubkey(), alice_id); + assert!(!invoice.payment_paths().is_empty()); + for (_, path) in invoice.payment_paths() { + assert_eq!(path.introduction_node, IntroductionNode::NodeId(alice_id)); + } + + assert!(bob.node.send_payment_for_bolt12_invoice(&invoice).is_ok()); + assert_eq!( + bob.node.send_payment_for_bolt12_invoice(&invoice), + Err(Bolt12PaymentError::DuplicateInvoice), + ); + + route_bolt12_payment(bob, &[alice], &invoice); + expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id); + + claim_bolt12_payment(bob, &[alice], payment_context); + expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id); + + assert_eq!( + bob.node.send_payment_for_bolt12_invoice(&invoice), + Err(Bolt12PaymentError::DuplicateInvoice), + ); + + for _ in 0..=IDEMPOTENCY_TIMEOUT_TICKS { + bob.node.timer_tick_occurred(); + } + + assert_eq!( + bob.node.send_payment_for_bolt12_invoice(&invoice), + Err(Bolt12PaymentError::UnexpectedInvoice), + ); +} + /// Fails creating an offer when a blinded path cannot be created without exposing the node's id. #[test] fn fails_creating_offer_without_blinded_paths() { diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 2a9e52c83c7..3ae128cb3bb 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -501,9 +501,9 @@ pub enum PaymentSendFailure { }, } -/// An error when attempting to pay a BOLT 12 invoice. +/// An error when attempting to pay a [`Bolt12Invoice`]. #[derive(Clone, Debug, PartialEq, Eq)] -pub(super) enum Bolt12PaymentError { +pub enum Bolt12PaymentError { /// The invoice was not requested. UnexpectedInvoice, /// Payment for an invoice with the corresponding [`PaymentId`] was already initiated. diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 5482e6f83ea..0d5d2caaa7e 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -124,7 +124,7 @@ use crate::offers::parse::{Bolt12ParseError, Bolt12SemanticError, ParsedMessage} use crate::offers::payer::{PAYER_METADATA_TYPE, PayerTlvStream, PayerTlvStreamRef}; use crate::offers::refund::{IV_BYTES as REFUND_IV_BYTES, Refund, RefundContents}; use crate::offers::signer; -use crate::util::ser::{HighZeroBytesDroppedBigSize, Iterable, SeekReadable, WithoutLength, Writeable, Writer}; +use crate::util::ser::{HighZeroBytesDroppedBigSize, Iterable, Readable, SeekReadable, WithoutLength, Writeable, Writer}; use crate::util::string::PrintableString; #[allow(unused_imports)] @@ -1205,6 +1205,13 @@ impl Writeable for Bolt12Invoice { } } +impl Readable for Bolt12Invoice { + fn read(reader: &mut R) -> Result { + let bytes: WithoutLength> = Readable::read(reader)?; + Self::try_from(bytes.0).map_err(|_| DecodeError::InvalidValue) + } +} + impl Writeable for InvoiceContents { fn write(&self, writer: &mut W) -> Result<(), io::Error> { self.as_tlv_stream().write(writer) diff --git a/lightning/src/onion_message/messenger.rs b/lightning/src/onion_message/messenger.rs index ee49d00e99d..0fb72c52d27 100644 --- a/lightning/src/onion_message/messenger.rs +++ b/lightning/src/onion_message/messenger.rs @@ -325,12 +325,18 @@ impl OnionMessageRecipient { /// The `Responder` struct creates an appropriate [`ResponseInstruction`] /// for responding to a message. +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Responder { /// The path along which a response can be sent. reply_path: BlindedPath, path_id: Option<[u8; 32]> } +impl_writeable_tlv_based!(Responder, { + (0, reply_path, required), + (2, path_id, option), +}); + impl Responder { /// Creates a new [`Responder`] instance with the provided reply path. pub(super) fn new(reply_path: BlindedPath, path_id: Option<[u8; 32]>) -> Self { diff --git a/lightning/src/util/config.rs b/lightning/src/util/config.rs index 2473eea2627..4e124c27fd9 100644 --- a/lightning/src/util/config.rs +++ b/lightning/src/util/config.rs @@ -18,19 +18,19 @@ use crate::util::ser::Readable; /// Configuration we set when applicable. /// -/// Default::default() provides sane defaults. +/// `Default::default()` provides sane defaults. #[derive(Copy, Clone, Debug)] pub struct ChannelHandshakeConfig { /// Confirmations we will wait for before considering the channel locked in. - /// Applied only for inbound channels (see ChannelHandshakeLimits::max_minimum_depth for the + /// Applied only for inbound channels (see [`ChannelHandshakeLimits::max_minimum_depth`] for the /// equivalent limit applied to outbound channels). /// - /// A lower-bound of 1 is applied, requiring all channels to have a confirmed commitment + /// A lower-bound of `1` is applied, requiring all channels to have a confirmed commitment /// transaction before operation. If you wish to accept channels with zero confirmations, see /// [`UserConfig::manually_accept_inbound_channels`] and /// [`ChannelManager::accept_inbound_channel_from_trusted_peer_0conf`]. /// - /// Default value: 6. + /// Default value: `6` /// /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel /// [`ChannelManager::accept_inbound_channel_from_trusted_peer_0conf`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel_from_trusted_peer_0conf @@ -48,16 +48,16 @@ pub struct ChannelHandshakeConfig { /// case of an honest unilateral channel close, which implicitly decrease the economic value of /// our channel. /// - /// Default value: [`BREAKDOWN_TIMEOUT`], we enforce it as a minimum at channel opening so you - /// can tweak config to ask for more security, not less. + /// Default value: [`BREAKDOWN_TIMEOUT`] (We enforce it as a minimum at channel opening so you + /// can tweak config to ask for more security, not less.) pub our_to_self_delay: u16, /// Set to the smallest value HTLC we will accept to process. /// /// This value is sent to our counterparty on channel-open and we close the channel any time /// our counterparty misbehaves by sending us an HTLC with a value smaller than this. /// - /// Default value: 1. If the value is less than 1, it is ignored and set to 1, as is required - /// by the protocol. + /// Default value: `1` (If the value is less than `1`, it is ignored and set to `1`, as is + /// required by the protocol. pub our_htlc_minimum_msat: u64, /// Sets the percentage of the channel value we will cap the total value of outstanding inbound /// HTLCs to. @@ -66,7 +66,7 @@ pub struct ChannelHandshakeConfig { /// channel value in whole percentages. /// /// Note that: - /// * If configured to another value than the default value 10, any new channels created with + /// * If configured to another value than the default value `10`, any new channels created with /// the non default value will cause versions of LDK prior to 0.0.104 to refuse to read the /// `ChannelManager`. /// @@ -79,9 +79,11 @@ pub struct ChannelHandshakeConfig { /// See [`ChannelHandshakeConfig::our_to_self_delay`] and [`ChannelConfig::cltv_expiry_delta`] /// for more information. /// - /// Default value: 10. - /// Minimum value: 1, any values less than 1 will be treated as 1 instead. - /// Maximum value: 100, any values larger than 100 will be treated as 100 instead. + /// Default value: `10` + /// + /// Minimum value: `1` (Any values less will be treated as `1` instead.) + /// + /// Maximum value: `100` (Any values larger will be treated as `100` instead.) pub max_inbound_htlc_value_in_flight_percent_of_channel: u8, /// If set, we attempt to negotiate the `scid_privacy` (referred to as `scid_alias` in the /// BOLTs) option for outbound private channels. This provides better privacy by not including @@ -100,7 +102,7 @@ pub struct ChannelHandshakeConfig { /// [`ChannelHandshakeConfig::announced_channel`] and /// [`ChannelHandshakeLimits::force_announced_channel_preference`] for more. /// - /// Default value: false. This value is likely to change to true in the future. + /// Default value: `false` (This value is likely to change to `true` in the future.) /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager /// [`DecodeError::InvalidValue`]: crate::ln::msgs::DecodeError::InvalidValue @@ -113,7 +115,7 @@ pub struct ChannelHandshakeConfig { /// As the node which funds a channel picks this value this will only apply for new outbound /// channels unless [`ChannelHandshakeLimits::force_announced_channel_preference`] is set. /// - /// Default value: false. + /// Default value: `false` pub announced_channel: bool, /// When set, we commit to an upfront shutdown_pubkey at channel open. If our counterparty /// supports it, they will then enforce the mutual-close output to us matches what we provided @@ -125,7 +127,7 @@ pub struct ChannelHandshakeConfig { /// /// The upfront key committed is provided from [`SignerProvider::get_shutdown_scriptpubkey`]. /// - /// Default value: true. + /// Default value: `true` /// /// [`SignerProvider::get_shutdown_scriptpubkey`]: crate::sign::SignerProvider::get_shutdown_scriptpubkey pub commit_upfront_shutdown_pubkey: bool, @@ -146,11 +148,15 @@ pub struct ChannelHandshakeConfig { /// Note: Versions of LDK earlier than v0.0.104 will fail to read channels with any channel reserve /// other than the default value. /// - /// Default value: 1% of channel value, i.e., configured as 10,000 millionths. - /// Minimum value: If the calculated proportional value is less than 1000 sats, it will be treated - /// as 1000 sats instead, which is a safe implementation-specific lower bound. - /// Maximum value: 1,000,000, any values larger than 1 Million will be treated as 1 Million (or 100%) - /// instead, although channel negotiations will fail in that case. + /// Default value: `10_000` millionths (i.e., 1% of channel value) + /// + /// Minimum value: If the calculated proportional value is less than `1000` sats, it will be + /// treated as `1000` sats instead, which is a safe implementation-specific lower + /// bound. + /// + /// Maximum value: `1_000_000` (i.e., 100% of channel value. Any values larger than one million + /// will be treated as one million instead, although channel negotiations will + /// fail in that case.) pub their_channel_reserve_proportional_millionths: u32, /// If set, we attempt to negotiate the `anchors_zero_fee_htlc_tx`option for all future /// channels. This feature requires having a reserve of onchain funds readily available to bump @@ -174,7 +180,7 @@ pub struct ChannelHandshakeConfig { /// vulnerability after its deployment. For more context, see the [`SIGHASH_SINGLE + update_fee /// Considered Harmful`] mailing list post. /// - /// Default value: false. This value is likely to change to true in the future. + /// Default value: `false` (This value is likely to change to `true` in the future.) /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager /// [`ChannelManager::accept_inbound_channel`]: crate::ln::channelmanager::ChannelManager::accept_inbound_channel @@ -190,9 +196,10 @@ pub struct ChannelHandshakeConfig { /// Note: Versions of LDK earlier than v0.0.115 will fail to read channels with a configuration /// other than the default value. /// - /// Default value: 50 - /// Maximum value: 483, any values larger will be treated as 483. - /// This is the BOLT #2 spec limit on `max_accepted_htlcs`. + /// Default value: `50` + /// + /// Maximum value: `483` (Any values larger will be treated as `483`. This is the BOLT #2 spec + /// limit on `max_accepted_htlcs`.) pub our_max_accepted_htlcs: u16, } @@ -238,7 +245,7 @@ impl Readable for ChannelHandshakeConfig { /// /// These limits are only applied to our counterparty's limits, not our own. /// -/// Use 0/`::max_value()` as appropriate to skip checking. +/// Use `0` or `::max_value()` as appropriate to skip checking. /// /// Provides sane defaults for most configurations. /// @@ -250,40 +257,40 @@ pub struct ChannelHandshakeLimits { /// Minimum allowed satoshis when a channel is funded. This is supplied by the sender and so /// only applies to inbound channels. /// - /// Default value: 0. + /// Default value: `0` pub min_funding_satoshis: u64, /// Maximum allowed satoshis when a channel is funded. This is supplied by the sender and so /// only applies to inbound channels. /// - /// Default value: 2^24 - 1. + /// Default value: `2^24 - 1` pub max_funding_satoshis: u64, /// The remote node sets a limit on the minimum size of HTLCs we can send to them. This allows /// you to limit the maximum minimum-size they can require. /// - /// Default value: u64::max_value. + /// Default value: `u64::max_value` pub max_htlc_minimum_msat: u64, /// The remote node sets a limit on the maximum value of pending HTLCs to them at any given /// time to limit their funds exposure to HTLCs. This allows you to set a minimum such value. /// - /// Default value: 0. + /// Default value: `0` pub min_max_htlc_value_in_flight_msat: u64, /// The remote node will require we keep a certain amount in direct payment to ourselves at all /// time, ensuring that we are able to be punished if we broadcast an old state. This allows to /// you limit the amount which we will have to keep to ourselves (and cannot use for HTLCs). /// - /// Default value: u64::max_value. + /// Default value: `u64::max_value`. pub max_channel_reserve_satoshis: u64, /// The remote node sets a limit on the maximum number of pending HTLCs to them at any given /// time. This allows you to set a minimum such value. /// - /// Default value: 0. + /// Default value: `0` pub min_max_accepted_htlcs: u16, /// Before a channel is usable the funding transaction will need to be confirmed by at least a /// certain number of blocks, specified by the node which is not the funder (as the funder can /// assume they aren't going to double-spend themselves). /// This config allows you to set a limit on the maximum amount of time to wait. /// - /// Default value: 144, or roughly one day and only applies to outbound channels. + /// Default value: `144`, or roughly one day and only applies to outbound channels pub max_minimum_depth: u32, /// Whether we implicitly trust funding transactions generated by us for our own outbound /// channels to not be double-spent. @@ -296,12 +303,12 @@ pub struct ChannelHandshakeLimits { /// You may wish to un-set this if you allow the user to (or do in an automated fashion) /// double-spend the funding transaction to RBF with an alternative channel open. /// - /// This only applies if our counterparty set their confirmations-required value to 0, and we - /// always trust our own funding transaction at 1 confirmation irrespective of this value. + /// This only applies if our counterparty set their confirmations-required value to `0`, and we + /// always trust our own funding transaction at `1` confirmation irrespective of this value. /// Thus, this effectively acts as a `min_minimum_depth`, with the only possible values being - /// `true` (0) and `false` (1). + /// `true` (`0`) and `false` (`1`). /// - /// Default value: true + /// Default value: `true` pub trust_own_funding_0conf: bool, /// Set to force an incoming channel to match our announced channel preference in /// [`ChannelHandshakeConfig::announced_channel`]. @@ -310,14 +317,14 @@ pub struct ChannelHandshakeLimits { /// [`ChannelHandshakeConfig::announced_channel`] set to false, ensuring that no announced (aka public) /// channels will ever be opened. /// - /// Default value: true. + /// Default value: `true` pub force_announced_channel_preference: bool, /// Set to the amount of time we're willing to wait to claim money back to us. /// /// Not checking this value would be a security issue, as our peer would be able to set it to /// max relative lock-time (a year) and we would "lose" money as it would be locked for a long time. /// - /// Default value: 2016, which we also enforce as a maximum value so you can tweak config to + /// Default value: `2016`, which we also enforce as a maximum value so you can tweak config to /// reduce the loss of having useless locked funds (if your peer accepts) pub their_to_self_delay: u16 } @@ -417,7 +424,7 @@ pub struct ChannelConfig { /// This may be allowed to change at runtime in a later update, however doing so must result in /// update messages sent to notify all nodes of our updated relay fee. /// - /// Default value: 0. + /// Default value: `0` pub forwarding_fee_proportional_millionths: u32, /// Amount (in milli-satoshi) charged for payments forwarded outbound over the channel, in /// excess of [`forwarding_fee_proportional_millionths`]. @@ -428,7 +435,7 @@ pub struct ChannelConfig { /// as of July 2021. Adjusting it upwards or downwards may change whether nodes route through /// this node. /// - /// Default value: 1000. + /// Default value: `1000` /// /// [`forwarding_fee_proportional_millionths`]: ChannelConfig::forwarding_fee_proportional_millionths pub forwarding_fee_base_msat: u32, @@ -446,9 +453,10 @@ pub struct ChannelConfig { /// enough time to broadcast and confirm a transaction, possibly with time in between to RBF /// the spending transaction). /// - /// Default value: 72 (12 hours at an average of 6 blocks/hour). - /// Minimum value: [`MIN_CLTV_EXPIRY_DELTA`], any values less than this will be treated as - /// [`MIN_CLTV_EXPIRY_DELTA`] instead. + /// Default value: `72` (12 hours at an average of 6 blocks/hour) + /// + /// Minimum value: [`MIN_CLTV_EXPIRY_DELTA`] (Any values less than this will be treated as + /// [`MIN_CLTV_EXPIRY_DELTA`] instead.) /// /// [`MIN_CLTV_EXPIRY_DELTA`]: crate::ln::channelmanager::MIN_CLTV_EXPIRY_DELTA pub cltv_expiry_delta: u16, @@ -508,7 +516,7 @@ pub struct ChannelConfig { /// while we use [`ConfirmationTarget::OnChainSweep`] (which should be relatively high) and /// feerate disagreement force-closures should only occur when theirs is higher than ours. /// - /// Default value: [`MaxDustHTLCExposure::FeeRateMultiplier`] with a multiplier of 10_000. + /// Default value: [`MaxDustHTLCExposure::FeeRateMultiplier`] with a multiplier of `10_000` /// /// [`ConfirmationTarget::OnChainSweep`]: crate::chain::chaininterface::ConfirmationTarget::OnChainSweep pub max_dust_htlc_exposure: MaxDustHTLCExposure, @@ -530,7 +538,7 @@ pub struct ChannelConfig { /// [`ChannelCloseMinimum`] fee estimate, but allow our counterparty to pay as much fee as they like. /// Thus, this value is ignored when we are not the funder. /// - /// Default value: 1000 satoshis. + /// Default value: `1000` /// /// [`NonAnchorChannelFee`]: crate::chain::chaininterface::ConfirmationTarget::NonAnchorChannelFee /// [`ChannelCloseMinimum`]: crate::chain::chaininterface::ConfirmationTarget::ChannelCloseMinimum @@ -558,7 +566,7 @@ pub struct ChannelConfig { /// Switching this config flag on may break compatibility with versions of LDK prior to 0.0.116. /// Unsetting this flag between restarts may lead to payment receive failures. /// - /// Default value: false. + /// Default value: `false` /// /// [intercept scids]: crate::ln::channelmanager::ChannelManager::get_intercept_scid /// [`forward_intercepted_htlc`]: crate::ln::channelmanager::ChannelManager::forward_intercepted_htlc @@ -781,8 +789,8 @@ impl crate::util::ser::Readable for LegacyChannelConfig { /// Top-level config which holds ChannelHandshakeLimits and ChannelConfig. /// -/// Default::default() provides sane defaults for most configurations -/// (but currently with 0 relay fees!) +/// `Default::default()` provides sane defaults for most configurations +/// (but currently with zero relay fees!) #[derive(Copy, Clone, Debug)] pub struct UserConfig { /// Channel handshake config that we propose to our counterparty. @@ -791,13 +799,13 @@ pub struct UserConfig { pub channel_handshake_limits: ChannelHandshakeLimits, /// Channel config which affects behavior during channel lifetime. pub channel_config: ChannelConfig, - /// If this is set to false, we will reject any HTLCs which were to be forwarded over private + /// If this is set to `false`, we will reject any HTLCs which were to be forwarded over private /// channels. This prevents us from taking on HTLC-forwarding risk when we intend to run as a /// node which is not online reliably. /// /// For nodes which are not online reliably, you should set all channels to *not* be announced /// (using [`ChannelHandshakeConfig::announced_channel`] and - /// [`ChannelHandshakeLimits::force_announced_channel_preference`]) and set this to false to + /// [`ChannelHandshakeLimits::force_announced_channel_preference`]) and set this to `false` to /// ensure you are not exposed to any forwarding risk. /// /// Note that because you cannot change a channel's announced state after creation, there is no @@ -806,47 +814,62 @@ pub struct UserConfig { /// all your channels and open new ones. For privacy, you should also change your node_id /// (swapping all private and public key material for new ones) at that time. /// - /// Default value: false. + /// Default value: `false` pub accept_forwards_to_priv_channels: bool, - /// If this is set to false, we do not accept inbound requests to open a new channel. - /// Default value: true. + /// If this is set to `false`, we do not accept inbound requests to open a new channel. + /// + /// Default value: `true` pub accept_inbound_channels: bool, - /// If this is set to true, the user needs to manually accept inbound requests to open a new + /// If this is set to `true`, the user needs to manually accept inbound requests to open a new /// channel. /// - /// When set to true, [`Event::OpenChannelRequest`] will be triggered once a request to open a + /// When set to `true`, [`Event::OpenChannelRequest`] will be triggered once a request to open a /// new inbound channel is received through a [`msgs::OpenChannel`] message. In that case, a /// [`msgs::AcceptChannel`] message will not be sent back to the counterparty node unless the /// user explicitly chooses to accept the request. /// - /// Default value: false. + /// Default value: `false` /// /// [`Event::OpenChannelRequest`]: crate::events::Event::OpenChannelRequest /// [`msgs::OpenChannel`]: crate::ln::msgs::OpenChannel /// [`msgs::AcceptChannel`]: crate::ln::msgs::AcceptChannel pub manually_accept_inbound_channels: bool, - /// If this is set to true, LDK will intercept HTLCs that are attempting to be forwarded over + /// If this is set to `true`, LDK will intercept HTLCs that are attempting to be forwarded over /// fake short channel ids generated via [`ChannelManager::get_intercept_scid`]. Upon HTLC /// intercept, LDK will generate an [`Event::HTLCIntercepted`] which MUST be handled by the user. /// - /// Setting this to true may break backwards compatibility with LDK versions < 0.0.113. + /// Setting this to `true` may break backwards compatibility with LDK versions < 0.0.113. /// - /// Default value: false. + /// Default value: `false` /// /// [`ChannelManager::get_intercept_scid`]: crate::ln::channelmanager::ChannelManager::get_intercept_scid /// [`Event::HTLCIntercepted`]: crate::events::Event::HTLCIntercepted pub accept_intercept_htlcs: bool, - /// If this is set to false, when receiving a keysend payment we'll fail it if it has multiple - /// parts. If this is set to true, we'll accept the payment. + /// If this is set to `false`, when receiving a keysend payment we'll fail it if it has multiple + /// parts. If this is set to `true`, we'll accept the payment. /// - /// Setting this to true will break backwards compatibility upon downgrading to an LDK - /// version < 0.0.116 while receiving an MPP keysend. If we have already received an MPP + /// Setting this to `true` will break backwards compatibility upon downgrading to an LDK + /// version prior to 0.0.116 while receiving an MPP keysend. If we have already received an MPP /// keysend, downgrading will cause us to fail to deserialize [`ChannelManager`]. /// - /// Default value: false. + /// Default value: `false` /// /// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager pub accept_mpp_keysend: bool, + /// If this is set to `true`, the user needs to manually pay [`Bolt12Invoice`]s when received. + /// + /// When set to `true`, [`Event::InvoiceReceived`] will be generated for each received + /// [`Bolt12Invoice`] instead of being automatically paid after verification. Use + /// [`ChannelManager::send_payment_for_bolt12_invoice`] to pay the invoice or + /// [`ChannelManager::abandon_payment`] to abandon the associated payment. + /// + /// Default value: `false` + /// + /// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice + /// [`Event::InvoiceReceived`]: crate::events::Event::InvoiceReceived + /// [`ChannelManager::send_payment_for_bolt12_invoice`]: crate::ln::channelmanager::ChannelManager::send_payment_for_bolt12_invoice + /// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment + pub manually_handle_bolt12_invoices: bool, } impl Default for UserConfig { @@ -860,6 +883,7 @@ impl Default for UserConfig { manually_accept_inbound_channels: false, accept_intercept_htlcs: false, accept_mpp_keysend: false, + manually_handle_bolt12_invoices: false, } } } @@ -879,6 +903,7 @@ impl Readable for UserConfig { manually_accept_inbound_channels: Readable::read(reader)?, accept_intercept_htlcs: Readable::read(reader)?, accept_mpp_keysend: Readable::read(reader)?, + manually_handle_bolt12_invoices: Readable::read(reader)?, }) } }