Skip to content

Commit

Permalink
merge bitcoin#23300: Implicitly sync after generate*, unless opted out
Browse files Browse the repository at this point in the history
  • Loading branch information
kwvg committed Sep 30, 2024
1 parent 5afcc80 commit c586562
Show file tree
Hide file tree
Showing 43 changed files with 160 additions and 210 deletions.
3 changes: 1 addition & 2 deletions test/functional/example_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,7 @@ def run_test(self):
peer_messaging = self.nodes[0].add_p2p_connection(BaseNode())

# Generating a block on one of the nodes will get us out of IBD
blocks = [int(self.generate(self.nodes[0], nblocks=1)[0], 16)]
self.sync_all(self.nodes[0:2])
blocks = [int(self.generate(self.nodes[0], sync_fun=lambda: self.sync_all(self.nodes[0:2]), nblocks=1)[0], 16)]

# Notice above how we called an RPC by calling a method with the same
# name on the node object. Notice also how we used a keyword argument
Expand Down
6 changes: 3 additions & 3 deletions test/functional/feature_abortnode.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,18 @@ def setup_network(self):
# We'll connect the nodes later

def run_test(self):
self.generate(self.nodes[0], 3)
self.generate(self.nodes[0], 3, sync_fun=self.no_op)
datadir = get_datadir_path(self.options.tmpdir, 0)

# Deleting the undo file will result in reorg failure
os.unlink(os.path.join(datadir, self.chain, 'blocks', 'rev00000.dat'))

# Connecting to a node with a more work chain will trigger a reorg
# attempt.
self.generate(self.nodes[1], 3)
self.generate(self.nodes[1], 3, sync_fun=self.no_op)
with self.nodes[0].assert_debug_log(["Failed to disconnect block"]):
self.connect_nodes(0, 1)
self.generate(self.nodes[1], 1)
self.generate(self.nodes[1], 1, sync_fun=self.no_op)

# Check that node0 aborted
self.log.info("Waiting for crash")
Expand Down
8 changes: 4 additions & 4 deletions test/functional/feature_bip68_sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
cur_time = self.mocktime
for _ in range(10):
self.nodes[0].setmocktime(cur_time + 600)
self.generate(self.nodes[0], 1)
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
cur_time += 600

assert tx2.hash in self.nodes[0].getrawmempool()
Expand Down Expand Up @@ -349,7 +349,7 @@ def test_nonzero_locks(orig_tx, node, relayfee, use_height_lock):
# Reset the chain and get rid of the mocktimed-blocks
self.nodes[0].setmocktime(self.mocktime)
self.nodes[0].invalidateblock(self.nodes[0].getblockhash(cur_height+1))
self.generate(self.nodes[0], 10)
self.generate(self.nodes[0], 10, sync_fun=self.no_op)

# Make sure that BIP68 isn't being used to validate blocks prior to
# activation height. If more blocks are mined prior to this test
Expand Down Expand Up @@ -402,9 +402,9 @@ def activateCSV(self):
min_activation_height = 432
height = self.nodes[0].getblockcount()
assert_greater_than(min_activation_height - height, 2)
self.generate(self.nodes[0], min_activation_height - height - 2)
self.generate(self.nodes[0], min_activation_height - height - 2, sync_fun=self.no_op)
assert not softfork_active(self.nodes[0], 'csv')
self.generate(self.nodes[0], 1)
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
assert softfork_active(self.nodes[0], 'csv')
self.sync_blocks()

Expand Down
4 changes: 2 additions & 2 deletions test/functional/feature_coinstatsindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ def _test_coin_stats_index(self):
res9 = index_node.gettxoutsetinfo('muhash')
assert_equal(res8, res9)

self.generate(index_node, 1)
self.generate(index_node, 1, sync_fun=self.no_op)
res10 = index_node.gettxoutsetinfo('muhash')
assert(res8['txouts'] < res10['txouts'])

Expand All @@ -268,7 +268,7 @@ def _test_reorg_index(self):
assert_equal(index_node.gettxoutsetinfo('muhash')['height'], 110)

# Add two new blocks
block = self.generate(index_node, 2)[1]
block = self.generate(index_node, 2, sync_fun=self.no_op)[1]
res = index_node.gettxoutsetinfo(hash_type='muhash', hash_or_height=None, use_index=False)

# Test that the result of the reorged block is not returned for its old block height
Expand Down
3 changes: 2 additions & 1 deletion test/functional/feature_dbcrash.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def run_test(self):

