@@ -270,6 +270,102 @@ async fn mining_block_template_lifecycle() {
270270 . await ;
271271}
272272
273+ /// getTransactionsByTxID and getTransactionsByWitnessID with empty lists and
274+ /// with a non-existent txid/wtxid.
275+ #[ tokio:: test]
276+ // Serialized because this test may mine blocks to recover wallet funding.
277+ #[ serial_test:: serial]
278+ async fn mining_get_transactions ( ) {
279+ let path = unix_socket_path ( ) ;
280+ let rpc_network = connect_unix_stream ( path) . await ;
281+ let rpc_system = RpcSystem :: new ( Box :: new ( rpc_network) , None ) ;
282+ LocalSet :: new ( )
283+ . run_until ( async move {
284+ let ( client, thread) = bootstrap ( rpc_system) . await ;
285+ let mining = make_mining ( & client, & thread) . await ;
286+ let wallet = bitcoin_test_wallet ( ) ;
287+ ensure_wallet_loaded_and_funded ( & wallet) ;
288+ let ( real_txid, real_wtxid, real_raw_tx) = create_mempool_self_transfer ( & wallet) ;
289+
290+ // getTransactionsByTxID — empty list should return empty list.
291+ let mut req = mining. get_transactions_by_tx_i_d_request ( ) ;
292+ req. get ( ) . get_context ( ) . unwrap ( ) . set_thread ( thread. clone ( ) ) ;
293+ req. get ( ) . init_txids ( 0 ) ;
294+ let resp = req. send ( ) . promise . await . unwrap ( ) ;
295+ let results = resp. get ( ) . unwrap ( ) . get_result ( ) . unwrap ( ) ;
296+ assert_eq ! (
297+ results. len( ) ,
298+ 0 ,
299+ "empty txid list should return empty results"
300+ ) ;
301+
302+ // getTransactionsByTxID — return real mempool tx and empty for unknown id.
303+ let fake_txid = [ 0x42u8 ; 32 ] ;
304+ let mut req = mining. get_transactions_by_tx_i_d_request ( ) ;
305+ req. get ( ) . get_context ( ) . unwrap ( ) . set_thread ( thread. clone ( ) ) ;
306+ {
307+ let mut txids = req. get ( ) . init_txids ( 2 ) ;
308+ txids. set ( 0 , & real_txid) ;
309+ txids. set ( 1 , & fake_txid) ;
310+ }
311+ let resp = req. send ( ) . promise . await . unwrap ( ) ;
312+ let results = resp. get ( ) . unwrap ( ) . get_result ( ) . unwrap ( ) ;
313+ assert_eq ! (
314+ results. len( ) ,
315+ 2 ,
316+ "should return one entry per requested txid, including misses"
317+ ) ;
318+ assert_eq ! (
319+ results. get( 0 ) . unwrap( ) ,
320+ real_raw_tx. as_slice( ) ,
321+ "known txid should return serialized transaction"
322+ ) ;
323+ assert ! (
324+ results. get( 1 ) . unwrap( ) . is_empty( ) ,
325+ "non-existent txid should return empty data"
326+ ) ;
327+
328+ // getTransactionsByWitnessID — empty list should return empty list.
329+ let mut req = mining. get_transactions_by_witness_i_d_request ( ) ;
330+ req. get ( ) . get_context ( ) . unwrap ( ) . set_thread ( thread. clone ( ) ) ;
331+ req. get ( ) . init_wtxids ( 0 ) ;
332+ let resp = req. send ( ) . promise . await . unwrap ( ) ;
333+ let results = resp. get ( ) . unwrap ( ) . get_result ( ) . unwrap ( ) ;
334+ assert_eq ! (
335+ results. len( ) ,
336+ 0 ,
337+ "empty wtxid list should return empty results"
338+ ) ;
339+
340+ // getTransactionsByWitnessID — return real mempool tx and empty for unknown id.
341+ let fake_wtxid = [ 0x43u8 ; 32 ] ;
342+ let mut req = mining. get_transactions_by_witness_i_d_request ( ) ;
343+ req. get ( ) . get_context ( ) . unwrap ( ) . set_thread ( thread. clone ( ) ) ;
344+ {
345+ let mut wtxids = req. get ( ) . init_wtxids ( 2 ) ;
346+ wtxids. set ( 0 , & real_wtxid) ;
347+ wtxids. set ( 1 , & fake_wtxid) ;
348+ }
349+ let resp = req. send ( ) . promise . await . unwrap ( ) ;
350+ let results = resp. get ( ) . unwrap ( ) . get_result ( ) . unwrap ( ) ;
351+ assert_eq ! (
352+ results. len( ) ,
353+ 2 ,
354+ "should return one entry per requested wtxid, including misses"
355+ ) ;
356+ assert_eq ! (
357+ results. get( 0 ) . unwrap( ) ,
358+ real_raw_tx. as_slice( ) ,
359+ "known wtxid should return serialized transaction"
360+ ) ;
361+ assert ! (
362+ results. get( 1 ) . unwrap( ) . is_empty( ) ,
363+ "non-existent wtxid should return empty data"
364+ ) ;
365+ } )
366+ . await ;
367+ }
368+
273369/// checkBlock with a template block payload, and interrupt.
274370#[ tokio:: test]
275371// Serialized because interrupt() can affect other in-flight mining waits.
0 commit comments