@@ -106,6 +106,7 @@ use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
106106
107107pub use balance:: { BalanceDetails , LightningBalance , PendingSweepBalance } ;
108108use bitcoin:: secp256k1:: PublicKey ;
109+ use bitcoin:: Amount ;
109110#[ cfg( feature = "uniffi" ) ]
110111pub use builder:: ArcedNodeBuilder as Builder ;
111112pub use builder:: BuildError ;
@@ -128,10 +129,11 @@ use graph::NetworkGraph;
128129pub use io:: utils:: generate_entropy_mnemonic;
129130use io:: utils:: write_node_metrics;
130131use lightning:: chain:: BestBlock ;
131- use lightning:: events:: bump_transaction:: Wallet as LdkWallet ;
132+ use lightning:: events:: bump_transaction:: { Input , Wallet as LdkWallet } ;
132133use lightning:: impl_writeable_tlv_based;
133134use lightning:: ln:: channel_state:: ChannelShutdownState ;
134135use lightning:: ln:: channelmanager:: PaymentId ;
136+ use lightning:: ln:: funding:: SpliceContribution ;
135137use lightning:: ln:: msgs:: SocketAddress ;
136138use lightning:: routing:: gossip:: NodeAlias ;
137139use lightning:: util:: persist:: KVStoreSync ;
@@ -1200,6 +1202,96 @@ impl Node {
12001202 )
12011203 }
12021204
1205+ /// Add funds from the on-chain wallet into an existing channel.
1206+ ///
1207+ /// This provides for increasing a channel's outbound liquidity without re-balancing or closing
1208+ /// it. Once negotiation with the counterparty is complete, the channel remains operational
1209+ /// while waiting for a new funding transaction to confirm.
1210+ pub fn splice_in (
1211+ & self , user_channel_id : & UserChannelId , counterparty_node_id : PublicKey ,
1212+ splice_amount_sats : u64 ,
1213+ ) -> Result < ( ) , Error > {
1214+ let open_channels =
1215+ self . channel_manager . list_channels_with_counterparty ( & counterparty_node_id) ;
1216+ if let Some ( channel_details) =
1217+ open_channels. iter ( ) . find ( |c| c. user_channel_id == user_channel_id. 0 )
1218+ {
1219+ self . check_sufficient_funds_for_channel ( splice_amount_sats, & counterparty_node_id) ?;
1220+
1221+ const EMPTY_SCRIPT_SIG_WEIGHT : u64 =
1222+ 1 /* empty script_sig */ * bitcoin:: constants:: WITNESS_SCALE_FACTOR as u64 ;
1223+ let funding_txo = channel_details. funding_txo . ok_or_else ( || {
1224+ log_error ! ( self . logger, "Failed to splice channel: channel not yet ready" , ) ;
1225+ Error :: ChannelSplicingFailed
1226+ } ) ?;
1227+ let shared_input = Input {
1228+ outpoint : funding_txo. into_bitcoin_outpoint ( ) ,
1229+ previous_utxo : bitcoin:: TxOut {
1230+ value : Amount :: from_sat ( channel_details. channel_value_satoshis ) ,
1231+ script_pubkey : lightning:: ln:: chan_utils:: make_funding_redeemscript (
1232+ & PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
1233+ & PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
1234+ )
1235+ . to_p2wsh ( ) ,
1236+ } ,
1237+ satisfaction_weight : EMPTY_SCRIPT_SIG_WEIGHT
1238+ + lightning:: ln:: chan_utils:: FUNDING_TRANSACTION_WITNESS_WEIGHT ,
1239+ } ;
1240+
1241+ let shared_output = bitcoin:: TxOut {
1242+ value : shared_input. previous_utxo . value + Amount :: from_sat ( splice_amount_sats) ,
1243+ script_pubkey : lightning:: ln:: chan_utils:: make_funding_redeemscript (
1244+ & PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
1245+ & PublicKey :: from_slice ( & [ 2 ; 33 ] ) . unwrap ( ) ,
1246+ )
1247+ . to_p2wsh ( ) ,
1248+ } ;
1249+
1250+ let fee_rate = self . wallet . estimate_channel_funding_fee_rate ( ) ;
1251+
1252+ let inputs = self
1253+ . wallet
1254+ . select_confirmed_utxos ( vec ! [ shared_input] , & [ shared_output] , fee_rate)
1255+ . map_err ( |( ) | {
1256+ log_error ! (
1257+ self . logger,
1258+ "Failed to splice channel: insufficient confirmed UTXOs" ,
1259+ ) ;
1260+ Error :: ChannelSplicingFailed
1261+ } ) ?;
1262+
1263+ let contribution = SpliceContribution :: SpliceIn {
1264+ value : Amount :: from_sat ( splice_amount_sats) ,
1265+ inputs,
1266+ change_script : None ,
1267+ } ;
1268+
1269+ let funding_feerate_per_kw = fee_rate. to_sat_per_kwu ( ) . try_into ( ) . unwrap_or ( u32:: MAX ) ;
1270+
1271+ self . channel_manager
1272+ . splice_channel (
1273+ & channel_details. channel_id ,
1274+ & counterparty_node_id,
1275+ contribution,
1276+ funding_feerate_per_kw,
1277+ None ,
1278+ )
1279+ . map_err ( |e| {
1280+ log_error ! ( self . logger, "Failed to splice channel: {:?}" , e) ;
1281+ Error :: ChannelSplicingFailed
1282+ } )
1283+ } else {
1284+ log_error ! (
1285+ self . logger,
1286+ "Channel not found for user_channel_id: {:?} and counterparty: {}" ,
1287+ user_channel_id,
1288+ counterparty_node_id
1289+ ) ;
1290+
1291+ Err ( Error :: ChannelSplicingFailed )
1292+ }
1293+ }
1294+
12031295 /// Manually sync the LDK and BDK wallets with the current chain state and update the fee rate
12041296 /// cache.
12051297 ///
0 commit comments