Skip to content

Commit 96cb470

Browse files
committed
Implement Flow for OffersMessageFlow
1 parent ba8de7c commit 96cb470

File tree

3 files changed

+288
-7
lines changed

3 files changed

+288
-7
lines changed

Diff for: lightning/src/ln/channel.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1807,7 +1807,7 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
18071807
/// Either the height at which this channel was created or the height at which it was last
18081808
/// serialized if it was serialized by versions prior to 0.0.103.
18091809
/// We use this to close if funding is never broadcasted.
1810-
pub(super) channel_creation_height: u32,
1810+
pub(crate) channel_creation_height: u32,
18111811

18121812
counterparty_dust_limit_satoshis: u64,
18131813

Diff for: lightning/src/ln/channelmanager.rs

+22-5
Original file line numberDiff line numberDiff line change
@@ -1349,11 +1349,11 @@ impl Readable for Option<RAAMonitorUpdateBlockingAction> {
13491349
}
13501350

13511351
/// State we hold per-peer.
1352-
pub(super) struct PeerState<SP: Deref> where SP::Target: SignerProvider {
1352+
pub(crate) struct PeerState<SP: Deref> where SP::Target: SignerProvider {
13531353
/// `channel_id` -> `Channel`
13541354
///
13551355
/// Holds all channels where the peer is the counterparty.
1356-
pub(super) channel_by_id: HashMap<ChannelId, Channel<SP>>,
1356+
pub(crate) channel_by_id: HashMap<ChannelId, Channel<SP>>,
13571357
/// `temporary_channel_id` -> `InboundChannelRequest`.
13581358
///
13591359
/// When manual channel acceptance is enabled, this holds all unaccepted inbound channels where
@@ -1362,7 +1362,7 @@ pub(super) struct PeerState<SP: Deref> where SP::Target: SignerProvider {
13621362
/// the channel is rejected, then the entry is simply removed.
13631363
pub(super) inbound_channel_request_by_id: HashMap<ChannelId, InboundChannelRequest>,
13641364
/// The latest `InitFeatures` we heard from the peer.
1365-
latest_features: InitFeatures,
1365+
pub(crate) latest_features: InitFeatures,
13661366
/// Messages to send to the peer - pushed to in the same lock that they are generated in (except
13671367
/// for broadcast messages, where ordering isn't as strict).
13681368
pub(super) pending_msg_events: Vec<MessageSendEvent>,
@@ -8035,7 +8035,7 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
80358035

80368036
let per_peer_state = self.per_peer_state.read().unwrap();
80378037
let peer_state_mutex = per_peer_state.get(counterparty_node_id)
8038-
.ok_or_else(|| {
8038+
.ok_or_else(|| {
80398039
debug_assert!(false);
80408040
MsgHandleErrInternal::send_err_msg_no_close(
80418041
format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id),
@@ -10202,7 +10202,7 @@ macro_rules! create_refund_builder { ($self: ident, $builder: ty) => {
1020210202
/// Sending multiple requests increases the chances of successful delivery in case some
1020310203
/// paths are unavailable. However, only one invoice for a given [`PaymentId`] will be paid,
1020410204
/// even if multiple invoices are received.
10205-
const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
10205+
pub(crate) const OFFERS_MESSAGE_REQUEST_LIMIT: usize = 10;
1020610206

1020710207
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>
1020810208
where
@@ -10812,6 +10812,23 @@ where
1081210812
.and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(()))
1081310813
}
1081410814

10815+
fn peer_for_blinded_path(&self) -> Vec<MessageForwardNode> {
10816+
self.per_peer_state.read().unwrap()
10817+
.iter()
10818+
.map(|(node_id, peer_state)| (node_id, peer_state.lock().unwrap()))
10819+
.filter(|(_, peer)| peer.is_connected)
10820+
.filter(|(_, peer)| peer.latest_features.supports_onion_messages())
10821+
.map(|(node_id, peer)| MessageForwardNode {
10822+
node_id: *node_id,
10823+
short_channel_id: peer.channel_by_id
10824+
.iter()
10825+
.filter(|(_, channel)| channel.context().is_usable())
10826+
.min_by_key(|(_, channel)| channel.context().channel_creation_height)
10827+
.and_then(|(_, channel)| channel.context().get_short_channel_id()),
10828+
})
10829+
.collect::<Vec<_>>()
10830+
}
10831+
1081510832
/// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
1081610833
/// [`Router::create_blinded_payment_paths`].
1081710834
fn create_blinded_payment_paths(

Diff for: lightning/src/offers/flow.rs

+265-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ use crate::blinded_path::message::{
1414
BlindedMessagePath, MessageContext, MessageForwardNode, OffersContext,
1515
};
1616
use crate::blinded_path::payment::BlindedPaymentPath;
17-
use crate::ln::channelmanager::PaymentId;
17+
use crate::ln::channelmanager::{
18+
PaymentId, MAX_SHORT_LIVED_RELATIVE_EXPIRY, OFFERS_MESSAGE_REQUEST_LIMIT,
19+
};
1820
use crate::ln::inbound_payment;
1921
use crate::offers::invoice::{Bolt12Invoice, DerivedSigningPubkey, InvoiceBuilder};
2022
use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestBuilder};
@@ -163,4 +165,266 @@ where
163165
pub fn get_our_node_id(&self) -> PublicKey {
164166
self.our_network_pubkey
165167
}
168+
169+
fn duration_since_epoch(&self) -> Duration {
170+
#[cfg(not(feature = "std"))]
171+
let now = Duration::from_secs(self.highest_seen_timestamp.load(Ordering::Acquire) as u64);
172+
#[cfg(feature = "std")]
173+
let now = std::time::SystemTime::now()
174+
.duration_since(std::time::SystemTime::UNIX_EPOCH)
175+
.expect("SystemTime::now() should come after SystemTime::UNIX_EPOCH");
176+
177+
now
178+
}
179+
}
180+
181+
impl<ES: Deref, MR: Deref> Flow for OffersMessageFlow<ES, MR>
182+
where
183+
ES::Target: EntropySource,
184+
MR::Target: MessageRouter,
185+
{
186+
fn create_offer_builder(
187+
&self, nonce: Nonce,
188+
) -> Result<OfferBuilder<DerivedMetadata, secp256k1::All>, Bolt12SemanticError> {
189+
let node_id = self.get_our_node_id();
190+
let expanded_key = &self.inbound_payment_key;
191+
let secp_ctx = &self.secp_ctx;
192+
193+
let builder = OfferBuilder::deriving_signing_pubkey(node_id, expanded_key, nonce, secp_ctx)
194+
.chain_hash(self.chain_hash);
195+
196+
Ok(builder)
197+
}
198+
199+
fn create_refund_builder(
200+
&self, amount_msats: u64, absolute_expiry: Duration, payment_id: PaymentId, nonce: Nonce,
201+
) -> Result<RefundBuilder<secp256k1::All>, Bolt12SemanticError> {
202+
let node_id = self.get_our_node_id();
203+
let expanded_key = &self.inbound_payment_key;
204+
let secp_ctx = &self.secp_ctx;
205+
206+
let builder = RefundBuilder::deriving_signing_pubkey(
207+
node_id,
208+
expanded_key,
209+
nonce,
210+
secp_ctx,
211+
amount_msats,
212+
payment_id,
213+
)?
214+
.chain_hash(self.chain_hash)
215+
.absolute_expiry(absolute_expiry);
216+
217+
Ok(builder)
218+
}
219+
220+
fn create_invoice_request_builder<'a>(
221+
&'a self, offer: &'a Offer, nonce: Nonce, quantity: Option<u64>, amount_msats: Option<u64>,
222+
payer_note: Option<String>, human_readable_name: Option<HumanReadableName>,
223+
payment_id: PaymentId,
224+
) -> Result<InvoiceRequestBuilder<'a, 'a, secp256k1::All>, Bolt12SemanticError> {
225+
let expanded_key = &self.inbound_payment_key;
226+
let secp_ctx = &self.secp_ctx;
227+
228+
let builder = offer
229+
.request_invoice(expanded_key, nonce, secp_ctx, payment_id)?
230+
.chain_hash(self.chain_hash)?;
231+
232+
let builder = match quantity {
233+
None => builder,
234+
Some(quantity) => builder.quantity(quantity)?,
235+
};
236+
let builder = match amount_msats {
237+
None => builder,
238+
Some(amount_msats) => builder.amount_msats(amount_msats)?,
239+
};
240+
let builder = match payer_note {
241+
None => builder,
242+
Some(payer_note) => builder.payer_note(payer_note),
243+
};
244+
let builder = match human_readable_name {
245+
None => builder,
246+
Some(hrn) => builder.sourced_from_human_readable_name(hrn),
247+
};
248+
249+
Ok(builder.into())
250+
}
251+
252+
fn create_invoice_builder<'a>(
253+
&'a self, refund: &'a Refund, payment_paths: Vec<BlindedPaymentPath>,
254+
payment_hash: PaymentHash,
255+
) -> Result<InvoiceBuilder<'a, DerivedSigningPubkey>, Bolt12SemanticError> {
256+
let expanded_key = &self.inbound_payment_key;
257+
let entropy = &*self.entropy_source;
258+
259+
#[cfg(feature = "std")]
260+
let builder = refund.respond_using_derived_keys(
261+
payment_paths,
262+
payment_hash,
263+
expanded_key,
264+
entropy,
265+
)?;
266+
#[cfg(not(feature = "std"))]
267+
let created_at = Duration::from_secs(self.highest_seen_timestamp.load(Ordering::Acquire) as u64);
268+
#[cfg(not(feature = "std"))]
269+
let builder = refund.respond_using_derived_keys_no_std(
270+
payment_paths,
271+
payment_hash,
272+
created_at,
273+
expanded_key,
274+
entropy,
275+
)?;
276+
let builder: InvoiceBuilder<DerivedSigningPubkey> = builder.into();
277+
278+
Ok(builder)
279+
}
280+
281+
fn create_blinded_paths(
282+
&self, peers: Vec<MessageForwardNode>, context: MessageContext,
283+
) -> Result<Vec<BlindedMessagePath>, ()> {
284+
let recipient = self.get_our_node_id();
285+
let secp_ctx = &self.secp_ctx;
286+
287+
let peers = peers.iter().map(|node| node.node_id).collect::<Vec<_>>();
288+
289+
self.message_router
290+
.create_blinded_paths(recipient, context, peers, secp_ctx)
291+
.and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(()))
292+
}
293+
294+
fn create_compact_blinded_paths(
295+
&self, peers: Vec<MessageForwardNode>, context: OffersContext,
296+
) -> Result<Vec<BlindedMessagePath>, ()> {
297+
let recipient = self.get_our_node_id();
298+
let secp_ctx = &self.secp_ctx;
299+
300+
self.message_router
301+
.create_compact_blinded_paths(
302+
recipient,
303+
MessageContext::Offers(context),
304+
peers,
305+
secp_ctx,
306+
)
307+
.and_then(|paths| (!paths.is_empty()).then(|| paths).ok_or(()))
308+
}
309+
310+
fn create_blinded_paths_using_absolute_expiry(
311+
&self, peers: Vec<MessageForwardNode>, context: OffersContext,
312+
absolute_expiry: Option<Duration>,
313+
) -> Result<Vec<BlindedMessagePath>, ()> {
314+
let now = self.duration_since_epoch();
315+
let max_short_lived_absolute_expiry = now.saturating_add(MAX_SHORT_LIVED_RELATIVE_EXPIRY);
316+
317+
if absolute_expiry.unwrap_or(Duration::MAX) <= max_short_lived_absolute_expiry {
318+
self.create_compact_blinded_paths(peers, context)
319+
} else {
320+
self.create_blinded_paths(peers, MessageContext::Offers(context))
321+
}
322+
}
323+
324+
fn enqueue_invoice_request(
325+
&self, invoice_request: InvoiceRequest, reply_paths: Vec<BlindedMessagePath>,
326+
) -> Result<(), Bolt12SemanticError> {
327+
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
328+
if !invoice_request.paths().is_empty() {
329+
reply_paths
330+
.iter()
331+
.flat_map(|reply_path| {
332+
invoice_request.paths().iter().map(move |path| (path, reply_path))
333+
})
334+
.take(OFFERS_MESSAGE_REQUEST_LIMIT)
335+
.for_each(|(path, reply_path)| {
336+
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
337+
destination: Destination::BlindedPath(path.clone()),
338+
reply_path: reply_path.clone(),
339+
};
340+
let message = OffersMessage::InvoiceRequest(invoice_request.clone());
341+
pending_offers_messages.push((message, instructions));
342+
});
343+
} else if let Some(node_id) = invoice_request.issuer_signing_pubkey() {
344+
for reply_path in reply_paths {
345+
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
346+
destination: Destination::Node(node_id),
347+
reply_path,
348+
};
349+
let message = OffersMessage::InvoiceRequest(invoice_request.clone());
350+
pending_offers_messages.push((message, instructions));
351+
}
352+
} else {
353+
debug_assert!(false);
354+
return Err(Bolt12SemanticError::MissingIssuerSigningPubkey);
355+
}
356+
357+
Ok(())
358+
}
359+
360+
fn enqueue_invoice(
361+
&self, invoice: Bolt12Invoice, refund: &Refund, reply_paths: Vec<BlindedMessagePath>,
362+
) -> Result<(), Bolt12SemanticError> {
363+
let mut pending_offers_messages = self.pending_offers_messages.lock().unwrap();
364+
if refund.paths().is_empty() {
365+
for reply_path in reply_paths {
366+
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
367+
destination: Destination::Node(refund.payer_signing_pubkey()),
368+
reply_path,
369+
};
370+
let message = OffersMessage::Invoice(invoice.clone());
371+
pending_offers_messages.push((message, instructions));
372+
}
373+
} else {
374+
reply_paths
375+
.iter()
376+
.flat_map(|reply_path| refund.paths().iter().map(move |path| (path, reply_path)))
377+
.take(OFFERS_MESSAGE_REQUEST_LIMIT)
378+
.for_each(|(path, reply_path)| {
379+
let instructions = MessageSendInstructions::WithSpecifiedReplyPath {
380+
destination: Destination::BlindedPath(path.clone()),
381+
reply_path: reply_path.clone(),
382+
};
383+
let message = OffersMessage::Invoice(invoice.clone());
384+
pending_offers_messages.push((message, instructions));
385+
});
386+
}
387+
388+
Ok(())
389+
}
390+
391+
fn enqueue_dns_onion_message(
392+
&self, message: DNSSECQuery, dns_resolvers: Vec<Destination>,
393+
reply_paths: Vec<BlindedMessagePath>,
394+
) -> Result<(), Bolt12SemanticError> {
395+
let message_params = dns_resolvers
396+
.iter()
397+
.flat_map(|destination| reply_paths.iter().map(move |path| (path, destination)))
398+
.take(OFFERS_MESSAGE_REQUEST_LIMIT);
399+
for (reply_path, destination) in message_params {
400+
self.pending_dns_onion_messages.lock().unwrap().push((
401+
DNSResolverMessage::DNSSECQuery(message.clone()),
402+
MessageSendInstructions::WithSpecifiedReplyPath {
403+
destination: destination.clone(),
404+
reply_path: reply_path.clone(),
405+
},
406+
));
407+
}
408+
409+
Ok(())
410+
}
411+
412+
fn get_and_clear_pending_offers_messages(
413+
&self,
414+
) -> Vec<(OffersMessage, MessageSendInstructions)> {
415+
core::mem::take(&mut self.pending_offers_messages.lock().unwrap())
416+
}
417+
418+
fn get_and_clear_pending_async_messages(
419+
&self,
420+
) -> Vec<(AsyncPaymentsMessage, MessageSendInstructions)> {
421+
core::mem::take(&mut self.pending_async_payments_messages.lock().unwrap())
422+
}
423+
424+
#[cfg(feature = "dnssec")]
425+
fn get_and_clear_pending_dns_messages(
426+
&self,
427+
) -> Vec<(DNSResolverMessage, MessageSendInstructions)> {
428+
core::mem::take(&mut self.pending_dns_onion_messages.lock().unwrap())
429+
}
166430
}

0 commit comments

Comments
 (0)