@@ -56,11 +56,12 @@ use crate::types::features::Bolt12InvoiceFeatures;
5656use crate :: ln:: functional_test_utils:: * ;
5757use crate :: ln:: msgs:: { BaseMessageHandler , ChannelMessageHandler , Init , NodeAnnouncement , OnionMessage , OnionMessageHandler , RoutingMessageHandler , SocketAddress , UnsignedGossipMessage , UnsignedNodeAnnouncement } ;
5858use crate :: ln:: outbound_payment:: IDEMPOTENCY_TIMEOUT_TICKS ;
59- use crate :: offers:: currency:: DefaultCurrencyConversion ;
59+ use crate :: offers:: currency:: { CurrencyConversion , DefaultCurrencyConversion } ;
6060use crate :: offers:: invoice:: Bolt12Invoice ;
6161use crate :: offers:: invoice_error:: InvoiceError ;
6262use crate :: offers:: invoice_request:: { InvoiceRequest , InvoiceRequestFields , InvoiceRequestVerifiedFromOffer } ;
6363use crate :: offers:: nonce:: Nonce ;
64+ use crate :: offers:: offer:: { Amount , CurrencyCode } ;
6465use crate :: offers:: parse:: Bolt12SemanticError ;
6566use crate :: onion_message:: messenger:: { DefaultMessageRouter , Destination , MessageSendInstructions , NodeIdMessageRouter , NullMessageRouter , PeeledOnion , DUMMY_HOPS_PATH_LENGTH , QR_CODED_DUMMY_HOPS_PATH_LENGTH } ;
6667use crate :: onion_message:: offers:: OffersMessage ;
@@ -94,6 +95,20 @@ macro_rules! expect_recent_payment {
9495 } }
9596}
9697
98+ macro_rules! expect_no_recent_payment {
99+ ( $node: expr, $payment_id: expr) => { {
100+ let found_payment = $node. node. list_recent_payments( ) . iter( ) . any( |payment| {
101+ match payment {
102+ RecentPaymentDetails :: AwaitingInvoice { payment_id, .. }
103+ | RecentPaymentDetails :: Pending { payment_id, .. }
104+ | RecentPaymentDetails :: Fulfilled { payment_id, .. }
105+ | RecentPaymentDetails :: Abandoned { payment_id, .. } => * payment_id == $payment_id,
106+ }
107+ } ) ;
108+ assert!( !found_payment) ;
109+ } }
110+ }
111+
97112fn connect_peers < ' a , ' b , ' c > ( node_a : & Node < ' a , ' b , ' c > , node_b : & Node < ' a , ' b , ' c > ) {
98113 let node_id_a = node_a. node . get_our_node_id ( ) ;
99114 let node_id_b = node_b. node . get_our_node_id ( ) ;
@@ -2463,6 +2478,249 @@ fn fails_paying_invoice_with_unknown_required_features() {
24632478 } ,
24642479 _ => panic ! ( "Expected Event::PaymentFailed with reason" ) ,
24652480 }
2481+ expect_no_recent_payment ! ( david, payment_id) ;
2482+ }
2483+
2484+ #[ test]
2485+ fn fails_paying_invoice_with_invalid_amount ( ) {
2486+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
2487+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
2488+
2489+ let chanmon_cfgs = create_chanmon_cfgs ( 6 ) ;
2490+ let node_cfgs = create_node_cfgs ( 6 , & chanmon_cfgs) ;
2491+ let node_chanmgrs = create_node_chanmgrs (
2492+ 6 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None ]
2493+ ) ;
2494+ let nodes = create_network ( 6 , & node_cfgs, & node_chanmgrs) ;
2495+
2496+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
2497+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
2498+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
2499+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
2500+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
2501+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
2502+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
2503+
2504+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
2505+ let alice_id = alice. node . get_our_node_id ( ) ;
2506+ let bob_id = bob. node . get_our_node_id ( ) ;
2507+ let charlie_id = charlie. node . get_our_node_id ( ) ;
2508+ let david_id = david. node . get_our_node_id ( ) ;
2509+
2510+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
2511+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
2512+
2513+ let conversion = TestCurrencyConversion ;
2514+ let offer = alice. node
2515+ . create_offer_builder ( )
2516+ . unwrap ( )
2517+ . amount (
2518+ Amount :: Currency {
2519+ iso4217_code : CurrencyCode :: new ( * b"USD" ) . unwrap ( ) ,
2520+ amount : 10 ,
2521+ } ,
2522+ & conversion,
2523+ )
2524+ . unwrap ( )
2525+ . build ( ) ;
2526+
2527+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
2528+ david. node . pay_for_offer ( & offer, None , payment_id, Default :: default ( ) ) . unwrap ( ) ;
2529+
2530+ connect_peers ( david, bob) ;
2531+
2532+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
2533+ bob. onion_messenger . handle_onion_message ( david_id, & onion_message) ;
2534+
2535+ connect_peers ( alice, charlie) ;
2536+
2537+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
2538+ let ( invoice_request, reply_path) = extract_invoice_request ( alice, & onion_message) ;
2539+ let nonce = extract_offer_nonce ( alice, & onion_message) ;
2540+ let payment_context = PaymentContext :: Bolt12Offer ( Bolt12OfferContext {
2541+ offer_id : offer. id ( ) ,
2542+ invoice_request : InvoiceRequestFields {
2543+ payer_signing_pubkey : invoice_request. payer_signing_pubkey ( ) ,
2544+ quantity : None ,
2545+ payer_note_truncated : None ,
2546+ human_readable_name : None ,
2547+ } ,
2548+ } ) ;
2549+
2550+ let expanded_key = alice. keys_manager . get_expanded_key ( ) ;
2551+ let secp_ctx = Secp256k1 :: new ( ) ;
2552+ let created_at = alice. node . duration_since_epoch ( ) ;
2553+ let requested_amount = invoice_request. payable_amount ( & conversion) . unwrap ( ) ;
2554+ let amount_msats = requested_amount. amount_msats ( ) ;
2555+ let invalid_amount_msats = requested_amount. maximum_msats ( ) . checked_add ( 1 ) . unwrap ( ) ;
2556+ let ( payment_hash, payment_secret) =
2557+ alice. node . create_inbound_payment ( Some ( amount_msats) , 3600 , None ) . unwrap ( ) ;
2558+ let payment_paths = alice
2559+ . node
2560+ . test_create_blinded_payment_paths ( Some ( amount_msats) , payment_secret, payment_context, 3600 )
2561+ . unwrap ( ) ;
2562+ let verified_invoice_request = invoice_request
2563+ . verify_using_recipient_data ( nonce, & expanded_key, & secp_ctx)
2564+ . unwrap ( ) ;
2565+
2566+ let invoice = match verified_invoice_request {
2567+ InvoiceRequestVerifiedFromOffer :: DerivedKeys ( request) => request
2568+ . respond_using_derived_keys_no_std ( & conversion, payment_paths, payment_hash, created_at)
2569+ . unwrap ( )
2570+ . amount_msats_unchecked ( invalid_amount_msats)
2571+ . build_and_sign ( & secp_ctx)
2572+ . unwrap ( ) ,
2573+ InvoiceRequestVerifiedFromOffer :: ExplicitKeys ( _) => panic ! ( "Expected invoice request with keys" ) ,
2574+ } ;
2575+
2576+ let instructions = MessageSendInstructions :: WithoutReplyPath {
2577+ destination : Destination :: BlindedPath ( reply_path) ,
2578+ } ;
2579+ let message = OffersMessage :: Invoice ( invoice) ;
2580+ alice. node . flow . pending_offers_messages . lock ( ) . unwrap ( ) . push ( ( message, instructions) ) ;
2581+
2582+ let onion_message = alice. onion_messenger . next_onion_message_for_peer ( charlie_id) . unwrap ( ) ;
2583+ charlie. onion_messenger . handle_onion_message ( alice_id, & onion_message) ;
2584+
2585+ let onion_message = charlie. onion_messenger . next_onion_message_for_peer ( david_id) . unwrap ( ) ;
2586+ david. onion_messenger . handle_onion_message ( charlie_id, & onion_message) ;
2587+
2588+ match get_event ! ( david, Event :: PaymentFailed ) {
2589+ Event :: PaymentFailed {
2590+ payment_id : event_payment_id,
2591+ payment_hash : None ,
2592+ reason : Some ( event_reason) ,
2593+ } => {
2594+ assert_eq ! ( event_payment_id, payment_id) ;
2595+ assert_eq ! ( event_reason, PaymentFailureReason :: UnexpectedError ) ;
2596+ } ,
2597+ _ => panic ! ( "Expected Event::PaymentFailed with reason" ) ,
2598+ }
2599+ expect_no_recent_payment ! ( david, payment_id) ;
2600+ }
2601+
2602+ #[ test]
2603+ fn fails_paying_invoice_with_unsupported_currency ( ) {
2604+ struct EuroConversion ;
2605+
2606+ impl CurrencyConversion for EuroConversion {
2607+ fn msats_per_minor_unit ( & self , iso4217_code : CurrencyCode ) -> Result < ( f64 , u8 ) , ( ) > {
2608+ if iso4217_code. as_str ( ) == "EUR" {
2609+ Ok ( ( 2_000.0 , 5 ) )
2610+ } else {
2611+ Err ( ( ) )
2612+ }
2613+ }
2614+ }
2615+
2616+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
2617+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
2618+
2619+ let chanmon_cfgs = create_chanmon_cfgs ( 6 ) ;
2620+ let node_cfgs = create_node_cfgs ( 6 , & chanmon_cfgs) ;
2621+ let node_chanmgrs = create_node_chanmgrs (
2622+ 6 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None ]
2623+ ) ;
2624+ let nodes = create_network ( 6 , & node_cfgs, & node_chanmgrs) ;
2625+
2626+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
2627+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
2628+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
2629+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
2630+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
2631+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
2632+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
2633+
2634+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
2635+ let alice_id = alice. node . get_our_node_id ( ) ;
2636+ let bob_id = bob. node . get_our_node_id ( ) ;
2637+ let charlie_id = charlie. node . get_our_node_id ( ) ;
2638+ let david_id = david. node . get_our_node_id ( ) ;
2639+
2640+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
2641+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
2642+
2643+ let offer = alice. node
2644+ . create_offer_builder ( )
2645+ . unwrap ( )
2646+ . amount ( Amount :: Currency { iso4217_code : CurrencyCode :: new ( * b"EUR" ) . unwrap ( ) , amount : 10 } , & EuroConversion )
2647+ . unwrap ( )
2648+ . build ( ) ;
2649+
2650+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
2651+ david. node . pay_for_offer ( & offer, None , payment_id, Default :: default ( ) ) . unwrap ( ) ;
2652+
2653+ connect_peers ( david, bob) ;
2654+
2655+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
2656+ bob. onion_messenger . handle_onion_message ( david_id, & onion_message) ;
2657+
2658+ connect_peers ( alice, charlie) ;
2659+
2660+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
2661+ let ( invoice_request, reply_path) = extract_invoice_request ( alice, & onion_message) ;
2662+ let nonce = extract_offer_nonce ( alice, & onion_message) ;
2663+ let amount_msats = invoice_request. payable_amount ( & EuroConversion ) . unwrap ( ) . amount_msats ( ) ;
2664+ let payment_context = PaymentContext :: Bolt12Offer ( Bolt12OfferContext {
2665+ offer_id : offer. id ( ) ,
2666+ invoice_request : InvoiceRequestFields {
2667+ payer_signing_pubkey : invoice_request. payer_signing_pubkey ( ) ,
2668+ quantity : None ,
2669+ payer_note_truncated : None ,
2670+ human_readable_name : None ,
2671+ } ,
2672+ } ) ;
2673+
2674+ let expanded_key = alice. keys_manager . get_expanded_key ( ) ;
2675+ let secp_ctx = Secp256k1 :: new ( ) ;
2676+ let created_at = alice. node . duration_since_epoch ( ) ;
2677+ let ( payment_hash, payment_secret) =
2678+ alice. node . create_inbound_payment ( Some ( amount_msats) , 3600 , None ) . unwrap ( ) ;
2679+ let payment_paths = alice
2680+ . node
2681+ . test_create_blinded_payment_paths ( Some ( amount_msats) , payment_secret, payment_context, 3600 )
2682+ . unwrap ( ) ;
2683+ let verified_invoice_request = invoice_request
2684+ . verify_using_recipient_data ( nonce, & expanded_key, & secp_ctx)
2685+ . unwrap ( ) ;
2686+
2687+ let invoice = match verified_invoice_request {
2688+ InvoiceRequestVerifiedFromOffer :: DerivedKeys ( request) => request
2689+ . respond_using_derived_keys_no_std (
2690+ & EuroConversion ,
2691+ payment_paths,
2692+ payment_hash,
2693+ created_at,
2694+ )
2695+ . unwrap ( )
2696+ . build_and_sign ( & secp_ctx)
2697+ . unwrap ( ) ,
2698+ InvoiceRequestVerifiedFromOffer :: ExplicitKeys ( _) => panic ! ( "Expected invoice request with keys" ) ,
2699+ } ;
2700+ let instructions = MessageSendInstructions :: WithoutReplyPath {
2701+ destination : Destination :: BlindedPath ( reply_path) ,
2702+ } ;
2703+ let message = OffersMessage :: Invoice ( invoice) ;
2704+ alice. node . flow . pending_offers_messages . lock ( ) . unwrap ( ) . push ( ( message, instructions) ) ;
2705+
2706+ let onion_message = alice. onion_messenger . next_onion_message_for_peer ( charlie_id) . unwrap ( ) ;
2707+ charlie. onion_messenger . handle_onion_message ( alice_id, & onion_message) ;
2708+
2709+ let onion_message = charlie. onion_messenger . next_onion_message_for_peer ( david_id) . unwrap ( ) ;
2710+ david. onion_messenger . handle_onion_message ( charlie_id, & onion_message) ;
2711+
2712+ match get_event ! ( david, Event :: PaymentFailed ) {
2713+ Event :: PaymentFailed {
2714+ payment_id : event_payment_id,
2715+ payment_hash : None ,
2716+ reason : Some ( event_reason) ,
2717+ } => {
2718+ assert_eq ! ( event_payment_id, payment_id) ;
2719+ assert_eq ! ( event_reason, PaymentFailureReason :: UnexpectedError ) ;
2720+ } ,
2721+ _ => panic ! ( "Expected Event::PaymentFailed with reason" ) ,
2722+ }
2723+ expect_no_recent_payment ! ( david, payment_id) ;
24662724}
24672725
24682726#[ test]
0 commit comments