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