20
20
"""
21
21
22
22
from 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
+ )
24
27
from test_framework .util import (
25
28
assert_equal ,
26
29
set_node_times ,
@@ -109,7 +112,7 @@ def check(self, txid=None, amount=None, confirmation_height=None):
109
112
110
113
address , = [ad for ad in addresses if txid in ad ["txids" ]]
111
114
assert_equal (address ["address" ], self .address ["address" ])
112
- assert_equal (address ["amount" ], self .expected_balance )
115
+ assert_equal (address ["amount" ], self .amount_received )
113
116
assert_equal (address ["confirmations" ], confirmations )
114
117
# Verify the transaction is correctly marked watchonly depending on
115
118
# whether the transaction pays to an imported public key or
@@ -223,11 +226,11 @@ def run_test(self):
223
226
variant .node = self .nodes [2 + IMPORT_NODES .index (ImportNode (variant .prune , expect_rescan ))]
224
227
variant .do_import (variant .timestamp )
225
228
if expect_rescan :
226
- variant .expected_balance = variant .initial_amount
229
+ variant .amount_received = variant .initial_amount
227
230
variant .expected_txs = 1
228
231
variant .check (variant .initial_txid , variant .initial_amount , variant .confirmation_height )
229
232
else :
230
- variant .expected_balance = 0
233
+ variant .amount_received = 0
231
234
variant .expected_txs = 0
232
235
variant .check ()
233
236
@@ -247,7 +250,7 @@ def run_test(self):
247
250
# Check the latest results from getbalance and listtransactions.
248
251
for variant in IMPORT_VARIANTS :
249
252
self .log .info ('Run check for variant {}' .format (variant ))
250
- variant .expected_balance += variant .sent_amount
253
+ variant .amount_received += variant .sent_amount
251
254
variant .expected_txs += 1
252
255
variant .check (variant .sent_txid , variant .sent_amount , variant .confirmation_height )
253
256
@@ -267,14 +270,45 @@ def run_test(self):
267
270
address_type = variant .address_type .value ,
268
271
))
269
272
variant .key = self .nodes [1 ].dumpprivkey (variant .address ["address" ])
270
- variant .initial_amount = get_rand_amount ()
273
+ variant .initial_amount = get_rand_amount () * 2
271
274
variant .initial_txid = self .nodes [0 ].sendtoaddress (variant .address ["address" ], variant .initial_amount )
272
275
variant .confirmation_height = 0
273
276
variant .timestamp = timestamp
274
277
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.
275
303
assert_equal (len (self .nodes [0 ].getrawmempool ()), len (mempool_variants ))
276
304
self .sync_mempools ()
277
305
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
+
278
312
# For each variation of wallet key import, invoke the import RPC and
279
313
# check the results from getbalance and listtransactions.
280
314
for variant in mempool_variants :
@@ -283,11 +317,15 @@ def run_test(self):
283
317
variant .node = self .nodes [2 + IMPORT_NODES .index (ImportNode (variant .prune , expect_rescan ))]
284
318
variant .do_import (variant .timestamp )
285
319
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
287
325
variant .expected_txs = 1
288
- variant .check (variant .initial_txid , variant .initial_amount )
326
+ variant .check (variant .initial_txid , variant .initial_amount , 0 )
289
327
else :
290
- variant .expected_balance = 0
328
+ variant .amount_received = 0
291
329
variant .expected_txs = 0
292
330
variant .check ()
293
331
0 commit comments