Changeset View
Changeset View
Standalone View
Standalone View
test/functional/feature_pruning.py
Show First 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | for _ in range(n): | ||||
node.submitblock(ToHex(block)) | node.submitblock(ToHex(block)) | ||||
previousblockhash = block.sha256 | previousblockhash = block.sha256 | ||||
height += 1 | height += 1 | ||||
mine_large_blocks.nTime += 1 | mine_large_blocks.nTime += 1 | ||||
def calc_usage(blockdir): | def calc_usage(blockdir): | ||||
return sum(os.path.getsize(blockdir + f) for f in os.listdir(blockdir) if os.path.isfile(os.path.join(blockdir, f))) / (1024. * 1024.) | return sum(os.path.getsize(blockdir + f) for f in os.listdir(blockdir) | ||||
if os.path.isfile(os.path.join(blockdir, f))) / (1024. * 1024.) | |||||
class PruneTest(BitcoinTestFramework): | class PruneTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.num_nodes = 6 | self.num_nodes = 6 | ||||
# Create nodes 0 and 1 to mine. | # Create nodes 0 and 1 to mine. | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | class PruneTest(BitcoinTestFramework): | ||||
def create_chain_with_staleblocks(self): | def create_chain_with_staleblocks(self): | ||||
# Create stale blocks in manageable sized chunks | # Create stale blocks in manageable sized chunks | ||||
self.log.info( | self.log.info( | ||||
"Mine 24 (stale) blocks on Node 1, followed by 25 (main chain) block reorg from Node 0, for 12 rounds") | "Mine 24 (stale) blocks on Node 1, followed by 25 (main chain) block reorg from Node 0, for 12 rounds") | ||||
for j in range(12): | for j in range(12): | ||||
# Disconnect node 0 so it can mine a longer reorg chain without knowing about node 1's soon-to-be-stale chain | # Disconnect node 0 so it can mine a longer reorg chain without knowing about node 1's soon-to-be-stale chain | ||||
# Node 2 stays connected, so it hears about the stale blocks and then reorg's when node0 reconnects | # Node 2 stays connected, so it hears about the stale blocks and | ||||
# then reorg's when node0 reconnects | |||||
disconnect_nodes(self.nodes[0], self.nodes[1]) | disconnect_nodes(self.nodes[0], self.nodes[1]) | ||||
disconnect_nodes(self.nodes[0], self.nodes[2]) | disconnect_nodes(self.nodes[0], self.nodes[2]) | ||||
# Mine 24 blocks in node 1 | # Mine 24 blocks in node 1 | ||||
mine_large_blocks(self.nodes[1], 24) | mine_large_blocks(self.nodes[1], 24) | ||||
# 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) | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | def manual_test(self, node_number, use_timestamp): | ||||
# now re-start in manual pruning mode | # now re-start in manual pruning mode | ||||
self.stop_node(node_number) | self.stop_node(node_number) | ||||
self.start_node(node_number, extra_args=["-prune=1"]) | self.start_node(node_number, extra_args=["-prune=1"]) | ||||
node = self.nodes[node_number] | node = self.nodes[node_number] | ||||
assert_equal(node.getblockcount(), 995) | assert_equal(node.getblockcount(), 995) | ||||
def height(index): | def height(index): | ||||
if use_timestamp: | if use_timestamp: | ||||
return node.getblockheader(node.getblockhash(index))["time"] + TIMESTAMP_WINDOW | return node.getblockheader(node.getblockhash(index))[ | ||||
"time"] + TIMESTAMP_WINDOW | |||||
else: | else: | ||||
return index | return index | ||||
def prune(index, expected_ret=None): | def prune(index, expected_ret=None): | ||||
ret = node.pruneblockchain(height(index)) | ret = node.pruneblockchain(height(index)) | ||||
# Check the return value. When use_timestamp is True, just check | # Check the return value. When use_timestamp is True, just check | ||||
# that the return value is less than or equal to the expected | # that the return value is less than or equal to the expected | ||||
# value, because when more than one block is generated per second, | # value, because when more than one block is generated per second, | ||||
# a timestamp will not be granular enough to uniquely identify an | # a timestamp will not be granular enough to uniquely identify an | ||||
# individual block. | # individual block. | ||||
if expected_ret is None: | if expected_ret is None: | ||||
expected_ret = index | expected_ret = index | ||||
if use_timestamp: | if use_timestamp: | ||||
assert_greater_than(ret, 0) | assert_greater_than(ret, 0) | ||||
assert_greater_than(expected_ret + 1, ret) | assert_greater_than(expected_ret + 1, ret) | ||||
else: | else: | ||||
assert_equal(ret, expected_ret) | assert_equal(ret, expected_ret) | ||||
def has_block(index): | def has_block(index): | ||||
return os.path.isfile(os.path.join(self.nodes[node_number].datadir, "regtest", "blocks", "blk{:05}.dat".format(index))) | return os.path.isfile(os.path.join( | ||||
self.nodes[node_number].datadir, "regtest", "blocks", "blk{:05}.dat".format(index))) | |||||
# should not prune because chain tip of node 3 (995) < PruneAfterHeight | # should not prune because chain tip of node 3 (995) < PruneAfterHeight | ||||
# (1000) | # (1000) | ||||
assert_raises_rpc_error( | assert_raises_rpc_error( | ||||
-1, "Blockchain is too short for pruning", node.pruneblockchain, height(500)) | -1, "Blockchain is too short for pruning", node.pruneblockchain, height(500)) | ||||
# Save block transaction count before pruning, assert value | # Save block transaction count before pruning, assert value | ||||
block1_details = node.getblock(node.getblockhash(1)) | block1_details = node.getblock(node.getblockhash(1)) | ||||
▲ Show 20 Lines • Show All 194 Lines • Show Last 20 Lines |