2020"""
2121
2222from test_framework .test_framework import BitcoinTestFramework
23- from test_framework .address import AddressType
23+ from test_framework .address import (
24+ AddressType ,
25+ ADDRESS_BCRT1_UNSPENDABLE ,
26+ )
2427from test_framework .util import (
2528 assert_equal ,
2629 set_node_times ,
@@ -109,7 +112,7 @@ def check(self, txid=None, amount=None, confirmation_height=None):
109112
110113 address , = [ad for ad in addresses if txid in ad ["txids" ]]
111114 assert_equal (address ["address" ], self .address ["address" ])
112- assert_equal (address ["amount" ], self .expected_balance )
115+ assert_equal (address ["amount" ], self .amount_received )
113116 assert_equal (address ["confirmations" ], confirmations )
114117 # Verify the transaction is correctly marked watchonly depending on
115118 # whether the transaction pays to an imported public key or
@@ -223,11 +226,11 @@ def run_test(self):
223226 variant .node = self .nodes [2 + IMPORT_NODES .index (ImportNode (variant .prune , expect_rescan ))]
224227 variant .do_import (variant .timestamp )
225228 if expect_rescan :
226- variant .expected_balance = variant .initial_amount
229+ variant .amount_received = variant .initial_amount
227230 variant .expected_txs = 1
228231 variant .check (variant .initial_txid , variant .initial_amount , variant .confirmation_height )
229232 else :
230- variant .expected_balance = 0
233+ variant .amount_received = 0
231234 variant .expected_txs = 0
232235 variant .check ()
233236
@@ -247,7 +250,7 @@ def run_test(self):
247250 # Check the latest results from getbalance and listtransactions.
248251 for variant in IMPORT_VARIANTS :
249252 self .log .info ('Run check for variant {}' .format (variant ))
250- variant .expected_balance += variant .sent_amount
253+ variant .amount_received += variant .sent_amount
251254 variant .expected_txs += 1
252255 variant .check (variant .sent_txid , variant .sent_amount , variant .confirmation_height )
253256
@@ -267,14 +270,45 @@ def run_test(self):
267270 address_type = variant .address_type .value ,
268271 ))
269272 variant .key = self .nodes [1 ].dumpprivkey (variant .address ["address" ])
270- variant .initial_amount = get_rand_amount ()
273+ variant .initial_amount = get_rand_amount () * 2
271274 variant .initial_txid = self .nodes [0 ].sendtoaddress (variant .address ["address" ], variant .initial_amount )
272275 variant .confirmation_height = 0
273276 variant .timestamp = timestamp
274277
278+ # Mine a block so these parents are confirmed
279+ assert_equal (len (self .nodes [0 ].getrawmempool ()), len (mempool_variants ))
280+ self .sync_mempools ()
281+ block_to_disconnect = self .generate (self .nodes [0 ], 1 )[0 ]
282+ assert_equal (len (self .nodes [0 ].getrawmempool ()), 0 )
283+
284+ # For each variant, create an unconfirmed child transaction from initial_txid, sending all
285+ # the funds to an unspendable address. Importantly, no change output is created so the
286+ # transaction can't be recognized using its outputs. The wallet rescan needs to know the
287+ # inputs of the transaction to detect it, so the parent must be processed before the child.
288+ # An equivalent test for descriptors exists in wallet_rescan_unconfirmed.py.
289+ unspent_txid_map = {txin ["txid" ] : txin for txin in self .nodes [1 ].listunspent ()}
290+ for variant in mempool_variants :
291+ # Send full amount, subtracting fee from outputs, to ensure no change is created.
292+ child = self .nodes [1 ].send (
293+ add_to_wallet = False ,
294+ inputs = [unspent_txid_map [variant .initial_txid ]],
295+ outputs = [{ADDRESS_BCRT1_UNSPENDABLE : variant .initial_amount }],
296+ subtract_fee_from_outputs = [0 ]
297+ )
298+ variant .child_txid = child ["txid" ]
299+ variant .amount_received = 0
300+ self .nodes [0 ].sendrawtransaction (child ["hex" ])
301+
302+ # Mempools should contain the child transactions for each variant.
275303 assert_equal (len (self .nodes [0 ].getrawmempool ()), len (mempool_variants ))
276304 self .sync_mempools ()
277305
306+ # Mock a reorg so the parent transactions are added back to the mempool
307+ for node in self .nodes :
308+ node .invalidateblock (block_to_disconnect )
309+ # Mempools should now contain the parent and child for each variant.
310+ assert_equal (len (node .getrawmempool ()), 2 * len (mempool_variants ))
311+
278312 # For each variation of wallet key import, invoke the import RPC and
279313 # check the results from getbalance and listtransactions.
280314 for variant in mempool_variants :
@@ -283,11 +317,15 @@ def run_test(self):
283317 variant .node = self .nodes [2 + IMPORT_NODES .index (ImportNode (variant .prune , expect_rescan ))]
284318 variant .do_import (variant .timestamp )
285319 if expect_rescan :
286- variant .expected_balance = variant .initial_amount
320+ # Ensure both transactions were rescanned. This would raise a JSONRPCError if the
321+ # transactions were not identified as belonging to the wallet.
322+ assert_equal (variant .node .gettransaction (variant .initial_txid )['confirmations' ], 0 )
323+ assert_equal (variant .node .gettransaction (variant .child_txid )['confirmations' ], 0 )
324+ variant .amount_received = variant .initial_amount
287325 variant .expected_txs = 1
288- variant .check (variant .initial_txid , variant .initial_amount )
326+ variant .check (variant .initial_txid , variant .initial_amount , 0 )
289327 else :
290- variant .expected_balance = 0
328+ variant .amount_received = 0
291329 variant .expected_txs = 0
292330 variant .check ()
293331
0 commit comments