@@ -50,6 +50,7 @@ use lightning::ln::channelmanager::{
5050 RecipientOnionFields ,
5151} ;
5252use lightning:: ln:: functional_test_utils:: * ;
53+ use lightning:: ln:: funding:: { FundingTxInput , SpliceContribution } ;
5354use lightning:: ln:: inbound_payment:: ExpandedKey ;
5455use lightning:: ln:: msgs:: {
5556 BaseMessageHandler , ChannelMessageHandler , CommitmentUpdate , Init , MessageSendEvent ,
@@ -68,6 +69,7 @@ use lightning::sign::{
6869} ;
6970use lightning:: types:: payment:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
7071use lightning:: util:: config:: UserConfig ;
72+ use lightning:: util:: errors:: APIError ;
7173use lightning:: util:: hash_tables:: * ;
7274use lightning:: util:: logger:: Logger ;
7375use lightning:: util:: ser:: { LengthReadable , ReadableArgs , Writeable , Writer } ;
@@ -163,6 +165,63 @@ impl Writer for VecWriter {
163165 }
164166}
165167
168+ pub struct TestWallet {
169+ secret_key : SecretKey ,
170+ utxos : Mutex < Vec < lightning:: events:: bump_transaction:: Utxo > > ,
171+ secp : Secp256k1 < bitcoin:: secp256k1:: All > ,
172+ }
173+
174+ impl TestWallet {
175+ pub fn new ( secret_key : SecretKey ) -> Self {
176+ Self { secret_key, utxos : Mutex :: new ( Vec :: new ( ) ) , secp : Secp256k1 :: new ( ) }
177+ }
178+
179+ fn get_change_script ( & self ) -> Result < ScriptBuf , ( ) > {
180+ let public_key = bitcoin:: PublicKey :: new ( self . secret_key . public_key ( & self . secp ) ) ;
181+ Ok ( ScriptBuf :: new_p2wpkh ( & public_key. wpubkey_hash ( ) . unwrap ( ) ) )
182+ }
183+
184+ pub fn add_utxo ( & self , outpoint : bitcoin:: OutPoint , value : Amount ) -> TxOut {
185+ let public_key = bitcoin:: PublicKey :: new ( self . secret_key . public_key ( & self . secp ) ) ;
186+ let utxo = lightning:: events:: bump_transaction:: Utxo :: new_v0_p2wpkh (
187+ outpoint,
188+ value,
189+ & public_key. wpubkey_hash ( ) . unwrap ( ) ,
190+ ) ;
191+ self . utxos . lock ( ) . unwrap ( ) . push ( utxo. clone ( ) ) ;
192+ utxo. output
193+ }
194+
195+ pub fn sign_tx (
196+ & self , mut tx : Transaction ,
197+ ) -> Result < Transaction , bitcoin:: sighash:: P2wpkhError > {
198+ let utxos = self . utxos . lock ( ) . unwrap ( ) ;
199+ for i in 0 ..tx. input . len ( ) {
200+ if let Some ( utxo) =
201+ utxos. iter ( ) . find ( |utxo| utxo. outpoint == tx. input [ i] . previous_output )
202+ {
203+ let sighash = bitcoin:: sighash:: SighashCache :: new ( & tx) . p2wpkh_signature_hash (
204+ i,
205+ & utxo. output . script_pubkey ,
206+ utxo. output . value ,
207+ bitcoin:: EcdsaSighashType :: All ,
208+ ) ?;
209+ let signature = self . secp . sign_ecdsa (
210+ & secp256k1:: Message :: from_digest ( sighash. to_byte_array ( ) ) ,
211+ & self . secret_key ,
212+ ) ;
213+ let bitcoin_sig = bitcoin:: ecdsa:: Signature {
214+ signature,
215+ sighash_type : bitcoin:: EcdsaSighashType :: All ,
216+ } ;
217+ tx. input [ i] . witness =
218+ bitcoin:: Witness :: p2wpkh ( & bitcoin_sig, & self . secret_key . public_key ( & self . secp ) ) ;
219+ }
220+ }
221+ Ok ( tx)
222+ }
223+ }
224+
166225/// The LDK API requires that any time we tell it we're done persisting a `ChannelMonitor[Update]`
167226/// we never pass it in as the "latest" `ChannelMonitor` on startup. However, we can pass
168227/// out-of-date monitors as long as we never told LDK we finished persisting them, which we do by
@@ -671,6 +730,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
671730 let mut config = UserConfig :: default ( ) ;
672731 config. channel_config. forwarding_fee_proportional_millionths = 0 ;
673732 config. channel_handshake_config. announce_for_forwarding = true ;
733+ config. reject_inbound_splices = false ;
674734 if anchors {
675735 config. channel_handshake_config. negotiate_anchors_zero_fee_htlc_tx = true ;
676736 config. manually_accept_inbound_channels = true ;
@@ -724,6 +784,7 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
724784 let mut config = UserConfig :: default ( ) ;
725785 config. channel_config . forwarding_fee_proportional_millionths = 0 ;
726786 config. channel_handshake_config . announce_for_forwarding = true ;
787+ config. reject_inbound_splices = false ;
727788 if anchors {
728789 config. channel_handshake_config . negotiate_anchors_zero_fee_htlc_tx = true ;
729790 config. manually_accept_inbound_channels = true ;
@@ -984,6 +1045,30 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
9841045 } } ;
9851046 }
9861047
1048+ let wallet_a = TestWallet :: new ( SecretKey :: from_slice ( & [ 1 ; 32 ] ) . unwrap ( ) ) ;
1049+ let wallet_b = TestWallet :: new ( SecretKey :: from_slice ( & [ 2 ; 32 ] ) . unwrap ( ) ) ;
1050+ let wallet_c = TestWallet :: new ( SecretKey :: from_slice ( & [ 3 ; 32 ] ) . unwrap ( ) ) ;
1051+ let wallets = vec ! [ wallet_a, wallet_b, wallet_c] ;
1052+ let coinbase_tx = bitcoin:: Transaction {
1053+ version : bitcoin:: transaction:: Version :: TWO ,
1054+ lock_time : bitcoin:: absolute:: LockTime :: ZERO ,
1055+ input : vec ! [ bitcoin:: TxIn { ..Default :: default ( ) } ] ,
1056+ output : wallets
1057+ . iter ( )
1058+ . map ( |w| TxOut {
1059+ value : Amount :: from_sat ( 100_000 ) ,
1060+ script_pubkey : w. get_change_script ( ) . unwrap ( ) ,
1061+ } )
1062+ . collect ( ) ,
1063+ } ;
1064+ let coinbase_txid = coinbase_tx. compute_txid ( ) ;
1065+ wallets. iter ( ) . enumerate ( ) . for_each ( |( i, w) | {
1066+ w. add_utxo (
1067+ bitcoin:: OutPoint { txid : coinbase_txid, vout : i as u32 } ,
1068+ Amount :: from_sat ( 100_000 ) ,
1069+ ) ;
1070+ } ) ;
1071+
9871072 let fee_est_a = Arc :: new ( FuzzEstimator { ret_val : atomic:: AtomicU32 :: new ( 253 ) } ) ;
9881073 let mut last_htlc_clear_fee_a = 253 ;
9891074 let fee_est_b = Arc :: new ( FuzzEstimator { ret_val : atomic:: AtomicU32 :: new ( 253 ) } ) ;
@@ -1073,6 +1158,34 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
10731158 if Some ( * node_id) == expect_drop_id { panic!( "peer_disconnected should drop msgs bound for the disconnected peer" ) ; }
10741159 * node_id == a_id
10751160 } ,
1161+ MessageSendEvent :: SendSpliceInit { ref node_id, .. } => {
1162+ if Some ( * node_id) == expect_drop_id { panic!( "peer_disconnected should drop msgs bound for the disconnected peer" ) ; }
1163+ * node_id == a_id
1164+ } ,
1165+ MessageSendEvent :: SendSpliceAck { ref node_id, .. } => {
1166+ if Some ( * node_id) == expect_drop_id { panic!( "peer_disconnected should drop msgs bound for the disconnected peer" ) ; }
1167+ * node_id == a_id
1168+ } ,
1169+ MessageSendEvent :: SendSpliceLocked { ref node_id, .. } => {
1170+ if Some ( * node_id) == expect_drop_id { panic!( "peer_disconnected should drop msgs bound for the disconnected peer" ) ; }
1171+ * node_id == a_id
1172+ } ,
1173+ MessageSendEvent :: SendTxAddInput { ref node_id, .. } => {
1174+ if Some ( * node_id) == expect_drop_id { panic!( "peer_disconnected should drop msgs bound for the disconnected peer" ) ; }
1175+ * node_id == a_id
1176+ } ,
1177+ MessageSendEvent :: SendTxAddOutput { ref node_id, .. } => {
1178+ if Some ( * node_id) == expect_drop_id { panic!( "peer_disconnected should drop msgs bound for the disconnected peer" ) ; }
1179+ * node_id == a_id
1180+ } ,
1181+ MessageSendEvent :: SendTxComplete { ref node_id, .. } => {
1182+ if Some ( * node_id) == expect_drop_id { panic!( "peer_disconnected should drop msgs bound for the disconnected peer" ) ; }
1183+ * node_id == a_id
1184+ } ,
1185+ MessageSendEvent :: SendTxAbort { ref node_id, .. } => {
1186+ if Some ( * node_id) == expect_drop_id { panic!( "peer_disconnected should drop msgs bound for the disconnected peer" ) ; }
1187+ * node_id == a_id
1188+ } ,
10761189 MessageSendEvent :: SendChannelReady { .. } => continue ,
10771190 MessageSendEvent :: SendAnnouncementSignatures { .. } => continue ,
10781191 MessageSendEvent :: SendChannelUpdate { ref node_id, ref msg } => {
@@ -1208,7 +1321,79 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
12081321 dest. handle_stfu( nodes[ $node] . get_our_node_id( ) , msg) ;
12091322 }
12101323 }
1211- }
1324+ } ,
1325+ MessageSendEvent :: SendTxAddInput { ref node_id, ref msg } => {
1326+ for ( idx, dest) in nodes. iter( ) . enumerate( ) {
1327+ if dest. get_our_node_id( ) == * node_id {
1328+ out. locked_write( format!( "Delivering tx_add_input from node {} to node {}.\n " , $node, idx) . as_bytes( ) ) ;
1329+ dest. handle_tx_add_input( nodes[ $node] . get_our_node_id( ) , msg) ;
1330+ }
1331+ }
1332+ } ,
1333+ MessageSendEvent :: SendTxAddOutput { ref node_id, ref msg } => {
1334+ for ( idx, dest) in nodes. iter( ) . enumerate( ) {
1335+ if dest. get_our_node_id( ) == * node_id {
1336+ out. locked_write( format!( "Delivering tx_add_output from node {} to node {}.\n " , $node, idx) . as_bytes( ) ) ;
1337+ dest. handle_tx_add_output( nodes[ $node] . get_our_node_id( ) , msg) ;
1338+ }
1339+ }
1340+ } ,
1341+ MessageSendEvent :: SendTxRemoveInput { ref node_id, ref msg } => {
1342+ for ( idx, dest) in nodes. iter( ) . enumerate( ) {
1343+ if dest. get_our_node_id( ) == * node_id {
1344+ out. locked_write( format!( "Delivering tx_remove_input from node {} to node {}.\n " , $node, idx) . as_bytes( ) ) ;
1345+ dest. handle_tx_remove_input( nodes[ $node] . get_our_node_id( ) , msg) ;
1346+ }
1347+ }
1348+ } ,
1349+ MessageSendEvent :: SendTxRemoveOutput { ref node_id, ref msg } => {
1350+ for ( idx, dest) in nodes. iter( ) . enumerate( ) {
1351+ if dest. get_our_node_id( ) == * node_id {
1352+ out. locked_write( format!( "Delivering tx_remove_output from node {} to node {}.\n " , $node, idx) . as_bytes( ) ) ;
1353+ dest. handle_tx_remove_output( nodes[ $node] . get_our_node_id( ) , msg) ;
1354+ }
1355+ }
1356+ } ,
1357+ MessageSendEvent :: SendTxComplete { ref node_id, ref msg } => {
1358+ for ( idx, dest) in nodes. iter( ) . enumerate( ) {
1359+ if dest. get_our_node_id( ) == * node_id {
1360+ out. locked_write( format!( "Delivering tx_complete from node {} to node {}.\n " , $node, idx) . as_bytes( ) ) ;
1361+ dest. handle_tx_complete( nodes[ $node] . get_our_node_id( ) , msg) ;
1362+ }
1363+ }
1364+ } ,
1365+ MessageSendEvent :: SendTxAbort { ref node_id, ref msg } => {
1366+ for ( idx, dest) in nodes. iter( ) . enumerate( ) {
1367+ if dest. get_our_node_id( ) == * node_id {
1368+ out. locked_write( format!( "Delivering tx_abort from node {} to node {}.\n " , $node, idx) . as_bytes( ) ) ;
1369+ dest. handle_tx_abort( nodes[ $node] . get_our_node_id( ) , msg) ;
1370+ }
1371+ }
1372+ } ,
1373+ MessageSendEvent :: SendSpliceInit { ref node_id, ref msg } => {
1374+ for ( idx, dest) in nodes. iter( ) . enumerate( ) {
1375+ if dest. get_our_node_id( ) == * node_id {
1376+ out. locked_write( format!( "Delivering splice_init from node {} to node {}.\n " , $node, idx) . as_bytes( ) ) ;
1377+ dest. handle_splice_init( nodes[ $node] . get_our_node_id( ) , msg) ;
1378+ }
1379+ }
1380+ } ,
1381+ MessageSendEvent :: SendSpliceAck { ref node_id, ref msg } => {
1382+ for ( idx, dest) in nodes. iter( ) . enumerate( ) {
1383+ if dest. get_our_node_id( ) == * node_id {
1384+ out. locked_write( format!( "Delivering splice_ack from node {} to node {}.\n " , $node, idx) . as_bytes( ) ) ;
1385+ dest. handle_splice_ack( nodes[ $node] . get_our_node_id( ) , msg) ;
1386+ }
1387+ }
1388+ } ,
1389+ MessageSendEvent :: SendSpliceLocked { ref node_id, ref msg } => {
1390+ for ( idx, dest) in nodes. iter( ) . enumerate( ) {
1391+ if dest. get_our_node_id( ) == * node_id {
1392+ out. locked_write( format!( "Delivering splice_locked from node {} to node {}.\n " , $node, idx) . as_bytes( ) ) ;
1393+ dest. handle_splice_locked( nodes[ $node] . get_our_node_id( ) , msg) ;
1394+ }
1395+ }
1396+ } ,
12121397 MessageSendEvent :: SendChannelReady { .. } => {
12131398 // Can be generated as a reestablish response
12141399 } ,
@@ -1347,6 +1532,25 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
13471532 events:: Event :: PaymentForwarded { .. } if $node == 1 => { } ,
13481533 events:: Event :: ChannelReady { .. } => { } ,
13491534 events:: Event :: HTLCHandlingFailed { .. } => { } ,
1535+
1536+ events:: Event :: FundingTransactionReadyForSigning {
1537+ channel_id,
1538+ counterparty_node_id,
1539+ unsigned_transaction,
1540+ ..
1541+ } => {
1542+ let signed_tx = wallets[ $node] . sign_tx( unsigned_transaction) . unwrap( ) ;
1543+ nodes[ $node]
1544+ . funding_transaction_signed(
1545+ & channel_id,
1546+ & counterparty_node_id,
1547+ signed_tx,
1548+ )
1549+ . unwrap( ) ;
1550+ } ,
1551+ events:: Event :: SplicePending { .. } => { } ,
1552+ events:: Event :: SpliceFailed { .. } => { } ,
1553+
13501554 _ => {
13511555 if out. may_fail. load( atomic:: Ordering :: Acquire ) {
13521556 return ;
@@ -1652,16 +1856,92 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
16521856 } ,
16531857
16541858 0xa0 => {
1655- nodes[ 0 ] . maybe_propose_quiescence ( & nodes[ 1 ] . get_our_node_id ( ) , & chan_a_id) . unwrap ( )
1859+ let input = FundingTxInput :: new_p2wpkh ( coinbase_tx. clone ( ) , 0 ) . unwrap ( ) ;
1860+ let contribution = SpliceContribution :: SpliceIn {
1861+ value : Amount :: from_sat ( 10_000 ) ,
1862+ inputs : vec ! [ input] ,
1863+ change_script : None ,
1864+ } ;
1865+ let funding_feerate_sat_per_kw = fee_est_a. ret_val . load ( atomic:: Ordering :: Acquire ) ;
1866+ if let Err ( e) = nodes[ 0 ] . splice_channel (
1867+ & chan_a_id,
1868+ & nodes[ 1 ] . get_our_node_id ( ) ,
1869+ contribution,
1870+ funding_feerate_sat_per_kw,
1871+ None ,
1872+ ) {
1873+ assert ! (
1874+ matches!( e, APIError :: APIMisuseError { ref err } if err. contains( "splice pending" ) ) ,
1875+ "{:?}" ,
1876+ e
1877+ ) ;
1878+ }
16561879 } ,
16571880 0xa1 => {
1658- nodes[ 1 ] . maybe_propose_quiescence ( & nodes[ 0 ] . get_our_node_id ( ) , & chan_a_id) . unwrap ( )
1881+ let input = FundingTxInput :: new_p2wpkh ( coinbase_tx. clone ( ) , 1 ) . unwrap ( ) ;
1882+ let contribution = SpliceContribution :: SpliceIn {
1883+ value : Amount :: from_sat ( 10_000 ) ,
1884+ inputs : vec ! [ input] ,
1885+ change_script : None ,
1886+ } ;
1887+ let funding_feerate_sat_per_kw = fee_est_b. ret_val . load ( atomic:: Ordering :: Acquire ) ;
1888+ if let Err ( e) = nodes[ 1 ] . splice_channel (
1889+ & chan_a_id,
1890+ & nodes[ 0 ] . get_our_node_id ( ) ,
1891+ contribution,
1892+ funding_feerate_sat_per_kw,
1893+ None ,
1894+ ) {
1895+ assert ! (
1896+ matches!( e, APIError :: APIMisuseError { ref err } if err. contains( "splice pending" ) ) ,
1897+ "{:?}" ,
1898+ e
1899+ ) ;
1900+ }
16591901 } ,
16601902 0xa2 => {
1661- nodes[ 1 ] . maybe_propose_quiescence ( & nodes[ 2 ] . get_our_node_id ( ) , & chan_b_id) . unwrap ( )
1903+ let input = FundingTxInput :: new_p2wpkh ( coinbase_tx. clone ( ) , 0 ) . unwrap ( ) ;
1904+ let contribution = SpliceContribution :: SpliceIn {
1905+ value : Amount :: from_sat ( 10_000 ) ,
1906+ inputs : vec ! [ input] ,
1907+ change_script : None ,
1908+ } ;
1909+ let funding_feerate_sat_per_kw = fee_est_b. ret_val . load ( atomic:: Ordering :: Acquire ) ;
1910+ if let Err ( e) = nodes[ 1 ] . splice_channel (
1911+ & chan_b_id,
1912+ & nodes[ 2 ] . get_our_node_id ( ) ,
1913+ contribution,
1914+ funding_feerate_sat_per_kw,
1915+ None ,
1916+ ) {
1917+ assert ! (
1918+ matches!( e, APIError :: APIMisuseError { ref err } if err. contains( "splice pending" ) ) ,
1919+ "{:?}" ,
1920+ e
1921+ ) ;
1922+ }
16621923 } ,
16631924 0xa3 => {
1664- nodes[ 2 ] . maybe_propose_quiescence ( & nodes[ 1 ] . get_our_node_id ( ) , & chan_b_id) . unwrap ( )
1925+ let input = FundingTxInput :: new_p2wpkh ( coinbase_tx. clone ( ) , 1 ) . unwrap ( ) ;
1926+ let contribution = SpliceContribution :: SpliceIn {
1927+ value : Amount :: from_sat ( 10_000 ) ,
1928+ inputs : vec ! [ input] ,
1929+ change_script : None ,
1930+ } ;
1931+ let funding_feerate_sat_per_kw = fee_est_c. ret_val . load ( atomic:: Ordering :: Acquire ) ;
1932+ if let Err ( e) = nodes[ 2 ] . splice_channel (
1933+ & chan_b_id,
1934+ & nodes[ 1 ] . get_our_node_id ( ) ,
1935+ contribution,
1936+ funding_feerate_sat_per_kw,
1937+ None ,
1938+ ) {
1939+ assert ! (
1940+ matches!( e, APIError :: APIMisuseError { ref err } if err. contains( "splice pending" ) ) ,
1941+ "{:?}" ,
1942+ e
1943+ ) ;
1944+ }
16651945 } ,
16661946
16671947 0xb0 | 0xb1 | 0xb2 => {
@@ -1832,14 +2112,6 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
18322112 // complete the quiescence handshake.
18332113 process_all_events ! ( ) ;
18342114
1835- // Then exit quiescence and process all messages again, to resolve any pending
1836- // HTLCs (only irrevocably committed ones) before attempting to send more payments.
1837- nodes[ 0 ] . exit_quiescence ( & nodes[ 1 ] . get_our_node_id ( ) , & chan_a_id) . unwrap ( ) ;
1838- nodes[ 1 ] . exit_quiescence ( & nodes[ 0 ] . get_our_node_id ( ) , & chan_a_id) . unwrap ( ) ;
1839- nodes[ 1 ] . exit_quiescence ( & nodes[ 2 ] . get_our_node_id ( ) , & chan_b_id) . unwrap ( ) ;
1840- nodes[ 2 ] . exit_quiescence ( & nodes[ 1 ] . get_our_node_id ( ) , & chan_b_id) . unwrap ( ) ;
1841- process_all_events ! ( ) ;
1842-
18432115 // Finally, make sure that at least one end of each channel can make a substantial payment
18442116 assert ! (
18452117 send_payment( & nodes[ 0 ] , & nodes[ 1 ] , chan_a, 10_000_000 , & mut p_id, & mut p_idx)
0 commit comments