Skip to content

Commit fb07fbb

Browse files
committed
Update create_offer_builder to use create_blinded_paths
This change updates the default `create_offer_builder` to always use `create_blinded_paths`, enabling deterministic creation of only full-length blinded paths. Now that we provide `create_offer_builder_using_router`, users who need custom path logic (like compact blinded path) can pass in their own `MessageRouter`. This allows the default builder to remain simple and consistent, while offering flexibility through the alternate function.
1 parent 12937fc commit fb07fbb

File tree

4 files changed

+69
-78
lines changed

4 files changed

+69
-78
lines changed

lightning-dns-resolver/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ mod test {
396396
let name = HumanReadableName::from_encoded("[email protected]").unwrap();
397397

398398
// When we get the proof back, override its contents to an offer from nodes[1]
399-
let bs_offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
399+
let bs_offer = nodes[1].node.create_offer_builder().unwrap().build().unwrap();
400400
let proof_override = &nodes[0].node.testing_dnssec_proof_offer_resolution_override;
401401
proof_override.lock().unwrap().insert(name.clone(), bs_offer);
402402

lightning/src/ln/channelmanager.rs

Lines changed: 38 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2091,9 +2091,8 @@ where
20912091
/// #
20922092
/// # fn example<T: AChannelManager>(channel_manager: T) -> Result<(), Bolt12SemanticError> {
20932093
/// # let channel_manager = channel_manager.get_cm();
2094-
/// # let absolute_expiry = None;
20952094
/// let offer = channel_manager
2096-
/// .create_offer_builder(absolute_expiry)?
2095+
/// .create_offer_builder()?
20972096
/// # ;
20982097
/// # // Needed for compiling for c_bindings
20992098
/// # let builder: lightning::offers::offer::OfferBuilder<_, _> = offer.into();
@@ -10173,15 +10172,36 @@ impl Default for Bolt11InvoiceParameters {
1017310172
}
1017410173

1017510174
macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
10175+
fn create_offer_builder_intern<PF>(&$self, make_path: PF) -> Result<$builder, Bolt12SemanticError>
10176+
where
10177+
PF: FnOnce(PublicKey, MessageContext, &secp256k1::Secp256k1<secp256k1::All>) -> Result<Option<BlindedMessagePath>, Bolt12SemanticError>,
10178+
{
10179+
let node_id = $self.get_our_node_id();
10180+
let expanded_key = &$self.inbound_payment_key;
10181+
let entropy = &*$self.entropy_source;
10182+
let secp_ctx = &$self.secp_ctx;
10183+
10184+
let nonce = Nonce::from_entropy_source(entropy);
10185+
let context = MessageContext::Offers(OffersContext::InvoiceRequest { nonce });
10186+
10187+
let mut builder = OfferBuilder::deriving_signing_pubkey(node_id, expanded_key, nonce, secp_ctx)
10188+
.chain_hash($self.chain_hash);
10189+
10190+
if let Some(path) = make_path(node_id, context, secp_ctx)? {
10191+
builder = builder.path(path)
10192+
}
10193+
10194+
Ok(builder.into())
10195+
}
10196+
1017610197
/// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
1017710198
/// [`ChannelManager`] when handling [`InvoiceRequest`] messages for the offer. The offer's
1017810199
/// expiration will be `absolute_expiry` if `Some`, otherwise it will not expire.
1017910200
///
1018010201
/// # Privacy
1018110202
///
10182-
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the offer based on the given
10183-
/// `absolute_expiry` according to [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`]. See those docs for
10184-
/// privacy implications as well as those of the parameterized [`Router`], which implements
10203+
/// Uses [`MessageRouter`] to construct a [`BlindedMessagePath`] for the offer. See those docs
10204+
/// for privacy implications as well as those of the parameterized [`Router`], which implements
1018510205
/// [`MessageRouter`].
1018610206
///
1018710207
/// Also, uses a derived signing pubkey in the offer for recipient privacy.
@@ -10197,29 +10217,13 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
1019710217
///
1019810218
/// [`Offer`]: crate::offers::offer::Offer
1019910219
/// [`InvoiceRequest`]: crate::offers::invoice_request::InvoiceRequest
10200-
pub fn create_offer_builder(
10201-
&$self, absolute_expiry: Option<Duration>
10202-
) -> Result<$builder, Bolt12SemanticError> {
10203-
let node_id = $self.get_our_node_id();
10204-
let expanded_key = &$self.inbound_payment_key;
10205-
let entropy = &*$self.entropy_source;
10206-
let secp_ctx = &$self.secp_ctx;
10207-
10208-
let nonce = Nonce::from_entropy_source(entropy);
10209-
let context = OffersContext::InvoiceRequest { nonce };
10210-
let path = $self.create_blinded_paths_using_absolute_expiry(context, absolute_expiry)
10211-
.and_then(|paths| paths.into_iter().next().ok_or(()))
10212-
.map_err(|_| Bolt12SemanticError::MissingPaths)?;
10213-
let builder = OfferBuilder::deriving_signing_pubkey(node_id, expanded_key, nonce, secp_ctx)
10214-
.chain_hash($self.chain_hash)
10215-
.path(path);
10216-
10217-
let builder = match absolute_expiry {
10218-
None => builder,
10219-
Some(absolute_expiry) => builder.absolute_expiry(absolute_expiry),
10220-
};
10221-
10222-
Ok(builder.into())
10220+
pub fn create_offer_builder(&$self) -> Result<$builder, Bolt12SemanticError> {
10221+
$self.create_offer_builder_intern(|_, context, _| {
10222+
$self.create_blinded_paths(context)
10223+
.and_then(|paths| paths.into_iter().next().ok_or(()))
10224+
.map(Some)
10225+
.map_err(|_| Bolt12SemanticError::MissingPaths)
10226+
})
1022310227
}
1022410228

1022510229
/// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
@@ -10248,28 +10252,12 @@ macro_rules! create_offer_builder { ($self: ident, $builder: ty) => {
1024810252
&$self,
1024910253
router: ME,
1025010254
) -> Result<$builder, Bolt12SemanticError> {
10251-
let node_id = $self.get_our_node_id();
10252-
let expanded_key = &$self.inbound_payment_key;
10253-
let entropy = &*$self.entropy_source;
10254-
let secp_ctx = &$self.secp_ctx;
10255-
10256-
let nonce = Nonce::from_entropy_source(entropy);
10257-
let context = MessageContext::Offers(OffersContext::InvoiceRequest { nonce });
10258-
10259-
let peers = $self.get_peers_for_blinded_path();
10260-
10261-
let path = router.create_blinded_paths(node_id, context, peers, secp_ctx)
10262-
.map_err(|_| Bolt12SemanticError::MissingPaths)?
10263-
.into_iter().next();
10264-
10265-
let mut builder = OfferBuilder::deriving_signing_pubkey(node_id, expanded_key, nonce, secp_ctx)
10266-
.chain_hash($self.chain_hash);
10267-
10268-
if let Some(path) = path {
10269-
builder = builder.path(path)
10270-
}
10271-
10272-
Ok(builder.into())
10255+
$self.create_offer_builder_intern(|node_id, context, secp_ctx| {
10256+
let peers = $self.get_peers_for_blinded_path();
10257+
router.create_blinded_paths(node_id, context, peers, secp_ctx)
10258+
.map(|paths| paths.into_iter().next())
10259+
.map_err(|_| Bolt12SemanticError::MissingPaths)
10260+
})
1027310261
}
1027410262
} }
1027510263

lightning/src/ln/max_payment_path_len_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@ fn bolt12_invoice_too_large_blinded_paths() {
396396
)
397397
]);
398398

