mirror of
https://github.com/Retropex/bitcoin.git
synced 2025-05-30 05:52: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)
|
CBlockFileInfo* BlockManager::GetBlockFileInfo(size_t n)
|
||||||
{
|
{
|
||||||
LOCK(cs_LastBlockFile);
|
LOCK(cs_LastBlockFile);
|
||||||
|
if (n > m_blockfile_info.size()-1) return nullptr;
|
||||||
return &m_blockfile_info.at(n);
|
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()
|
static RPCHelpMan getblocklocations()
|
||||||
{
|
{
|
||||||
return RPCHelpMan{"getblocklocations",
|
return RPCHelpMan{"getblocklocations",
|
||||||
@ -3211,6 +3251,7 @@ void RegisterBlockchainRPCCommands(CRPCTable& t)
|
|||||||
{"blockchain", &dumptxoutset},
|
{"blockchain", &dumptxoutset},
|
||||||
{"hidden", &loadtxoutset},
|
{"hidden", &loadtxoutset},
|
||||||
{"blockchain", &getchainstates},
|
{"blockchain", &getchainstates},
|
||||||
|
{"hidden", &getblockfileinfo},
|
||||||
{"hidden", &invalidateblock},
|
{"hidden", &invalidateblock},
|
||||||
{"hidden", &reconsiderblock},
|
{"hidden", &reconsiderblock},
|
||||||
{"hidden", &waitfornewblock},
|
{"hidden", &waitfornewblock},
|
||||||
|
@ -258,6 +258,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "verifychain", 1, "nblocks" },
|
{ "verifychain", 1, "nblocks" },
|
||||||
{ "getblockstats", 0, "hash_or_height" },
|
{ "getblockstats", 0, "hash_or_height" },
|
||||||
{ "getblockstats", 1, "stats" },
|
{ "getblockstats", 1, "stats" },
|
||||||
|
{ "getblockfileinfo", 0, "file_number" },
|
||||||
{ "setprunelock", 1, "lock_info" },
|
{ "setprunelock", 1, "lock_info" },
|
||||||
{ "pruneblockchain", 0, "height" },
|
{ "pruneblockchain", 0, "height" },
|
||||||
{ "keypoolrefill", 0, "newsize" },
|
{ "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
|
"getblockfrompeer", // when no peers are connected, no p2p message is sent
|
||||||
"getblockhash",
|
"getblockhash",
|
||||||
"getblockheader",
|
"getblockheader",
|
||||||
|
"getblockfileinfo",
|
||||||
"getblocklocations",
|
"getblocklocations",
|
||||||
"getblockstats",
|
"getblockstats",
|
||||||
"getblocktemplate",
|
"getblocktemplate",
|
||||||
|
@ -135,10 +135,21 @@ class GetBlockFromPeerTest(BitcoinTestFramework):
|
|||||||
# We need to generate more blocks to be able to prune
|
# We need to generate more blocks to be able to prune
|
||||||
self.generate(self.nodes[0], 400, sync_fun=self.no_op)
|
self.generate(self.nodes[0], 400, sync_fun=self.no_op)
|
||||||
self.sync_blocks([self.nodes[0], pruned_node])
|
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
|
# 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)
|
assert_raises_rpc_error(-1, "Block not available (pruned data)", pruned_node.getblock, pruned_block)
|
||||||
|
|
||||||
self.log.info("Fetch 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)
|
self.wait_until(lambda: self.check_for_block(node=2, hash=pruned_block), timeout=1)
|
||||||
assert_equal(result, {})
|
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.log.info("Fetched block persists after next pruning event")
|
||||||
self.generate(self.nodes[0], 250, sync_fun=self.no_op)
|
self.generate(self.nodes[0], 250, sync_fun=self.no_op)
|
||||||
self.sync_blocks([self.nodes[0], pruned_node])
|
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")
|
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.generate(self.nodes[0], 250, sync_fun=self.no_op)
|
||||||
self.sync_blocks([self.nodes[0], pruned_node])
|
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)
|
assert_raises_rpc_error(-1, "Block not available (pruned data)", pruned_node.getblock, pruned_block)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user