From 890607e0132cbd885f7bcffdd044b4d5131b0b15 Mon Sep 17 00:00:00 2001 From: shaavan Date: Tue, 9 Jul 2024 19:59:05 +0530 Subject: [PATCH] Update Offers Test to Verify BOLT12 Invoice Reply Paths 1. Updated the Offers Test to check the reply paths in BOLT12 Invoices. 2. Changed the `extract_invoice` return type from `Option` to `BlindedMessagePath` since all BOLT12Invoices now have a corresponding reply path by default. --- lightning/src/ln/channelmanager.rs | 2 +- lightning/src/ln/offers_tests.rs | 40 +++++++++++++++++++----------- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/lightning/src/ln/channelmanager.rs b/lightning/src/ln/channelmanager.rs index a594230c0e5..9331b7b1dc1 100644 --- a/lightning/src/ln/channelmanager.rs +++ b/lightning/src/ln/channelmanager.rs @@ -10853,7 +10853,7 @@ where match response { Ok(invoice) => { - let context = MessageContext::Offers(OffersContext::Unknown {}); + let context = MessageContext::Offers(OffersContext::InboundPayment { payment_hash }); responder.respond_with_reply_path(OffersMessage::Invoice(invoice), context) }, Err(error) => responder.respond(OffersMessage::InvoiceError(error.into())), diff --git a/lightning/src/ln/offers_tests.rs b/lightning/src/ln/offers_tests.rs index b1c09fd54f8..2b3a34424a7 100644 --- a/lightning/src/ln/offers_tests.rs +++ b/lightning/src/ln/offers_tests.rs @@ -219,12 +219,12 @@ fn extract_invoice_request<'a, 'b, 'c>( } } -fn extract_invoice<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> (Bolt12Invoice, Option) { +fn extract_invoice<'a, 'b, 'c>(node: &Node<'a, 'b, 'c>, message: &OnionMessage) -> (Bolt12Invoice, BlindedMessagePath) { match node.onion_messenger.peel_onion_message(message) { Ok(PeeledOnion::Receive(message, _, reply_path)) => match message { ParsedOnionMessageContents::Offers(offers_message) => match offers_message { OffersMessage::InvoiceRequest(invoice_request) => panic!("Unexpected invoice_request: {:?}", invoice_request), - OffersMessage::Invoice(invoice) => (invoice, reply_path), + OffersMessage::Invoice(invoice) => (invoice, reply_path.unwrap()), #[cfg(async_payments)] OffersMessage::StaticInvoice(invoice) => panic!("Unexpected static invoice: {:?}", invoice), OffersMessage::InvoiceError(error) => panic!("Unexpected invoice_error: {:?}", error), @@ -508,15 +508,15 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { features.set_onion_messages_optional(); features.set_route_blinding_optional(); - let chanmon_cfgs = create_chanmon_cfgs(6); - let node_cfgs = create_node_cfgs(6, &chanmon_cfgs); + let chanmon_cfgs = create_chanmon_cfgs(7); + let node_cfgs = create_node_cfgs(7, &chanmon_cfgs); *node_cfgs[1].override_init_features.borrow_mut() = Some(features); let node_chanmgrs = create_node_chanmgrs( - 6, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None] + 7, &node_cfgs, &[None, Some(accept_forward_cfg), None, None, None, None, None] ); - let nodes = create_network(6, &node_cfgs, &node_chanmgrs); + let nodes = create_network(7, &node_cfgs, &node_chanmgrs); create_unannounced_chan_between_nodes_with_value(&nodes, 0, 1, 10_000_000, 1_000_000_000); create_unannounced_chan_between_nodes_with_value(&nodes, 2, 3, 10_000_000, 1_000_000_000); @@ -526,6 +526,12 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { create_announced_chan_between_nodes_with_value(&nodes, 2, 4, 10_000_000, 1_000_000_000); create_announced_chan_between_nodes_with_value(&nodes, 2, 5, 10_000_000, 1_000_000_000); + // Create an announced channel between Bob and node[6] to ensure that in the event of a tie + // between Bob and Charlie for becoming the introduction node candidate, Bob is deterministically + // preferred over Charlie. + create_announced_chan_between_nodes_with_value(&nodes, 1, 6, 10_000_000, 1_000_000_000); + + let (alice, bob, charlie, david) = (&nodes[0], &nodes[1], &nodes[2], &nodes[3]); let alice_id = alice.node.get_our_node_id(); let bob_id = bob.node.get_our_node_id(); @@ -580,13 +586,14 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() { let onion_message = charlie.onion_messenger.next_onion_message_for_peer(david_id).unwrap(); david.onion_messenger.handle_onion_message(&charlie_id, &onion_message); - let (invoice, _) = extract_invoice(david, &onion_message); + let (invoice, reply_path) = extract_invoice(david, &onion_message); assert_eq!(invoice.amount_msats(), 10_000_000); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty()); for path in invoice.payment_paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); } + assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(bob_id)); route_bolt12_payment(david, &[charlie, bob, alice], &invoice); expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id); @@ -659,7 +666,7 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() { let onion_message = charlie.onion_messenger.next_onion_message_for_peer(david_id).unwrap(); david.onion_messenger.handle_onion_message(&charlie_id, &onion_message); - let (invoice, _) = extract_invoice(david, &onion_message); + let (invoice, reply_path) = extract_invoice(david, &onion_message); assert_eq!(invoice, expected_invoice); assert_eq!(invoice.amount_msats(), 10_000_000); @@ -668,6 +675,8 @@ fn creates_and_pays_for_refund_using_two_hop_blinded_path() { for path in invoice.payment_paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); } + assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(bob_id)); + route_bolt12_payment(david, &[charlie, bob, alice], &invoice); expect_recent_payment!(david, RecentPaymentDetails::Pending, payment_id); @@ -726,13 +735,14 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() { let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap(); bob.onion_messenger.handle_onion_message(&alice_id, &onion_message); - let (invoice, _) = extract_invoice(bob, &onion_message); + let (invoice, reply_path) = extract_invoice(bob, &onion_message); assert_eq!(invoice.amount_msats(), 10_000_000); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty()); for path in invoice.payment_paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id)); } + assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(alice_id)); route_bolt12_payment(bob, &[alice], &invoice); expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id); @@ -779,7 +789,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() { let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap(); bob.onion_messenger.handle_onion_message(&alice_id, &onion_message); - let (invoice, _) = extract_invoice(bob, &onion_message); + let (invoice, reply_path) = extract_invoice(bob, &onion_message); assert_eq!(invoice, expected_invoice); assert_eq!(invoice.amount_msats(), 10_000_000); @@ -788,6 +798,7 @@ fn creates_and_pays_for_refund_using_one_hop_blinded_path() { for path in invoice.payment_paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(alice_id)); } + assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(alice_id)); route_bolt12_payment(bob, &[alice], &invoice); expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id); @@ -1044,7 +1055,7 @@ fn send_invoice_for_refund_with_distinct_reply_path() { let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); let (_, reply_path) = extract_invoice(alice, &onion_message); - assert_eq!(reply_path.unwrap().introduction_node(), &IntroductionNode::NodeId(charlie_id)); + assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(charlie_id)); // Send, extract and verify the second Invoice Request message let onion_message = david.onion_messenger.next_onion_message_for_peer(bob_id).unwrap(); @@ -1053,7 +1064,7 @@ fn send_invoice_for_refund_with_distinct_reply_path() { let onion_message = bob.onion_messenger.next_onion_message_for_peer(alice_id).unwrap(); let (_, reply_path) = extract_invoice(alice, &onion_message); - assert_eq!(reply_path.unwrap().introduction_node(), &IntroductionNode::NodeId(nodes[6].node.get_our_node_id())); + assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(nodes[6].node.get_our_node_id())); } /// Checks that a deferred invoice can be paid asynchronously from an Event::InvoiceReceived. @@ -1190,12 +1201,13 @@ fn creates_offer_with_blinded_path_using_unannounced_introduction_node() { let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap(); bob.onion_messenger.handle_onion_message(&alice_id, &onion_message); - let (invoice, _) = extract_invoice(bob, &onion_message); + let (invoice, reply_path) = extract_invoice(bob, &onion_message); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty()); for path in invoice.payment_paths() { assert_eq!(path.introduction_node(), &IntroductionNode::NodeId(bob_id)); } + assert_eq!(reply_path.introduction_node(), &IntroductionNode::NodeId(bob_id)); route_bolt12_payment(bob, &[alice], &invoice); expect_recent_payment!(bob, RecentPaymentDetails::Pending, payment_id); @@ -1239,7 +1251,7 @@ fn creates_refund_with_blinded_path_using_unannounced_introduction_node() { let onion_message = alice.onion_messenger.next_onion_message_for_peer(bob_id).unwrap(); - let (invoice, _) = extract_invoice(bob, &onion_message); + let (invoice, _reply_path) = extract_invoice(bob, &onion_message); assert_eq!(invoice, expected_invoice); assert_ne!(invoice.signing_pubkey(), alice_id); assert!(!invoice.payment_paths().is_empty());