2323 assert_equal ,
2424 assert_raises_rpc_error ,
2525)
26+ from test_framework .wallet import (
27+ MiniWallet ,
28+ )
2629from test_framework .netutil import test_ipv6_local
2730from io import BytesIO
2831from time import sleep
@@ -100,8 +103,6 @@ def caused_notification(self, notification):
100103class ZMQTest (BitcoinTestFramework ):
101104 def set_test_params (self ):
102105 self .num_nodes = 2
103- if self .is_wallet_compiled ():
104- self .requires_wallet = True
105106 # This test isn't testing txn relay/timing, so set whitelist on the
106107 # peers for instant txn relay. This speeds up the test run time 2-3x.
107108 self .
extra_args = [[
"[email protected] " ]]
* self .
num_nodes @@ -111,6 +112,7 @@ def skip_test_if_missing_module(self):
111112 self .skip_if_no_bitcoind_zmq ()
112113
113114 def run_test (self ):
115+ self .wallet = MiniWallet (self .nodes [0 ])
114116 self .ctx = zmq .Context ()
115117 try :
116118 self .test_basic ()
@@ -211,25 +213,25 @@ def test_basic(self):
211213 assert_equal ([txid .hex ()], self .nodes [1 ].getblock (hash )["tx" ])
212214
213215
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 ())
222224
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 ())
226228
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 ())
233235
234236
235237 self .log .info ("Test the getzmqnotifications RPC" )
@@ -243,9 +245,6 @@ def test_basic(self):
243245 assert_equal (self .nodes [1 ].getzmqnotifications (), [])
244246
245247 def test_reorg (self ):
246- if not self .is_wallet_compiled ():
247- self .log .info ("Skipping reorg test because wallet is disabled" )
248- return
249248
250249 address = 'tcp://127.0.0.1:28333'
251250
@@ -256,7 +255,7 @@ def test_reorg(self):
256255 self .disconnect_nodes (0 , 1 )
257256
258257 # 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' ]
260259 disconnect_block = self .generatetoaddress (self .nodes [0 ], 1 , ADDRESS_BCRT1_UNSPENDABLE , sync_fun = self .no_op )[0 ]
261260 disconnect_cb = self .nodes [0 ].getblock (disconnect_block )["tx" ][0 ]
262261 assert_equal (self .nodes [0 ].getbestblockhash (), hashblock .receive ().hex ())
@@ -325,126 +324,124 @@ def test_sequence(self):
325324 assert_equal ((self .nodes [1 ].getblockhash (block_count - 1 ), "C" , None ), seq .receive_sequence ())
326325 assert_equal ((self .nodes [1 ].getblockhash (block_count ), "C" , None ), seq .receive_sequence ())
327326
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 :
414416 (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
418418
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 ())
429424 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
440440
441441 def test_mempool_sync (self ):
442442 """
443443 Use sequence notification plus getrawmempool sequence results to "sync mempool"
444444 """
445- if not self .is_wallet_compiled ():
446- self .log .info ("Skipping mempool sync test" )
447- return
448445
449446 self .log .info ("Testing 'mempool sync' usage of sequence notifier" )
450447 [seq ] = self .setup_zmq_test ([("sequence" , "tcp://127.0.0.1:28333" )])
@@ -455,10 +452,10 @@ def test_mempool_sync(self):
455452
456453 # Some transactions have been happening but we aren't consuming zmq notifications yet
457454 # or we lost a ZMQ message somehow and want to start over
458- txids = []
455+ txs = []
459456 num_txs = 5
460457 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 ] ))
462459 self .sync_all ()
463460
464461 # 1) Consume backlog until we get a mempool sequence number
@@ -484,11 +481,12 @@ def test_mempool_sync(self):
484481 # Things continue to happen in the "interim" while waiting for snapshot results
485482 # We have node 0 do all these to avoid p2p races with RBF announcements
486483 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 ())
489487 self .sync_all ()
490488 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' ]
492490
493491 # 3) Consume ZMQ backlog until we get to "now" for the mempool snapshot
494492 while True :
0 commit comments