Skip to content

Commit 8f470ec

Browse files
author
MarcoFalke
committed
Merge #15419: qa: Always refresh cache to be out of ibd
fa2cdc9 test: Simplify create_cache (MarcoFalke) fa25210 qa: Fix wallet_txn_doublespend issue (MarcoFalke) 1111aec qa: Always refresh stale cache to be out of ibd (MarcoFalke) fab0d85 qa: Remove mocktime unless required (MarcoFalke) Pull request description: When starting a test, we are always in IBD because the timestamps on cached blocks are in the past. Usually, we solve that by generating a block at the beginning of the test. That is clumsy and might even lead to other problems such as #15360 and bitcoin/bitcoin#14446 (comment) So fix that by getting rid of mocktime and always refreshing the last block of the cache when starting the test framework. Should fix #14446 Tree-SHA512: 6af09800f9c86131349a103af617a54551f5f3f3260d38e14e3f30fdd3d91a0feb0100c56cbb12eae4aeac5571ae4b530b16345cbb831d2670237b53351a22c1
2 parents b4fc525 + fa2cdc9 commit 8f470ec

File tree

7 files changed

+59
-34
lines changed

7 files changed

+59
-34
lines changed

test/functional/feature_proxy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
class ProxyTest(BitcoinTestFramework):
4545
def set_test_params(self):
4646
self.num_nodes = 4
47+
self.setup_clean_chain = True
4748

4849
def setup_nodes(self):
4950
self.have_ipv6 = test_ipv6_local()
@@ -198,4 +199,3 @@ def networks_dict(d):
198199

199200
if __name__ == '__main__':
200201
ProxyTest().main()
201-

test/functional/mempool_accept.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
assert_raises_rpc_error,
3030
bytes_to_hex_str,
3131
hex_str_to_bytes,
32-
wait_until,
3332
)
3433

3534

@@ -38,7 +37,6 @@ def set_test_params(self):
3837
self.num_nodes = 1
3938
self.extra_args = [[
4039
'-txindex',
41-
'-reindex', # Need reindex for txindex
4240
'-acceptnonstdtxn=0', # Try to mimic main-net
4341
]] * self.num_nodes
4442

@@ -56,7 +54,7 @@ def run_test(self):
5654

5755
self.log.info('Start with empty mempool, and 200 blocks')
5856
self.mempool_size = 0
59-
wait_until(lambda: node.getblockcount() == 200)
57+
assert_equal(node.getblockcount(), 200)
6058
assert_equal(node.getmempoolinfo()['size'], self.mempool_size)
6159
coins = node.listunspent()
6260

test/functional/rpc_blockchain.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
from test_framework.blocktools import (
3636
create_block,
3737
create_coinbase,
38+
TIME_GENESIS_BLOCK,
3839
)
3940
from test_framework.messages import (
4041
msg_block,
@@ -46,9 +47,11 @@
4647

4748
class BlockchainTest(BitcoinTestFramework):
4849
def set_test_params(self):
50+
self.setup_clean_chain = True
4951
self.num_nodes = 1
5052

5153
def run_test(self):
54+
self.mine_chain()
5255
self.restart_node(0, extra_args=['-stopatheight=207', '-prune=1']) # Set extra args with pruning after rescan is complete
5356

5457
self._test_getblockchaininfo()
@@ -61,6 +64,15 @@ def run_test(self):
6164
self._test_waitforblockheight()
6265
assert self.nodes[0].verifychain(4, 0)
6366

67+
def mine_chain(self):
68+
self.log.info('Create some old blocks')
69+
address = self.nodes[0].get_deterministic_priv_key().address
70+
for t in range(TIME_GENESIS_BLOCK, TIME_GENESIS_BLOCK + 200 * 600, 600):
71+
# ten-minute steps from genesis block time
72+
self.nodes[0].setmocktime(t)
73+
self.nodes[0].generatetoaddress(1, address)
74+
assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200)
75+
6476
def _test_getblockchaininfo(self):
6577
self.log.info("Test getblockchaininfo")
6678

