Changeset View
Changeset View
Standalone View
Standalone View
test/functional/feature_blockfilterindex_prune.py
Show All 12 Lines | |||||
class FeatureBlockfilterindexPruneTest(BitcoinTestFramework): | class FeatureBlockfilterindexPruneTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.extra_args = [["-fastprune", "-prune=1", "-blockfilterindex=1"]] | self.extra_args = [["-fastprune", "-prune=1", "-blockfilterindex=1"]] | ||||
def sync_index(self, height): | def sync_index(self, height): | ||||
expected = { | expected = { | ||||
'basic block filter index': { | "basic block filter index": {"synced": True, "best_block_height": height} | ||||
'synced': True, | |||||
'best_block_height': height | |||||
} | |||||
} | } | ||||
self.wait_until(lambda: self.nodes[0].getindexinfo() == expected) | self.wait_until(lambda: self.nodes[0].getindexinfo() == expected) | ||||
def run_test(self): | def run_test(self): | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
self.log.info("check if we can access a blockfilter when pruning is " | self.log.info( | ||||
"enabled but no blocks are actually pruned") | "check if we can access a blockfilter when pruning is " | ||||
"enabled but no blocks are actually pruned" | |||||
) | |||||
self.sync_index(200) | self.sync_index(200) | ||||
assert_greater_than( | assert_greater_than( | ||||
len(node.getblockfilter(node.getbestblockhash())['filter']), | len(node.getblockfilter(node.getbestblockhash())["filter"]), 0 | ||||
0) | ) | ||||
self.generate(node, 500) | self.generate(node, 500) | ||||
self.sync_index(height=700) | self.sync_index(height=700) | ||||
self.log.info("prune some blocks") | self.log.info("prune some blocks") | ||||
pruneheight = node.pruneblockchain(400) | pruneheight = node.pruneblockchain(400) | ||||
# The prune heights used here and below are magic numbers that are | # The prune heights used here and below are magic numbers that are | ||||
# determined by the thresholds at which block files wrap, so they depend | # determined by the thresholds at which block files wrap, so they depend | ||||
# on disk serialization and default block file size. | # on disk serialization and default block file size. | ||||
# The difference in number of blocks per block file between Bitcoin ABC | # The difference in number of blocks per block file between Bitcoin ABC | ||||
# and Bitcoin Core is caused by additional witness data in coinbase | # and Bitcoin Core is caused by additional witness data in coinbase | ||||
# transactions for core. | # transactions for core. | ||||
assert_equal(pruneheight, 346) | assert_equal(pruneheight, 346) | ||||
self.log.info("check if we can access the tips blockfilter when we have" | self.log.info( | ||||
" pruned some blocks") | "check if we can access the tips blockfilter when we have" | ||||
" pruned some blocks" | |||||
) | |||||
assert_greater_than( | assert_greater_than( | ||||
len(node.getblockfilter(node.getbestblockhash())['filter']), | len(node.getblockfilter(node.getbestblockhash())["filter"]), 0 | ||||
0) | ) | ||||
self.log.info("check if we can access the blockfilter of a pruned " | self.log.info("check if we can access the blockfilter of a pruned block") | ||||
"block") | assert_greater_than(len(node.getblockfilter(node.getblockhash(2))["filter"]), 0) | ||||
assert_greater_than( | |||||
len(node.getblockfilter(node.getblockhash(2))['filter']), | |||||
0) | |||||
# mine and sync index up to a height that will later be the pruneheight | # mine and sync index up to a height that will later be the pruneheight | ||||
self.generate(node, 338) | self.generate(node, 338) | ||||
# Backport note: 3 blk?????.dat file with 346 blocks each makes 1038. | # Backport note: 3 blk?????.dat file with 346 blocks each makes 1038. | ||||
self.sync_index(height=1038) | self.sync_index(height=1038) | ||||
self.log.info("start node without blockfilterindex") | self.log.info("start node without blockfilterindex") | ||||
self.restart_node(0, extra_args=["-fastprune", "-prune=1"]) | self.restart_node(0, extra_args=["-fastprune", "-prune=1"]) | ||||
self.log.info("make sure accessing the blockfilters throws an error") | self.log.info("make sure accessing the blockfilters throws an error") | ||||
assert_raises_rpc_error( | assert_raises_rpc_error( | ||||
-1, "Index is not enabled for filtertype basic", | -1, | ||||
node.getblockfilter, node.getblockhash(2)) | "Index is not enabled for filtertype basic", | ||||
node.getblockfilter, | |||||
node.getblockhash(2), | |||||
) | |||||
self.generate(node, 462) | self.generate(node, 462) | ||||
self.log.info("prune exactly up to the blockfilterindexes best block " | self.log.info( | ||||
"while blockfilters are disabled") | "prune exactly up to the blockfilterindexes best block " | ||||
"while blockfilters are disabled" | |||||
) | |||||
pruneheight_2 = self.nodes[0].pruneblockchain(1040) | pruneheight_2 = self.nodes[0].pruneblockchain(1040) | ||||
assert_equal(pruneheight_2, 1038) | assert_equal(pruneheight_2, 1038) | ||||
self.restart_node( | self.restart_node( | ||||
0, extra_args=["-fastprune", "-prune=1", "-blockfilterindex=1"]) | 0, extra_args=["-fastprune", "-prune=1", "-blockfilterindex=1"] | ||||
self.log.info("make sure that we can continue with the partially synced" | ) | ||||
" index after having pruned up to the index height") | self.log.info( | ||||
"make sure that we can continue with the partially synced" | |||||
" index after having pruned up to the index height" | |||||
) | |||||
self.sync_index(height=1500) | self.sync_index(height=1500) | ||||
self.log.info("prune below the blockfilterindexes best block while " | self.log.info( | ||||
"blockfilters are disabled") | "prune below the blockfilterindexes best block while " | ||||
self.restart_node( | "blockfilters are disabled" | ||||
0, | ) | ||||
extra_args=["-fastprune", "-prune=1"]) | self.restart_node(0, extra_args=["-fastprune", "-prune=1"]) | ||||
self.generate(node, 1000) | self.generate(node, 1000) | ||||
pruneheight_3 = self.nodes[0].pruneblockchain(2000) | pruneheight_3 = self.nodes[0].pruneblockchain(2000) | ||||
assert_greater_than(pruneheight_3, pruneheight_2) | assert_greater_than(pruneheight_3, pruneheight_2) | ||||
self.stop_node(0) | self.stop_node(0) | ||||
self.log.info("make sure we get an init error when starting the node " | self.log.info( | ||||
"again with block filters") | "make sure we get an init error when starting the node " | ||||
"again with block filters" | |||||
) | |||||
with node.assert_debug_log( | with node.assert_debug_log( | ||||
["basic block filter index best block of the index goes beyond " | [ | ||||
"basic block filter index best block of the index goes beyond " | |||||
"pruned data. Please disable the index or reindex (which will " | "pruned data. Please disable the index or reindex (which will " | ||||
"download the whole blockchain again)"]): | "download the whole blockchain again)" | ||||
] | |||||
): | |||||
node.assert_start_raises_init_error( | node.assert_start_raises_init_error( | ||||
extra_args=["-fastprune", "-prune=1", "-blockfilterindex=1"]) | extra_args=["-fastprune", "-prune=1", "-blockfilterindex=1"] | ||||
) | |||||
self.log.info("make sure the node starts again with the -reindex arg") | self.log.info("make sure the node starts again with the -reindex arg") | ||||
self.start_node( | self.start_node( | ||||
0, | 0, extra_args=["-fastprune", "-prune=1", "-blockfilterindex", "-reindex"] | ||||
extra_args=["-fastprune", "-prune=1", "-blockfilterindex", | ) | ||||
"-reindex"]) | |||||
if __name__ == '__main__': | if __name__ == "__main__": | ||||
FeatureBlockfilterindexPruneTest().main() | FeatureBlockfilterindexPruneTest().main() |