@@ -72,6 +72,7 @@ use crate::offers::parse::Bolt12SemanticError;
72
72
use crate::offers::refund::{Refund, RefundBuilder};
73
73
use crate::offers::signer;
74
74
use crate::onion_message::async_payments::{AsyncPaymentsMessage, HeldHtlcAvailable, ReleaseHeldHtlc, AsyncPaymentsMessageHandler};
75
+ use crate::onion_message::dns_resolution::HumanReadableName;
75
76
use crate::onion_message::messenger::{Destination, MessageRouter, Responder, ResponseInstruction, MessageSendInstructions};
76
77
use crate::onion_message::offers::{OffersMessage, OffersMessageHandler};
77
78
use crate::sign::{EntropySource, NodeSigner, Recipient, SignerProvider};
@@ -84,6 +85,11 @@ use crate::util::ser::{BigSize, FixedLengthReader, Readable, ReadableArgs, Maybe
84
85
use crate::util::logger::{Level, Logger, WithContext};
85
86
use crate::util::errors::APIError;
86
87
88
+ #[cfg(feature = "dnssec")]
89
+ use crate::blinded_path::message::DNSResolverContext;
90
+ #[cfg(feature = "dnssec")]
91
+ use crate::onion_message::dns_resolution::{DNSResolverMessage, DNSResolverMessageHandler, DNSSECQuery, DNSSECProof, OMNameResolver};
92
+
87
93
#[cfg(not(c_bindings))]
88
94
use {
89
95
crate::offers::offer::DerivedMetadata,
@@ -2300,6 +2306,11 @@ where
2300
2306
/// [`ConfirmationTarget::MinAllowedNonAnchorChannelRemoteFee`] estimate.
2301
2307
last_days_feerates: Mutex<VecDeque<(u32, u32)>>,
2302
2308
2309
+ #[cfg(feature = "dnssec")]
2310
+ dns_resolver: OMNameResolver,
2311
+ #[cfg(feature = "dnssec")]
2312
+ pending_dns_onion_messages: Mutex<Vec<(DNSResolverMessage, MessageSendInstructions)>>,
2313
+
2303
2314
entropy_source: ES,
2304
2315
node_signer: NS,
2305
2316
signer_provider: SP,
@@ -3110,6 +3121,11 @@ where
3110
3121
signer_provider,
3111
3122
3112
3123
logger,
3124
+
3125
+ #[cfg(feature = "dnssec")]
3126
+ dns_resolver: OMNameResolver::new(current_timestamp, params.best_block.height),
3127
+ #[cfg(feature = "dnssec")]
3128
+ pending_dns_onion_messages: Mutex::new(Vec::new()),
3113
3129
}
3114
3130
}
3115
3131
@@ -9059,6 +9075,21 @@ where
9059
9075
&self, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>,
9060
9076
payer_note: Option<String>, payment_id: PaymentId, retry_strategy: Retry,
9061
9077
max_total_routing_fee_msat: Option<u64>
9078
+ ) -> Result<(), Bolt12SemanticError> {
9079
+ self.pay_for_offer_intern(offer, quantity, amount_msats, payer_note, payment_id, None, || {
9080
+ let expiration = StaleExpiration::TimerTicks(1);
9081
+ self.pending_outbound_payments
9082
+ .add_new_awaiting_invoice(
9083
+ payment_id, expiration, retry_strategy, max_total_routing_fee_msat
9084
+ )
9085
+ .map_err(|_| Bolt12SemanticError::DuplicatePaymentId)
9086
+ })
9087
+ }
9088
+
9089
+ fn pay_for_offer_intern<CPP: FnOnce() -> Result<(), Bolt12SemanticError>>(
9090
+ &self, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>,
9091
+ payer_note: Option<String>, payment_id: PaymentId,
9092
+ human_readable_name: Option<HumanReadableName>, create_pending_payment: CPP,
9062
9093
) -> Result<(), Bolt12SemanticError> {
9063
9094
let expanded_key = &self.inbound_payment_key;
9064
9095
let entropy = &*self.entropy_source;
@@ -9082,6 +9113,10 @@ where
9082
9113
None => builder,
9083
9114
Some(payer_note) => builder.payer_note(payer_note),
9084
9115
};
9116
+ let builder = match human_readable_name {
9117
+ None => builder,
9118
+ Some(hrn) => builder.sourced_from_human_readable_name(hrn),
9119
+ };
9085
9120
let invoice_request = builder.build_and_sign()?;
9086
9121
9087
9122
let hmac = payment_id.hmac_for_offer_payment(nonce, expanded_key);
@@ -9091,12 +9126,7 @@ where
9091
9126
9092
9127
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
9093
9128
9094
- let expiration = StaleExpiration::TimerTicks(1);
9095
- self.pending_outbound_payments
9096
- .add_new_awaiting_invoice(
9097
- payment_id, expiration, retry_strategy, max_total_routing_fee_msat
9098
- )
9099
- .map_err(|_| Bolt12SemanticError::DuplicatePaymentId)?;
9129
+ create_pending_payment()?;
9100
9130
9101
9131
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
9102
9132
if !offer.paths().is_empty() {
@@ -9227,6 +9257,77 @@ where
9227
9257
}
9228
9258
}
9229
9259
9260
+ /// Pays for an [`Offer`] looked up using [BIP 353] Human Readable Names resolved by the DNS
9261
+ /// resolver which resolves names according to bLIP 32 at the `dns_resolver` [`Destination`].
9262
+ ///
9263
+ /// If the wallet supports paying on-chain schemes, you should instead use
9264
+ /// [`OMNameResolver::resolve_name`] and [`OMNameResolver::handle_dnssec_proof_for_uri`] (by
9265
+ /// implementing [`DNSResolverMessageHandler`]) directly to look up a URI and then delegate to
9266
+ /// your normal URI handling.
9267
+ ///
9268
+ /// If `max_total_routing_fee_msat` is not specified, The default from
9269
+ /// [`RouteParameters::from_payment_params_and_value`] is applied.
9270
+ ///
9271
+ /// # Payment
9272
+ ///
9273
+ /// The provided `payment_id` is used to ensure that only one invoice is paid for the request
9274
+ /// when received. See [Avoiding Duplicate Payments] for other requirements once the payment has
9275
+ /// been sent.
9276
+ ///
9277
+ /// To revoke the request, use [`ChannelManager::abandon_payment`] prior to receiving the
9278
+ /// invoice. If abandoned, or an invoice isn't received in a reasonable amount of time, the
9279
+ /// payment will fail with an [`Event::InvoiceRequestFailed`].
9280
+ ///
9281
+ /// # Privacy
9282
+ ///
9283
+ /// For payer privacy, uses a derived payer id and uses [`MessageRouter::create_blinded_paths`]
9284
+ /// to construct a [`BlindedPath`] for the reply path. For further privacy implications, see the
9285
+ /// docs of the parameterized [`Router`], which implements [`MessageRouter`].
9286
+ ///
9287
+ /// # Limitations
9288
+ ///
9289
+ /// Requires a direct connection to the given [`Destination`] as well as an introduction node in
9290
+ /// [`Offer::paths`] or to [`Offer::signing_pubkey`], if empty. A similar restriction applies to
9291
+ /// the responding [`Bolt12Invoice::payment_paths`].
9292
+ ///
9293
+ /// # Errors
9294
+ ///
9295
+ /// Errors if:
9296
+ /// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
9297
+ ///
9298
+ /// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths
9299
+ /// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments
9300
+ #[cfg(feature = "dnssec")]
9301
+ pub fn pay_for_offer_from_human_readable_name(
9302
+ &self, name: HumanReadableName, amount_msats: u64, payment_id: PaymentId,
9303
+ retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>,
9304
+ dns_resolvers: Vec<Destination>,
9305
+ ) -> Result<(), ()> {
9306
+ let mut context = DNSResolverContext {
9307
+ nonce: [0; 16],
9308
+ };
9309
+ context.nonce[..].copy_from_slice(&self.entropy_source.get_secure_random_bytes()[..16]);
9310
+
9311
+ let onion_message = self.dns_resolver.resolve_name(payment_id, name.clone(), context.clone())?;
9312
+ let reply_paths = self.create_blinded_paths(MessageContext::DNSResolver(context))?;
9313
+ let expiration = StaleExpiration::TimerTicks(2);
9314
+ self.pending_outbound_payments.add_new_awaiting_offer(payment_id, expiration, retry_strategy, max_total_routing_fee_msat, amount_msats, name)?;
9315
+ let message_params = dns_resolvers
9316
+ .iter()
9317
+ .flat_map(|destination| reply_paths.iter().map(move |path| (path, destination)))
9318
+ .take(OFFERS_MESSAGE_REQUEST_LIMIT);
9319
+ for (reply_path, destination) in message_params {
9320
+ self.pending_dns_onion_messages.lock().unwrap().push((
9321
+ DNSResolverMessage::DNSSECQuery(onion_message.clone()),
9322
+ MessageSendInstructions::WithSpecifiedReplyPath {
9323
+ destination: destination.clone(),
9324
+ reply_path: reply_path.clone(),
9325
+ },
9326
+ ));
9327
+ }
9328
+ Ok(())
9329
+ }
9330
+
9230
9331
/// Gets a payment secret and payment hash for use in an invoice given to a third party wishing
9231
9332
/// to pay us.
9232
9333
///
@@ -9850,6 +9951,10 @@ where
9850
9951
payment_secrets.retain(|_, inbound_payment| {
9851
9952
inbound_payment.expiry_time > header.time as u64
9852
9953
});
9954
+ #[cfg(feature = "dnssec")] {
9955
+ let timestamp = self.highest_seen_timestamp.load(Ordering::Relaxed) as u32;
9956
+ self.dns_resolver.new_best_block(height, timestamp);
9957
+ }
9853
9958
}
9854
9959
9855
9960
fn get_relevant_txids(&self) -> Vec<(Txid, u32, Option<BlockHash>)> {
@@ -11004,6 +11109,56 @@ where
11004
11109
}
11005
11110
}
11006
11111
11112
+ #[cfg(feature = "dnssec")]
11113
+ impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>
11114
+ DNSResolverMessageHandler for ChannelManager<M, T, ES, NS, SP, F, R, L>
11115
+ where
11116
+ M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
11117
+ T::Target: BroadcasterInterface,
11118
+ ES::Target: EntropySource,
11119
+ NS::Target: NodeSigner,
11120
+ SP::Target: SignerProvider,
11121
+ F::Target: FeeEstimator,
11122
+ R::Target: Router,
11123
+ L::Target: Logger,
11124
+ {
11125
+ fn dnssec_query(
11126
+ &self, _message: DNSSECQuery, _responder: Option<Responder>,
11127
+ ) -> Option<(DNSResolverMessage, ResponseInstruction)> {
11128
+ None
11129
+ }
11130
+
11131
+ fn dnssec_proof(&self, message: DNSSECProof, context: DNSResolverContext) {
11132
+ let offer_opt = self.dns_resolver.handle_dnssec_proof_for_offer(message, context);
11133
+ if let Some((completed_requests, offer)) = offer_opt {
11134
+ for (name, payment_id) in completed_requests {
11135
+ if let Ok((amt_msats, _hrn)) = self.pending_outbound_payments.received_offer(payment_id) {
11136
+ debug_assert_eq!(name, _hrn);
11137
+ let offer_pay_res =
11138
+ self.pay_for_offer_intern(&offer, None, Some(amt_msats), None, payment_id, Some(name), || {
11139
+ // We already marked the payment as in-flight
11140
+ Ok(())
11141
+ });
11142
+ if offer_pay_res.is_err() {
11143
+ // The offer we tried to pay is the canonical current offer for the name we
11144
+ // wanted to pay. If we can't pay it, there's no way to recover so fail the
11145
+ // payment.
11146
+ // Note that the PaymentFailureReason should be ignored for an
11147
+ // AwaitingInvoice payment.
11148
+ self.pending_outbound_payments.abandon_payment(
11149
+ payment_id, PaymentFailureReason::RouteNotFound, &self.pending_events,
11150
+ );
11151
+ }
11152
+ }
11153
+ }
11154
+ }
11155
+ }
11156
+
11157
+ fn release_pending_messages(&self) -> Vec<(DNSResolverMessage, MessageSendInstructions)> {
11158
+ core::mem::take(&mut self.pending_dns_onion_messages.lock().unwrap())
11159
+ }
11160
+ }
11161
+
11007
11162
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, L: Deref>
11008
11163
NodeIdLookUp for ChannelManager<M, T, ES, NS, SP, F, R, L>
11009
11164
where
@@ -12745,6 +12900,11 @@ where
12745
12900
12746
12901
logger: args.logger,
12747
12902
default_configuration: args.default_config,
12903
+
12904
+ #[cfg(feature = "dnssec")]
12905
+ dns_resolver: OMNameResolver::new(highest_seen_timestamp, best_block_height),
12906
+ #[cfg(feature = "dnssec")]
12907
+ pending_dns_onion_messages: Mutex::new(Vec::new()),
12748
12908
};
12749
12909
12750
12910
for htlc_source in failed_htlcs.drain(..) {
0 commit comments