test/functional/test_framework/test_framework.py

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@
2929
get_datadir_path,
3030
initialize_datadir,
3131
p2p_port,
32-
set_node_times,
3332
sync_blocks,
3433
sync_mempools,
3534
)
3635

36+
3737
class TestStatus(Enum):
3838
PASSED = 1
3939
FAILED = 2
@@ -94,7 +94,6 @@ def __init__(self):
9494
self.setup_clean_chain = False
9595
self.nodes = []
9696
self.network_thread = None
97-
self.mocktime = 0
9897
self.rpc_timeout = 60 # Wait for up to 60 seconds for the RPC server to respond
9998
self.supports_cli = False
10099
self.bind_to_localhost_only = True
@@ -275,6 +274,19 @@ def setup_nodes(self):
275274
self.add_nodes(self.num_nodes, extra_args)
276275
self.start_nodes()
277276
self.import_deterministic_coinbase_privkeys()
277+
if not self.setup_clean_chain:
278+
for n in self.nodes:
279+
assert_equal(n.getblockchaininfo()["blocks"], 199)
280+
# To ensure that all nodes are out of IBD, the most recent block
281+
# must have a timestamp not too old (see IsInitialBlockDownload()).
282+
self.log.debug('Generate a block with current time')
283+
block_hash = self.nodes[0].generate(1)[0]
284+
block = self.nodes[0].getblock(blockhash=block_hash, verbosity=0)
285+
for n in self.nodes:
286+
n.submitblock(block)
287+
chain_info = n.getblockchaininfo()
288+
assert_equal(chain_info["blocks"], 200)
289+
assert_equal(chain_info["initialblockdownload"], False)
278290

279291
def import_deterministic_coinbase_privkeys(self):
280292
for n in self.nodes:
@@ -316,7 +328,6 @@ def add_nodes(self, num_nodes, extra_args=None, *, rpchost=None, binary=None):
316328
timewait=self.rpc_timeout,
317329
bitcoind=binary[i],
318330
bitcoin_cli=self.options.bitcoincli,
319-
mocktime=self.mocktime,
320331
coverage_dir=self.options.coveragedir,
321332
cwd=self.options.tmpdir,
322333
extra_conf=extra_confs[i],
@@ -435,7 +446,7 @@ def _start_logging(self):
435446
def _initialize_chain(self):
436447
"""Initialize a pre-mined blockchain for use by the test.
437448
438-
Create a cache of a 200-block-long chain (with wallet) for MAX_NODES
449+
Create a cache of a 199-block-long chain (with wallet) for MAX_NODES
439450
Afterward, create num_nodes copies from the cache."""
440451

441452
assert self.num_nodes <= MAX_NODES
@@ -468,7 +479,6 @@ def _initialize_chain(self):
468479
timewait=self.rpc_timeout,
469480
bitcoind=self.options.bitcoind,
470481
bitcoin_cli=self.options.bitcoincli,
471-
mocktime=self.mocktime,
472482
coverage_dir=None,
473483
cwd=self.options.tmpdir,
474484
))
@@ -479,32 +489,22 @@ def _initialize_chain(self):
479489
for node in self.nodes:
480490
node.wait_for_rpc_connection()
481491

