Skip to content

Commit fa47330

Browse files
author
MarcoFalke
committed
test: Speed up cache creation
1 parent fa6ad7a commit fa47330

File tree

2 files changed

+37
-51
lines changed

2 files changed

+37
-51
lines changed

test/functional/test_framework/test_framework.py

Lines changed: 29 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
disconnect_nodes,
3030
get_datadir_path,
3131
initialize_datadir,
32-
p2p_port,
3332
sync_blocks,
3433
sync_mempools,
3534
)
@@ -468,48 +467,34 @@ def _start_logging(self):
468467
def _initialize_chain(self):
469468
"""Initialize a pre-mined blockchain for use by the test.
470469
471-
Create a cache of a 199-block-long chain (with wallet) for MAX_NODES
470+
Create a cache of a 199-block-long chain
472471
Afterward, create num_nodes copies from the cache."""
473472

473+
CACHE_NODE_ID = 0 # Use node 0 to create the cache for all other nodes
474+
cache_node_dir = get_datadir_path(self.options.cachedir, CACHE_NODE_ID)
474475
assert self.num_nodes <= MAX_NODES
475-
create_cache = False
476-
for i in range(MAX_NODES):
477-
if not os.path.isdir(get_datadir_path(self.options.cachedir, i)):
478-
create_cache = True
479-
break
480-
481-
if create_cache:
482-
self.log.debug("Creating data directories from cached datadir")
483-
484-
# find and delete old cache directories if any exist
485-
for i in range(MAX_NODES):
486-
if os.path.isdir(get_datadir_path(self.options.cachedir, i)):
487-
shutil.rmtree(get_datadir_path(self.options.cachedir, i))
488-
489-
# Create cache directories, run bitcoinds:
490-
for i in range(MAX_NODES):
491-
datadir = initialize_datadir(self.options.cachedir, i)
492-
args = [self.options.bitcoind, "-datadir=" + datadir, '-disablewallet']
493-
if i > 0:
494-
args.append("-connect=127.0.0.1:" + str(p2p_port(0)))
495-
self.nodes.append(TestNode(
496-
i,
497-
get_datadir_path(self.options.cachedir, i),
476+
477+
if not os.path.isdir(cache_node_dir):
478+
self.log.debug("Creating cache directory {}".format(cache_node_dir))
479+
480+
initialize_datadir(self.options.cachedir, CACHE_NODE_ID)
481+
self.nodes.append(
482+
TestNode(
483+
CACHE_NODE_ID,
484+
cache_node_dir,
498485
extra_conf=["bind=127.0.0.1"],
499-
extra_args=[],
486+
extra_args=['-disablewallet'],
500487
rpchost=None,
501488
timewait=self.rpc_timeout,
502489
bitcoind=self.options.bitcoind,
503490
bitcoin_cli=self.options.bitcoincli,
504491
coverage_dir=None,
505492
cwd=self.options.tmpdir,
506493
))
507-
self.nodes[i].args = args
508-
self.start_node(i)
494+
self.start_node(CACHE_NODE_ID)
509495

510496
# Wait for RPC connections to be ready
511-
for node in self.nodes:
512-
node.wait_for_rpc_connection()
497+
self.nodes[CACHE_NODE_ID].wait_for_rpc_connection()
513498

514499
# Create a 199-block-long chain; each of the 4 first nodes
515500
# gets 25 mature blocks and 25 immature.
@@ -518,29 +503,29 @@ def _initialize_chain(self):
518503
# This is needed so that we are out of IBD when the test starts,
519504
# see the tip age check in IsInitialBlockDownload().
520505
for i in range(8):
521-
self.nodes[0].generatetoaddress(25 if i != 7 else 24, self.nodes[i % 4].get_deterministic_priv_key().address)
522-
self.sync_blocks()
506+
self.nodes[CACHE_NODE_ID].generatetoaddress(
507+
nblocks=25 if i != 7 else 24,
508+
address=TestNode.PRIV_KEYS[i % 4].address,
509+
)
523510

524-
for n in self.nodes:
525-
assert_equal(n.getblockchaininfo()["blocks"], 199)
511+
assert_equal(self.nodes[CACHE_NODE_ID].getblockchaininfo()["blocks"], 199)
526512

527-
# Shut them down, and clean up cache directories:
513+
# Shut it down, and clean up cache directories:
528514
self.stop_nodes()
529515
self.nodes = []
530516

531-
def cache_path(n, *paths):
532-
return os.path.join(get_datadir_path(self.options.cachedir, n), "regtest", *paths)
517+
def cache_path(*paths):
518+
return os.path.join(cache_node_dir, "regtest", *paths)
533519

534-
for i in range(MAX_NODES):
535-
os.rmdir(cache_path(i, 'wallets')) # Remove empty wallets dir
536-
for entry in os.listdir(cache_path(i)):
537-
if entry not in ['chainstate', 'blocks']:
538-
os.remove(cache_path(i, entry))
520+
os.rmdir(cache_path('wallets')) # Remove empty wallets dir
521+
for entry in os.listdir(cache_path()):
522+
if entry not in ['chainstate', 'blocks']: # Only keep chainstate and blocks folder
523+
os.remove(cache_path(entry))
539524

540525
for i in range(self.num_nodes):
541-
from_dir = get_datadir_path(self.options.cachedir, i)
526+
self.log.debug("Copy cache directory {} to node {}".format(cache_node_dir, i))
542527
to_dir = get_datadir_path(self.options.tmpdir, i)
543-
shutil.copytree(from_dir, to_dir)
528+
shutil.copytree(cache_node_dir, to_dir)
544529
initialize_datadir(self.options.tmpdir, i) # Overwrite port/rpcport in bitcoin.conf
545530

546531
def _initialize_chain_clean(self):

test/functional/test_framework/test_node.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,8 @@ def __init__(self, i, datadir, *, rpchost, timewait, bitcoind, bitcoin_cli, cove
111111

112112
self.p2ps = []
113113

114-
def get_deterministic_priv_key(self):
115-
"""Return a deterministic priv key in base58, that only depends on the node's index"""
116-
AddressKeyPair = collections.namedtuple('AddressKeyPair', ['address', 'key'])
117-
PRIV_KEYS = [
114+
AddressKeyPair = collections.namedtuple('AddressKeyPair', ['address', 'key'])
115+
PRIV_KEYS = [
118116
# address , privkey
119117
AddressKeyPair('mjTkW3DjgyZck4KbiRusZsqTgaYTxdSz6z', 'cVpF924EspNh8KjYsfhgY96mmxvT6DgdWiTYMtMjuM74hJaU5psW'),
120118
AddressKeyPair('msX6jQXvxiNhx3Q62PKeLPrhrqZQdSimTg', 'cUxsWyKyZ9MAQTaAhUQWJmBbSvHMwSmuv59KgxQV7oZQU3PXN3KE'),
@@ -128,9 +126,12 @@ def get_deterministic_priv_key(self):
128126
AddressKeyPair('mq4fBNdckGtvY2mijd9am7DRsbRB4KjUkf', 'cN55daf1HotwBAgAKWVgDcoppmUNDtQSfb7XLutTLeAgVc3u8hik'),
129127
AddressKeyPair('mpFAHDjX7KregM3rVotdXzQmkbwtbQEnZ6', 'cT7qK7g1wkYEMvKowd2ZrX1E5f6JQ7TM246UfqbCiyF7kZhorpX3'),
130128
AddressKeyPair('mzRe8QZMfGi58KyWCse2exxEFry2sfF2Y7', 'cPiRWE8KMjTRxH1MWkPerhfoHFn5iHPWVK5aPqjW8NxmdwenFinJ'),
131-
]
132-
assert len(PRIV_KEYS) == MAX_NODES
133-
return PRIV_KEYS[self.index]
129+
]
130+
131+
def get_deterministic_priv_key(self):
132+
"""Return a deterministic priv key in base58, that only depends on the node's index"""
133+
assert len(self.PRIV_KEYS) == MAX_NODES
134+
return self.PRIV_KEYS[self.index]
134135

135136
def get_mem_rss_kilobytes(self):
136137
"""Get the memory usage (RSS) per `ps`.

0 commit comments

Comments
 (0)