@@ -1750,6 +1750,151 @@ pub fn test_invalid_funding_tx() {
17501750 mine_transaction ( & nodes[ 1 ] , & spend_tx) ;
17511751}
17521752
1753+ #[ xtest( feature = "_externalize_tests" ) ]
1754+ pub fn test_open_channel_request_channel_reserve_satoshis ( ) {
1755+ // Test that the `channel_reserve_satoshis` field is correctly populated in the
1756+ // `OpenChannelRequest` event's `params` field for V1 channels.
1757+ let mut manually_accept_conf = UserConfig :: default ( ) ;
1758+ manually_accept_conf. manually_accept_inbound_channels = true ;
1759+
1760+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
1761+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
1762+ let node_chanmgrs =
1763+ create_node_chanmgrs ( 2 , & node_cfgs, & [ None , Some ( manually_accept_conf. clone ( ) ) ] ) ;
1764+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
1765+
1766+ let node_a_id = nodes[ 0 ] . node . get_our_node_id ( ) ;
1767+ let node_b_id = nodes[ 1 ] . node . get_our_node_id ( ) ;
1768+
1769+ // Create channel with 100,000 sats
1770+ nodes[ 0 ]
1771+ . node
1772+ . create_channel ( node_b_id, 100_000 , 10_001 , 42 , None , Some ( manually_accept_conf) )
1773+ . unwrap ( ) ;
1774+ let open_channel_msg = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendOpenChannel , node_b_id) ;
1775+
1776+ // The channel_reserve_satoshis in the open_channel message is set by the opener
1777+ let expected_reserve = open_channel_msg. channel_reserve_satoshis ;
1778+
1779+ nodes[ 1 ] . node . handle_open_channel ( node_a_id, & open_channel_msg) ;
1780+
1781+ // Verify the OpenChannelRequest event contains the correct channel_reserve_satoshis
1782+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
1783+ assert_eq ! ( events. len( ) , 1 ) ;
1784+ match & events[ 0 ] {
1785+ Event :: OpenChannelRequest { temporary_channel_id, params, .. } => {
1786+ // For V1 channels, channel_reserve_satoshis should be Some with the value from the message
1787+ assert_eq ! (
1788+ params. channel_reserve_satoshis,
1789+ Some ( expected_reserve) ,
1790+ "channel_reserve_satoshis in OpenChannelRequest params should match the open_channel message"
1791+ ) ;
1792+
1793+ // Verify other params fields are also correctly populated
1794+ assert_eq ! (
1795+ params. dust_limit_satoshis,
1796+ open_channel_msg. common_fields. dust_limit_satoshis
1797+ ) ;
1798+ assert_eq ! (
1799+ params. max_htlc_value_in_flight_msat,
1800+ open_channel_msg. common_fields. max_htlc_value_in_flight_msat
1801+ ) ;
1802+ assert_eq ! ( params. htlc_minimum_msat, open_channel_msg. common_fields. htlc_minimum_msat) ;
1803+ assert_eq ! ( params. to_self_delay, open_channel_msg. common_fields. to_self_delay) ;
1804+ assert_eq ! (
1805+ params. max_accepted_htlcs,
1806+ open_channel_msg. common_fields. max_accepted_htlcs
1807+ ) ;
1808+
1809+ // Accept the channel to clean up
1810+ nodes[ 1 ]
1811+ . node
1812+ . accept_inbound_channel ( temporary_channel_id, & node_a_id, 0 , None )
1813+ . unwrap ( ) ;
1814+ } ,
1815+ _ => panic ! ( "Expected OpenChannelRequest event" ) ,
1816+ }
1817+
1818+ // Clear the SendAcceptChannel message event generated by accepting the channel
1819+ nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
1820+ }
1821+
1822+ #[ xtest( feature = "_externalize_tests" ) ]
1823+ pub fn test_open_channel_request_channel_reserve_satoshis_v2 ( ) {
1824+ // Test that the `channel_reserve_satoshis` field is `None` in the
1825+ // `OpenChannelRequest` event's `params` field for V2 (dual-funded) channels.
1826+ let mut manually_accept_conf = UserConfig :: default ( ) ;
1827+ manually_accept_conf. manually_accept_inbound_channels = true ;
1828+ manually_accept_conf. enable_dual_funded_channels = true ;
1829+
1830+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
1831+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
1832+ let node_chanmgrs =
1833+ create_node_chanmgrs ( 2 , & node_cfgs, & [ Some ( manually_accept_conf. clone ( ) ) , Some ( manually_accept_conf. clone ( ) ) ] ) ;
1834+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
1835+
1836+ let node_a_id = nodes[ 0 ] . node . get_our_node_id ( ) ;
1837+ let node_b_id = nodes[ 1 ] . node . get_our_node_id ( ) ;
1838+
1839+ // Get the open_channel message from node 0 to use as a template for the common fields
1840+ nodes[ 0 ]
1841+ . node
1842+ . create_channel ( node_b_id, 100_000 , 10_001 , 42 , None , Some ( manually_accept_conf. clone ( ) ) )
1843+ . unwrap ( ) ;
1844+ let open_channel_v1_msg = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendOpenChannel , node_b_id) ;
1845+
1846+ // Create an OpenChannelV2 message using the common fields from V1
1847+ let open_channel_v2_msg = msgs:: OpenChannelV2 {
1848+ common_fields : open_channel_v1_msg. common_fields . clone ( ) ,
1849+ funding_feerate_sat_per_1000_weight : 1000 ,
1850+ locktime : 0 ,
1851+ second_per_commitment_point : open_channel_v1_msg. common_fields . first_per_commitment_point ,
1852+ require_confirmed_inputs : None ,
1853+ } ;
1854+
1855+ nodes[ 1 ] . node . handle_open_channel_v2 ( node_a_id, & open_channel_v2_msg) ;
1856+
1857+ // Verify the OpenChannelRequest event contains channel_reserve_satoshis = None for V2 channels
1858+ let events = nodes[ 1 ] . node . get_and_clear_pending_events ( ) ;
1859+ assert_eq ! ( events. len( ) , 1 ) ;
1860+ match & events[ 0 ] {
1861+ Event :: OpenChannelRequest { temporary_channel_id, params, .. } => {
1862+ // For V2 channels, channel_reserve_satoshis should be None
1863+ assert_eq ! (
1864+ params. channel_reserve_satoshis,
1865+ None ,
1866+ "channel_reserve_satoshis in OpenChannelRequest params should be None for V2 channels"
1867+ ) ;
1868+
1869+ // Verify other params fields are correctly populated
1870+ assert_eq ! (
1871+ params. dust_limit_satoshis,
1872+ open_channel_v2_msg. common_fields. dust_limit_satoshis
1873+ ) ;
1874+ assert_eq ! (
1875+ params. max_htlc_value_in_flight_msat,
1876+ open_channel_v2_msg. common_fields. max_htlc_value_in_flight_msat
1877+ ) ;
1878+ assert_eq ! ( params. htlc_minimum_msat, open_channel_v2_msg. common_fields. htlc_minimum_msat) ;
1879+ assert_eq ! ( params. to_self_delay, open_channel_v2_msg. common_fields. to_self_delay) ;
1880+ assert_eq ! (
1881+ params. max_accepted_htlcs,
1882+ open_channel_v2_msg. common_fields. max_accepted_htlcs
1883+ ) ;
1884+
1885+ // Accept the channel to clean up
1886+ nodes[ 1 ]
1887+ . node
1888+ . accept_inbound_channel ( temporary_channel_id, & node_a_id, 0 , None )
1889+ . unwrap ( ) ;
1890+ } ,
1891+ _ => panic ! ( "Expected OpenChannelRequest event" ) ,
1892+ }
1893+
1894+ // Clear the SendAcceptChannelV2 message event generated by accepting the channel
1895+ nodes[ 1 ] . node . get_and_clear_pending_msg_events ( ) ;
1896+ }
1897+
17531898#[ xtest( feature = "_externalize_tests" ) ]
17541899pub fn test_coinbase_funding_tx ( ) {
17551900 // Miners are able to fund channels directly from coinbase transactions, however
0 commit comments