Changeset View
Changeset View
Standalone View
Standalone View
test/functional/feature_pruning.py
Show All 15 Lines | |||||
from test_framework.script import CScript, OP_RETURN, OP_NOP | from test_framework.script import CScript, OP_RETURN, OP_NOP | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import ( | from test_framework.util import ( | ||||
assert_equal, | assert_equal, | ||||
assert_greater_than, | assert_greater_than, | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
connect_nodes, | connect_nodes, | ||||
disconnect_nodes, | disconnect_nodes, | ||||
sync_blocks, | |||||
wait_until, | wait_until, | ||||
) | ) | ||||
MIN_BLOCKS_TO_KEEP = 288 | MIN_BLOCKS_TO_KEEP = 288 | ||||
# Rescans start at the earliest block up to 2 hours before a key timestamp, so | # Rescans start at the earliest block up to 2 hours before a key timestamp, so | ||||
# the manual prune RPC avoids pruning blocks in the same window to be | # the manual prune RPC avoids pruning blocks in the same window to be | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | def setup_network(self): | ||||
self.prunedir = os.path.join( | self.prunedir = os.path.join( | ||||
self.nodes[2].datadir, 'regtest', 'blocks', '') | self.nodes[2].datadir, 'regtest', 'blocks', '') | ||||
connect_nodes(self.nodes[0], self.nodes[1]) | connect_nodes(self.nodes[0], self.nodes[1]) | ||||
connect_nodes(self.nodes[1], self.nodes[2]) | connect_nodes(self.nodes[1], self.nodes[2]) | ||||
connect_nodes(self.nodes[0], self.nodes[2]) | connect_nodes(self.nodes[0], self.nodes[2]) | ||||
connect_nodes(self.nodes[0], self.nodes[3]) | connect_nodes(self.nodes[0], self.nodes[3]) | ||||
connect_nodes(self.nodes[0], self.nodes[4]) | connect_nodes(self.nodes[0], self.nodes[4]) | ||||
sync_blocks(self.nodes[0:5]) | self.sync_blocks(self.nodes[0:5]) | ||||
def setup_nodes(self): | def setup_nodes(self): | ||||
self.add_nodes(self.num_nodes, self.extra_args) | self.add_nodes(self.num_nodes, self.extra_args) | ||||
self.start_nodes() | self.start_nodes() | ||||
for n in self.nodes: | for n in self.nodes: | ||||
n.importprivkey( | n.importprivkey( | ||||
privkey=n.get_deterministic_priv_key().key, | privkey=n.get_deterministic_priv_key().key, | ||||
label='coinbase', | label='coinbase', | ||||
rescan=False) | rescan=False) | ||||
def create_big_chain(self): | def create_big_chain(self): | ||||
# Start by creating some coinbases we can spend later | # Start by creating some coinbases we can spend later | ||||
self.nodes[1].generate(200) | self.nodes[1].generate(200) | ||||
sync_blocks(self.nodes[0:2]) | self.sync_blocks(self.nodes[0:2]) | ||||
self.nodes[0].generate(150) | self.nodes[0].generate(150) | ||||
# Then mine enough full blocks to create more than 550MiB of data | # Then mine enough full blocks to create more than 550MiB of data | ||||
mine_large_blocks(self.nodes[0], 645) | mine_large_blocks(self.nodes[0], 645) | ||||
sync_blocks(self.nodes[0:5]) | self.sync_blocks(self.nodes[0:5]) | ||||
def test_height_min(self): | def test_height_min(self): | ||||
assert os.path.isfile(os.path.join( | assert os.path.isfile(os.path.join( | ||||
self.prunedir, "blk00000.dat")), "blk00000.dat is missing, pruning too early" | self.prunedir, "blk00000.dat")), "blk00000.dat is missing, pruning too early" | ||||
self.log.info("Success") | self.log.info("Success") | ||||
self.log.info("Though we're already using more than 550MiB, current usage: {}".format( | self.log.info("Though we're already using more than 550MiB, current usage: {}".format( | ||||
calc_usage(self.prunedir))) | calc_usage(self.prunedir))) | ||||
self.log.info( | self.log.info( | ||||
Show All 27 Lines | def create_chain_with_staleblocks(self): | ||||
# Reorg back with 25 block chain from node 0 | # Reorg back with 25 block chain from node 0 | ||||
mine_large_blocks(self.nodes[0], 25) | mine_large_blocks(self.nodes[0], 25) | ||||
# Create connections in the order so both nodes can see the reorg | # Create connections in the order so both nodes can see the reorg | ||||
# at the same time | # at the same time | ||||
connect_nodes(self.nodes[0], self.nodes[1]) | connect_nodes(self.nodes[0], self.nodes[1]) | ||||
connect_nodes(self.nodes[0], self.nodes[2]) | connect_nodes(self.nodes[0], self.nodes[2]) | ||||
sync_blocks(self.nodes[0:3]) | self.sync_blocks(self.nodes[0:3]) | ||||
self.log.info("Usage can be over target because of high stale rate: {}".format( | self.log.info("Usage can be over target because of high stale rate: {}".format( | ||||
calc_usage(self.prunedir))) | calc_usage(self.prunedir))) | ||||
def reorg_test(self): | def reorg_test(self): | ||||
# Node 1 will mine a 300 block chain starting 287 blocks back from Node | # Node 1 will mine a 300 block chain starting 287 blocks back from Node | ||||
# 0 and Node 2's tip. This will cause Node 2 to do a reorg requiring | # 0 and Node 2's tip. This will cause Node 2 to do a reorg requiring | ||||
# 288 blocks of undo data to the reorg_test chain. | # 288 blocks of undo data to the reorg_test chain. | ||||
Show All 25 Lines | def reorg_test(self): | ||||
disconnect_nodes(self.nodes[1], self.nodes[2]) | disconnect_nodes(self.nodes[1], self.nodes[2]) | ||||
self.log.info("Generating new longer chain of 300 more blocks") | self.log.info("Generating new longer chain of 300 more blocks") | ||||
self.nodes[1].generate(300) | self.nodes[1].generate(300) | ||||
self.log.info("Reconnect nodes") | self.log.info("Reconnect nodes") | ||||
connect_nodes(self.nodes[0], self.nodes[1]) | connect_nodes(self.nodes[0], self.nodes[1]) | ||||
connect_nodes(self.nodes[1], self.nodes[2]) | connect_nodes(self.nodes[1], self.nodes[2]) | ||||
sync_blocks(self.nodes[0:3], timeout=120) | self.sync_blocks(self.nodes[0:3], timeout=120) | ||||
self.log.info("Verify height on node 2: {}".format( | self.log.info("Verify height on node 2: {}".format( | ||||
self.nodes[2].getblockcount())) | self.nodes[2].getblockcount())) | ||||
self.log.info("Usage possibly still high because of stale blocks in block files: {}".format( | self.log.info("Usage possibly still high because of stale blocks in block files: {}".format( | ||||
calc_usage(self.prunedir))) | calc_usage(self.prunedir))) | ||||
self.log.info( | self.log.info( | ||||
"Mine 220 more large blocks so we have requisite history") | "Mine 220 more large blocks so we have requisite history") | ||||
mine_large_blocks(self.nodes[0], 220) | mine_large_blocks(self.nodes[0], 220) | ||||
sync_blocks(self.nodes[0:3], timeout=120) | self.sync_blocks(self.nodes[0:3], timeout=120) | ||||
usage = calc_usage(self.prunedir) | usage = calc_usage(self.prunedir) | ||||
self.log.info("Usage should be below target: {}".format(usage)) | self.log.info("Usage should be below target: {}".format(usage)) | ||||
assert_greater_than(550, usage) | assert_greater_than(550, usage) | ||||
def reorg_back(self): | def reorg_back(self): | ||||
# Verify that a block on the old main chain fork has been pruned away | # Verify that a block on the old main chain fork has been pruned away | ||||
assert_raises_rpc_error( | assert_raises_rpc_error( | ||||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | def wallet_test(self): | ||||
2, extra_args=["-prune=550", "-noparkdeepreorg", "-maxreorgdepth=-1"]) | 2, extra_args=["-prune=550", "-noparkdeepreorg", "-maxreorgdepth=-1"]) | ||||
self.log.info("Success") | self.log.info("Success") | ||||
# check that wallet loads successfully when restarting a pruned node after IBD. | # check that wallet loads successfully when restarting a pruned node after IBD. | ||||
# this was reported to fail in #7494. | # this was reported to fail in #7494. | ||||
self.log.info("Syncing node 5 to test wallet") | self.log.info("Syncing node 5 to test wallet") | ||||
connect_nodes(self.nodes[0], self.nodes[5]) | connect_nodes(self.nodes[0], self.nodes[5]) | ||||
nds = [self.nodes[0], self.nodes[5]] | nds = [self.nodes[0], self.nodes[5]] | ||||
sync_blocks(nds, wait=5, timeout=300) | self.sync_blocks(nds, wait=5, timeout=300) | ||||
# Stop and start to trigger rescan | # Stop and start to trigger rescan | ||||
self.stop_node(5) | self.stop_node(5) | ||||
self.start_node( | self.start_node( | ||||
5, extra_args=["-prune=550", "-noparkdeepreorg", "-maxreorgdepth=-1"]) | 5, extra_args=["-prune=550", "-noparkdeepreorg", "-maxreorgdepth=-1"]) | ||||
self.log.info("Success") | self.log.info("Success") | ||||
def run_test(self): | def run_test(self): | ||||
self.log.info("Warning! This test requires 4GB of disk space") | self.log.info("Warning! This test requires 4GB of disk space") | ||||
▲ Show 20 Lines • Show All 115 Lines • Show Last 20 Lines |