@@ -2986,6 +2986,137 @@ async fn do_lsps2_client_service_integration(client_trusts_lsp: bool) {
29862986 assert_eq ! ( client_node. payment( & payment_id) . unwrap( ) . status, PaymentStatus :: Failed ) ;
29872987}
29882988
2989+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
2990+ async fn bolt12_lsps2_client_service_integration ( ) {
2991+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
2992+ let esplora_url = format ! ( "http://{}" , electrsd. esplora_url. as_ref( ) . unwrap( ) ) ;
2993+
2994+ let mut sync_config = EsploraSyncConfig :: default ( ) ;
2995+ sync_config. background_sync_config = None ;
2996+
2997+ let channel_opening_fee_ppm = 10_000 ;
2998+ let lsps2_service_config = LSPS2ServiceConfig {
2999+ require_token : None ,
3000+ advertise_service : false ,
3001+ channel_opening_fee_ppm,
3002+ channel_over_provisioning_ppm : 100_000 ,
3003+ max_payment_size_msat : 1_000_000_000 ,
3004+ min_payment_size_msat : 0 ,
3005+ min_channel_lifetime : 100 ,
3006+ min_channel_opening_fee_msat : 0 ,
3007+ max_client_to_self_delay : 1024 ,
3008+ client_trusts_lsp : true ,
3009+ disable_client_reserve : false ,
3010+ } ;
3011+
3012+ let service_config = random_config ( ) ;
3013+ setup_builder ! ( service_builder, service_config. node_config) ;
3014+ service_builder. set_chain_source_esplora ( esplora_url. clone ( ) , Some ( sync_config) ) ;
3015+ service_builder. enable_liquidity_provider ( lsps2_service_config) ;
3016+ let service_node = service_builder. build ( service_config. node_entropy . into ( ) ) . unwrap ( ) ;
3017+ service_node. start ( ) . unwrap ( ) ;
3018+
3019+ let service_node_id = service_node. node_id ( ) ;
3020+ let service_addr = service_node. listening_addresses ( ) . unwrap ( ) . first ( ) . unwrap ( ) . clone ( ) ;
3021+
3022+ let client_config = random_config ( ) ;
3023+ setup_builder ! ( client_builder, client_config. node_config) ;
3024+ client_builder. set_chain_source_esplora ( esplora_url. clone ( ) , Some ( sync_config) ) ;
3025+ client_builder. add_liquidity_source ( service_node_id, service_addr, None , true ) ;
3026+ let client_node = client_builder. build ( client_config. node_entropy . into ( ) ) . unwrap ( ) ;
3027+ client_node. start ( ) . unwrap ( ) ;
3028+
3029+ let payer_config = random_config ( ) ;
3030+ setup_builder ! ( payer_builder, payer_config. node_config) ;
3031+ payer_builder. set_chain_source_esplora ( esplora_url. clone ( ) , Some ( sync_config) ) ;
3032+ let payer_node = payer_builder. build ( payer_config. node_entropy . into ( ) ) . unwrap ( ) ;
3033+ payer_node. start ( ) . unwrap ( ) ;
3034+
3035+ let client_addr = client_node. listening_addresses ( ) . unwrap ( ) . first ( ) . unwrap ( ) . clone ( ) ;
3036+ payer_node. connect ( client_node. node_id ( ) , client_addr, false ) . unwrap ( ) ;
3037+
3038+ let service_onchain_addr = service_node. onchain_payment ( ) . new_address ( ) . unwrap ( ) ;
3039+ let client_onchain_addr = client_node. onchain_payment ( ) . new_address ( ) . unwrap ( ) ;
3040+ let payer_onchain_addr = payer_node. onchain_payment ( ) . new_address ( ) . unwrap ( ) ;
3041+ premine_and_distribute_funds (
3042+ & bitcoind. client ,
3043+ & electrsd. client ,
3044+ vec ! [ service_onchain_addr, client_onchain_addr, payer_onchain_addr] ,
3045+ Amount :: from_sat ( 10_000_000 ) ,
3046+ )
3047+ . await ;
3048+ service_node. sync_wallets ( ) . unwrap ( ) ;
3049+ client_node. sync_wallets ( ) . unwrap ( ) ;
3050+ payer_node. sync_wallets ( ) . unwrap ( ) ;
3051+
3052+ open_channel ( & payer_node, & service_node, 5_000_000 , true , & electrsd) . await ;
3053+ generate_blocks_and_wait ( & bitcoind. client , & electrsd. client , 6 ) . await ;
3054+ service_node. sync_wallets ( ) . unwrap ( ) ;
3055+ payer_node. sync_wallets ( ) . unwrap ( ) ;
3056+ expect_channel_ready_event ! ( payer_node, service_node. node_id( ) ) ;
3057+ expect_channel_ready_event ! ( service_node, payer_node. node_id( ) ) ;
3058+ while payer_node. status ( ) . latest_node_announcement_broadcast_timestamp . is_none ( ) {
3059+ tokio:: time:: sleep ( std:: time:: Duration :: from_millis ( 10 ) ) . await ;
3060+ }
3061+ tokio:: time:: sleep ( std:: time:: Duration :: from_secs ( 1 ) ) . await ;
3062+
3063+ let fixed_amount_msat = 100_000_000 ;
3064+ let fixed_offer = client_node
3065+ . bolt12_payment ( )
3066+ . receive_via_jit_channel ( fixed_amount_msat, "fixed" , None , None , None )
3067+ . unwrap ( ) ;
3068+ assert ! ( fixed_offer. paths( ) . is_empty( ) ) ;
3069+ assert_eq ! ( fixed_offer. issuer_signing_pubkey( ) , Some ( client_node. node_id( ) ) ) ;
3070+ let fixed_payment_id =
3071+ payer_node. bolt12_payment ( ) . send ( & fixed_offer, None , None , None ) . unwrap ( ) ;
3072+
3073+ expect_channel_pending_event ! ( service_node, client_node. node_id( ) ) ;
3074+ expect_channel_ready_event ! ( service_node, client_node. node_id( ) ) ;
3075+ expect_event ! ( service_node, PaymentForwarded ) ;
3076+ expect_channel_pending_event ! ( client_node, service_node. node_id( ) ) ;
3077+ expect_channel_ready_event ! ( client_node, service_node. node_id( ) ) ;
3078+ expect_payment_successful_event ! ( payer_node, Some ( fixed_payment_id) , None ) ;
3079+ let fixed_fee_msat = fixed_amount_msat * channel_opening_fee_ppm as u64 / 1_000_000 ;
3080+ let fixed_received_msat = fixed_amount_msat - fixed_fee_msat;
3081+ let fixed_receiver_payment_id =
3082+ expect_payment_received_event ! ( client_node, fixed_received_msat) . unwrap ( ) ;
3083+ match client_node. payment ( & fixed_receiver_payment_id) . unwrap ( ) . kind {
3084+ PaymentKind :: Bolt12Offer { counterparty_skimmed_fee_msat, .. } => {
3085+ assert_eq ! ( counterparty_skimmed_fee_msat, Some ( fixed_fee_msat) ) ;
3086+ } ,
3087+ _ => panic ! ( "Unexpected payment kind" ) ,
3088+ }
3089+
3090+ // The first JIT channel cannot carry this larger variable payment. The variable offer disables
3091+ // MPP, so the payer must use the fresh JIT path rather than splitting across both paths.
3092+ let variable_amount_msat = 200_000_000 ;
3093+ let variable_offer = client_node
3094+ . bolt12_payment ( )
3095+ . receive_variable_amount_via_jit_channel ( "variable" , None , None )
3096+ . unwrap ( ) ;
3097+ let variable_payment_id = payer_node
3098+ . bolt12_payment ( )
3099+ . send_using_amount ( & variable_offer, variable_amount_msat, None , None , None )
3100+ . unwrap ( ) ;
3101+
3102+ expect_channel_pending_event ! ( service_node, client_node. node_id( ) ) ;
3103+ expect_channel_ready_event ! ( service_node, client_node. node_id( ) ) ;
3104+ expect_event ! ( service_node, PaymentForwarded ) ;
3105+ expect_channel_pending_event ! ( client_node, service_node. node_id( ) ) ;
3106+ expect_channel_ready_event ! ( client_node, service_node. node_id( ) ) ;
3107+ expect_payment_successful_event ! ( payer_node, Some ( variable_payment_id) , None ) ;
3108+ let variable_fee_msat = variable_amount_msat * channel_opening_fee_ppm as u64 / 1_000_000 ;
3109+ let variable_received_msat = variable_amount_msat - variable_fee_msat;
3110+ let variable_receiver_payment_id =
3111+ expect_payment_received_event ! ( client_node, variable_received_msat) . unwrap ( ) ;
3112+ match client_node. payment ( & variable_receiver_payment_id) . unwrap ( ) . kind {
3113+ PaymentKind :: Bolt12Offer { counterparty_skimmed_fee_msat, .. } => {
3114+ assert_eq ! ( counterparty_skimmed_fee_msat, Some ( variable_fee_msat) ) ;
3115+ } ,
3116+ _ => panic ! ( "Unexpected payment kind" ) ,
3117+ }
3118+ }
3119+
29893120#[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
29903121async fn facade_logging ( ) {
29913122 let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
0 commit comments