482-
# For backward compatibility of the python scripts with previous
483-
# versions of the cache, set mocktime to Jan 1,
484-
# 2014 + (201 * 10 * 60)"""
485-
self.mocktime = 1388534400 + (201 * 10 * 60)
486-
487-
# Create a 200-block-long chain; each of the 4 first nodes
492+
# Create a 199-block-long chain; each of the 4 first nodes
488493
# gets 25 mature blocks and 25 immature.
489-
# Note: To preserve compatibility with older versions of
490-
# initialize_chain, only 4 nodes will generate coins.
491-
#
492-
# blocks are created with timestamps 10 minutes apart
493-
# starting from 2010 minutes in the past
494-
block_time = self.mocktime - (201 * 10 * 60)
495-
for i in range(2):
496-
for peer in range(4):
497-
for j in range(25):
498-
set_node_times(self.nodes, block_time)
499-
self.nodes[peer].generatetoaddress(1, self.nodes[peer].get_deterministic_priv_key().address)
500-
block_time += 10 * 60
501-
# Must sync before next peer starts generating blocks
502-
sync_blocks(self.nodes)
494+
# The 4th node gets only 24 immature blocks so that the very last
495+
# block in the cache does not age too much (have an old tip age).
496+
# This is needed so that we are out of IBD when the test starts,
497+
# see the tip age check in IsInitialBlockDownload().
498+
for i in range(8):
499+
self.nodes[0].generatetoaddress(25 if i != 7 else 24, self.nodes[i % 4].get_deterministic_priv_key().address)
500+
sync_blocks(self.nodes)
501+
502+
for n in self.nodes:
503+
assert_equal(n.getblockchaininfo()["blocks"], 199)
503504

504505
# Shut them down, and clean up cache directories:
505506
self.stop_nodes()
506507
self.nodes = []
507-
self.mocktime = 0
508508

509509
def cache_path(n, *paths):
510510
return os.path.join(get_datadir_path(self.options.cachedir, n), "regtest", *paths)

test/functional/test_framework/test_node.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class TestNode():
6161
To make things easier for the test writer, any unrecognised messages will
6262
be dispatched to the RPC connection."""
6363

64-
def __init__(self, i, datadir, *, rpchost, timewait, bitcoind, bitcoin_cli, mocktime, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False):
64+
def __init__(self, i, datadir, *, rpchost, timewait, bitcoind, bitcoin_cli, coverage_dir, cwd, extra_conf=None, extra_args=None, use_cli=False, start_perf=False):
6565
"""
6666
Kwargs:
6767
start_perf (bool): If True, begin profiling the node with `perf` as soon as
@@ -90,8 +90,7 @@ def __init__(self, i, datadir, *, rpchost, timewait, bitcoind, bitcoin_cli, mock
9090
"-debug",
9191
"-debugexclude=libevent",
9292
"-debugexclude=leveldb",
93-
"-mocktime=" + str(mocktime),
94-
"-uacomment=testnode%d" % i
93+
"-uacomment=testnode%d" % i,
9594
]
9695

9796
self.cli = TestNodeCLI(bitcoin_cli, self.datadir)

test/functional/wallet_create_tx.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,25 @@
77
from test_framework.util import (
88
assert_equal,
99
)
10+
from test_framework.blocktools import (
11+
TIME_GENESIS_BLOCK,
12+
)
1013

1114

1215
class CreateTxWalletTest(BitcoinTestFramework):
1316
def set_test_params(self):
14-
self.setup_clean_chain = False
17+
self.setup_clean_chain = True
1518
self.num_nodes = 1
1619

1720
def skip_test_if_missing_module(self):
1821
self.skip_if_no_wallet()
1922

2023
def run_test(self):
24+
self.log.info('Create some old blocks')
25+
self.nodes[0].setmocktime(TIME_GENESIS_BLOCK)
26+
self.nodes[0].generate(200)
27+
self.nodes[0].setmocktime(0)
28+
2129
self.log.info('Check that we have some (old) blocks and that anti-fee-sniping is disabled')
2230
assert_equal(self.nodes[0].getblockchaininfo()['blocks'], 200)
2331
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)

test/functional/wallet_txn_doublespend.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ def setup_network(self):
3434
def run_test(self):
3535
# All nodes should start with 1,250 BTC:
3636
starting_balance = 1250
37+
38+
# All nodes should be out of IBD.
39+
# If the nodes are not all out of IBD, that can interfere with
40+
# blockchain sync later in the test when nodes are connected, due to
41+
# timing issues.
42+
for n in self.nodes:
43+
assert n.getblockchaininfo()["initialblockdownload"] == False
44+
3745
for i in range(4):
3846
assert_equal(self.nodes[i].getbalance(), starting_balance)
3947
self.nodes[i].getnewaddress("") # bug workaround, coins generated assigned to first getnewaddress!

0 commit comments

Comments
 (0)