# Start by creating a lot of utxos on node3
initial_height = self.nodes[3].getblockcount()
utxo_list = create_confirmed_utxos(self, self.nodes[3].getnetworkinfo()['relayfee'], self.nodes[3], 5000)
utxo_list = create_confirmed_utxos(self, self.nodes[3].getnetworkinfo()['relayfee'], self.nodes[3], 5000, sync_fun=self.no_op)
self.log.info("Prepped %d utxo entries", len(utxo_list))

# Sync these blocks with the other nodes
Expand Down Expand Up @@ -258,6 +258,7 @@ def run_test(self):
nblocks=min(10, current_height + 1 - self.nodes[3].getblockcount()),
# new address to avoid mining a block that has just been invalidated
address=self.nodes[3].getnewaddress(),
sync_fun=self.no_op,
))
self.log.debug("Syncing %d new blocks...", len(block_hashes))
self.sync_node3blocks(block_hashes)
Expand Down
6 changes: 3 additions & 3 deletions test/functional/feature_fee_estimation.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def run_test(self):

# Mine
while len(self.nodes[0].getrawmempool()) > 0:
self.generate(self.nodes[0], 1)
self.generate(self.nodes[0], 1, sync_fun=self.no_op)

# Repeatedly split those 2 outputs, doubling twice for each rep
# Use txouts to monitor the available utxo, since these won't be tracked in wallet
Expand All @@ -241,12 +241,12 @@ def run_test(self):
while len(self.txouts) > 0:
split_inputs(self.nodes[0], self.txouts, self.txouts2)
while len(self.nodes[0].getrawmempool()) > 0:
self.generate(self.nodes[0], 1)
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
# Double txouts2 to txouts
while len(self.txouts2) > 0:
split_inputs(self.nodes[0], self.txouts2, self.txouts)
while len(self.nodes[0].getrawmempool()) > 0:
self.generate(self.nodes[0], 1)
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
reps += 1
self.log.info("Finished splitting")

Expand Down
2 changes: 1 addition & 1 deletion test/functional/feature_loadblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def set_test_params(self):

def run_test(self):
self.nodes[1].setnetworkactive(state=False)
self.generate(self.nodes[0], COINBASE_MATURITY)
self.generate(self.nodes[0], COINBASE_MATURITY, sync_fun=self.no_op)

# Parsing the url of our node to get settings for config file
data_dir = self.nodes[0].datadir
Expand Down
4 changes: 2 additions & 2 deletions test/functional/feature_minchainwork.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def run_test(self):
num_blocks_to_generate = int((self.node_min_work[1] - starting_chain_work) / REGTEST_WORK_PER_BLOCK)
self.log.info("Generating %d blocks on node0", num_blocks_to_generate)
hashes = self.generatetoaddress(self.nodes[0], num_blocks_to_generate,
self.nodes[0].get_deterministic_priv_key().address)
self.nodes[0].get_deterministic_priv_key().address, sync_fun=self.no_op)

self.log.info("Node0 current chain work: %s", self.nodes[0].getblockheader(hashes[-1])['chainwork'])

Expand Down Expand Up @@ -88,7 +88,7 @@ def run_test(self):
assert ("headers" not in peer.last_message or len(peer.last_message["headers"].headers) == 0)

self.log.info("Generating one more block")
self.generatetoaddress(self.nodes[0], 1, self.nodes[0].get_deterministic_priv_key().address)
self.generate(self.nodes[0], 1)

self.log.info("Verifying nodes are all synced")

Expand Down
2 changes: 1 addition & 1 deletion test/functional/feature_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def run_test(self):

self.log.info("Mine single block, wait for chainlock")
self.bump_mocktime(1)
tip = self.generate(self.nodes[0], 1)[-1]
tip = self.generate(self.nodes[0], 1, sync_fun=self.no_op)[-1]
self.wait_for_chainlocked_block_all_nodes(tip)
# directory content should equal the chainlocked block hash
assert_equal([tip], sorted(os.listdir(self.chainlocknotify_dir)))
Expand Down
13 changes: 6 additions & 7 deletions test/functional/feature_pruning.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,8 @@ def setup_nodes(self):

def create_big_chain(self):
# Start by creating some coinbases we can spend later
self.generate(self.nodes[1], 200)
self.sync_blocks(self.nodes[0:2])
self.generate(self.nodes[0], 150)
self.generate(self.nodes[1], 200, sync_fun=lambda: self.sync_blocks(self.nodes[0:2]))
self.generate(self.nodes[0], 150, sync_fun=self.no_op)

