Skip to content

Commit 449252f

Browse files
committed
Functional tests for offers without blinded paths
1 parent 2e22006 commit 449252f

File tree

3 files changed

+96
-0
lines changed

3 files changed

+96
-0
lines changed

lightning/src/ln/offers_tests.rs

+86
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,89 @@ fn creates_and_pays_for_refund_using_blinded_paths() {
211211
claim_bolt12_payment(bob, &[alice]);
212212
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
213213
}
214+
215+
/// Similar to `creates_and_pays_for_offer_using_blinded_paths` but for an offer without any blinded
216+
/// paths. Note that while the invoice is requested directly using the node's pubkey, the response
217+
/// and the payment still use blinded paths as required by the spec.
218+
#[test]
219+
fn creates_and_pays_for_offer_without_blinded_paths() {
220+
let chanmon_cfgs = create_chanmon_cfgs(2);
221+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
222+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
223+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
224+
225+
create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
226+
227+
let alice = &nodes[0];
228+
let alice_id = alice.node.get_our_node_id();
229+
let bob = &nodes[1];
230+
let bob_id = bob.node.get_our_node_id();
231+
232+
let offer = alice.node
233+
.create_offer_builder("coffee".to_string())
234+
.clear_paths()
235+
.amount_msats(10_000_000)
236+
.build().unwrap();
237+
assert_eq!(offer.signing_pubkey(), alice_id);
238+
assert!(offer.paths().is_empty());
239+
240+
let payment_id = PaymentId([1; 32]);
241+
bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None).unwrap();
242+
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
243+
244+
let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
245+
alice.onion_messenger.handle_onion_message(&bob_id, &onion_message);
246+
247+
let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
248+
bob.onion_messenger.handle_onion_message(&alice_id, &onion_message);
249+
250+
let invoice = extract_invoice(bob, &onion_message);
251+
route_bolt12_payment(bob, &[alice], &invoice);
252+
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
253+
254+
claim_bolt12_payment(bob, &[alice]);
255+
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
256+
}
257+
258+
/// Similar to `creates_and_pays_for_refund_using_blinded_paths` but for a refund without any
259+
/// blinded paths. Note that while the invoice is sent directly using the node's pubkey, the payment
260+
/// still uses blinded paths as required by the spec.
261+
#[test]
262+
fn creates_and_pays_for_refund_without_blinded_paths() {
263+
let chanmon_cfgs = create_chanmon_cfgs(2);
264+
let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
265+
let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
266+
let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
267+
268+
create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
269+
270+
let alice = &nodes[0];
271+
let alice_id = alice.node.get_our_node_id();
272+
let bob = &nodes[1];
273+
let bob_id = bob.node.get_our_node_id();
274+
275+
let absolute_expiry = Duration::from_secs(u64::MAX);
276+
let payment_id = PaymentId([1; 32]);
277+
let refund = bob.node
278+
.create_refund_builder(
279+
"refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None
280+
)
281+
.unwrap()
282+
.clear_paths()
283+
.build().unwrap();
284+
assert_eq!(refund.payer_id(), bob_id);
285+
assert!(refund.paths().is_empty());
286+
expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
287+
288+
alice.node.request_refund_payment(&refund).unwrap();
289+
290+
let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
291+
bob.onion_messenger.handle_onion_message(&alice_id, &onion_message);
292+
293+
let invoice = extract_invoice(bob, &onion_message);
294+
route_bolt12_payment(bob, &[alice], &invoice);
295+
expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
296+
297+
claim_bolt12_payment(bob, &[alice]);
298+
expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
299+
}

lightning/src/offers/offer.rs

+5
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,11 @@ impl<'a, M: MetadataStrategy, T: secp256k1::Signing> OfferBuilder<'a, M, T> {
339339
self
340340
}
341341

342+
pub(crate) fn clear_paths(mut self) -> Self {
343+
self.offer.paths = None;
344+
self
345+
}
346+
342347
pub(super) fn build_unchecked(self) -> Offer {
343348
self.build_without_checks()
344349
}

lightning/src/offers/refund.rs

+5
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,11 @@ impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> {
297297

298298
#[cfg(test)]
299299
impl<'a, T: secp256k1::Signing> RefundBuilder<'a, T> {
300+
pub(crate) fn clear_paths(mut self) -> Self {
301+
self.refund.paths = None;
302+
self
303+
}
304+
300305
fn features_unchecked(mut self, features: InvoiceRequestFeatures) -> Self {
301306
self.refund.features = features;
302307
self

0 commit comments

Comments
 (0)