@@ -5423,3 +5423,160 @@ fn max_out_mpp_path() {
54235423 check_added_monitors ( & nodes[ 0 ] , 2 ) ; // one monitor update per MPP part
54245424 nodes[ 0 ] . node . get_and_clear_pending_msg_events ( ) ;
54255425}
5426+
5427+ #[ test]
5428+ fn bolt11_multi_node_mpp ( ) {
5429+ // Test that multiple nodes can collaborate to pay a single BOLT 11 invoice, with each node
5430+ // paying a portion of the total invoice amount. This is useful for scenarios like:
5431+ // - Paying from multiple wallets (e.g., ecash wallets with funds in multiple mints)
5432+ // - Graduated wallets (funds split between trusted and self-custodial wallets)
5433+
5434+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
5435+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
5436+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
5437+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
5438+
5439+ // Create channels: A<>C and B<>C
5440+ create_announced_chan_between_nodes ( & nodes, 0 , 2 ) ;
5441+ create_announced_chan_between_nodes ( & nodes, 1 , 2 ) ;
5442+
5443+ // Node C creates a BOLT 11 invoice for 100_000 msat
5444+ let invoice_amt_msat = 100_000 ;
5445+ let invoice_params = crate :: ln:: channelmanager:: Bolt11InvoiceParameters {
5446+ amount_msats : Some ( invoice_amt_msat) ,
5447+ ..Default :: default ( )
5448+ } ;
5449+ let invoice = nodes[ 2 ] . node . create_bolt11_invoice ( invoice_params) . unwrap ( ) ;
5450+
5451+ // Node A pays 60_000 msat (part of the total)
5452+ let node_a_payment_amt = 60_000 ;
5453+ let payment_id_a = PaymentId ( [ 1 ; 32 ] ) ;
5454+ let optional_params_a = crate :: ln:: channelmanager:: OptionalBolt11PaymentParams {
5455+ declared_total_mpp_value_override : Some ( invoice_amt_msat) ,
5456+ ..Default :: default ( )
5457+ } ;
5458+ nodes[ 0 ]
5459+ . node
5460+ . pay_for_bolt11_invoice ( & invoice, payment_id_a, Some ( node_a_payment_amt) , optional_params_a)
5461+ . unwrap ( ) ;
5462+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
5463+
5464+ // Node B pays 40_000 msat (the remaining part)
5465+ let node_b_payment_amt = 40_000 ;
5466+ let payment_id_b = PaymentId ( [ 2 ; 32 ] ) ;
5467+ let optional_params_b = crate :: ln:: channelmanager:: OptionalBolt11PaymentParams {
5468+ declared_total_mpp_value_override : Some ( invoice_amt_msat) ,
5469+ ..Default :: default ( )
5470+ } ;
5471+ nodes[ 1 ]
5472+ . node
5473+ . pay_for_bolt11_invoice ( & invoice, payment_id_b, Some ( node_b_payment_amt) , optional_params_b)
5474+ . unwrap ( ) ;
5475+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
5476+
5477+ let payment_event_a = SendEvent :: from_node ( & nodes[ 0 ] ) ;
5478+ nodes[ 2 ] . node . handle_update_add_htlc ( nodes[ 0 ] . node . get_our_node_id ( ) , & payment_event_a. msgs [ 0 ] ) ;
5479+ do_commitment_signed_dance ( & nodes[ 2 ] , & nodes[ 0 ] , & payment_event_a. commitment_msg , false , false ) ;
5480+
5481+ let payment_event_b = SendEvent :: from_node ( & nodes[ 1 ] ) ;
5482+ nodes[ 2 ] . node . handle_update_add_htlc ( nodes[ 1 ] . node . get_our_node_id ( ) , & payment_event_b. msgs [ 0 ] ) ;
5483+ do_commitment_signed_dance ( & nodes[ 2 ] , & nodes[ 1 ] , & payment_event_b. commitment_msg , false , false ) ;
5484+
5485+ // Process the pending HTLCs on node C and generate the PaymentClaimable event
5486+ assert ! ( nodes[ 2 ] . node. get_and_clear_pending_events( ) . is_empty( ) ) ;
5487+ expect_and_process_pending_htlcs ( & nodes[ 2 ] , false ) ;
5488+ let events = nodes[ 2 ] . node . get_and_clear_pending_events ( ) ;
5489+ assert_eq ! ( events. len( ) , 1 ) ;
5490+ let payment_preimage = match & events[ 0 ] {
5491+ Event :: PaymentClaimable {
5492+ payment_hash,
5493+ amount_msat,
5494+ purpose : PaymentPurpose :: Bolt11InvoicePayment { payment_preimage, .. } ,
5495+ ..
5496+ } => {
5497+ assert_eq ! ( * payment_hash, invoice. payment_hash( ) ) ;
5498+ assert_eq ! ( * amount_msat, invoice_amt_msat) ;
5499+ payment_preimage. unwrap ( )
5500+ } ,
5501+ _ => panic ! ( "Unexpected event: {:?}" , events[ 0 ] ) ,
5502+ } ;
5503+
5504+ nodes[ 2 ] . node . claim_funds ( payment_preimage) ;
5505+
5506+ expect_payment_claimed ! ( nodes[ 2 ] , invoice. payment_hash( ) , invoice_amt_msat) ;
5507+ check_added_monitors ( & nodes[ 2 ] , 2 ) ;
5508+
5509+ // Get the fulfill messages from C to both A and B
5510+ let mut events_c = nodes[ 2 ] . node . get_and_clear_pending_msg_events ( ) ;
5511+ assert_eq ! ( events_c. len( ) , 2 ) ;
5512+
5513+ // Handle fulfill message from C to A
5514+ let fulfill_idx_a = events_c
5515+ . iter ( )
5516+ . position ( |ev| {
5517+ if let MessageSendEvent :: UpdateHTLCs { node_id, .. } = ev {
5518+ * node_id == nodes[ 0 ] . node . get_our_node_id ( )
5519+ } else {
5520+ false
5521+ }
5522+ } )
5523+ . unwrap ( ) ;
5524+ let fulfill_idx_b = 1 - fulfill_idx_a;
5525+
5526+ if let MessageSendEvent :: UpdateHTLCs { ref updates, .. } = events_c[ fulfill_idx_a] {
5527+ nodes[ 0 ] . node . handle_update_fulfill_htlc (
5528+ nodes[ 2 ] . node . get_our_node_id ( ) ,
5529+ updates. update_fulfill_htlcs [ 0 ] . clone ( ) ,
5530+ ) ;
5531+ do_commitment_signed_dance ( & nodes[ 0 ] , & nodes[ 2 ] , & updates. commitment_signed , false , false ) ;
5532+ }
5533+
5534+ let payment_sent = nodes[ 0 ] . node . get_and_clear_pending_events ( ) ;
5535+ check_added_monitors ( & nodes[ 0 ] , 1 ) ;
5536+
5537+ assert_eq ! ( payment_sent. len( ) , 2 , "{payment_sent:?}" ) ;
5538+ if let Event :: PaymentSent { payment_id, payment_hash, amount_msat, fee_paid_msat, .. } =
5539+ & payment_sent[ 0 ]
5540+ {
5541+ assert_eq ! ( * payment_id, Some ( payment_id_a) ) ;
5542+ assert_eq ! ( * payment_hash, invoice. payment_hash( ) ) ;
5543+ assert_eq ! ( * amount_msat, Some ( node_a_payment_amt) ) ;
5544+ assert_eq ! ( * fee_paid_msat, Some ( 0 ) ) ;
5545+ } else {
5546+ panic ! ( "{payment_sent:?}" ) ;
5547+ }
5548+ if let Event :: PaymentPathSuccessful { payment_id, .. } = & payment_sent[ 1 ] {
5549+ assert_eq ! ( * payment_id, payment_id_a) ;
5550+ } else {
5551+ panic ! ( "{payment_sent:?}" ) ;
5552+ }
5553+
5554+ // Handle fulfill message from C to B
5555+ if let MessageSendEvent :: UpdateHTLCs { ref updates, .. } = events_c[ fulfill_idx_b] {
5556+ nodes[ 1 ] . node . handle_update_fulfill_htlc (
5557+ nodes[ 2 ] . node . get_our_node_id ( ) ,
5558+ updates. update_fulfill_htlcs [ 0 ] . clone ( ) ,
5559+ ) ;
5560+ do_commitment_signed_dance ( & nodes[ 1 ] , & nodes[ 2 ] , & updates. commitment_signed , false , false ) ;
5561+ }
5562+
5563+ let payment_sent = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
5564+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
5565+
5566+ assert_eq ! ( payment_sent. len( ) , 2 , "{payment_sent:?}" ) ;
5567+ if let Event :: PaymentSent { payment_id, payment_hash, amount_msat, fee_paid_msat, .. } =
5568+ & payment_sent[ 0 ]
5569+ {
5570+ assert_eq ! ( * payment_id, Some ( payment_id_b) ) ;
5571+ assert_eq ! ( * payment_hash, invoice. payment_hash( ) ) ;
5572+ assert_eq ! ( * amount_msat, Some ( node_b_payment_amt) ) ;
5573+ assert_eq ! ( * fee_paid_msat, Some ( 0 ) ) ;
5574+ } else {
5575+ panic ! ( "{payment_sent:?}" ) ;
5576+ }
5577+ if let Event :: PaymentPathSuccessful { payment_id, .. } = & payment_sent[ 1 ] {
5578+ assert_eq ! ( * payment_id, payment_id_b) ;
5579+ } else {
5580+ panic ! ( "{payment_sent:?}" ) ;
5581+ }
5582+ }
0 commit comments