Skip to content

Commit b1b28ca

Browse files
committed
Move DNSResolverMessageHandler impl to OffersMessageFlow
1 parent d94a368 commit b1b28ca

File tree

6 files changed

+234
-164
lines changed

6 files changed

+234
-164
lines changed

lightning-dns-resolver/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ mod test {
393393
// When we get the proof back, override its contents to an offer from nodes[1]
394394
let bs_offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
395395
nodes[0]
396-
.node
396+
.offers_handler
397397
.testing_dnssec_proof_offer_resolution_override
398398
.lock()
399399
.unwrap()
@@ -404,7 +404,7 @@ mod test {
404404
let retry = Retry::Attempts(0);
405405
let amt = 42_000;
406406
nodes[0]
407-
.node
407+
.offers_handler
408408
.pay_for_offer_from_human_readable_name(name, amt, payment_id, retry, None, resolvers)
409409
.unwrap();
410410

lightning/src/ln/channelmanager.rs

Lines changed: 37 additions & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,7 @@ use crate::util::errors::APIError;
9393
};
9494

9595
#[cfg(feature = "dnssec")]
96-
use crate::blinded_path::message::DNSResolverContext;
97-
#[cfg(feature = "dnssec")]
98-
use crate::onion_message::dns_resolution::{DNSResolverMessage, DNSResolverMessageHandler, DNSSECQuery, DNSSECProof, OMNameResolver};
96+
use crate::onion_message::dns_resolution::OMNameResolver;
9997

10098
#[cfg(not(c_bindings))]
10199
use {
@@ -2670,16 +2668,6 @@ where
26702668

26712669
#[cfg(feature = "dnssec")]
26722670
hrn_resolver: OMNameResolver,
2673-
#[cfg(feature = "dnssec")]
2674-
pending_dns_onion_messages: Mutex<Vec<(DNSResolverMessage, MessageSendInstructions)>>,
2675-
2676-
#[cfg(feature = "_test_utils")]
2677-
/// In testing, it is useful be able to forge a name -> offer mapping so that we can pay an
2678-
/// offer generated in the test.
2679-
///
2680-
/// This allows for doing so, validating proofs as normal, but, if they pass, replacing the
2681-
/// offer they resolve to to the given one.
2682-
pub testing_dnssec_proof_offer_resolution_override: Mutex<HashMap<HumanReadableName, Offer>>,
26832671

26842672
#[cfg(test)]
26852673
pub(super) entropy_source: ES,
@@ -3604,11 +3592,6 @@ where
36043592

36053593
#[cfg(feature = "dnssec")]
36063594
hrn_resolver: OMNameResolver::new(current_timestamp, params.best_block.height),
3607-
#[cfg(feature = "dnssec")]
3608-
pending_dns_onion_messages: Mutex::new(Vec::new()),
3609-
3610-
#[cfg(feature = "_test_utils")]
3611-
testing_dnssec_proof_offer_resolution_override: Mutex::new(new_hash_map()),
36123595
}
36133596
}
36143597

@@ -9937,6 +9920,11 @@ where
99379920
Duration::from_secs(self.highest_seen_timestamp.load(Ordering::Acquire) as u64)
99389921
}
99399922

9923+
#[cfg(feature = "dnssec")]
9924+
fn get_hrn_resolver(&self) -> &OMNameResolver {
9925+
&self.hrn_resolver
9926+
}
9927+
99409928
fn get_peer_for_blinded_path(&self) -> Vec<MessageForwardNode> {
99419929
self.per_peer_state.read().unwrap()
99429930
.iter()
@@ -9983,6 +9971,26 @@ where
99839971
self.abandon_payment_with_reason(payment_id, reason);
99849972
}
99859973

