7171 crate :: offers:: refund:: RefundMaybeWithDerivedMetadataBuilder ,
7272} ;
7373
74+ #[ cfg( feature = "dnssec" ) ]
75+ use crate :: onion_message:: dns_resolution:: { DNSResolverMessage , OMNameResolver } ;
76+
7477/// Functions commonly shared in usage between [`ChannelManager`] & `OffersMessageFlow`
7578///
7679/// [`ChannelManager`]: crate::ln::channelmanager::ChannelManager
@@ -80,6 +83,16 @@ pub trait OffersMessageCommons {
8083 & self ,
8184 ) -> MutexGuard < ' _ , Vec < ( OffersMessage , MessageSendInstructions ) > > ;
8285
86+ #[ cfg( feature = "dnssec" ) ]
87+ /// Get pending DNS onion messages
88+ fn get_pending_dns_onion_messages (
89+ & self ,
90+ ) -> MutexGuard < ' _ , Vec < ( DNSResolverMessage , MessageSendInstructions ) > > ;
91+
92+ #[ cfg( feature = "dnssec" ) ]
93+ /// Get hrn resolver
94+ fn get_hrn_resolver ( & self ) -> & OMNameResolver ;
95+
8396 /// Signs the [`TaggedHash`] of a BOLT 12 invoice.
8497 ///
8598 /// May be called by a function passed to [`UnsignedBolt12Invoice::sign`] where `invoice` is the
@@ -202,6 +215,13 @@ pub trait OffersMessageCommons {
202215 /// Get the approximate current time using the highest seen timestamp
203216 fn get_highest_seen_timestamp ( & self ) -> Duration ;
204217
218+ #[ cfg( feature = "dnssec" ) ]
219+ /// Add new awaiting offer
220+ fn add_new_awaiting_offer (
221+ & self , payment_id : PaymentId , expiration : StaleExpiration , retry_strategy : Retry ,
222+ max_total_routing_fee_msat : Option < u64 > , amount_msats : u64 ,
223+ ) -> Result < ( ) , ( ) > ;
224+
205225 /// Internal pay_for_offer
206226 fn pay_for_offer_intern <
207227 CPP : FnOnce ( & InvoiceRequest , Nonce ) -> Result < ( ) , Bolt12SemanticError > ,
@@ -1383,4 +1403,81 @@ where
13831403 Err ( ( ) ) => Err ( Bolt12SemanticError :: InvalidAmount ) ,
13841404 }
13851405 }
1406+
1407+ /// Pays for an [`Offer`] looked up using [BIP 353] Human Readable Names resolved by the DNS
1408+ /// resolver(s) at `dns_resolvers` which resolve names according to bLIP 32.
1409+ ///
1410+ /// If the wallet supports paying on-chain schemes, you should instead use
1411+ /// [`OMNameResolver::resolve_name`] and [`OMNameResolver::handle_dnssec_proof_for_uri`] (by
1412+ /// implementing [`DNSResolverMessageHandler`]) directly to look up a URI and then delegate to
1413+ /// your normal URI handling.
1414+ ///
1415+ /// If `max_total_routing_fee_msat` is not specified, the default from
1416+ /// [`RouteParameters::from_payment_params_and_value`] is applied.
1417+ ///
1418+ /// # Payment
1419+ ///
1420+ /// The provided `payment_id` is used to ensure that only one invoice is paid for the request
1421+ /// when received. See [Avoiding Duplicate Payments] for other requirements once the payment has
1422+ /// been sent.
1423+ ///
1424+ /// To revoke the request, use [`ChannelManager::abandon_payment`] prior to receiving the
1425+ /// invoice. If abandoned, or an invoice isn't received in a reasonable amount of time, the
1426+ /// payment will fail with an [`Event::InvoiceRequestFailed`].
1427+ ///
1428+ /// # Privacy
1429+ ///
1430+ /// For payer privacy, uses a derived payer id and uses [`MessageRouter::create_blinded_paths`]
1431+ /// to construct a [`BlindedPath`] for the reply path. For further privacy implications, see the
1432+ /// docs of the parameterized [`Router`], which implements [`MessageRouter`].
1433+ ///
1434+ /// # Limitations
1435+ ///
1436+ /// Requires a direct connection to the given [`Destination`] as well as an introduction node in
1437+ /// [`Offer::paths`] or to [`Offer::signing_pubkey`], if empty. A similar restriction applies to
1438+ /// the responding [`Bolt12Invoice::payment_paths`].
1439+ ///
1440+ /// # Errors
1441+ ///
1442+ /// Errors if:
1443+ /// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
1444+ ///
1445+ /// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths
1446+ /// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments
1447+ #[ cfg( feature = "dnssec" ) ]
1448+ pub fn pay_for_offer_from_human_readable_name (
1449+ & self , name : HumanReadableName , amount_msats : u64 , payment_id : PaymentId ,
1450+ retry_strategy : Retry , max_total_routing_fee_msat : Option < u64 > ,
1451+ dns_resolvers : Vec < Destination > ,
1452+ ) -> Result < ( ) , ( ) > {
1453+ let ( onion_message, context) = self . commons . get_hrn_resolver ( ) . resolve_name (
1454+ payment_id,
1455+ name,
1456+ & * self . entropy_source ,
1457+ ) ?;
1458+ let reply_paths =
1459+ self . commons . create_blinded_paths ( MessageContext :: DNSResolver ( context) ) ?;
1460+ let expiration = StaleExpiration :: TimerTicks ( 1 ) ;
1461+ self . commons . add_new_awaiting_offer (
1462+ payment_id,
1463+ expiration,
1464+ retry_strategy,
1465+ max_total_routing_fee_msat,
1466+ amount_msats,
1467+ ) ?;
1468+ let message_params = dns_resolvers
1469+ . iter ( )
1470+ . flat_map ( |destination| reply_paths. iter ( ) . map ( move |path| ( path, destination) ) )
1471+ . take ( OFFERS_MESSAGE_REQUEST_LIMIT ) ;
1472+ for ( reply_path, destination) in message_params {
1473+ self . commons . get_pending_dns_onion_messages ( ) . push ( (
1474+ DNSResolverMessage :: DNSSECQuery ( onion_message. clone ( ) ) ,
1475+ MessageSendInstructions :: WithSpecifiedReplyPath {
1476+ destination : destination. clone ( ) ,
1477+ reply_path : reply_path. clone ( ) ,
1478+ } ,
1479+ ) ) ;
1480+ }
1481+ Ok ( ( ) )
1482+ }
13861483}
0 commit comments