@@ -5,9 +5,15 @@ use bdk_chain::{
55 spk_txout:: SpkTxOutIndex ,
66 Balance , ConfirmationBlockTime , IndexedTxGraph , Indexer , Merge , TxGraph ,
77} ;
8+ use bdk_core:: bitcoin:: Network ;
89use bdk_electrum:: BdkElectrumClient ;
9- use bdk_testenv:: { anyhow, bitcoincore_rpc:: RpcApi , TestEnv } ;
10+ use bdk_testenv:: {
11+ anyhow,
12+ bitcoincore_rpc:: { json:: CreateRawTransactionInput , RawTx , RpcApi } ,
13+ TestEnv ,
14+ } ;
1015use core:: time:: Duration ;
16+ use electrum_client:: ElectrumApi ;
1117use std:: collections:: { BTreeSet , HashSet } ;
1218use std:: str:: FromStr ;
1319
5460 Ok ( update)
5561}
5662
63+ /// If an spk history contains a tx that spends another unconfirmed tx (chained mempool history),
64+ /// the Electrum API will return the tx with a negative height. This should succeed and not panic.
65+ #[ test]
66+ pub fn chained_mempool_tx_sync ( ) -> anyhow:: Result < ( ) > {
67+ let env = TestEnv :: new ( ) ?;
68+ let rpc_client = env. rpc_client ( ) ;
69+ let electrum_client = electrum_client:: Client :: new ( env. electrsd . electrum_url . as_str ( ) ) ?;
70+
71+ let tracked_addr = rpc_client
72+ . get_new_address ( None , None ) ?
73+ . require_network ( Network :: Regtest ) ?;
74+
75+ env. mine_blocks ( 100 , None ) ?;
76+
77+ // First unconfirmed tx.
78+ env. send ( & tracked_addr, Amount :: from_btc ( 1.0 ) ?) ?;
79+
80+ // Create second unconfirmed tx that spends the first.
81+ let utxo = rpc_client
82+ . list_unspent ( None , Some ( 0 ) , None , Some ( true ) , None ) ?
83+ . into_iter ( )
84+ . find ( |utxo| utxo. script_pub_key == tracked_addr. script_pubkey ( ) )
85+ . expect ( "must find the newly created utxo" ) ;
86+ let tx_that_spends_unconfirmed = rpc_client. create_raw_transaction (
87+ & [ CreateRawTransactionInput {
88+ txid : utxo. txid ,
89+ vout : utxo. vout ,
90+ sequence : None ,
91+ } ] ,
92+ & [ (
93+ tracked_addr. to_string ( ) ,
94+ utxo. amount - Amount :: from_sat ( 1000 ) ,
95+ ) ]
96+ . into ( ) ,
97+ None ,
98+ None ,
99+ ) ?;
100+ let signed_tx = rpc_client
101+ . sign_raw_transaction_with_wallet ( tx_that_spends_unconfirmed. raw_hex ( ) , None , None ) ?
102+ . transaction ( ) ?;
103+ rpc_client. send_raw_transaction ( signed_tx. raw_hex ( ) ) ?;
104+
105+ env. wait_until_electrum_sees_txid ( signed_tx. compute_txid ( ) , Duration :: from_secs ( 5 ) ) ?;
106+
107+ let spk_history = electrum_client. script_get_history ( & tracked_addr. script_pubkey ( ) ) ?;
108+ assert ! (
109+ spk_history. into_iter( ) . any( |tx_res| tx_res. height < 0 ) ,
110+ "must find tx with negative height"
111+ ) ;
112+
113+ let client = BdkElectrumClient :: new ( electrum_client) ;
114+ let request = SyncRequest :: builder ( ) . spks ( core:: iter:: once ( tracked_addr. script_pubkey ( ) ) ) ;
115+ let _response = client. sync ( request, 1 , false ) ?;
116+
117+ Ok ( ( ) )
118+ }
119+
57120#[ test]
58121pub fn test_update_tx_graph_without_keychain ( ) -> anyhow:: Result < ( ) > {
59122 let env = TestEnv :: new ( ) ?;
0 commit comments