Skip to content

Commit 8a24949

Browse files
f use a smaller offer
Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
1 parent e147725 commit 8a24949

File tree

3 files changed

+39
-12
lines changed

3 files changed

+39
-12
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13062,10 +13062,10 @@ where
1306213062
} else {
1306313063
builder
1306413064
};
13065-
// Create a minimal offer for BLIP-42 contact exchange (just node_id, no description/paths)
13066-
// TODO: Create a better minimal offer with a single blinded path hop for privacy,
13067-
// while keeping the size small enough to fit in the onion packet.
13068-
let payer_offer = self.create_offer_builder()?.build()?;
13065+
// Create a minimal compact offer for BLIP-42 contact exchange.
13066+
// This uses derived metadata (for verification) but no blinded paths, making it small
13067+
// enough to fit in the onion packet (~70 bytes vs 300+ bytes with blinded paths).
13068+
let payer_offer = self.flow.create_compact_offer_builder(&*self.entropy_source)?.build()?;
1306913069
let builder = builder.payer_offer(&payer_offer);
1307013070

1307113071
let invoice_request = builder.build_and_sign()?;

lightning/src/ln/offers_tests.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2659,27 +2659,27 @@ fn pay_offer_and_add_contacts_info_blip42() {
26592659
assert!(invoice_request.payer_offer().is_some());
26602660

26612661
let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
2662-
bob.onion_messenger.handle_onion_message(bob_id, &onion_message);
2662+
alice.onion_messenger.handle_onion_message(bob_id, &onion_message);
26632663

26642664
let (invoice, _reply_path) = extract_invoice(alice, &onion_message);
2665-
assert_eq!(invoice.amount_msats(), 10_000_000);
2665+
assert_eq!(invoice.amount_msats(), 5_000_000);
26662666
assert_ne!(invoice.signing_pubkey(), alice_id);
26672667
assert!(!invoice.payment_paths().is_empty());
26682668

2669-
route_bolt12_payment(bob, &[alice], &invoice);
2670-
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
2669+
route_bolt12_payment(alice, &[bob], &invoice);
2670+
expect_recent_payment!(alice, RecentPaymentDetails::Pending, payment_id);
26712671

2672-
let (_, alice_payment_preimage) = match get_event!(alice, Event::PaymentClaimable) {
2672+
let (_, bob_payment_preimage) = match get_event!(bob, Event::PaymentClaimable) {
26732673
Event::PaymentClaimable { purpose, .. } => {
26742674
let preimage = match purpose.preimage() {
26752675
Some(p) => p,
26762676
None => panic!("No preimage in PaymentClaimable"),
26772677
};
26782678
(purpose, preimage)
26792679
},
2680-
_ => panic!("No Event::PaymentClaimable for Alice"),
2680+
_ => panic!("No Event::PaymentClaimable for Bob"),
26812681
};
26822682

2683-
let (_, _) = claim_payment(bob, &[alice], alice_payment_preimage);
2684-
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
2683+
let (_, _) = claim_payment(alice, &[bob], bob_payment_preimage);
2684+
expect_recent_payment!(alice, RecentPaymentDetails::Fulfilled, payment_id);
26852685
}

lightning/src/offers/flow.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,33 @@ where
574574
Ok((builder.into(), nonce))
575575
}
576576

577+
/// Creates a minimal [`OfferBuilder`] with derived metadata but no blinded paths.
578+
///
579+
/// This is useful for scenarios where size constraints require the smallest possible offer,
580+
/// such as including a payer offer in a BLIP-42 invoice request. The resulting offer uses
581+
/// derived metadata (so invoice requests can be verified) but has no blinded paths, making
582+
/// it very compact (~70 bytes).
583+
///
584+
/// # Privacy
585+
///
586+
/// This offer exposes the derived signing pubkey directly without any blinded path privacy.
587+
/// This is acceptable for BLIP-42 use cases where the payer is intentionally sharing
588+
/// their contact information with the recipient.
589+
///
590+
/// This is not exported to bindings users as builder patterns don't map outside of move semantics.
591+
pub fn create_compact_offer_builder<ES: Deref>(
592+
&self, entropy_source: ES,
593+
) -> Result<OfferBuilder<'_, DerivedMetadata, secp256k1::All>, Bolt12SemanticError>
594+
where
595+
ES::Target: EntropySource,
596+
{
597+
// Use the internal builder but don't add any paths
598+
self.create_offer_builder_intern(&*entropy_source, |_, _, _| {
599+
Ok(core::iter::empty())
600+
})
601+
.map(|(builder, _)| builder)
602+
}
603+
577604
/// Creates an [`OfferBuilder`] such that the [`Offer`] it builds is recognized by the
578605
/// [`OffersMessageFlow`], and any corresponding [`InvoiceRequest`] can be verified using
579606
/// [`Self::verify_invoice_request`]. The offer will expire at `absolute_expiry` if `Some`,

0 commit comments

Comments
 (0)