9974+
#[cfg(feature = "dnssec")]
9975+
fn add_new_awaiting_offer(
9976+
&self, payment_id: PaymentId, expiration: StaleExpiration, retry_strategy: Retry,
9977+
max_total_routing_fee_msat: Option<u64>, amount_msats: u64,
9978+
) -> Result<(), ()> {
9979+
self.pending_outbound_payments.add_new_awaiting_offer(payment_id, expiration, retry_strategy, max_total_routing_fee_msat, amount_msats)
9980+
}
9981+
9982+
#[cfg(feature = "dnssec")]
9983+
fn amt_msats_for_payment_awaiting_offer(&self, payment_id: PaymentId) -> Result<u64, ()> {
9984+
self.pending_outbound_payments.amt_msats_for_payment_awaiting_offer(payment_id)
9985+
}
9986+
9987+
#[cfg(feature = "dnssec")]
9988+
fn received_offer(
9989+
&self, payment_id: PaymentId, retryable_invoice_request: Option<RetryableInvoiceRequest>,
9990+
) -> Result<(), ()> {
9991+
self.pending_outbound_payments.received_offer(payment_id, retryable_invoice_request)
9992+
}
9993+
99869994
// ----Temporary Functions----
99879995
// Set of functions temporarily moved to OffersMessageCommons for easier
99889996
// transition of code from ChannelManager to OffersMessageFlow
@@ -9995,6 +10003,14 @@ where
999510003
self.enqueue_invoice_request(invoice_request, reply_paths)
999610004
}
999710005

10006+
fn pay_for_offer_intern<CPP: FnOnce(&InvoiceRequest, Nonce) -> Result<(), Bolt12SemanticError>>(
10007+
&self, offer: &Offer, quantity: Option<u64>, amount_msats: Option<u64>,
10008+
payer_note: Option<String>, payment_id: PaymentId,
10009+
human_readable_name: Option<HumanReadableName>, create_pending_payment: CPP,
10010+
) -> Result<(), Bolt12SemanticError> {
10011+
self.pay_for_offer_intern(offer, quantity, amount_msats, payer_note, payment_id, human_readable_name, create_pending_payment)
10012+
}
10013+
999810014
#[cfg(async_payments)]
999910015
fn initiate_async_payment(
1000010016
&self, invoice: &StaticInvoice, payment_id: PaymentId
@@ -10008,7 +10024,7 @@ where
1000810024
/// Sending multiple requests increases the chances of successful delivery in case some
1000910025
/// paths are unavailable. However, only one invoice for a given [`PaymentId`] will be paid,
1001010026
/// even if multiple invoices are received.
10011-
const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
10027+
pub(crate) const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
1001210028

1001310029
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref> ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
1001410030
where
@@ -10229,7 +10245,8 @@ where
1022910245
let reply_paths = self.create_blinded_paths(context)
1023010246
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
1023110247

10232-
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
10248+
// Temporarily removing this to find the best way to integrate the guard
10249+
// let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
1023310250

1023410251
create_pending_payment(&invoice_request, nonce)?;
1023510252

@@ -10372,73 +10389,6 @@ where
1037210389
}
1037310390
}
1037410391