# Then mine enough full blocks to create more than 550MiB of data
mine_large_blocks(self.nodes[0], 645)
Expand Down Expand Up @@ -220,7 +219,7 @@ def reorg_test(self):
self.disconnect_nodes(1, 2)

self.log.info("Generating new longer chain of 300 more blocks")
self.generate(self.nodes[1], 299)
self.generate(self.nodes[1], 299, sync_fun=self.no_op)

self.log.info("Reconnect nodes")
self.connect_nodes(0, 1)
Expand Down Expand Up @@ -272,7 +271,7 @@ def reorg_back(self):
self.nodes[0].invalidateblock(curchainhash)
assert_equal(self.nodes[0].getblockcount(), self.mainchainheight)
assert_equal(self.nodes[0].getbestblockhash(), self.mainchainhash2)
goalbesthash = self.generate(self.nodes[0], blocks_to_mine)[-1]
goalbesthash = self.generate(self.nodes[0], blocks_to_mine, sync_fun=self.no_op)[-1]
goalbestheight = first_reorg_height + 1

self.log.info("Verify node 2 reorged back to the main chain, some blocks of which it had to redownload")
Expand Down Expand Up @@ -315,7 +314,7 @@ def has_block(index):
assert_equal(block1_details["nTx"], len(block1_details["tx"]))

# mine 6 blocks so we are at height 1001 (i.e., above PruneAfterHeight)
self.generate(node, 6)
self.generate(node, 6, sync_fun=self.no_op)
assert_equal(node.getblockchaininfo()["blocks"], 1001)

# prune parameter in the future (block or timestamp) should raise an exception
Expand Down Expand Up @@ -353,7 +352,7 @@ def has_block(index):
assert has_block(2), "blk00002.dat is still there, should be pruned by now"

