Skip to content

Commit 8197a99

Browse files
committed
Update create_offer_builder to use create_blinded_paths
To simplify blinded path creation and uphold the principle of "One `MessageRouter`, one `BlindedPath` type," this commit updates `create_offer_builder` to use the `create_blinded_paths` method of the `MessageRouter`. Now, when `create_offer_builder` is called, the offer will be created using the `MessageRouter` implementation that the `ChannelManager` or `OffersMessageFlow` is parameterized with. If a user wishes to create an offer with a different type of blinded path, they can explicitly use `create_offer_builder_using_router`, which allows passing a custom `MessageRouter`. The reasoning behind this change is to give users clearer, more deterministic control over the type of blinded path used in the offer. It also improves user awareness, ensuring that creating a non-default blinded path becomes an *intentional choice*.
1 parent 1956a73 commit 8197a99

File tree

6 files changed

+152
-92
lines changed

6 files changed

+152
-92
lines changed

lightning-dns-resolver/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ mod test {
482482

483483
let name = HumanReadableName::from_encoded("[email protected]").unwrap();
484484

485-
let bs_offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
485+
let bs_offer = nodes[1].node.create_offer_builder().unwrap().build().unwrap();
486486
let resolvers = vec![Destination::Node(resolver_id)];
487487
let retry = Retry::Attempts(0);
488488
let amt = 42_000;

lightning/src/ln/channelmanager.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2212,9 +2212,8 @@ where
22122212
/// #
22132213
/// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> {
22142214
/// # let channel_manager = channel_manager.get_cm();
2215-
/// # let absolute_expiry = None;
22162215
/// let offer = channel_manager
2217-
/// .create_offer_builder(absolute_expiry)?
2216+
/// .create_offer_builder()?
22182217
/// # ;
22192218
/// # // Needed for compiling for c_bindings
22202219
/// # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into();
@@ -10852,9 +10851,8 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
1085210851
///
1085310852
/// # Privacy
1085410853
///
10855-
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the offer based on the given
10856-
/// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
10857-
/// privacy implications.
10854+
/// Uses the [`ChannelManager`]'s [`MessageRouter`] to construct a [`BlindedMessagePath`] for
10855+
/// the offer. See those docs for privacy implications.
1085810856
///
1085910857
/// Also, uses a derived signing pubkey in the offer for recipient privacy.
1086010858
///
@@ -10869,12 +10867,46 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
1086910867
/// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath
1087010868
/// [`Offer`]: crate::offers::offer::Offer
1087110869
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
10872-
pub fn create_offer_builder(
10873-
&$self, absolute_expiry: Option<Duration>
10874-
) -> Result<$builder, Bolt12SemanticError> {
10875-
let entropy = &*$self.entropy_source;
10870+
pub fn create_offer_builder(&$self) -> Result<$builder, Bolt12SemanticError> {
10871+
let builder = $self.flow.create_offer_builder(
10872+
&*$self.entropy_source, $self.get_peers_for_blinded_path()
10873+
)?;
10874+
10875+
Ok(builder.into())
10876+
}
1087610877

10877-
let builder = $self.flow.create_offer_builder(entropy, absolute_expiry, $self.get_peers_for_blinded_path())?;
10878+
/// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
10879+
/// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer.
10880+
///
10881+
/// # Privacy
10882+
///
10883+
/// Constructs a [`BlindedMessagePath`] for the offer using a custom [`MessageRouter`].
10884+
/// Users can implement a custom [`MessageRouter`] to define properties of the
10885+
/// [`BlindedMessagePath`] as required or opt not to create any `BlindedMessagePath`.
10886+
///
10887+
/// Also, uses a derived signing pubkey in the offer for recipient privacy.
10888+
///
10889+
/// # Limitations
10890+
///
10891+
/// See [`OffersMessageFlow::create_offer_builder`] for limitations on the offer builder.
10892+
///
10893+
/// # Errors
10894+
///
10895+
/// Errors if the provided [`MessageRouter`] is unable to create a blinded path for the offer.
10896+
///
10897+
/// [`BlindedMessagePath`]: crate::blinded_path::message::BlindedMessagePath
10898+
/// [`Offer`]: crate::offers::offer::Offer
10899+
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
10900+
pub fn create_offer_builder_using_router<ME: Deref>(
10901+
&$self,
10902+
router: ME,
10903+
) -> Result<$builder, Bolt12SemanticError>
10904+
where
10905+
ME::Target: MessageRouter,
10906+
{
10907+
let builder = $self.flow.create_offer_builder_using_router(
10908+
router, &*$self.entropy_source, $self.get_peers_for_blinded_path()
10909+
)?;
1087810910

1087910911
Ok(builder.into())
1088010912
}

lightning/src/ln/max_payment_path_len_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ fn bolt12_invoice_too_large_blinded_paths() {
517517
),
518518
]);
519519

520-
let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
520+
let offer = nodes[1].node.create_offer_builder().unwrap().build().unwrap();
521521
let payment_id = PaymentId([1; 32]);
522522
let route_config = RouteParametersConfig::default();
523523
nodes[0]

