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