Skip to content

Commit a697a3f

Browse files
author
MarcoFalke
committed
Merge bitcoin/bitcoin#24653: test: use MiniWallet in test/functional/interface_zmq
bc90b8d [move only] remove `is_wallet_compiled` checks (josibake) 0bfbf7f test: use MiniWallet in `interfaces_zmq` (josibake) Pull request description: While working on #24584 , `interface_zmq` started failing due to coin selection not running deterministically. The test doesn't actually need the wallet, so this PR migrates it to use MiniWallet _Note for reviewers:_ the second commit moves large chunks of code out of an if block, so it may be helpful to review with something that ignores whitespace, e.g `git diff -w master` ACKs for top commit: vincenzopalazzo: ACK bitcoin/bitcoin@bc90b8d Tree-SHA512: c618e23d00635d72dafdef28e68cbc88b9cc2030d4898fc5b7eac926fd621684c1958c075ed167192716b18308da5a0c1f1393396e31b99d0d3bde78b78fefc5
2 parents 65e9ca2 + bc90b8d commit a697a3f

File tree

1 file changed

+138
-140
lines changed

1 file changed

+138
-140
lines changed

test/functional/interface_zmq.py

Lines changed: 138 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
assert_equal,
2424
assert_raises_rpc_error,
2525
)
26+
from test_framework.wallet import (
27+
MiniWallet,
28+
)
2629
from test_framework.netutil import test_ipv6_local
2730
from io import BytesIO
2831
from time import sleep
@@ -100,8 +103,6 @@ def caused_notification(self, notification):
100103
class 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

Comments
 (0)