lightning/src/ln/offers_tests.rs

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ fn prefers_non_tor_nodes_in_blinded_paths() {
307307
announce_node_address(charlie, &[alice, bob, david, &nodes[4], &nodes[5]], tor.clone());
308308

309309
let offer = bob.node
310-
.create_offer_builder(None).unwrap()
310+
.create_offer_builder().unwrap()
311311
.amount_msats(10_000_000)
312312
.build().unwrap();
313313
assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id));
@@ -323,7 +323,7 @@ fn prefers_non_tor_nodes_in_blinded_paths() {
323323
announce_node_address(&nodes[5], &[alice, bob, charlie, david, &nodes[4]], tor.clone());
324324

325325
let offer = bob.node
326-
.create_offer_builder(None).unwrap()
326+
.create_offer_builder().unwrap()
327327
.amount_msats(10_000_000)
328328
.build().unwrap();
329329
assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id));
@@ -374,7 +374,7 @@ fn prefers_more_connected_nodes_in_blinded_paths() {
374374
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
375375

376376
let offer = bob.node
377-
.create_offer_builder(None).unwrap()
377+
.create_offer_builder().unwrap()
378378
.amount_msats(10_000_000)
379379
.build().unwrap();
380380
assert_ne!(offer.issuer_signing_pubkey(), Some(bob_id));
@@ -399,11 +399,9 @@ fn creates_short_lived_offer() {
399399
let alice_id = alice.node.get_our_node_id();
400400
let bob = &nodes[1];
401401

402-
let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
403402
let offer = alice.node
404-
.create_offer_builder(Some(absolute_expiry)).unwrap()
403+
.create_offer_builder().unwrap()
405404
.build().unwrap();
406-
assert_eq!(offer.absolute_expiry(), Some(absolute_expiry));
407405
assert!(!offer.paths().is_empty());
408406
for path in offer.paths() {
409407
let introduction_node_id = resolve_introduction_node(bob, &path);
@@ -425,20 +423,17 @@ fn creates_long_lived_offer() {
425423
let alice = &nodes[0];
426424
let alice_id = alice.node.get_our_node_id();
427425

428-
let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY
429-
+ Duration::from_secs(1);
430426
let offer = alice.node
431-
.create_offer_builder(Some(absolute_expiry))
427+
.create_offer_builder()
432428
.unwrap()
433429
.build().unwrap();
434-
assert_eq!(offer.absolute_expiry(), Some(absolute_expiry));
435430
assert!(!offer.paths().is_empty());
436431
for path in offer.paths() {
437432
assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id));
438433
}
439434

440435
let offer = alice.node
441-
.create_offer_builder(None).unwrap()
436+
.create_offer_builder().unwrap()
442437
.build().unwrap();
443438
assert_eq!(offer.absolute_expiry(), None);
444439
assert!(!offer.paths().is_empty());
@@ -542,7 +537,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
542537
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
543538

544539
let offer = alice.node
545-
.create_offer_builder(None)
540+
.create_offer_builder()
546541
.unwrap()
547542
.amount_msats(10_000_000)
548543
.build().unwrap();
@@ -709,7 +704,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
709704
let bob_id = bob.node.get_our_node_id();
710705

711706
let offer = alice.node
712-
.create_offer_builder(None).unwrap()
707+
.create_offer_builder().unwrap()
713708
.amount_msats(10_000_000)
714709
.build().unwrap();
715710
assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
@@ -832,7 +827,7 @@ fn pays_for_offer_without_blinded_paths() {
832827
let bob_id = bob.node.get_our_node_id();
833828

834829
let offer = alice.node
835-
.create_offer_builder(None).unwrap()
830+
.create_offer_builder().unwrap()
836831
.clear_paths()
837832
.amount_msats(10_000_000)
838833
.build().unwrap();
@@ -956,7 +951,7 @@ fn send_invoice_requests_with_distinct_reply_path() {
956951
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
957952

958953
let offer = alice.node
959-
.create_offer_builder(None)
954+
.create_offer_builder()
960955
.unwrap()
961956
.amount_msats(10_000_000)
962957
.build().unwrap();
@@ -1092,7 +1087,7 @@ fn creates_and_pays_for_offer_with_retry() {
10921087
let bob_id = bob.node.get_our_node_id();
10931088

10941089
let offer = alice.node
1095-
.create_offer_builder(None).unwrap()
1090+
.create_offer_builder().unwrap()
10961091
.amount_msats(10_000_000)
10971092
.build().unwrap();
10981093
assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
@@ -1168,7 +1163,7 @@ fn pays_bolt12_invoice_asynchronously() {
11681163
let bob_id = bob.node.get_our_node_id();
11691164

11701165
let offer = alice.node
1171-
.create_offer_builder(None).unwrap()
1166+
.create_offer_builder().unwrap()
11721167
.amount_msats(10_000_000)
11731168
.build().unwrap();
11741169

@@ -1260,7 +1255,7 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() {
12601255
let bob_id = bob.node.get_our_node_id();
12611256

12621257
let offer = alice.node
1263-
.create_offer_builder(None).unwrap()
1258+
.create_offer_builder().unwrap()
12641259
.amount_msats(10_000_000)
12651260
.build().unwrap();
12661261
assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
@@ -1390,7 +1385,7 @@ fn fails_authentication_when_handling_invoice_request() {
13901385
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
13911386

13921387
let offer = alice.node
1393-
.create_offer_builder(None)
1388+
.create_offer_builder()
13941389
.unwrap()
13951390
.amount_msats(10_000_000)
13961391
.build().unwrap();
@@ -1402,7 +1397,7 @@ fn fails_authentication_when_handling_invoice_request() {
14021397
}
14031398

14041399
let invalid_path = alice.node
1405-
.create_offer_builder(None)
1400+
.create_offer_builder()
14061401
.unwrap()
14071402
.build().unwrap()
14081403
.paths().first().unwrap()
@@ -1502,7 +1497,7 @@ fn fails_authentication_when_handling_invoice_for_offer() {
15021497
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
15031498

15041499
let offer = alice.node
1505-
.create_offer_builder(None)
1500+
.create_offer_builder()
15061501
.unwrap()
15071502
.amount_msats(10_000_000)
15081503
.build().unwrap();
@@ -1698,8 +1693,7 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() {
16981693
disconnect_peers(alice, &[bob, charlie, david, &nodes[4], &nodes[5]]);
16991694
disconnect_peers(david, &[bob, charlie, &nodes[4], &nodes[5]]);
17001695

1701-
let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
1702-
match alice.node.create_offer_builder(Some(absolute_expiry)) {
1696+
match alice.node.create_offer_builder() {
17031697
Ok(_) => panic!("Expected error"),
17041698
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
17051699
}
@@ -1708,9 +1702,11 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() {
17081702
args.send_channel_ready = (true, true);
17091703
reconnect_nodes(args);
17101704

1705+
let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
17111706
let offer = alice.node
1712-
.create_offer_builder(Some(absolute_expiry)).unwrap()
1707+
.create_offer_builder().unwrap()
17131708
.amount_msats(10_000_000)
1709+
.absolute_expiry(absolute_expiry)
17141710
.build().unwrap();
17151711

17161712
let payment_id = PaymentId([1; 32]);
@@ -1813,7 +1809,7 @@ fn fails_creating_invoice_request_for_unsupported_chain() {
18131809
let bob = &nodes[1];
18141810

18151811
let offer = alice.node
1816-
.create_offer_builder(None).unwrap()
1812+
.create_offer_builder().unwrap()
18171813
.clear_chains()
18181814
.chain(Network::Signet)
18191815
.build().unwrap();
@@ -1872,7 +1868,7 @@ fn fails_creating_invoice_request_without_blinded_reply_path() {
18721868
disconnect_peers(david, &[bob, charlie, &nodes[4], &nodes[5]]);
18731869

18741870
let offer = alice.node
1875-
.create_offer_builder(None).unwrap()
1871+
.create_offer_builder().unwrap()
18761872
.amount_msats(10_000_000)
18771873
.build().unwrap();
18781874

@@ -1906,7 +1902,7 @@ fn fails_creating_invoice_request_with_duplicate_payment_id() {
19061902
disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]);
19071903

19081904
let offer = alice.node
1909-
.create_offer_builder(None).unwrap()
1905+
.create_offer_builder().unwrap()
19101906
.amount_msats(10_000_000)
19111907
.build().unwrap();
19121908

@@ -1992,7 +1988,7 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() {
19921988
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
19931989

19941990
let offer = alice.node
1995-
.create_offer_builder(None).unwrap()
1991+
.create_offer_builder().unwrap()
19961992
.amount_msats(10_000_000)
19971993
.build().unwrap();
19981994

@@ -2201,7 +2197,7 @@ fn fails_paying_invoice_with_unknown_required_features() {
22012197
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
22022198

22032199
let offer = alice.node
2204-
.create_offer_builder(None).unwrap()
2200+
.create_offer_builder().unwrap()
22052201
.amount_msats(10_000_000)
22062202
.build().unwrap();
22072203

@@ -2280,7 +2276,7 @@ fn rejects_keysend_to_non_static_invoice_path() {
22802276
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
22812277

22822278
// First pay the offer and save the payment preimage and invoice.
2283-
let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
2279+
let offer = nodes[1].node.create_offer_builder().unwrap().build().unwrap();
22842280
let amt_msat = 5000;
22852281
let payment_id = PaymentId([1; 32]);
22862282
nodes[0].node.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), RouteParametersConfig::default()).unwrap();
@@ -2360,7 +2356,7 @@ fn no_double_pay_with_stale_channelmanager() {
23602356

23612357
let amt_msat = nodes[0].node.list_usable_channels()[0].next_outbound_htlc_limit_msat + 1; // Force MPP
23622358
let offer = nodes[1].node
2363-
.create_offer_builder(None).unwrap()
2359+
.create_offer_builder().unwrap()
23642360
.clear_paths()
23652361
.amount_msats(amt_msat)
23662362
.build().unwrap();

0 commit comments

Comments
 (0)