Functional tests for offers with blinded paths
[rust-lightning] / lightning / src / ln / offers_tests.rs
1 // This file is Copyright its original authors, visible in version control
2 // history.
3 //
4 // This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5 // or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7 // You may not use this file except in accordance with one or both of these
8 // licenses.
9
10 //! Functional tests for the BOLT 12 Offers payment flow.
11 //!
12 //! [`ChannelManager`] provides utilities to create [`Offer`]s and [`Refund`]s along with utilities
13 //! to initiate and request payment for them, respectively. It also manages the payment flow via
14 //! implementing [`OffersMessageHandler`]. This module tests that functionality, including the
15 //! resulting [`Event`] generation.
16
17 use core::time::Duration;
18 use crate::blinded_path::BlindedPath;
19 use crate::events::{Event, MessageSendEventsProvider, PaymentPurpose};
20 use crate::ln::channelmanager::{PaymentId, RecentPaymentDetails, Retry, self};
21 use crate::ln::functional_test_utils::*;
22 use crate::ln::msgs::{ChannelMessageHandler, Init, OnionMessage, OnionMessageHandler};
23 use crate::offers::invoice::Bolt12Invoice;
24 use crate::offers::invoice_request::InvoiceRequest;
25 use crate::onion_message::messenger::PeeledOnion;
26 use crate::onion_message::offers::OffersMessage;
27 use crate::onion_message::packet::ParsedOnionMessageContents;
28
29 use crate::prelude::*;
30
31 macro_rules! expect_recent_payment {
32         ($node: expr, $payment_state: path, $payment_id: expr) => {
33                 match $node.node.list_recent_payments().first() {
34                         Some(&$payment_state { payment_id: actual_payment_id, .. }) => {
35                                 assert_eq!($payment_id, actual_payment_id);
36                         },
37                         Some(_) => panic!("Unexpected recent payment state"),
38                         None => panic!("No recent payments"),
39                 }
40         }
41 }
42
43 fn connect_peers<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, node_b: &Node<'a, 'b, 'c>) {
44         let node_id_a = node_a.node.get_our_node_id();
45         let node_id_b = node_b.node.get_our_node_id();
46
47         let init_a = Init {
48                 features: node_a.init_features(&node_id_b),
49                 networks: None,
50                 remote_network_address: None,
51         };
52         let init_b = Init {
53                 features: node_b.init_features(&node_id_a),
54                 networks: None,
55                 remote_network_address: None,
56         };
57
58         node_a.node.peer_connected(&node_id_b, &init_b, true).unwrap();
59         node_b.node.peer_connected(&node_id_a, &init_a, false).unwrap();
60         node_a.onion_messenger.peer_connected(&node_id_b, &init_b, true).unwrap();
61         node_b.onion_messenger.peer_connected(&node_id_a, &init_a, false).unwrap();
62 }
63
64 fn disconnect_peers<'a, 'b, 'c>(node_a: &Node<'a, 'b, 'c>, peers: &[&Node<'a, 'b, 'c>]) {
65         for node_b in peers {
66                 node_a.node.peer_disconnected(&node_b.node.get_our_node_id());
67                 node_b.node.peer_disconnected(&node_a.node.get_our_node_id());
68                 node_a.onion_messenger.peer_disconnected(&node_b.node.get_our_node_id());
69                 node_b.onion_messenger.peer_disconnected(&node_a.node.get_our_node_id());
70         }
71 }
72
73 fn route_bolt12_payment<'a, 'b, 'c>(
74         node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>], invoice: &Bolt12Invoice
75 ) {
76         // Monitor added when handling the invoice onion message.
77         check_added_monitors(node, 1);
78
79         let mut events = node.node.get_and_clear_pending_msg_events();
80         assert_eq!(events.len(), 1);
81         let ev = remove_first_msg_event_to_node(&path[0].node.get_our_node_id(), &mut events);
82
83         // Use a fake payment_hash and bypass checking for the PaymentClaimable event since the
84         // invoice contains the payment_hash but it was encrypted inside an onion message.
85         let amount_msats = invoice.amount_msats();
86         let payment_hash = invoice.payment_hash();
87         do_pass_along_path(
88                 node, path, amount_msats, payment_hash, None, ev, false, false, None, false
89         );
90 }
91
92 fn claim_bolt12_payment<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, path: &[&Node<'a, 'b, 'c>]) {
93         let recipient = &path[path.len() - 1];
94         match get_event!(recipient, Event::PaymentClaimable) {
95                 Event::PaymentClaimable {
96                         purpose: PaymentPurpose::InvoicePayment {
97                                 payment_preimage: Some(payment_preimage), ..
98                         }, ..
99                 } => claim_payment(node, path, payment_preimage),
100                 _ => panic!(),
101         };
102 }
103
104 fn extract_invoice_request<'a, 'b, 'c>(
105         node: &Node<'a, 'b, 'c>, message: &OnionMessage
106 ) -> (InvoiceRequest, Option<BlindedPath>) {
107         match node.onion_messenger.peel_onion_message(message) {
108                 Ok(PeeledOnion::Receive(message, _, reply_path)) => match message {
109                         ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
110                                 OffersMessage::InvoiceRequest(invoice_request) => (invoice_request, reply_path),
111                                 OffersMessage::Invoice(invoice) => panic!("Unexpected invoice: {:?}", invoice),
112                                 OffersMessage::InvoiceError(error) => panic!("Unexpected invoice_error: {:?}", error),
113                         },
114                         ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message),
115                 },
116                 Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"),
117                 Err(e) => panic!("Failed to process onion message {:?}", e),
118         }
119 }
120
121 fn extract_invoice<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> Bolt12Invoice {
122         match node.onion_messenger.peel_onion_message(message) {
123                 Ok(PeeledOnion::Receive(message, _, _)) => match message {
124                         ParsedOnionMessageContents::Offers(offers_message) => match offers_message {
125                                 OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request),
126                                 OffersMessage::Invoice(invoice) => invoice,
127                                 OffersMessage::InvoiceError(error) => panic!("Unexpected invoice_error: {:?}", error),
128                         },
129                         ParsedOnionMessageContents::Custom(message) => panic!("Unexpected custom message: {:?}", message),
130                 },
131                 Ok(PeeledOnion::Forward(_, _)) => panic!("Unexpected onion message forward"),
132                 Err(e) => panic!("Failed to process onion message {:?}", e),
133         }
134 }
135
136 /// Checks that an offer can be paid through blinded paths and that ephemeral pubkeys are used
137 /// rather than exposing a node's pubkey.
138 #[test]
139 fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
140         let mut accept_forward_cfg = test_default_channel_config();
141         accept_forward_cfg.accept_forwards_to_priv_channels = true;
142
143         let mut features = channelmanager::provided_init_features(&accept_forward_cfg);
144         features.set_onion_messages_optional();
145         features.set_route_blinding_optional();
146
147         let chanmon_cfgs = create_chanmon_cfgs(6);
148         let node_cfgs = create_node_cfgs(6, &chanmon_cfgs);
149
150         *node_cfgs[1].override_init_features.borrow_mut() = Some(features);
151
152         let node_chanmgrs = create_node_chanmgrs(
153                 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None]
154         );
155         let nodes = create_network(6, &node_cfgs, &node_chanmgrs);
156
157         create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
158         create_unannounced_chan_between_nodes_with_value(&nodes, 2, 3, 10_000_000, 1_000_000_000);
159         create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000_000, 1_000_000_000);
160         create_announced_chan_between_nodes_with_value(&nodes, 1, 4, 10_000_000, 1_000_000_000);
161         create_announced_chan_between_nodes_with_value(&nodes, 1, 5, 10_000_000, 1_000_000_000);
162         create_announced_chan_between_nodes_with_value(&nodes, 2, 4, 10_000_000, 1_000_000_000);
163         create_announced_chan_between_nodes_with_value(&nodes, 2, 5, 10_000_000, 1_000_000_000);
164
165         let (alice, bob, charlie, david) = (&nodes[0], &nodes[1], &nodes[2], &nodes[3]);
166         let alice_id = alice.node.get_our_node_id();
167         let bob_id = bob.node.get_our_node_id();
168         let charlie_id = charlie.node.get_our_node_id();
169         let david_id = david.node.get_our_node_id();
170
171         disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]);
172         disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
173
174         let offer = alice.node
175                 .create_offer_builder("coffee".to_string()).unwrap()
176                 .amount_msats(10_000_000)
177                 .build().unwrap();
178         assert_ne!(offer.signing_pubkey(), alice_id);
179         assert!(!offer.paths().is_empty());
180         for path in offer.paths() {
181                 assert_eq!(path.introduction_node_id, bob_id);
182         }
183
184         let payment_id = PaymentId([1; 32]);
185         david.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None)
186                 .unwrap();
187         expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
188
189         connect_peers(david, bob);
190
191         let onion_message = david.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
192         bob.onion_messenger.handle_onion_message(&david_id, &onion_message);
193
194         connect_peers(alice, charlie);
195
196         let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
197         alice.onion_messenger.handle_onion_message(&bob_id, &onion_message);
198
199         let (invoice_request, reply_path) = extract_invoice_request(alice, &onion_message);
200         assert_eq!(invoice_request.amount_msats(), None);
201         assert_ne!(invoice_request.payer_id(), david_id);
202         assert_eq!(reply_path.unwrap().introduction_node_id, charlie_id);
203
204         let onion_message = alice.onion_messenger.next_onion_message_for_peer(charlie_id).unwrap();
205         charlie.onion_messenger.handle_onion_message(&alice_id, &onion_message);
206
207         let onion_message = charlie.onion_messenger.next_onion_message_for_peer(david_id).unwrap();
208         david.onion_messenger.handle_onion_message(&charlie_id, &onion_message);
209
210         let invoice = extract_invoice(david, &onion_message);
211         assert_eq!(invoice.amount_msats(), 10_000_000);
212         assert_ne!(invoice.signing_pubkey(), alice_id);
213         assert!(!invoice.payment_paths().is_empty());
214         for (_, path) in invoice.payment_paths() {
215                 assert_eq!(path.introduction_node_id, bob_id);
216         }
217
218         route_bolt12_payment(david, &[charlie, bob, alice], &invoice);
219         expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id);
220
221         claim_bolt12_payment(david, &[charlie, bob, alice]);
222         expect_recent_payment!(david, RecentPaymentDetails::Fulfilled, payment_id);
223 }
224
225 /// Checks that a refund can be paid through blinded paths and that ephemeral pubkeys are used
226 /// rather than exposing a node's pubkey.
227 #[test]
228 fn creates_and_pays_for_refund_using_two_hop_blinded_path() {
229         let mut accept_forward_cfg = test_default_channel_config();
230         accept_forward_cfg.accept_forwards_to_priv_channels = true;
231
232         let mut features = channelmanager::provided_init_features(&accept_forward_cfg);
233         features.set_onion_messages_optional();
234         features.set_route_blinding_optional();
235
236         let chanmon_cfgs = create_chanmon_cfgs(6);
237         let node_cfgs = create_node_cfgs(6, &chanmon_cfgs);
238
239         *node_cfgs[1].override_init_features.borrow_mut() = Some(features);
240
241         let node_chanmgrs = create_node_chanmgrs(
242                 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None]
243         );
244         let nodes = create_network(6, &node_cfgs, &node_chanmgrs);
245
246         create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
247         create_unannounced_chan_between_nodes_with_value(&nodes, 2, 3, 10_000_000, 1_000_000_000);
248         create_announced_chan_between_nodes_with_value(&nodes, 1, 2, 10_000_000, 1_000_000_000);
249         create_announced_chan_between_nodes_with_value(&nodes, 1, 4, 10_000_000, 1_000_000_000);
250         create_announced_chan_between_nodes_with_value(&nodes, 1, 5, 10_000_000, 1_000_000_000);
251         create_announced_chan_between_nodes_with_value(&nodes, 2, 4, 10_000_000, 1_000_000_000);
252         create_announced_chan_between_nodes_with_value(&nodes, 2, 5, 10_000_000, 1_000_000_000);
253
254         let (alice, bob, charlie, david) = (&nodes[0], &nodes[1], &nodes[2], &nodes[3]);
255         let alice_id = alice.node.get_our_node_id();
256         let bob_id = bob.node.get_our_node_id();
257         let charlie_id = charlie.node.get_our_node_id();
258         let david_id = david.node.get_our_node_id();
259
260         disconnect_peers(alice, &[charlie, david, &nodes[4], &nodes[5]]);
261         disconnect_peers(david, &[bob, &nodes[4], &nodes[5]]);
262
263         let absolute_expiry = Duration::from_secs(u64::MAX);
264         let payment_id = PaymentId([1; 32]);
265         let refund = david.node
266                 .create_refund_builder(
267                         "refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None
268                 )
269                 .unwrap()
270                 .build().unwrap();
271         assert_eq!(refund.amount_msats(), 10_000_000);
272         assert_eq!(refund.absolute_expiry(), Some(absolute_expiry));
273         assert_ne!(refund.payer_id(), david_id);
274         assert!(!refund.paths().is_empty());
275         for path in refund.paths() {
276                 assert_eq!(path.introduction_node_id, charlie_id);
277         }
278         expect_recent_payment!(david, RecentPaymentDetails::AwaitingInvoice, payment_id);
279
280         alice.node.request_refund_payment(&refund).unwrap();
281
282         connect_peers(alice, charlie);
283
284         let onion_message = alice.onion_messenger.next_onion_message_for_peer(charlie_id).unwrap();
285         charlie.onion_messenger.handle_onion_message(&alice_id, &onion_message);
286
287         let onion_message = charlie.onion_messenger.next_onion_message_for_peer(david_id).unwrap();
288         david.onion_messenger.handle_onion_message(&charlie_id, &onion_message);
289
290         let invoice = extract_invoice(david, &onion_message);
291         assert_eq!(invoice.amount_msats(), 10_000_000);
292         assert_ne!(invoice.signing_pubkey(), alice_id);
293         assert!(!invoice.payment_paths().is_empty());
294         for (_, path) in invoice.payment_paths() {
295                 assert_eq!(path.introduction_node_id, bob_id);
296         }
297
298         route_bolt12_payment(david, &[charlie, bob, alice], &invoice);
299         expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id);
300
301         claim_bolt12_payment(david, &[charlie, bob, alice]);
302         expect_recent_payment!(david, RecentPaymentDetails::Fulfilled, payment_id);
303 }
304
305 /// Checks that an offer can be paid through a one-hop blinded path and that ephemeral pubkeys are
306 /// used rather than exposing a node's pubkey. However, the node's pubkey is still used as the
307 /// introduction node of the blinded path.
308 #[test]
309 fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
310         let chanmon_cfgs = create_chanmon_cfgs(2);
311         let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
312         let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
313         let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
314
315         create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
316
317         let alice = &nodes[0];
318         let alice_id = alice.node.get_our_node_id();
319         let bob = &nodes[1];
320         let bob_id = bob.node.get_our_node_id();
321
322         let offer = alice.node
323                 .create_offer_builder("coffee".to_string()).unwrap()
324                 .amount_msats(10_000_000)
325                 .build().unwrap();
326         assert_ne!(offer.signing_pubkey(), alice_id);
327         assert!(!offer.paths().is_empty());
328         for path in offer.paths() {
329                 assert_eq!(path.introduction_node_id, alice_id);
330         }
331
332         let payment_id = PaymentId([1; 32]);
333         bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None).unwrap();
334         expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
335
336         let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
337         alice.onion_messenger.handle_onion_message(&bob_id, &onion_message);
338
339         let (invoice_request, reply_path) = extract_invoice_request(alice, &onion_message);
340         assert_eq!(invoice_request.amount_msats(), None);
341         assert_ne!(invoice_request.payer_id(), bob_id);
342         assert_eq!(reply_path.unwrap().introduction_node_id, bob_id);
343
344         let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
345         bob.onion_messenger.handle_onion_message(&alice_id, &onion_message);
346
347         let invoice = extract_invoice(bob, &onion_message);
348         assert_eq!(invoice.amount_msats(), 10_000_000);
349         assert_ne!(invoice.signing_pubkey(), alice_id);
350         assert!(!invoice.payment_paths().is_empty());
351         for (_, path) in invoice.payment_paths() {
352                 assert_eq!(path.introduction_node_id, alice_id);
353         }
354
355         route_bolt12_payment(bob, &[alice], &invoice);
356         expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
357
358         claim_bolt12_payment(bob, &[alice]);
359         expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
360 }
361
362 /// Checks that a refund can be paid through a one-hop blinded path and that ephemeral pubkeys are
363 /// used rather than exposing a node's pubkey. However, the node's pubkey is still used as the
364 /// introduction node of the blinded path.
365 #[test]
366 fn creates_and_pays_for_refund_using_one_hop_blinded_path() {
367         let chanmon_cfgs = create_chanmon_cfgs(2);
368         let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
369         let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
370         let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
371
372         create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
373
374         let alice = &nodes[0];
375         let alice_id = alice.node.get_our_node_id();
376         let bob = &nodes[1];
377         let bob_id = bob.node.get_our_node_id();
378
379         let absolute_expiry = Duration::from_secs(u64::MAX);
380         let payment_id = PaymentId([1; 32]);
381         let refund = bob.node
382                 .create_refund_builder(
383                         "refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None
384                 )
385                 .unwrap()
386                 .build().unwrap();
387         assert_eq!(refund.amount_msats(), 10_000_000);
388         assert_eq!(refund.absolute_expiry(), Some(absolute_expiry));
389         assert_ne!(refund.payer_id(), bob_id);
390         assert!(!refund.paths().is_empty());
391         for path in refund.paths() {
392                 assert_eq!(path.introduction_node_id, bob_id);
393         }
394         expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
395
396         alice.node.request_refund_payment(&refund).unwrap();
397
398         let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
399         bob.onion_messenger.handle_onion_message(&alice_id, &onion_message);
400
401         let invoice = extract_invoice(bob, &onion_message);
402         assert_eq!(invoice.amount_msats(), 10_000_000);
403         assert_ne!(invoice.signing_pubkey(), alice_id);
404         assert!(!invoice.payment_paths().is_empty());
405         for (_, path) in invoice.payment_paths() {
406                 assert_eq!(path.introduction_node_id, alice_id);
407         }
408
409         route_bolt12_payment(bob, &[alice], &invoice);
410         expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
411
412         claim_bolt12_payment(bob, &[alice]);
413         expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
414 }
415
416 /// Checks that an invoice for an offer without any blinded paths can be requested. Note that while
417 /// the requested is sent directly using the node's pubkey, the response and the payment still use
418 /// blinded paths as required by the spec.
419 #[test]
420 fn pays_for_offer_without_blinded_paths() {
421         let chanmon_cfgs = create_chanmon_cfgs(2);
422         let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
423         let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
424         let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
425
426         create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
427
428         let alice = &nodes[0];
429         let alice_id = alice.node.get_our_node_id();
430         let bob = &nodes[1];
431         let bob_id = bob.node.get_our_node_id();
432
433         let offer = alice.node
434                 .create_offer_builder("coffee".to_string()).unwrap()
435                 .clear_paths()
436                 .amount_msats(10_000_000)
437                 .build().unwrap();
438         assert_eq!(offer.signing_pubkey(), alice_id);
439         assert!(offer.paths().is_empty());
440
441         let payment_id = PaymentId([1; 32]);
442         bob.node.pay_for_offer(&offer, None, None, None, payment_id, Retry::Attempts(0), None).unwrap();
443         expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
444
445         let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap();
446         alice.onion_messenger.handle_onion_message(&bob_id, &onion_message);
447
448         let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
449         bob.onion_messenger.handle_onion_message(&alice_id, &onion_message);
450
451         let invoice = extract_invoice(bob, &onion_message);
452         route_bolt12_payment(bob, &[alice], &invoice);
453         expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
454
455         claim_bolt12_payment(bob, &[alice]);
456         expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
457 }
458
459 /// Checks that a refund without any blinded paths can be paid. Note that while the invoice is sent
460 /// directly using the node's pubkey, the payment still use blinded paths as required by the spec.
461 #[test]
462 fn pays_for_refund_without_blinded_paths() {
463         let chanmon_cfgs = create_chanmon_cfgs(2);
464         let node_cfgs = create_node_cfgs(2, &chanmon_cfgs);
465         let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]);
466         let nodes = create_network(2, &node_cfgs, &node_chanmgrs);
467
468         create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000);
469
470         let alice = &nodes[0];
471         let alice_id = alice.node.get_our_node_id();
472         let bob = &nodes[1];
473         let bob_id = bob.node.get_our_node_id();
474
475         let absolute_expiry = Duration::from_secs(u64::MAX);
476         let payment_id = PaymentId([1; 32]);
477         let refund = bob.node
478                 .create_refund_builder(
479                         "refund".to_string(), 10_000_000, absolute_expiry, payment_id, Retry::Attempts(0), None
480                 )
481                 .unwrap()
482                 .clear_paths()
483                 .build().unwrap();
484         assert_eq!(refund.payer_id(), bob_id);
485         assert!(refund.paths().is_empty());
486         expect_recent_payment!(bob, RecentPaymentDetails::AwaitingInvoice, payment_id);
487
488         alice.node.request_refund_payment(&refund).unwrap();
489
490         let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap();
491         bob.onion_messenger.handle_onion_message(&alice_id, &onion_message);
492
493         let invoice = extract_invoice(bob, &onion_message);
494         route_bolt12_payment(bob, &[alice], &invoice);
495         expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id);
496
497         claim_bolt12_payment(bob, &[alice]);
498         expect_recent_payment!(bob, RecentPaymentDetails::Fulfilled, payment_id);
499 }