@@ -14,7 +14,7 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH};
1414use e2e_tests:: {
1515 assert_replacement, close_channel, find_available_port, list_payments, mine_and_sync,
1616 payment_for_tx, run_cli, run_cli_raw, run_cli_with_config, send_bolt11_payment,
17- setup_funded_channel, wait_for_channels, wait_for_event, wait_for_gossip,
17+ setup_funded_channel, splice_txid , wait_for_channels, wait_for_event, wait_for_gossip,
1818 wait_for_onchain_balance, wait_for_settled_balance, wait_for_transaction,
1919 wait_for_usable_channel, wait_for_wallet_sync, LdkServerConfig , LdkServerHandle , TestBitcoind ,
2020 TestConfigBuilder ,
@@ -26,12 +26,12 @@ use ldk_node::lightning::ln::msgs::SocketAddress;
2626use ldk_node:: lightning:: offers:: offer:: Offer ;
2727use ldk_node:: lightning:: offers:: refund:: Refund ;
2828use ldk_node:: lightning_invoice:: Bolt11Invoice ;
29- use ldk_server_client:: error:: LdkServerErrorCode :: InvalidRequestError ;
29+ use ldk_server_client:: error:: LdkServerErrorCode :: { InvalidRequestError , LightningError } ;
3030use ldk_server_client:: ldk_server_grpc:: api:: {
3131 onchain_send_request, open_channel_request, Bolt11ClaimForIdRequest , Bolt11FailForIdRequest ,
32- Bolt11ReceiveRequest , Bolt11SendRequest , Bolt12ReceiveRequest ,
32+ Bolt11ReceiveRequest , Bolt11SendRequest , Bolt12ReceiveRequest , BumpChannelFundingFeeRequest ,
3333 GetChannelForwardingStatsRequest , GetForwardedPaymentDetailsRequest , GetPaymentDetailsRequest ,
34- ListChannelForwardingStatsRequest , ListChannelPairForwardingStatsRequest ,
34+ ListChannelForwardingStatsRequest , ListChannelPairForwardingStatsRequest , ListChannelsRequest ,
3535 ListForwardedPaymentsRequest , OnchainBumpFeeRequest , OnchainReceiveRequest , OnchainSendRequest ,
3636 OpenChannelRequest ,
3737} ;
@@ -1522,6 +1522,132 @@ async fn test_cli_splice_out() {
15221522 assert ! ( address. starts_with( "bcrt1" ) , "Expected regtest address, got: {}" , address) ;
15231523}
15241524
1525+ #[ tokio:: test]
1526+ async fn test_pending_splice_fee_bump_client_cli ( ) {
1527+ let bitcoind = TestBitcoind :: new ( ) ;
1528+ let server = LdkServerHandle :: start ( & bitcoind) . await ;
1529+ let peer = LdkServerHandle :: start ( & bitcoind) . await ;
1530+ let channel = setup_funded_channel ( & bitcoind, & server, & peer, 100_000 ) . await ;
1531+ let request = BumpChannelFundingFeeRequest {
1532+ user_channel_id : channel. clone ( ) ,
1533+ counterparty_node_id : peer. node_id ( ) . into ( ) ,
1534+ } ;
1535+ let error = server. client ( ) . bump_channel_funding_fee ( request. clone ( ) ) . await . unwrap_err ( ) ;
1536+ assert_eq ! ( error. error_code, LightningError ) ;
1537+ let mut wrong_peer = request. clone ( ) ;
1538+ wrong_peer. counterparty_node_id = server. node_id ( ) . into ( ) ;
1539+ assert_eq ! (
1540+ server. client( ) . bump_channel_funding_fee( wrong_peer) . await . unwrap_err( ) . error_code,
1541+ LightningError
1542+ ) ;
1543+
1544+ let mut events = server. client ( ) . subscribe_events ( ) . await . unwrap ( ) ;
1545+ // Use the same funded channel and splice-in operation as the existing splice fixtures.
1546+ run_cli ( & server, & [ "splice-in" , & channel, peer. node_id ( ) , "50000sat" ] ) ;
1547+ let original = splice_txid ( & mut events) . await ;
1548+ let original_tx = wait_for_transaction ( & bitcoind, & original) . await ;
1549+ let funding_output = original_tx[ "vout" ]
1550+ . as_array ( )
1551+ . unwrap ( )
1552+ . iter ( )
1553+ . find ( |output| output[ "scriptPubKey" ] [ "type" ] == "witness_v0_scripthash" )
1554+ . unwrap ( ) ;
1555+ let expected_channel_value =
1556+ ldk_node:: bitcoin:: Amount :: from_btc ( funding_output[ "value" ] . as_f64 ( ) . unwrap ( ) )
1557+ . unwrap ( )
1558+ . to_sat ( ) ;
1559+ assert ! ( expected_channel_value >= 150_000 ) ;
1560+
1561+ let funding = payment_for_tx ( & server, & original) . await ;
1562+ let error = server
1563+ . client ( )
1564+ . onchain_bump_fee ( OnchainBumpFeeRequest {
1565+ payment_id : funding. payment_id ,
1566+ fee_rate_sat_per_vb : Some ( 10 ) ,
1567+ } )
1568+ . await
1569+ . unwrap_err ( ) ;
1570+ assert_eq ! ( error. error_code, InvalidRequestError ) ;
1571+
1572+ server. client ( ) . bump_channel_funding_fee ( request. clone ( ) ) . await . unwrap ( ) ;
1573+ let replacement = splice_txid ( & mut events) . await ;
1574+ assert_ne ! ( original, replacement) ;
1575+ wait_for_transaction ( & bitcoind, & replacement) . await ;
1576+ let cli = run_cli ( & server, & [ "bump-channel-funding-fee" , & channel, peer. node_id ( ) ] ) ;
1577+ assert_eq ! ( cli, json!( { } ) ) ;
1578+ let cli_txid = splice_txid ( & mut events) . await ;
1579+ assert_ne ! ( replacement, cli_txid) ;
1580+ let replacement_tx = wait_for_transaction ( & bitcoind, & cli_txid) . await ;
1581+ let replacement_output = replacement_tx[ "vout" ]
1582+ . as_array ( )
1583+ . unwrap ( )
1584+ . iter ( )
1585+ . find ( |output| output[ "scriptPubKey" ] == funding_output[ "scriptPubKey" ] )
1586+ . unwrap ( ) ;
1587+ assert_eq ! ( replacement_output[ "value" ] , funding_output[ "value" ] ) ;
1588+ let mempool: Vec < String > = bitcoind. bitcoind . client . call ( "getrawmempool" , & [ ] ) . unwrap ( ) ;
1589+ for old in [ & original, & replacement] {
1590+ assert ! ( !mempool. contains( old) ) ;
1591+ }
1592+ mine_and_sync ( & bitcoind, & [ & server, & peer] , 6 ) . await ;
1593+ tokio:: time:: timeout ( Duration :: from_secs ( 30 ) , async {
1594+ loop {
1595+ let channels = server. client ( ) . list_channels ( ListChannelsRequest { } ) . await . unwrap ( ) ;
1596+ if channels. channels . iter ( ) . any ( |c| {
1597+ c. user_channel_id == channel
1598+ && c. channel_value_sats == expected_channel_value
1599+ && c. is_usable
1600+ } ) {
1601+ break ;
1602+ }
1603+ tokio:: time:: sleep ( Duration :: from_millis ( 100 ) ) . await ;
1604+ }
1605+ } )
1606+ . await
1607+ . expect ( "replacement splice did not confirm with the original amount" ) ;
1608+ assert_eq ! (
1609+ server. client( ) . bump_channel_funding_fee( request) . await . unwrap_err( ) . error_code,
1610+ LightningError
1611+ ) ;
1612+ }
1613+
1614+ #[ tokio:: test]
1615+ async fn test_pending_splice_fee_bump_invalid_requests ( ) {
1616+ let bitcoind = TestBitcoind :: new ( ) ;
1617+ let server = LdkServerHandle :: start ( & bitcoind) . await ;
1618+ for id in [ "" , "-1" , "xyz" , "340282366920938463463374607431768211456" ] {
1619+ let error = server
1620+ . client ( )
1621+ . bump_channel_funding_fee ( BumpChannelFundingFeeRequest {
1622+ user_channel_id : id. into ( ) ,
1623+ counterparty_node_id : server. node_id ( ) . into ( ) ,
1624+ } )
1625+ . await
1626+ . unwrap_err ( ) ;
1627+ assert_eq ! ( error. error_code, InvalidRequestError ) ;
1628+ }
1629+ for peer in [ "" , "invalid" , & "00" . repeat ( 33 ) ] {
1630+ let error = server
1631+ . client ( )
1632+ . bump_channel_funding_fee ( BumpChannelFundingFeeRequest {
1633+ user_channel_id : "1" . into ( ) ,
1634+ counterparty_node_id : peer. into ( ) ,
1635+ } )
1636+ . await
1637+ . unwrap_err ( ) ;
1638+ assert_eq ! ( error. error_code, InvalidRequestError ) ;
1639+ }
1640+ let error = server
1641+ . client ( )
1642+ . bump_channel_funding_fee ( BumpChannelFundingFeeRequest {
1643+ user_channel_id : u128:: MAX . to_string ( ) ,
1644+ counterparty_node_id : server. node_id ( ) . into ( ) ,
1645+ } )
1646+ . await
1647+ . unwrap_err ( ) ;
1648+ assert_eq ! ( error. error_code, LightningError ) ;
1649+ }
1650+
15251651#[ tokio:: test]
15261652async fn test_cli_graph_list_channels_empty ( ) {
15271653 let bitcoind = TestBitcoind :: new ( ) ;
0 commit comments