From 2637b387ad851e7763fafc16efce3caa71ca0618 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 7 Apr 2026 01:14:56 +0000 Subject: [PATCH 1/3] Drop stale DNSSec resolution logic in `OffersMessageFlow` In 884158d0914c64df4807c394e3155646dead478d we dropped built-in BIP 353 resolution logic in favor of the `bitcoin-payment-instructions` crate but forgot to do so in the `OffersMessageFlow`. Here we do so. --- lightning/src/offers/flow.rs | 65 ------------------------------------ 1 file changed, 65 deletions(-) diff --git a/lightning/src/offers/flow.rs b/lightning/src/offers/flow.rs index c1c3ce26aee..79e23321fd9 100644 --- a/lightning/src/offers/flow.rs +++ b/lightning/src/offers/flow.rs @@ -62,12 +62,6 @@ use crate::types::payment::{PaymentHash, PaymentSecret}; use crate::util::logger::Logger; use crate::util::ser::Writeable; -#[cfg(feature = "dnssec")] -use { - crate::blinded_path::message::DNSResolverContext, - crate::onion_message::dns_resolution::{DNSResolverMessage, DNSSECQuery, OMNameResolver}, -}; - /// A BOLT12 offers code and flow utility provider, which facilitates /// BOLT12 builder generation and onion message handling. /// @@ -94,11 +88,6 @@ pub struct OffersMessageFlow { pending_async_payments_messages: Mutex>, async_receive_offer_cache: Mutex, - #[cfg(feature = "dnssec")] - pub(crate) hrn_resolver: OMNameResolver, - #[cfg(feature = "dnssec")] - pending_dns_onion_messages: Mutex>, - logger: L, } @@ -126,11 +115,6 @@ impl OffersMessageFlow { pending_offers_messages: Mutex::new(Vec::new()), pending_async_payments_messages: Mutex::new(Vec::new()), - #[cfg(feature = "dnssec")] - hrn_resolver: OMNameResolver::new(current_timestamp, best_block.height), - #[cfg(feature = "dnssec")] - pending_dns_onion_messages: Mutex::new(Vec::new()), - async_receive_offer_cache: Mutex::new(AsyncReceiveOfferCache::new()), logger, @@ -220,12 +204,6 @@ impl OffersMessageFlow { break; } } - - #[cfg(feature = "dnssec")] - { - let updated_time = timestamp.load(Ordering::Acquire) as u32; - self.hrn_resolver.new_best_block(_height, updated_time); - } } } @@ -1306,41 +1284,6 @@ impl OffersMessageFlow { ) } - /// Enqueues the created [`DNSSECQuery`] to be sent to the counterparty. - /// - /// # Peers - /// - /// The user must provide a list of [`MessageForwardNode`] that will be used to generate - /// valid reply paths for the counterparty to send back the corresponding response for - /// the [`DNSSECQuery`] message. - /// - /// [`supports_onion_messages`]: crate::types::features::Features::supports_onion_messages - #[cfg(feature = "dnssec")] - pub fn enqueue_dns_onion_message( - &self, message: DNSSECQuery, context: DNSResolverContext, dns_resolvers: Vec, - peers: Vec, - ) -> Result<(), Bolt12SemanticError> { - let reply_paths = self - .create_blinded_paths(peers, MessageContext::DNSResolver(context)) - .map_err(|_| Bolt12SemanticError::MissingPaths)?; - - let message_params = dns_resolvers - .iter() - .flat_map(|destination| reply_paths.iter().map(move |path| (path, destination))) - .take(OFFERS_MESSAGE_REQUEST_LIMIT); - for (reply_path, destination) in message_params { - self.pending_dns_onion_messages.lock().unwrap().push(( - DNSResolverMessage::DNSSECQuery(message.clone()), - MessageSendInstructions::WithSpecifiedReplyPath { - destination: destination.clone(), - reply_path: reply_path.clone(), - }, - )); - } - - Ok(()) - } - /// Gets the enqueued [`OffersMessage`] with their corresponding [`MessageSendInstructions`]. pub fn release_pending_offers_messages(&self) -> Vec<(OffersMessage, MessageSendInstructions)> { core::mem::take(&mut self.pending_offers_messages.lock().unwrap()) @@ -1353,14 +1296,6 @@ impl OffersMessageFlow { core::mem::take(&mut self.pending_async_payments_messages.lock().unwrap()) } - /// Gets the enqueued [`DNSResolverMessage`] with their corresponding [`MessageSendInstructions`]. - #[cfg(feature = "dnssec")] - pub fn release_pending_dns_messages( - &self, - ) -> Vec<(DNSResolverMessage, MessageSendInstructions)> { - core::mem::take(&mut self.pending_dns_onion_messages.lock().unwrap()) - } - /// Retrieve an [`Offer`] for receiving async payments as an often-offline recipient. Will only /// return an offer if [`Self::set_paths_to_static_invoice_server`] was called and we succeeded in /// interactively building a [`StaticInvoice`] with the static invoice server. From 417b06585cf78728e3d0659e078b24c096d78bca Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 7 Apr 2026 01:19:01 +0000 Subject: [PATCH 2/3] Add missing `OffersMessageHandler::best_block` updating It seems we forgot to ensure `OffersMessageHandler::best_block` is consistently updated, leading to us building invalid blinded payment paths for short-lived payment paths after two weeks without restart. --- lightning/src/offers/flow.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lightning/src/offers/flow.rs b/lightning/src/offers/flow.rs index 79e23321fd9..901866f1e8f 100644 --- a/lightning/src/offers/flow.rs +++ b/lightning/src/offers/flow.rs @@ -183,10 +183,12 @@ impl OffersMessageFlow { /// /// Must be called whenever a new chain tip becomes available. May be skipped /// for intermediary blocks. - pub fn best_block_updated(&self, header: &Header, _height: u32) { + pub fn best_block_updated(&self, header: &Header, height: u32) { let timestamp = &self.highest_seen_timestamp; let block_time = header.time as usize; + *self.best_block.write().unwrap() = BestBlock::new(header.block_hash(), height); + loop { // Update timestamp to be the max of its current value and the block // timestamp. This should keep us close to the current time without relying on From 5704e8e75a18f0d9946ab734ea53046818c814f3 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Tue, 7 Apr 2026 11:07:12 +0000 Subject: [PATCH 3/3] Note why we don't use `update_for_new_tip` in offers flow block upd --- lightning/src/offers/flow.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lightning/src/offers/flow.rs b/lightning/src/offers/flow.rs index 901866f1e8f..2edcbc8aba8 100644 --- a/lightning/src/offers/flow.rs +++ b/lightning/src/offers/flow.rs @@ -187,6 +187,8 @@ impl OffersMessageFlow { let timestamp = &self.highest_seen_timestamp; let block_time = header.time as usize; + // Note that we deliberately don't use `update_for_new_tip` as we dont rely on receiving + // disconnection information instead expecting to simply "jump" to the new tip. *self.best_block.write().unwrap() = BestBlock::new(header.block_hash(), height); loop {