@@ -756,6 +756,9 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
756756 }
757757
758758 /// Send an on-chain payment to the given address.
759+ ///
760+ /// This will respect any on-chain reserve we need to keep, i.e., won't allow to cut into
761+ /// [`BalanceDetails::total_anchor_channels_reserve_sats`].
759762 pub fn send_to_onchain_address (
760763 & self , address : & bitcoin:: Address , amount_sats : u64 ,
761764 ) -> Result < Txid , Error > {
@@ -764,15 +767,29 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
764767 return Err ( Error :: NotRunning ) ;
765768 }
766769
767- let cur_balance = self . wallet . get_balance ( ) ?;
768- if cur_balance. get_spendable ( ) < amount_sats {
769- log_error ! ( self . logger, "Unable to send payment due to insufficient funds." ) ;
770+ let cur_anchor_reserve_sats =
771+ total_anchor_channels_reserve_sats ( & self . channel_manager , & self . config ) ;
772+ let spendable_amount_sats =
773+ self . wallet . get_balances ( cur_anchor_reserve_sats) . map ( |( _, s) | s) . unwrap_or ( 0 ) ;
774+
775+ if spendable_amount_sats < amount_sats {
776+ log_error ! ( self . logger,
777+ "Unable to send payment due to insufficient funds. Available: {}sats, Required: {}sats" ,
778+ spendable_amount_sats, amount_sats
779+ ) ;
770780 return Err ( Error :: InsufficientFunds ) ;
771781 }
772782 self . wallet . send_to_address ( address, Some ( amount_sats) )
773783 }
774784
775785 /// Send an on-chain payment to the given address, draining all the available funds.
786+ ///
787+ /// This is useful if you have closed all channels and want to migrate funds to another
788+ /// on-chain wallet.
789+ ///
790+ /// Please note that this will **not** retain any on-chain reserves, which might be potentially
791+ /// dangerous if you have open Anchor channels for which you can't trust the counterparty to
792+ /// spend the Anchor output after channel closure.
776793 pub fn send_all_to_onchain_address ( & self , address : & bitcoin:: Address ) -> Result < Txid , Error > {
777794 let rt_lock = self . runtime . read ( ) . unwrap ( ) ;
778795 if rt_lock. is_none ( ) {
@@ -854,6 +871,10 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
854871 /// channel counterparty on channel open. This can be useful to start out with the balance not
855872 /// entirely shifted to one side, therefore allowing to receive payments from the getgo.
856873 ///
874+ /// If Anchor channels are enabled, this will ensure the configured
875+ /// [`AnchorChannelsConfig::per_channel_reserve_sats`] is available and will be retained before
876+ /// opening the channel.
877+ ///
857878 /// Returns a temporary channel id.
858879 pub fn connect_open_channel (
859880 & self , node_id : PublicKey , address : SocketAddress , channel_amount_sats : u64 ,
@@ -866,9 +887,25 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
866887 }
867888 let runtime = rt_lock. as_ref ( ) . unwrap ( ) ;
868889
869- let cur_balance = self . wallet . get_balance ( ) ?;
870- if cur_balance. get_spendable ( ) < channel_amount_sats {
871- log_error ! ( self . logger, "Unable to create channel due to insufficient funds." ) ;
890+ let required_funds_sats = channel_amount_sats
891+ + self . config . anchor_channels_config . as_ref ( ) . map_or ( 0 , |c| {
892+ if c. trusted_peers_no_reserve . contains ( & node_id) {
893+ 0
894+ } else {
895+ c. per_channel_reserve_sats
896+ }
897+ } ) ;
898+
899+ let cur_anchor_reserve_sats =
900+ total_anchor_channels_reserve_sats ( & self . channel_manager , & self . config ) ;
901+ let spendable_amount_sats =
902+ self . wallet . get_balances ( cur_anchor_reserve_sats) . map ( |( _, s) | s) . unwrap_or ( 0 ) ;
903+
904+ if spendable_amount_sats < required_funds_sats {
905+ log_error ! ( self . logger,
906+ "Unable to create channel due to insufficient funds. Available: {}sats, Required: {}sats" ,
907+ spendable_amount_sats, required_funds_sats
908+ ) ;
872909 return Err ( Error :: InsufficientFunds ) ;
873910 }
874911
@@ -892,6 +929,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
892929 channel_handshake_limits : Default :: default ( ) ,
893930 channel_handshake_config : ChannelHandshakeConfig {
894931 announced_channel : announce_channel,
932+ negotiate_anchors_zero_fee_htlc_tx : self . config . anchor_channels_config . is_some ( ) ,
895933 ..Default :: default ( )
896934 } ,
897935 channel_config,
@@ -1450,11 +1488,13 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
14501488
14511489 /// Retrieves an overview of all known balances.
14521490 pub fn list_balances ( & self ) -> BalanceDetails {
1453- let ( total_onchain_balance_sats, spendable_onchain_balance_sats) = self
1454- . wallet
1455- . get_balance ( )
1456- . map ( |bal| ( bal. get_total ( ) , bal. get_spendable ( ) ) )
1457- . unwrap_or ( ( 0 , 0 ) ) ;
1491+ let cur_anchor_reserve_sats =
1492+ total_anchor_channels_reserve_sats ( & self . channel_manager , & self . config ) ;
1493+ let ( total_onchain_balance_sats, spendable_onchain_balance_sats) =
1494+ self . wallet . get_balances ( cur_anchor_reserve_sats) . unwrap_or ( ( 0 , 0 ) ) ;
1495+
1496+ let total_anchor_channels_reserve_sats =
1497+ std:: cmp:: min ( cur_anchor_reserve_sats, total_onchain_balance_sats) ;
14581498
14591499 let mut total_lightning_balance_sats = 0 ;
14601500 let mut lightning_balances = Vec :: new ( ) ;
@@ -1487,6 +1527,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
14871527 BalanceDetails {
14881528 total_onchain_balance_sats,
14891529 spendable_onchain_balance_sats,
1530+ total_anchor_channels_reserve_sats,
14901531 total_lightning_balance_sats,
14911532 lightning_balances,
14921533 pending_balances_from_channel_closures,
@@ -1635,3 +1676,21 @@ async fn do_connect_peer<K: KVStore + Sync + Send + 'static>(
16351676 }
16361677 }
16371678}
1679+
1680+ pub ( crate ) fn total_anchor_channels_reserve_sats < K : KVStore + Sync + Send + ' static > (
1681+ channel_manager : & ChannelManager < K > , config : & Config ,
1682+ ) -> u64 {
1683+ config. anchor_channels_config . as_ref ( ) . map_or ( 0 , |anchor_channels_config| {
1684+ channel_manager
1685+ . list_channels ( )
1686+ . into_iter ( )
1687+ . filter ( |c| {
1688+ !anchor_channels_config. trusted_peers_no_reserve . contains ( & c. counterparty . node_id )
1689+ && c. channel_type
1690+ . as_ref ( )
1691+ . map_or ( false , |t| t. supports_anchors_zero_fee_htlc_tx ( ) )
1692+ } )
1693+ . count ( ) as u64
1694+ * anchor_channels_config. per_channel_reserve_sats
1695+ } )
1696+ }
0 commit comments