10375-
/// Pays for an [`Offer`] looked up using [BIP 353] Human Readable Names resolved by the DNS
10376-
/// resolver(s) at `dns_resolvers` which resolve names according to bLIP 32.
10377-
///
10378-
/// If the wallet supports paying on-chain schemes, you should instead use
10379-
/// [`OMNameResolver::resolve_name`] and [`OMNameResolver::handle_dnssec_proof_for_uri`] (by
10380-
/// implementing [`DNSResolverMessageHandler`]) directly to look up a URI and then delegate to
10381-
/// your normal URI handling.
10382-
///
10383-
/// If `max_total_routing_fee_msat` is not specified, the default from
10384-
/// [`RouteParameters::from_payment_params_and_value`] is applied.
10385-
///
10386-
/// # Payment
10387-
///
10388-
/// The provided `payment_id` is used to ensure that only one invoice is paid for the request
10389-
/// when received. See [Avoiding Duplicate Payments] for other requirements once the payment has
10390-
/// been sent.
10391-
///
10392-
/// To revoke the request, use [`ChannelManager::abandon_payment`] prior to receiving the
10393-
/// invoice. If abandoned, or an invoice isn't received in a reasonable amount of time, the
10394-
/// payment will fail with an [`Event::InvoiceRequestFailed`].
10395-
///
10396-
/// # Privacy
10397-
///
10398-
/// For payer privacy, uses a derived payer id and uses [`MessageRouter::create_blinded_paths`]
10399-
/// to construct a [`BlindedPath`] for the reply path. For further privacy implications, see the
10400-
/// docs of the parameterized [`Router`], which implements [`MessageRouter`].
10401-
///
10402-
/// # Limitations
10403-
///
10404-
/// Requires a direct connection to the given [`Destination`] as well as an introduction node in
10405-
/// [`Offer::paths`] or to [`Offer::signing_pubkey`], if empty. A similar restriction applies to
10406-
/// the responding [`Bolt12Invoice::payment_paths`].
10407-
///
10408-
/// # Errors
10409-
///
10410-
/// Errors if:
10411-
/// - a duplicate `payment_id` is provided given the caveats in the aforementioned link,
10412-
///
10413-
/// [`Bolt12Invoice::payment_paths`]: crate::offers::invoice::Bolt12Invoice::payment_paths
10414-
/// [Avoiding Duplicate Payments]: #avoiding-duplicate-payments
10415-
#[cfg(feature = "dnssec")]
10416-
pub fn pay_for_offer_from_human_readable_name(
10417-
&self, name: HumanReadableName, amount_msats: u64, payment_id: PaymentId,
10418-
retry_strategy: Retry, max_total_routing_fee_msat: Option<u64>,
10419-
dns_resolvers: Vec<Destination>,
10420-
) -> Result<(), ()> {
10421-
let (onion_message, context) =
10422-
self.hrn_resolver.resolve_name(payment_id, name, &*self.entropy_source)?;
10423-
let reply_paths = self.create_blinded_paths(MessageContext::DNSResolver(context))?;
10424-
let expiration = StaleExpiration::TimerTicks(1);
10425-
self.pending_outbound_payments.add_new_awaiting_offer(payment_id, expiration, retry_strategy, max_total_routing_fee_msat, amount_msats)?;
10426-
let message_params = dns_resolvers
10427-
.iter()
10428-
.flat_map(|destination| reply_paths.iter().map(move |path| (path, destination)))
10429-
.take(OFFERS_MESSAGE_REQUEST_LIMIT);
10430-
for (reply_path, destination) in message_params {
10431-
self.pending_dns_onion_messages.lock().unwrap().push((
10432-
DNSResolverMessage::DNSSECQuery(onion_message.clone()),
10433-
MessageSendInstructions::WithSpecifiedReplyPath {
10434-
destination: destination.clone(),
10435-
reply_path: reply_path.clone(),
10436-
},
10437-
));
10438-
}
10439-
Ok(())
10440-
}
10441-
1044210392
/// Gets a payment secret and payment hash for use in an invoice given to a third party wishing
1044310393
/// to pay us.
1044410394
///
@@ -12113,70 +12063,6 @@ where
1211312063
}
1211412064
}
1211512065

12116-
#[cfg(feature = "dnssec")]
12117-
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref>
12118-
DNSResolverMessageHandler for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
12119-
where
12120-
M::Target: chain::Watch<<SP::Target as SignerProvider>::EcdsaSigner>,
12121-
T::Target: BroadcasterInterface,
12122-
ES::Target: EntropySource,
12123-
NS::Target: NodeSigner,
12124-
SP::Target: SignerProvider,
12125-
F::Target: FeeEstimator,
12126-
R::Target: Router,
12127-
MR::Target: MessageRouter,
12128-
L::Target: Logger,
12129-
{
12130-
fn handle_dnssec_query(
12131-
&self, _message: DNSSECQuery, _responder: Option<Responder>,
12132-
) -> Option<(DNSResolverMessage, ResponseInstruction)> {
12133-
None
12134-
}
12135-
12136-
fn handle_dnssec_proof(&self, message: DNSSECProof, context: DNSResolverContext) {
12137-
let offer_opt = self.hrn_resolver.handle_dnssec_proof_for_offer(message, context);
12138-
#[cfg_attr(not(feature = "_test_utils"), allow(unused_mut))]
12139-
if let Some((completed_requests, mut offer)) = offer_opt {
12140-
for (name, payment_id) in completed_requests {
12141-
#[cfg(feature = "_test_utils")]
12142-
if let Some(replacement_offer) = self.testing_dnssec_proof_offer_resolution_override.lock().unwrap().remove(&name) {
12143-
// If we have multiple pending requests we may end up over-using the override
12144-
// offer, but tests can deal with that.
12145-
offer = replacement_offer;
12146-
}
12147-
if let Ok(amt_msats) = self.pending_outbound_payments.amt_msats_for_payment_awaiting_offer(payment_id) {
12148-
let offer_pay_res =
12149-
self.pay_for_offer_intern(&offer, None, Some(amt_msats), None, payment_id, Some(name),
12150-
|invoice_request, nonce| {
12151-
let retryable_invoice_request = RetryableInvoiceRequest {
12152-
invoice_request: invoice_request.clone(),
12153-
nonce,
12154-
needs_retry: true,
12155-
};
12156-
self.pending_outbound_payments
12157-
.received_offer(payment_id, Some(retryable_invoice_request))
12158-
.map_err(|_| Bolt12SemanticError::DuplicatePaymentId)
12159-
});
12160-
if offer_pay_res.is_err() {
12161-
// The offer we tried to pay is the canonical current offer for the name we
12162-
// wanted to pay. If we can't pay it, there's no way to recover so fail the
12163-
// payment.
12164-
// Note that the PaymentFailureReason should be ignored for an
12165-
// AwaitingInvoice payment.
12166-
self.pending_outbound_payments.abandon_payment(
12167-
payment_id, PaymentFailureReason::RouteNotFound, &self.pending_events,
12168-
);
12169-
}
12170-
}
12171-
}
12172-
}
12173-
}
12174-
12175-
fn release_pending_messages(&self) -> Vec<(DNSResolverMessage, MessageSendInstructions)> {
12176-
core::mem::take(&mut self.pending_dns_onion_messages.lock().unwrap())
12177-
}
12178-
}
12179-
1218012066
impl<M: Deref, T: Deref, ES: Deref, NS: Deref, SP: Deref, F: Deref, R: Deref, MR: Deref, L: Deref>
1218112067
NodeIdLookUp for ChannelManager<M, T, ES, NS, SP, F, R, MR, L>
1218212068
where
@@ -14146,11 +14032,6 @@ where
1414614032