399-
let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
399+
let offer = nodes[1].node.create_offer_builder().unwrap().build().unwrap();
400400
let payment_id = PaymentId([1; 32]);
401401
nodes[0].node.pay_for_offer(&offer, None, Some(5000), None, payment_id, Retry::Attempts(0), RouteParametersConfig::default()).unwrap();
402402
let invreq_om = nodes[0].onion_messenger.next_onion_message_for_peer(nodes[1].node.get_our_node_id()).unwrap();

lightning/src/ln/offers_tests.rs

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ use crate::offers::invoice_error::InvoiceError;
5858
use crate::offers::invoice_request::{InvoiceRequest, InvoiceRequestFields};
5959
use crate::offers::nonce::Nonce;
6060
use crate::offers::parse::Bolt12SemanticError;
61-
use crate::onion_message::messenger::{Destination, PeeledOnion, MessageSendInstructions};
61+
use crate::onion_message::messenger::{Destination, MessageSendInstructions, PeeledOnion};
6262
use crate::onion_message::offers::OffersMessage;
6363
use crate::onion_message::packet::ParsedOnionMessageContents;
6464
use crate::routing::gossip::{NodeAlias, NodeId};
@@ -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));
@@ -401,7 +401,8 @@ fn creates_short_lived_offer() {
401401

402402
let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
403403
let offer = alice.node
404-
.create_offer_builder(Some(absolute_expiry)).unwrap()
404+
.create_offer_builder().unwrap()
405+
.absolute_expiry(absolute_expiry)
405406
.build().unwrap();
406407
assert_eq!(offer.absolute_expiry(), Some(absolute_expiry));
407408
assert!(!offer.paths().is_empty());
@@ -428,8 +429,9 @@ fn creates_long_lived_offer() {
428429
let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY
429430
+ Duration::from_secs(1);
430431
let offer = alice.node
431-
.create_offer_builder(Some(absolute_expiry))
432+
.create_offer_builder()
432433
.unwrap()
434+
.absolute_expiry(absolute_expiry)
433435
.build().unwrap();
434436
assert_eq!(offer.absolute_expiry(), Some(absolute_expiry));
435437
assert!(!offer.paths().is_empty());
@@ -438,7 +440,7 @@ fn creates_long_lived_offer() {
438440
}
439441

440442
let offer = alice.node
441-
.create_offer_builder(None).unwrap()
443+
.create_offer_builder().unwrap()
442444
.build().unwrap();
443445
assert_eq!(offer.absolute_expiry(), None);
444446
assert!(!offer.paths().is_empty());
@@ -542,7 +544,7 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
542544
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
543545

544546
let offer = alice.node
545-
.create_offer_builder(None)
547+
.create_offer_builder()
546548
.unwrap()
547549
.amount_msats(10_000_000)
548550
.build().unwrap();
@@ -709,7 +711,7 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
709711
let bob_id = bob.node.get_our_node_id();
710712

711713
let offer = alice.node
712-
.create_offer_builder(None).unwrap()
714+
.create_offer_builder().unwrap()
713715
.amount_msats(10_000_000)
714716
.build().unwrap();
715717
assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
@@ -832,7 +834,7 @@ fn pays_for_offer_without_blinded_paths() {
832834
let bob_id = bob.node.get_our_node_id();
833835

834836
let offer = alice.node
835-
.create_offer_builder(None).unwrap()
837+
.create_offer_builder().unwrap()
836838
.clear_paths()
837839
.amount_msats(10_000_000)
838840
.build().unwrap();
@@ -956,7 +958,7 @@ fn send_invoice_requests_with_distinct_reply_path() {
956958
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
957959

958960
let offer = alice.node
959-
.create_offer_builder(None)
961+
.create_offer_builder()
960962
.unwrap()
961963
.amount_msats(10_000_000)
962964
.build().unwrap();
@@ -1092,7 +1094,7 @@ fn creates_and_pays_for_offer_with_retry() {
10921094
let bob_id = bob.node.get_our_node_id();
10931095

10941096
let offer = alice.node
1095-
.create_offer_builder(None).unwrap()
1097+
.create_offer_builder().unwrap()
10961098
.amount_msats(10_000_000)
10971099
.build().unwrap();
10981100
assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
@@ -1168,7 +1170,7 @@ fn pays_bolt12_invoice_asynchronously() {
11681170
let bob_id = bob.node.get_our_node_id();
11691171

11701172
let offer = alice.node
1171-
.create_offer_builder(None).unwrap()
1173+
.create_offer_builder().unwrap()
11721174
.amount_msats(10_000_000)
11731175
.build().unwrap();
11741176

@@ -1253,7 +1255,7 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() {
12531255
let bob_id = bob.node.get_our_node_id();
12541256

12551257
let offer = alice.node
1256-
.create_offer_builder(None).unwrap()
1258+
.create_offer_builder().unwrap()
12571259
.amount_msats(10_000_000)
12581260
.build().unwrap();
12591261
assert_ne!(offer.issuer_signing_pubkey(), Some(alice_id));
@@ -1383,7 +1385,7 @@ fn fails_authentication_when_handling_invoice_request() {
13831385
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
13841386

13851387
let offer = alice.node
1386-
.create_offer_builder(None)
1388+
.create_offer_builder()
13871389
.unwrap()
13881390
.amount_msats(10_000_000)
13891391
.build().unwrap();
@@ -1395,7 +1397,7 @@ fn fails_authentication_when_handling_invoice_request() {
13951397
}
13961398

13971399
let invalid_path = alice.node
1398-
.create_offer_builder(None)
1400+
.create_offer_builder()
13991401
.unwrap()
14001402
.build().unwrap()
14011403
.paths().first().unwrap()
@@ -1495,7 +1497,7 @@ fn fails_authentication_when_handling_invoice_for_offer() {
14951497
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
14961498

14971499
let offer = alice.node
1498-
.create_offer_builder(None)
1500+
.create_offer_builder()
14991501
.unwrap()
15001502
.amount_msats(10_000_000)
15011503
.build().unwrap();
@@ -1692,7 +1694,7 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() {
16921694
disconnect_peers(david, &[bob, charlie, &nodes[4], &nodes[5]]);
16931695

16941696
let absolute_expiry = alice.node.duration_since_epoch() + MAX_SHORT_LIVED_RELATIVE_EXPIRY;
1695-
match alice.node.create_offer_builder(Some(absolute_expiry)) {
1697+
match alice.node.create_offer_builder() {
16961698
Ok(_) => panic!("Expected error"),
16971699
Err(e) => assert_eq!(e, Bolt12SemanticError::MissingPaths),
16981700
}
@@ -1702,8 +1704,9 @@ fn fails_creating_or_paying_for_offer_without_connected_peers() {
17021704
reconnect_nodes(args);
17031705

17041706
let offer = alice.node
1705-
.create_offer_builder(Some(absolute_expiry)).unwrap()
1707+
.create_offer_builder().unwrap()
17061708
.amount_msats(10_000_000)
1709+
.absolute_expiry(absolute_expiry)
17071710
.build().unwrap();
17081711

17091712
let payment_id = PaymentId([1; 32]);
@@ -1806,7 +1809,7 @@ fn fails_creating_invoice_request_for_unsupported_chain() {
18061809
let bob = &nodes[1];
18071810

18081811
let offer = alice.node
1809-
.create_offer_builder(None).unwrap()
1812+
.create_offer_builder().unwrap()
18101813
.clear_chains()
18111814
.chain(Network::Signet)
18121815
.build().unwrap();
@@ -1865,7 +1868,7 @@ fn fails_creating_invoice_request_without_blinded_reply_path() {
18651868
disconnect_peers(david, &[bob, charlie, &nodes[4], &nodes[5]]);
18661869

18671870
let offer = alice.node
1868-
.create_offer_builder(None).unwrap()
1871+
.create_offer_builder().unwrap()
18691872
.amount_msats(10_000_000)
18701873
.build().unwrap();
18711874

@@ -1899,7 +1902,7 @@ fn fails_creating_invoice_request_with_duplicate_payment_id() {
18991902
disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]);
19001903

19011904
let offer = alice.node
1902-
.create_offer_builder(None).unwrap()
1905+
.create_offer_builder().unwrap()
19031906
.amount_msats(10_000_000)
19041907
.build().unwrap();
19051908

@@ -1985,7 +1988,7 @@ fn fails_sending_invoice_without_blinded_payment_paths_for_offer() {
19851988
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
19861989

19871990
let offer = alice.node
1988-
.create_offer_builder(None).unwrap()
1991+
.create_offer_builder().unwrap()
19891992
.amount_msats(10_000_000)
19901993
.build().unwrap();
19911994

@@ -2194,7 +2197,7 @@ fn fails_paying_invoice_with_unknown_required_features() {
21942197
disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
21952198

21962199
let offer = alice.node
2197-
.create_offer_builder(None).unwrap()
2200+
.create_offer_builder().unwrap()
21982201
.amount_msats(10_000_000)
21992202
.build().unwrap();
22002203

@@ -2273,7 +2276,7 @@ fn rejects_keysend_to_non_static_invoice_path() {
22732276
create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 1_000_000, 0);
22742277

22752278
// First pay the offer and save the payment preimage and invoice.
2276-
let offer = nodes[1].node.create_offer_builder(None).unwrap().build().unwrap();
2279+
let offer = nodes[1].node.create_offer_builder().unwrap().build().unwrap();
22772280
let amt_msat = 5000;
22782281
let payment_id = PaymentId([1; 32]);
22792282
nodes[0].node.pay_for_offer(&offer, None, Some(amt_msat), None, payment_id, Retry::Attempts(1), RouteParametersConfig::default()).unwrap();
@@ -2353,7 +2356,7 @@ fn no_double_pay_with_stale_channelmanager() {
23532356

23542357
let amt_msat = nodes[0].node.list_usable_channels()[0].next_outbound_htlc_limit_msat + 1; // Force MPP
23552358
let offer = nodes[1].node
2356-
.create_offer_builder(None).unwrap()
2359+
.create_offer_builder().unwrap()
23572360
.clear_paths()
23582361
.amount_msats(amt_msat)
23592362
.build().unwrap();

0 commit comments

Comments
 (0)