# advance the tip so blk00002.dat and blk00003.dat can be pruned (the last 288 blocks should now be in blk00004.dat)
self.generate(node, 288)
self.generate(node, 288, sync_fun=self.no_op)
prune(1000)
assert not has_block(2), "blk00002.dat is still there, should be pruned by now"
assert not has_block(3), "blk00003.dat is still there, should be pruned by now"
Expand Down
15 changes: 7 additions & 8 deletions test/functional/interface_zmq.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,8 @@ class ZMQTestSetupBlock:
the generated block's hash, it's (coinbase) transaction id, the raw block or
raw transaction data.
"""

def __init__(self, test_framework, node):
self.block_hash = test_framework.generate(node, 1)[0]
self.block_hash = test_framework.generate(node, 1, sync_fun=test_framework.no_op)[0]
coinbase = node.getblock(self.block_hash, 2)['tx'][0]
self.tx_hash = coinbase['txid']
self.raw_tx = coinbase['hex']
Expand Down Expand Up @@ -261,14 +260,14 @@ def test_reorg(self):

# Generate 1 block in nodes[0] with 1 mempool tx and receive all notifications
payment_txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1.0)
disconnect_block = self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_UNSPENDABLE)[0]
disconnect_block = self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_UNSPENDABLE, sync_fun=self.no_op)[0]
disconnect_cb = self.nodes[0].getblock(disconnect_block)["tx"][0]
assert_equal(self.nodes[0].getbestblockhash(), hashblock.receive().hex())
assert_equal(hashtx.receive().hex(), payment_txid)
assert_equal(hashtx.receive().hex(), disconnect_cb)

# Generate 2 blocks in nodes[1] to a different address to ensure split
connect_blocks = self.generatetoaddress(self.nodes[1], 2, ADDRESS_BCRT1_P2SH_OP_TRUE)
connect_blocks = self.generatetoaddress(self.nodes[1], 2, ADDRESS_BCRT1_P2SH_OP_TRUE, sync_fun=self.no_op)

# nodes[0] will reorg chain after connecting back nodes[1]
self.connect_nodes(0, 1)
Expand Down Expand Up @@ -312,13 +311,13 @@ def test_sequence(self):
seq_num = 1

# Generate 1 block in nodes[0] and receive all notifications
dc_block = self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_UNSPENDABLE)[0]
dc_block = self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_UNSPENDABLE, sync_fun=self.no_op)[0]

# Note: We are not notified of any block transactions, coinbase or mined
assert_equal((self.nodes[0].getbestblockhash(), "C", None), seq.receive_sequence())

# Generate 2 blocks in nodes[1] to a different address to ensure a chain split
self.generatetoaddress(self.nodes[1], 2, ADDRESS_BCRT1_P2SH_OP_TRUE)
self.generatetoaddress(self.nodes[1], 2, ADDRESS_BCRT1_P2SH_OP_TRUE, sync_fun=self.no_op)

# nodes[0] will reorg chain after connecting back nodes[1]
self.connect_nodes(0, 1)
Expand Down Expand Up @@ -458,7 +457,7 @@ def test_mempool_sync(self):
# 1) Consume backlog until we get a mempool sequence number
(hash_str, label, zmq_mem_seq) = seq.receive_sequence()
while zmq_mem_seq is None:
(hash_str, label, zmq_mem_seq) = seq.receive_sequence()
(hash_str, label, zmq_mem_seq) = seq.receive_sequence()

assert label == "A" or label == "R"
assert hash_str is not None
Expand Down Expand Up @@ -548,7 +547,7 @@ def test_multiple_interfaces(self):
], sync_blocks=False)

# Generate 1 block in nodes[0] and receive all notifications
self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_UNSPENDABLE)
self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_UNSPENDABLE, sync_fun=self.no_op)

# Should receive the same block hash on both subscribers
assert_equal(self.nodes[0].getbestblockhash(), subscribers[0].receive().hex())
Expand Down
4 changes: 2 additions & 2 deletions test/functional/mempool_compatibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ def run_test(self):

old_node, new_node = self.nodes
new_wallet = MiniWallet(new_node)
self.generate(new_wallet, 1)
self.generate(new_node, 100)
self.generate(new_wallet, 1, sync_fun=self.no_op)
self.generate(new_node, 100, sync_fun=self.no_op)
# Sync the nodes to ensure old_node has the block that contains the coinbase that new_wallet will spend.
# Otherwise, because coinbases are only valid in a block and not as loose txns, if the nodes aren't synced
# unbroadcasted_tx won't pass old_node's `MemPoolAccept::PreChecks`.
Expand Down
2 changes: 1 addition & 1 deletion test/functional/mempool_persist.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ def test_persist_unbroadcast(self):
self.start_node(0)

# clear out mempool
self.generate(node0, 1)
self.generate(node0, 1, sync_fun=self.no_op)

# ensure node0 doesn't have any connections
# make a transaction that will remain in the unbroadcast set
Expand Down
3 changes: 1 addition & 2 deletions test/functional/mempool_reorg.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,8 @@ def run_test(self):
spend_3_1_id = self.nodes[0].sendrawtransaction(spend_3_1['hex'])
self.log.info("Generate a block")
last_block = self.generate(self.nodes[0], 1)
# Sync blocks, so that peer 1 gets the block before timelock_tx
# generate() implicitly syncs blocks, so that peer 1 gets the block before timelock_tx
# Otherwise, peer 1 would put the timelock_tx in m_recent_rejects
self.sync_all()

self.log.info("The time-locked transaction can now be spent")
timelock_tx_id = self.nodes[0].sendrawtransaction(timelock_tx)
Expand Down
3 changes: 2 additions & 1 deletion test/functional/mempool_unbroadcast.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ def test_txn_removal(self):
# a block
removal_reason = "Removed {} from set of unbroadcast txns before confirmation that txn was sent out".format(txhsh)
with node.assert_debug_log([removal_reason]):
self.generate(node, 1)
self.generate(node, 1, sync_fun=self.no_op)


if __name__ == "__main__":
MempoolUnbroadcastTest().main()
2 changes: 1 addition & 1 deletion test/functional/mining_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def mine_chain(self):
self.log.info('Create some old blocks')
for t in range(TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK + 200 * 156, 156):
self.bump_mocktime(156)
self.generate(self.nodes[0], 1)
self.generate(self.nodes[0], 1, sync_fun=self.no_op)
mining_info = self.nodes[0].getmininginfo()
assert_equal(mining_info['blocks'], 200)
assert_equal(mining_info['currentblocktx'], 0)
Expand Down
2 changes: 1 addition & 1 deletion test/functional/mining_prioritisetransaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def run_test(self):
# the other high fee transactions. Keep mining until our mempool has
# decreased by all the high fee size that we calculated above.
while (self.nodes[0].getmempoolinfo()['bytes'] > sizes[0] + sizes[1]):
self.generate(self.nodes[0], 1)
self.generate(self.nodes[0], 1, sync_fun=self.no_op)

# High fee transaction should not have been mined, but other high fee rate
# transactions should have been.
Expand Down
4 changes: 2 additions & 2 deletions test/functional/p2p_blockfilters.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ def run_test(self):
# Stale blocks by disconnecting nodes 0 & 1, mining, then reconnecting
self.disconnect_nodes(0, 1)

stale_block_hash = self.generate(self.nodes[0], 1)[0]
stale_block_hash = self.generate(self.nodes[0], 1, sync_fun=self.no_op)[0]
self.nodes[0].syncwithvalidationinterfacequeue()
assert_equal(self.nodes[0].getblockcount(), 1000)

self.generate(self.nodes[1], 1001)
self.generate(self.nodes[1], 1001, sync_fun=self.no_op)
assert_equal(self.nodes[1].getblockcount(), 2000)

# Check that nodes have signalled NODE_COMPACT_FILTERS correctly.
Expand Down
2 changes: 1 addition & 1 deletion test/functional/p2p_compactblocks_blocksonly.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def setup_network(self):
self.sync_all()

def build_block_on_tip(self):
blockhash = self.generate(self.nodes[2], 1)[0]
blockhash = self.generate(self.nodes[2], 1, sync_fun=self.no_op)[0]
block_hex = self.nodes[2].getblock(blockhash=blockhash, verbosity=0)
block = from_hex(CBlock(), block_hex)
block.rehash()
Expand Down
4 changes: 2 additions & 2 deletions test/functional/p2p_node_network_limited.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def run_test(self):

self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.")
self.connect_nodes(0, 1)
blocks = self.generatetoaddress(self.nodes[1], 292, self.nodes[1].get_deterministic_priv_key().address)
blocks = self.generate(self.nodes[1], 292, sync_fun=self.no_op)
self.sync_blocks([self.nodes[0], self.nodes[1]])

self.log.info("Make sure we can max retrieve block at tip-288.")
Expand Down Expand Up @@ -89,7 +89,7 @@ def run_test(self):
self.disconnect_all()

# mine 10 blocks on node 0 (pruned node)
self.generatetoaddress(self.nodes[0], 10, self.nodes[0].get_deterministic_priv_key().address)
self.generate(self.nodes[0], 10, sync_fun=self.no_op)

# connect node1 (non pruned) with node0 (pruned) and check if the can sync
self.connect_nodes(0, 1)
Expand Down
2 changes: 1 addition & 1 deletion test/functional/p2p_unrequested_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def run_test(self):
min_work_node = self.nodes[1].add_p2p_connection(P2PInterface())

# 1. Have nodes mine a block (leave IBD)
[self.generatetoaddress(n, 1, n.get_deterministic_priv_key().address) for n in self.nodes]
[self.generate(n, 1, sync_fun=self.no_op) for n in self.nodes]
tips = [int("0x" + n.getbestblockhash(), 0) for n in self.nodes]

# 2. Send one block that builds on each tip.
Expand Down
2 changes: 1 addition & 1 deletion test/functional/rpc_blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ def _test_stopatheight(self):
self.log.debug('Node should not stop at this height')
assert_raises(subprocess.TimeoutExpired, lambda: self.nodes[0].process.wait(timeout=3))
try:
self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_P2SH_OP_TRUE)
self.generatetoaddress(self.nodes[0], 1, ADDRESS_BCRT1_P2SH_OP_TRUE, sync_fun=self.no_op)
except (ConnectionError, http.client.BadStatusLine):
pass # The node already shut down before response
self.log.debug('Node should stop at this height...')
Expand Down
4 changes: 2 additions & 2 deletions test/functional/rpc_getblockfilter.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ def run_test(self):
# Create two chains by disconnecting nodes 0 & 1, mining, then reconnecting
self.disconnect_nodes(0, 1)

self.generate(self.nodes[0], 3)
self.generate(self.nodes[1], 4)
self.generate(self.nodes[0], 3, sync_fun=self.no_op)
self.generate(self.nodes[1], 4, sync_fun=self.no_op)

assert_equal(self.nodes[0].getblockcount(), 3)
chain0_hashes = [self.nodes[0].getblockhash(block_height) for block_height in range(4)]
Expand Down
Loading

0 comments on commit c586562

Please sign in to comment.