1414714033
#[cfg(feature = "dnssec")]
1414814034
hrn_resolver: OMNameResolver::new(highest_seen_timestamp, best_block_height),
14149-
#[cfg(feature = "dnssec")]
14150-
pending_dns_onion_messages: Mutex::new(Vec::new()),
14151-
14152-
#[cfg(feature = "_test_utils")]
14153-
testing_dnssec_proof_offer_resolution_override: Mutex::new(new_hash_map()),
1415414035
};
1415514036

1415614037
let mut processed_claims: HashSet<Vec<MPPClaimHTLCSource>> = new_hash_set();

lightning/src/ln/functional_test_utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ type TestOnionMessenger<'chan_man, 'node_cfg, 'chan_mon_cfg> = OnionMessenger<
441441
&'node_cfg test_utils::TestMessageRouter<'chan_mon_cfg>,
442442
Arc<TestOffersMessageFlow<'chan_man, 'node_cfg, 'chan_mon_cfg>>,
443443
&'chan_man TestChannelManager<'node_cfg, 'chan_mon_cfg>,
444-
&'chan_man TestChannelManager<'node_cfg, 'chan_mon_cfg>,
444+
Arc<TestOffersMessageFlow<'chan_man, 'node_cfg, 'chan_mon_cfg>>,
445445
IgnoringMessageHandler,
446446
>;
447447

@@ -3372,7 +3372,7 @@ pub fn create_network<'a, 'b: 'a, 'c: 'b>(node_count: usize, cfgs: &'b Vec<NodeC
33723372
#[cfg(feature = "dnssec")]
33733373
let onion_messenger = OnionMessenger::new(
33743374
dedicated_entropy, cfgs[i].keys_manager, cfgs[i].logger, &chan_mgrs[i],
3375-
&cfgs[i].message_router, offers_handler.clone(), &chan_mgrs[i], &chan_mgrs[i],
3375+
&cfgs[i].message_router, offers_handler.clone(), &chan_mgrs[i], offers_handler.clone(),
33763376
IgnoringMessageHandler {},
33773377
);
33783378
#[cfg(not(feature = "dnssec"))]

lightning/src/ln/outbound_payment.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ pub(crate) enum PendingOutboundPayment {
143143
pub struct RetryableInvoiceRequest {
144144
pub(crate) invoice_request: InvoiceRequest,
145145
pub(crate) nonce: Nonce,
146-
pub(super) needs_retry: bool,
146+
pub(crate) needs_retry: bool,
147147
}
148148

149149
impl_writeable_tlv_based!(RetryableInvoiceRequest, {
@@ -454,7 +454,7 @@ impl Display for PaymentAttempts {
454454
/// [`PendingOutboundPayment::AwaitingOffer`] should be considered stale and candidate for removal
455455
/// in [`OutboundPayments::remove_stale_payments`].
456456
#[derive(Clone, Copy)]
457-
pub(crate) enum StaleExpiration {
457+
pub enum StaleExpiration {
458458
/// Number of times [`OutboundPayments::remove_stale_payments`] is called.
459459
TimerTicks(u64),
460460
/// Duration since the Unix epoch.

0 commit comments

Comments
 (0)