mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-29 13:32:33 +02:00
Merge 27770 via rpc_getblockfileinfo-26+knots
This commit is contained in:
commit
c9fb60733c
@ -755,7 +755,7 @@ void BlockManager::CleanupBlockRevFiles() const
|
||||
CBlockFileInfo* BlockManager::GetBlockFileInfo(size_t n)
|
||||
{
|
||||
LOCK(cs_LastBlockFile);
|
||||
|
||||
if (n > m_blockfile_info.size()-1) return nullptr;
|
||||
return &m_blockfile_info.at(n);
|
||||
}
|
||||
|
||||
|
@ -3111,6 +3111,46 @@ return RPCHelpMan{
|
||||
};
|
||||
}
|
||||
|
||||
static RPCHelpMan getblockfileinfo()
|
||||
{
|
||||
return RPCHelpMan{
|
||||
"getblockfileinfo",
|
||||
"Retrieves information about a certain block file.",
|
||||
{
|
||||
{"file_number", RPCArg::Type::NUM, RPCArg::Optional::NO, "block file number"},
|
||||
},
|
||||
RPCResult{
|
||||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::NUM, "blocks_num", "the number of blocks stored in the file"},
|
||||
{RPCResult::Type::NUM, "lowest_block", "the height of the lowest block inside the file"},
|
||||
{RPCResult::Type::NUM, "highest_block", "the height of the highest block inside the file"},
|
||||
{RPCResult::Type::NUM, "data_size", "the number of used bytes in the block file"},
|
||||
{RPCResult::Type::NUM, "undo_size", "the number of used bytes in the undo file"},
|
||||
}
|
||||
},
|
||||
RPCExamples{ HelpExampleCli("getblockfileinfo", "0") },
|
||||
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue {
|
||||
NodeContext& node = EnsureAnyNodeContext(request.context);
|
||||
|
||||
int block_num = request.params[0].getInt<int>();
|
||||
if (block_num < 0) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block number");
|
||||
|
||||
CBlockFileInfo* info = node.chainman->m_blockman.GetBlockFileInfo(block_num);
|
||||
if (!info) throw JSONRPCError(RPC_INVALID_PARAMETER, "block file not found");
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.pushKV("blocks_num", info->nBlocks);
|
||||
result.pushKV("lowest_block", info->nHeightFirst);
|
||||
result.pushKV("highest_block", info->nHeightLast);
|
||||
result.pushKV("data_size", info->nSize);
|
||||
result.pushKV("undo_size", info->nUndoSize);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static RPCHelpMan getblocklocations()
|
||||
{
|
||||
return RPCHelpMan{"getblocklocations",
|
||||
@ -3211,6 +3251,7 @@ void RegisterBlockchainRPCCommands(CRPCTable& t)
|
||||
{"blockchain", &dumptxoutset},
|
||||
{"hidden", &loadtxoutset},
|
||||
{"blockchain", &getchainstates},
|
||||
{"hidden", &getblockfileinfo},
|
||||
{"hidden", &invalidateblock},
|
||||
{"hidden", &reconsiderblock},
|
||||
{"hidden", &waitfornewblock},
|
||||
|
@ -258,6 +258,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
||||
{ "verifychain", 1, "nblocks" },
|
||||
{ "getblockstats", 0, "hash_or_height" },
|
||||
{ "getblockstats", 1, "stats" },
|
||||
{ "getblockfileinfo", 0, "file_number" },
|
||||
{ "setprunelock", 1, "lock_info" },
|
||||
{ "pruneblockchain", 0, "height" },
|
||||
{ "keypoolrefill", 0, "newsize" },
|
||||
|
@ -121,6 +121,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
|
||||
"getblockfrompeer", // when no peers are connected, no p2p message is sent
|
||||
"getblockhash",
|
||||
"getblockheader",
|
||||
"getblockfileinfo",
|
||||
"getblocklocations",
|
||||
"getblockstats",
|
||||
"getblocktemplate",
|
||||
|
@ -135,10 +135,21 @@ class GetBlockFromPeerTest(BitcoinTestFramework):
|
||||
# We need to generate more blocks to be able to prune
|
||||
self.generate(self.nodes[0], 400, sync_fun=self.no_op)
|
||||
self.sync_blocks([self.nodes[0], pruned_node])
|
||||
pruneheight = pruned_node.pruneblockchain(300)
|
||||
assert_equal(pruneheight, 248)
|
||||
|
||||
# The goal now will be to mimic the automatic pruning process and verify what happens when we fetch an historic
|
||||
# block at any point of time.
|
||||
#
|
||||
# Starting with three blocks files. The pruning process will prune them one by one. And, at the second pruning
|
||||
# event, the test will fetch the past block. Which will be stored at the latest block file. Which can only be
|
||||
# pruned when the latest block file is full (in this case, the third one), and a new one is created.
|
||||
|
||||
# First prune event, prune first block file
|
||||
highest_pruned_block_num = pruned_node.getblockfileinfo(0)["highest_block"]
|
||||
pruneheight = pruned_node.pruneblockchain(highest_pruned_block_num + 1)
|
||||
assert_equal(pruneheight, highest_pruned_block_num)
|
||||
# Ensure the block is actually pruned
|
||||
pruned_block = self.nodes[0].getblockhash(2)
|
||||
fetch_block_num = 2
|
||||
pruned_block = self.nodes[0].getblockhash(fetch_block_num)
|
||||
assert_raises_rpc_error(-1, "Block not available (pruned data)", pruned_node.getblock, pruned_block)
|
||||
|
||||
self.log.info("Fetch pruned block")
|
||||
@ -149,18 +160,29 @@ class GetBlockFromPeerTest(BitcoinTestFramework):
|
||||
self.wait_until(lambda: self.check_for_block(node=2, hash=pruned_block), timeout=1)
|
||||
assert_equal(result, {})
|
||||
|
||||
# Validate that the re-fetched block was stored at the last, current, block file
|
||||
assert_equal(fetch_block_num, pruned_node.getblockfileinfo(2)["lowest_block"])
|
||||
|
||||
self.log.info("Fetched block persists after next pruning event")
|
||||
self.generate(self.nodes[0], 250, sync_fun=self.no_op)
|
||||
self.sync_blocks([self.nodes[0], pruned_node])
|
||||
pruneheight += 251
|
||||
assert_equal(pruned_node.pruneblockchain(700), pruneheight)
|
||||
|
||||
# Second prune event, prune second block file
|
||||
highest_pruned_block_num = pruned_node.getblockfileinfo(1)["highest_block"]
|
||||
pruneheight = pruned_node.pruneblockchain(highest_pruned_block_num + 1)
|
||||
assert_equal(pruneheight, highest_pruned_block_num)
|
||||
# As the re-fetched block is in the third file, and we just pruned the second one, 'getblock' must work.
|
||||
assert_equal(pruned_node.getblock(pruned_block)["hash"], "36c56c5b5ebbaf90d76b0d1a074dcb32d42abab75b7ec6fa0ffd9b4fbce8f0f7")
|
||||
|
||||
self.log.info("Fetched block can be pruned again when prune height exceeds the height of the tip at the time when the block was fetched")
|
||||
self.log.info("Re-fetched block can be pruned again when a new block file is created")
|
||||
self.generate(self.nodes[0], 250, sync_fun=self.no_op)
|
||||
self.sync_blocks([self.nodes[0], pruned_node])
|
||||
pruneheight += 250
|
||||
assert_equal(pruned_node.pruneblockchain(1000), pruneheight)
|
||||
|
||||
# Third prune event, prune third block file
|
||||
highest_pruned_block_num = pruned_node.getblockfileinfo(2)["highest_block"]
|
||||
pruneheight = pruned_node.pruneblockchain(highest_pruned_block_num + 1)
|
||||
assert_equal(pruneheight, highest_pruned_block_num)
|
||||
# and check that the re-fetched block file is now pruned
|
||||
assert_raises_rpc_error(-1, "Block not available (pruned data)", pruned_node.getblock, pruned_block)
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user