23
23
assert_equal ,
24
24
assert_raises_rpc_error ,
25
25
)
26
+ from test_framework .wallet import (
27
+ MiniWallet ,
28
+ )
26
29
from test_framework .netutil import test_ipv6_local
27
30
from io import BytesIO
28
31
from time import sleep
@@ -100,8 +103,6 @@ def caused_notification(self, notification):
100
103
class ZMQTest (BitcoinTestFramework ):
101
104
def set_test_params (self ):
102
105
self .num_nodes = 2
103
- if self .is_wallet_compiled ():
104
- self .requires_wallet = True
105
106
# This test isn't testing txn relay/timing, so set whitelist on the
106
107
# peers for instant txn relay. This speeds up the test run time 2-3x.
107
108
self .
extra_args = [[
"[email protected] " ]]
* self .
num_nodes
@@ -111,6 +112,7 @@ def skip_test_if_missing_module(self):
111
112
self .skip_if_no_bitcoind_zmq ()
112
113
113
114
def run_test (self ):
115
+ self .wallet = MiniWallet (self .nodes [0 ])
114
116
self .ctx = zmq .Context ()
115
117
try :
116
118
self .test_basic ()
@@ -211,25 +213,25 @@ def test_basic(self):
211
213
assert_equal ([txid .hex ()], self .nodes [1 ].getblock (hash )["tx" ])
212
214
213
215
214
- if self .is_wallet_compiled ():
215
- self .log .info ("Wait for tx from second node" )
216
- payment_txid = self .nodes [ 1 ]. sendtoaddress ( self .nodes [0 ]. getnewaddress (), 1.0 )
217
- self . sync_all ()
218
-
219
- # Should receive the broadcasted txid.
220
- txid = hashtx .receive ()
221
- assert_equal (payment_txid , txid .hex ())
216
+ self .wallet . rescan_utxos ()
217
+ self .log .info ("Wait for tx from second node" )
218
+ payment_tx = self .wallet . send_self_transfer ( from_node = self .nodes [1 ] )
219
+ payment_txid = payment_tx [ 'txid' ]
220
+ self . sync_all ()
221
+ # Should receive the broadcasted txid.
222
+ txid = hashtx .receive ()
223
+ assert_equal (payment_txid , txid .hex ())
222
224
223
- # Should receive the broadcasted raw transaction.
224
- hex = rawtx .receive ()
225
- assert_equal (payment_txid , hash256_reversed (hex ).hex ())
225
+ # Should receive the broadcasted raw transaction.
226
+ hex = rawtx .receive ()
227
+ assert_equal (payment_tx [ 'wtxid' ] , hash256_reversed (hex ).hex ())
226
228
227
- # Mining the block with this tx should result in second notification
228
- # after coinbase tx notification
229
- self .generatetoaddress (self .nodes [0 ], 1 , ADDRESS_BCRT1_UNSPENDABLE )
230
- hashtx .receive ()
231
- txid = hashtx .receive ()
232
- assert_equal (payment_txid , txid .hex ())
229
+ # Mining the block with this tx should result in second notification
230
+ # after coinbase tx notification
231
+ self .generatetoaddress (self .nodes [0 ], 1 , ADDRESS_BCRT1_UNSPENDABLE )
232
+ hashtx .receive ()
233
+ txid = hashtx .receive ()
234
+ assert_equal (payment_txid , txid .hex ())
233
235
234
236
235
237
self .log .info ("Test the getzmqnotifications RPC" )
@@ -243,9 +245,6 @@ def test_basic(self):
243
245
assert_equal (self .nodes [1 ].getzmqnotifications (), [])
244
246
245
247
def test_reorg (self ):
246
- if not self .is_wallet_compiled ():
247
- self .log .info ("Skipping reorg test because wallet is disabled" )
248
- return
249
248
250
249
address = 'tcp://127.0.0.1:28333'
251
250
@@ -256,7 +255,7 @@ def test_reorg(self):
256
255
self .disconnect_nodes (0 , 1 )
257
256
258
257
# Generate 1 block in nodes[0] with 1 mempool tx and receive all notifications
259
- payment_txid = self .nodes [ 0 ]. sendtoaddress ( self .nodes [0 ]. getnewaddress (), 1.0 )
258
+ payment_txid = self .wallet . send_self_transfer ( from_node = self .nodes [0 ])[ 'txid' ]
260
259
disconnect_block = self .generatetoaddress (self .nodes [0 ], 1 , ADDRESS_BCRT1_UNSPENDABLE , sync_fun = self .no_op )[0 ]
261
260
disconnect_cb = self .nodes [0 ].getblock (disconnect_block )["tx" ][0 ]
262
261
assert_equal (self .nodes [0 ].getbestblockhash (), hashblock .receive ().hex ())
@@ -325,126 +324,124 @@ def test_sequence(self):
325
324
assert_equal ((self .nodes [1 ].getblockhash (block_count - 1 ), "C" , None ), seq .receive_sequence ())
326
325
assert_equal ((self .nodes [1 ].getblockhash (block_count ), "C" , None ), seq .receive_sequence ())
327
326
328
- # Rest of test requires wallet functionality
329
- if self .is_wallet_compiled ():
330
- self .log .info ("Wait for tx from second node" )
331
- payment_txid = self .nodes [1 ].sendtoaddress (address = self .nodes [0 ].getnewaddress (), amount = 5.0 , replaceable = True )
332
- self .sync_all ()
333
- self .log .info ("Testing sequence notifications with mempool sequence values" )
334
-
335
- # Should receive the broadcasted txid.
336
- assert_equal ((payment_txid , "A" , seq_num ), seq .receive_sequence ())
337
- seq_num += 1
338
-
339
- self .log .info ("Testing RBF notification" )
340
- # Replace it to test eviction/addition notification
341
- rbf_info = self .nodes [1 ].bumpfee (payment_txid )
342
- self .sync_all ()
343
- assert_equal ((payment_txid , "R" , seq_num ), seq .receive_sequence ())
344
- seq_num += 1
345
- assert_equal ((rbf_info ["txid" ], "A" , seq_num ), seq .receive_sequence ())
346
- seq_num += 1
347
-
348
- # Doesn't get published when mined, make a block and tx to "flush" the possibility
349
- # though the mempool sequence number does go up by the number of transactions
350
- # removed from the mempool by the block mining it.
351
- mempool_size = len (self .nodes [0 ].getrawmempool ())
352
- c_block = self .generatetoaddress (self .nodes [0 ], 1 , ADDRESS_BCRT1_UNSPENDABLE )[0 ]
353
- # Make sure the number of mined transactions matches the number of txs out of mempool
354
- mempool_size_delta = mempool_size - len (self .nodes [0 ].getrawmempool ())
355
- assert_equal (len (self .nodes [0 ].getblock (c_block )["tx" ])- 1 , mempool_size_delta )
356
- seq_num += mempool_size_delta
357
- payment_txid_2 = self .nodes [1 ].sendtoaddress (self .nodes [0 ].getnewaddress (), 1.0 )
358
- self .sync_all ()
359
- assert_equal ((c_block , "C" , None ), seq .receive_sequence ())
360
- assert_equal ((payment_txid_2 , "A" , seq_num ), seq .receive_sequence ())
361
- seq_num += 1
362
-
363
- # Spot check getrawmempool results that they only show up when asked for
364
- assert type (self .nodes [0 ].getrawmempool ()) is list
365
- assert type (self .nodes [0 ].getrawmempool (mempool_sequence = False )) is list
366
- assert "mempool_sequence" not in self .nodes [0 ].getrawmempool (verbose = True )
367
- assert_raises_rpc_error (- 8 , "Verbose results cannot contain mempool sequence values." , self .nodes [0 ].getrawmempool , True , True )
368
- assert_equal (self .nodes [0 ].getrawmempool (mempool_sequence = True )["mempool_sequence" ], seq_num )
369
-
370
- self .log .info ("Testing reorg notifications" )
371
- # Manually invalidate the last block to test mempool re-entry
372
- # N.B. This part could be made more lenient in exact ordering
373
- # since it greatly depends on inner-workings of blocks/mempool
374
- # during "deep" re-orgs. Probably should "re-construct"
375
- # blockchain/mempool state from notifications instead.
376
- block_count = self .nodes [0 ].getblockcount ()
377
- best_hash = self .nodes [0 ].getbestblockhash ()
378
- self .nodes [0 ].invalidateblock (best_hash )
379
- sleep (2 ) # Bit of room to make sure transaction things happened
380
-
381
- # Make sure getrawmempool mempool_sequence results aren't "queued" but immediately reflective
382
- # of the time they were gathered.
383
- assert self .nodes [0 ].getrawmempool (mempool_sequence = True )["mempool_sequence" ] > seq_num
384
-
385
- assert_equal ((best_hash , "D" , None ), seq .receive_sequence ())
386
- assert_equal ((rbf_info ["txid" ], "A" , seq_num ), seq .receive_sequence ())
387
- seq_num += 1
388
-
389
- # Other things may happen but aren't wallet-deterministic so we don't test for them currently
390
- self .nodes [0 ].reconsiderblock (best_hash )
391
- self .generatetoaddress (self .nodes [1 ], 1 , ADDRESS_BCRT1_UNSPENDABLE )
392
-
393
- self .log .info ("Evict mempool transaction by block conflict" )
394
- orig_txid = self .nodes [0 ].sendtoaddress (address = self .nodes [0 ].getnewaddress (), amount = 1.0 , replaceable = True )
395
-
396
- # More to be simply mined
397
- more_tx = []
398
- for _ in range (5 ):
399
- more_tx .append (self .nodes [0 ].sendtoaddress (self .nodes [0 ].getnewaddress (), 0.1 ))
400
-
401
- raw_tx = self .nodes [0 ].getrawtransaction (orig_txid )
402
- bump_info = self .nodes [0 ].bumpfee (orig_txid )
403
- # Mine the pre-bump tx
404
- txs_to_add = [raw_tx ] + [self .nodes [0 ].getrawtransaction (txid ) for txid in more_tx ]
405
- block = create_block (int (self .nodes [0 ].getbestblockhash (), 16 ), create_coinbase (self .nodes [0 ].getblockcount ()+ 1 ), txlist = txs_to_add )
406
- add_witness_commitment (block )
407
- block .solve ()
408
- assert_equal (self .nodes [0 ].submitblock (block .serialize ().hex ()), None )
409
- tip = self .nodes [0 ].getbestblockhash ()
410
- assert_equal (int (tip , 16 ), block .sha256 )
411
- orig_txid_2 = self .nodes [0 ].sendtoaddress (address = self .nodes [0 ].getnewaddress (), amount = 1.0 , replaceable = True )
412
-
413
- # Flush old notifications until evicted tx original entry
327
+ self .log .info ("Wait for tx from second node" )
328
+ payment_tx = self .wallet .send_self_transfer (from_node = self .nodes [1 ])
329
+ payment_txid = payment_tx ['txid' ]
330
+ self .sync_all ()
331
+ self .log .info ("Testing sequence notifications with mempool sequence values" )
332
+
333
+ # Should receive the broadcasted txid.
334
+ assert_equal ((payment_txid , "A" , seq_num ), seq .receive_sequence ())
335
+ seq_num += 1
336
+
337
+ self .log .info ("Testing RBF notification" )
338
+ # Replace it to test eviction/addition notification
339
+ payment_tx ['tx' ].vout [0 ].nValue -= 1000
340
+ rbf_txid = self .nodes [1 ].sendrawtransaction (payment_tx ['tx' ].serialize ().hex ())
341
+ self .sync_all ()
342
+ assert_equal ((payment_txid , "R" , seq_num ), seq .receive_sequence ())
343
+ seq_num += 1
344
+ assert_equal ((rbf_txid , "A" , seq_num ), seq .receive_sequence ())
345
+ seq_num += 1
346
+
347
+ # Doesn't get published when mined, make a block and tx to "flush" the possibility
348
+ # though the mempool sequence number does go up by the number of transactions
349
+ # removed from the mempool by the block mining it.
350
+ mempool_size = len (self .nodes [0 ].getrawmempool ())
351
+ c_block = self .generatetoaddress (self .nodes [0 ], 1 , ADDRESS_BCRT1_UNSPENDABLE )[0 ]
352
+ # Make sure the number of mined transactions matches the number of txs out of mempool
353
+ mempool_size_delta = mempool_size - len (self .nodes [0 ].getrawmempool ())
354
+ assert_equal (len (self .nodes [0 ].getblock (c_block )["tx" ])- 1 , mempool_size_delta )
355
+ seq_num += mempool_size_delta
356
+ payment_txid_2 = self .wallet .send_self_transfer (from_node = self .nodes [1 ])['txid' ]
357
+ self .sync_all ()
358
+ assert_equal ((c_block , "C" , None ), seq .receive_sequence ())
359
+ assert_equal ((payment_txid_2 , "A" , seq_num ), seq .receive_sequence ())
360
+ seq_num += 1
361
+
362
+ # Spot check getrawmempool results that they only show up when asked for
363
+ assert type (self .nodes [0 ].getrawmempool ()) is list
364
+ assert type (self .nodes [0 ].getrawmempool (mempool_sequence = False )) is list
365
+ assert "mempool_sequence" not in self .nodes [0 ].getrawmempool (verbose = True )
366
+ assert_raises_rpc_error (- 8 , "Verbose results cannot contain mempool sequence values." , self .nodes [0 ].getrawmempool , True , True )
367
+ assert_equal (self .nodes [0 ].getrawmempool (mempool_sequence = True )["mempool_sequence" ], seq_num )
368
+
369
+ self .log .info ("Testing reorg notifications" )
370
+ # Manually invalidate the last block to test mempool re-entry
371
+ # N.B. This part could be made more lenient in exact ordering
372
+ # since it greatly depends on inner-workings of blocks/mempool
373
+ # during "deep" re-orgs. Probably should "re-construct"
374
+ # blockchain/mempool state from notifications instead.
375
+ block_count = self .nodes [0 ].getblockcount ()
376
+ best_hash = self .nodes [0 ].getbestblockhash ()
377
+ self .nodes [0 ].invalidateblock (best_hash )
378
+ sleep (2 ) # Bit of room to make sure transaction things happened
379
+
380
+ # Make sure getrawmempool mempool_sequence results aren't "queued" but immediately reflective
381
+ # of the time they were gathered.
382
+ assert self .nodes [0 ].getrawmempool (mempool_sequence = True )["mempool_sequence" ] > seq_num
383
+
384
+ assert_equal ((best_hash , "D" , None ), seq .receive_sequence ())
385
+ assert_equal ((rbf_txid , "A" , seq_num ), seq .receive_sequence ())
386
+ seq_num += 1
387
+
388
+ # Other things may happen but aren't wallet-deterministic so we don't test for them currently
389
+ self .nodes [0 ].reconsiderblock (best_hash )
390
+ self .generatetoaddress (self .nodes [1 ], 1 , ADDRESS_BCRT1_UNSPENDABLE )
391
+
392
+ self .log .info ("Evict mempool transaction by block conflict" )
393
+ orig_tx = self .wallet .send_self_transfer (from_node = self .nodes [0 ])
394
+ orig_txid = orig_tx ['txid' ]
395
+
396
+ # More to be simply mined
397
+ more_tx = []
398
+ for _ in range (5 ):
399
+ more_tx .append (self .wallet .send_self_transfer (from_node = self .nodes [0 ]))
400
+
401
+ orig_tx ['tx' ].vout [0 ].nValue -= 1000
402
+ bump_txid = self .nodes [0 ].sendrawtransaction (orig_tx ['tx' ].serialize ().hex ())
403
+ # Mine the pre-bump tx
404
+ txs_to_add = [orig_tx ['hex' ]] + [tx ['hex' ] for tx in more_tx ]
405
+ block = create_block (int (self .nodes [0 ].getbestblockhash (), 16 ), create_coinbase (self .nodes [0 ].getblockcount ()+ 1 ), txlist = txs_to_add )
406
+ add_witness_commitment (block )
407
+ block .solve ()
408
+ assert_equal (self .nodes [0 ].submitblock (block .serialize ().hex ()), None )
409
+ tip = self .nodes [0 ].getbestblockhash ()
410
+ assert_equal (int (tip , 16 ), block .sha256 )
411
+ orig_txid_2 = self .wallet .send_self_transfer (from_node = self .nodes [0 ])['txid' ]
412
+
413
+ # Flush old notifications until evicted tx original entry
414
+ (hash_str , label , mempool_seq ) = seq .receive_sequence ()
415
+ while hash_str != orig_txid :
414
416
(hash_str , label , mempool_seq ) = seq .receive_sequence ()
415
- while hash_str != orig_txid :
416
- (hash_str , label , mempool_seq ) = seq .receive_sequence ()
417
- mempool_seq += 1
417
+ mempool_seq += 1
418
418
419
- # Added original tx
420
- assert_equal (label , "A" )
421
- # More transactions to be simply mined
422
- for i in range (len (more_tx )):
423
- assert_equal ((more_tx [i ], "A" , mempool_seq ), seq .receive_sequence ())
424
- mempool_seq += 1
425
- # Bumped by rbf
426
- assert_equal ((orig_txid , "R" , mempool_seq ), seq .receive_sequence ())
427
- mempool_seq += 1
428
- assert_equal ((bump_info ["txid" ], "A" , mempool_seq ), seq .receive_sequence ())
419
+ # Added original tx
420
+ assert_equal (label , "A" )
421
+ # More transactions to be simply mined
422
+ for i in range (len (more_tx )):
423
+ assert_equal ((more_tx [i ]['txid' ], "A" , mempool_seq ), seq .receive_sequence ())
429
424
mempool_seq += 1
430
- # Conflict announced first, then block
431
- assert_equal ((bump_info ["txid" ], "R" , mempool_seq ), seq .receive_sequence ())
432
- mempool_seq += 1
433
- assert_equal ((tip , "C" , None ), seq .receive_sequence ())
434
- mempool_seq += len (more_tx )
435
- # Last tx
436
- assert_equal ((orig_txid_2 , "A" , mempool_seq ), seq .receive_sequence ())
437
- mempool_seq += 1
438
- self .generatetoaddress (self .nodes [0 ], 1 , ADDRESS_BCRT1_UNSPENDABLE )
439
- self .sync_all () # want to make sure we didn't break "consensus" for other tests
425
+ # Bumped by rbf
426
+ assert_equal ((orig_txid , "R" , mempool_seq ), seq .receive_sequence ())
427
+ mempool_seq += 1
428
+ assert_equal ((bump_txid , "A" , mempool_seq ), seq .receive_sequence ())
429
+ mempool_seq += 1
430
+ # Conflict announced first, then block
431
+ assert_equal ((bump_txid , "R" , mempool_seq ), seq .receive_sequence ())
432
+ mempool_seq += 1
433
+ assert_equal ((tip , "C" , None ), seq .receive_sequence ())
434
+ mempool_seq += len (more_tx )
435
+ # Last tx
436
+ assert_equal ((orig_txid_2 , "A" , mempool_seq ), seq .receive_sequence ())
437
+ mempool_seq += 1
438
+ self .generatetoaddress (self .nodes [0 ], 1 , ADDRESS_BCRT1_UNSPENDABLE )
439
+ self .sync_all () # want to make sure we didn't break "consensus" for other tests
440
440
441
441
def test_mempool_sync (self ):
442
442
"""
443
443
Use sequence notification plus getrawmempool sequence results to "sync mempool"
444
444
"""
445
- if not self .is_wallet_compiled ():
446
- self .log .info ("Skipping mempool sync test" )
447
- return
448
445
449
446
self .log .info ("Testing 'mempool sync' usage of sequence notifier" )
450
447
[seq ] = self .setup_zmq_test ([("sequence" , "tcp://127.0.0.1:28333" )])
@@ -455,10 +452,10 @@ def test_mempool_sync(self):
455
452
456
453
# Some transactions have been happening but we aren't consuming zmq notifications yet
457
454
# or we lost a ZMQ message somehow and want to start over
458
- txids = []
455
+ txs = []
459
456
num_txs = 5
460
457
for _ in range (num_txs ):
461
- txids .append (self .nodes [ 1 ]. sendtoaddress ( address = self .nodes [0 ]. getnewaddress (), amount = 1.0 , replaceable = True ))
458
+ txs .append (self .wallet . send_self_transfer ( from_node = self .nodes [1 ] ))
462
459
self .sync_all ()
463
460
464
461
# 1) Consume backlog until we get a mempool sequence number
@@ -484,11 +481,12 @@ def test_mempool_sync(self):
484
481
# Things continue to happen in the "interim" while waiting for snapshot results
485
482
# We have node 0 do all these to avoid p2p races with RBF announcements
486
483
for _ in range (num_txs ):
487
- txids .append (self .nodes [0 ].sendtoaddress (address = self .nodes [0 ].getnewaddress (), amount = 0.1 , replaceable = True ))
488
- self .nodes [0 ].bumpfee (txids [- 1 ])
484
+ txs .append (self .wallet .send_self_transfer (from_node = self .nodes [0 ]))
485
+ txs [- 1 ]['tx' ].vout [0 ].nValue -= 1000
486
+ self .nodes [0 ].sendrawtransaction (txs [- 1 ]['tx' ].serialize ().hex ())
489
487
self .sync_all ()
490
488
self .generatetoaddress (self .nodes [0 ], 1 , ADDRESS_BCRT1_UNSPENDABLE )
491
- final_txid = self .nodes [ 0 ]. sendtoaddress ( address = self .nodes [0 ]. getnewaddress (), amount = 0.1 , replaceable = True )
489
+ final_txid = self .wallet . send_self_transfer ( from_node = self .nodes [0 ])[ 'txid' ]
492
490
493
491
# 3) Consume ZMQ backlog until we get to "now" for the mempool snapshot
494
492
while True :
0 commit comments