@@ -36,7 +36,7 @@ use ldk_node::payment::{
3636 ConfirmationStatus , PaymentDetails , PaymentDirection , PaymentKind , PaymentStatus ,
3737 TransactionType , UnifiedPaymentResult ,
3838} ;
39- use ldk_node:: { BuildError , Builder , Event , Node , NodeError } ;
39+ use ldk_node:: { BuildError , Builder , Event , Node , NodeError , ReserveType } ;
4040use lightning:: ln:: channelmanager:: PaymentId ;
4141use lightning:: routing:: gossip:: { NodeAlias , NodeId } ;
4242use lightning:: routing:: router:: RouteParametersConfig ;
@@ -3937,6 +3937,161 @@ async fn open_channel_with_all_with_anchors() {
39373937 node_b. stop ( ) . unwrap ( ) ;
39383938}
39393939
3940+ #[ derive( Clone , Copy ) ]
3941+ enum OpenChannelVariant {
3942+ Standard ,
3943+ Announced ,
3944+ ZeroReserve ,
3945+ StandardWithAll ,
3946+ AnnouncedWithAll ,
3947+ ZeroReserveWithAll ,
3948+ }
3949+
3950+ impl OpenChannelVariant {
3951+ fn label ( & self ) -> & ' static str {
3952+ match self {
3953+ Self :: Standard => "open_channel" ,
3954+ Self :: Announced => "open_announced_channel" ,
3955+ Self :: ZeroReserve => "open_0reserve_channel" ,
3956+ Self :: StandardWithAll => "open_channel_with_all" ,
3957+ Self :: AnnouncedWithAll => "open_announced_channel_with_all" ,
3958+ Self :: ZeroReserveWithAll => "open_0reserve_channel_with_all" ,
3959+ }
3960+ }
3961+ }
3962+
3963+ fn open_channel_variant (
3964+ variant : OpenChannelVariant , node_a : & Node , node_b : & Node , channel_amount_sats : u64 ,
3965+ ) -> Result < ( ) , NodeError > {
3966+ let address = node_b. listening_addresses ( ) . unwrap ( ) . first ( ) . unwrap ( ) . clone ( ) ;
3967+ match variant {
3968+ OpenChannelVariant :: Standard => node_a
3969+ . open_channel ( node_b. node_id ( ) , address, channel_amount_sats, None , None )
3970+ . map ( |_| ( ) ) ,
3971+ OpenChannelVariant :: Announced => node_a
3972+ . open_announced_channel ( node_b. node_id ( ) , address, channel_amount_sats, None , None )
3973+ . map ( |_| ( ) ) ,
3974+ OpenChannelVariant :: ZeroReserve => node_a
3975+ . open_0reserve_channel ( node_b. node_id ( ) , address, channel_amount_sats, None , None )
3976+ . map ( |_| ( ) ) ,
3977+ OpenChannelVariant :: StandardWithAll => {
3978+ node_a. open_channel_with_all ( node_b. node_id ( ) , address, None , None ) . map ( |_| ( ) )
3979+ } ,
3980+ OpenChannelVariant :: AnnouncedWithAll => node_a
3981+ . open_announced_channel_with_all ( node_b. node_id ( ) , address, None , None )
3982+ . map ( |_| ( ) ) ,
3983+ OpenChannelVariant :: ZeroReserveWithAll => {
3984+ node_a. open_0reserve_channel_with_all ( node_b. node_id ( ) , address, None , None ) . map ( |_| ( ) )
3985+ } ,
3986+ }
3987+ }
3988+
3989+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
3990+ async fn open_channel_variants_reserve_funds_for_anchor_peers ( ) {
3991+ let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
3992+ let chain_source = random_chain_source ( & bitcoind, & electrsd) ;
3993+
3994+ let exact_variants = [
3995+ OpenChannelVariant :: Standard ,
3996+ OpenChannelVariant :: Announced ,
3997+ OpenChannelVariant :: ZeroReserve ,
3998+ ] ;
3999+ let with_all_variants = [
4000+ OpenChannelVariant :: StandardWithAll ,
4001+ OpenChannelVariant :: AnnouncedWithAll ,
4002+ OpenChannelVariant :: ZeroReserveWithAll ,
4003+ ] ;
4004+
4005+ let premine_amount_sat = 1_000_000 ;
4006+ let exact_channel_amount_sat = premine_amount_sat - 10_000 ;
4007+ let anchor_reserve_sat = 25_000 ;
4008+
4009+ let mut addresses = Vec :: new ( ) ;
4010+ let mut exact_cases = Vec :: new ( ) ;
4011+ for variant in exact_variants {
4012+ let ( node_a, node_b) = setup_two_nodes ( & chain_source, false , true , false ) ;
4013+ addresses. push ( node_a. onchain_payment ( ) . new_address ( ) . unwrap ( ) ) ;
4014+ addresses. push ( node_b. onchain_payment ( ) . new_address ( ) . unwrap ( ) ) ;
4015+ exact_cases. push ( ( variant, node_a, node_b) ) ;
4016+ }
4017+
4018+ let mut with_all_cases = Vec :: new ( ) ;
4019+ for variant in with_all_variants {
4020+ let ( node_a, node_b) = setup_two_nodes ( & chain_source, false , true , false ) ;
4021+ addresses. push ( node_a. onchain_payment ( ) . new_address ( ) . unwrap ( ) ) ;
4022+ addresses. push ( node_b. onchain_payment ( ) . new_address ( ) . unwrap ( ) ) ;
4023+ with_all_cases. push ( ( variant, node_a, node_b) ) ;
4024+ }
4025+
4026+ premine_and_distribute_funds (
4027+ & bitcoind. client ,
4028+ & electrsd. client ,
4029+ addresses,
4030+ Amount :: from_sat ( premine_amount_sat) ,
4031+ )
4032+ . await ;
4033+
4034+ for ( _, node_a, node_b) in exact_cases. iter ( ) . chain ( with_all_cases. iter ( ) ) {
4035+ node_a. sync_wallets ( ) . unwrap ( ) ;
4036+ node_b. sync_wallets ( ) . unwrap ( ) ;
4037+ assert_eq ! ( node_a. list_balances( ) . spendable_onchain_balance_sats, premine_amount_sat) ;
4038+ assert_eq ! ( node_b. list_balances( ) . spendable_onchain_balance_sats, premine_amount_sat) ;
4039+ }
4040+
4041+ for ( variant, node_a, node_b) in exact_cases {
4042+ assert_eq ! (
4043+ Err ( NodeError :: InsufficientFunds ) ,
4044+ open_channel_variant( variant, & node_a, & node_b, exact_channel_amount_sat) ,
4045+ "{} should require funds for the channel amount plus anchor reserve" ,
4046+ variant. label( )
4047+ ) ;
4048+ node_a. stop ( ) . unwrap ( ) ;
4049+ node_b. stop ( ) . unwrap ( ) ;
4050+ }
4051+
4052+ let mut opened_with_all_cases = Vec :: new ( ) ;
4053+ for ( variant, node_a, node_b) in with_all_cases {
4054+ open_channel_variant ( variant, & node_a, & node_b, 0 )
4055+ . unwrap_or_else ( |e| panic ! ( "{} failed: {e:?}" , variant. label( ) ) ) ;
4056+
4057+ let funding_txo_a = expect_channel_pending_event ! ( node_a, node_b. node_id( ) ) ;
4058+ let funding_txo_b = expect_channel_pending_event ! ( node_b, node_a. node_id( ) ) ;
4059+ assert_eq ! ( funding_txo_a, funding_txo_b, "{} funding txo mismatch" , variant. label( ) ) ;
4060+ wait_for_tx ( & electrsd. client , funding_txo_a. txid ) . await ;
4061+
4062+ opened_with_all_cases. push ( ( variant, node_a, node_b, funding_txo_a) ) ;
4063+ }
4064+
4065+ generate_blocks_and_wait ( & bitcoind. client , & electrsd. client , 6 ) . await ;
4066+
4067+ for ( variant, node_a, node_b, funding_txo) in opened_with_all_cases {
4068+ node_a. sync_wallets ( ) . unwrap ( ) ;
4069+ node_b. sync_wallets ( ) . unwrap ( ) ;
4070+
4071+ let _user_channel_id_a = expect_channel_ready_event ! ( node_a, node_b. node_id( ) ) ;
4072+ let _user_channel_id_b = expect_channel_ready_event ! ( node_b, node_a. node_id( ) ) ;
4073+
4074+ let balances = node_a. list_balances ( ) ;
4075+ assert_eq ! ( balances. total_onchain_balance_sats, anchor_reserve_sat - 1 ) ;
4076+ assert_eq ! ( balances. total_anchor_channels_reserve_sats, anchor_reserve_sat - 1 ) ;
4077+ assert_eq ! ( balances. spendable_onchain_balance_sats, 0 ) ;
4078+
4079+ let channels = node_a. list_channels ( ) ;
4080+ assert_eq ! ( channels. len( ) , 1 , "{} should have one channel" , variant. label( ) ) ;
4081+ let channel = & channels[ 0 ] ;
4082+ // Also subtract the fees spent to open the channel
4083+ assert_eq ! ( channel. channel_value_sats, premine_amount_sat - anchor_reserve_sat - 155 ) ;
4084+ assert_eq ! ( channel. counterparty. node_id, node_b. node_id( ) ) ;
4085+ assert ! ( channel. counterparty. features. supports_anchors_zero_fee_htlc_tx( ) ) ;
4086+ assert ! ( !channel. counterparty. features. requires_anchors_zero_fee_htlc_tx( ) ) ;
4087+ assert_eq ! ( channel. funding_txo. unwrap( ) , funding_txo) ;
4088+ assert_eq ! ( channel. reserve_type, Some ( ReserveType :: Adaptive ) ) ;
4089+
4090+ node_a. stop ( ) . unwrap ( ) ;
4091+ node_b. stop ( ) . unwrap ( ) ;
4092+ }
4093+ }
4094+
39404095#[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
39414096async fn open_channel_with_all_without_anchors ( ) {
39424097 let ( bitcoind, electrsd) = setup_bitcoind_and_electrsd ( ) ;
0 commit comments