Merge f6013265b7 into merged_master (Bitcoin PR bitcoin/bitcoin#20295)

This commit is contained in:
Byron Hambly 2023-06-06 09:10:04 +00:00
commit b0b2f3deff
18 changed files with 296 additions and 93 deletions

View file

@ -19,6 +19,8 @@
#include <hash.h>
#include <index/blockfilterindex.h>
#include <index/coinstatsindex.h>
#include <net.h>
#include <net_processing.h>
#include <node/blockstorage.h>
#include <logging/timer.h>
#include <node/coinstats.h>
@ -30,6 +32,7 @@
#include <policy/rbf.h>
#include <primitives/transaction.h>
#include <rpc/server.h>
#include <rpc/server_util.h>
#include <rpc/util.h>
#include <script/descriptor.h>
#include <streams.h>
@ -39,7 +42,6 @@
#include <undo.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/system.h>
#include <util/translation.h>
#include <validation.h>
#include <validationinterface.h>
@ -66,54 +68,6 @@ static Mutex cs_blockchange;
static std::condition_variable cond_blockchange;
static CUpdatedBlock latestblock GUARDED_BY(cs_blockchange);
NodeContext& EnsureAnyNodeContext(const std::any& context)
{
auto node_context = util::AnyPtr<NodeContext>(context);
if (!node_context) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Node context not found");
}
return *node_context;
}
CTxMemPool& EnsureMemPool(const NodeContext& node)
{
if (!node.mempool) {
throw JSONRPCError(RPC_CLIENT_MEMPOOL_DISABLED, "Mempool disabled or instance not found");
}
return *node.mempool;
}
CTxMemPool& EnsureAnyMemPool(const std::any& context)
{
return EnsureMemPool(EnsureAnyNodeContext(context));
}
ChainstateManager& EnsureChainman(const NodeContext& node)
{
if (!node.chainman) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Node chainman not found");
}
return *node.chainman;
}
ChainstateManager& EnsureAnyChainman(const std::any& context)
{
return EnsureChainman(EnsureAnyNodeContext(context));
}
CBlockPolicyEstimator& EnsureFeeEstimator(const NodeContext& node)
{
if (!node.fee_estimator) {
throw JSONRPCError(RPC_INTERNAL_ERROR, "Fee estimation disabled");
}
return *node.fee_estimator;
}
CBlockPolicyEstimator& EnsureAnyFeeEstimator(const std::any& context)
{
return EnsureFeeEstimator(EnsureAnyNodeContext(context));
}
/* Calculate the difficulty for a given block index.
*/
double GetDifficulty(const CBlockIndex* blockindex)
@ -906,6 +860,58 @@ static RPCHelpMan getmempoolentry()
};
}
static RPCHelpMan getblockfrompeer()
{
return RPCHelpMan{"getblockfrompeer",
"\nAttempt to fetch block from a given peer.\n"
"\nWe must have the header for this block, e.g. using submitheader.\n"
"\nReturns {} if a block-request was successfully scheduled\n",
{
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"},
{"nodeid", RPCArg::Type::NUM, RPCArg::Optional::NO, "The node ID (see getpeerinfo for node IDs)"},
},
RPCResult{RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::STR, "warnings", "any warnings"}
}},
RPCExamples{
HelpExampleCli("getblockfrompeer", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 0")
+ HelpExampleRpc("getblockfrompeer", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 0")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
const NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = EnsureChainman(node);
PeerManager& peerman = EnsurePeerman(node);
CConnman& connman = EnsureConnman(node);
uint256 hash(ParseHashV(request.params[0], "hash"));
const NodeId nodeid = static_cast<NodeId>(request.params[1].get_int64());
// Check that the peer with nodeid exists
if (!connman.ForNode(nodeid, [](CNode* node) {return true;})) {
throw JSONRPCError(RPC_MISC_ERROR, strprintf("Peer nodeid %d does not exist", nodeid));
}
const CBlockIndex* const index = WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(hash););
if (!index) {
throw JSONRPCError(RPC_MISC_ERROR, "Block header missing");
}
UniValue result = UniValue::VOBJ;
if (index->nStatus & BLOCK_HAVE_DATA) {
result.pushKV("warnings", "Block already downloaded");
} else if (!peerman.FetchBlock(nodeid, hash, *index)) {
throw JSONRPCError(RPC_MISC_ERROR, "Failed to fetch block from peer");
}
return result;
},
};
}
static RPCHelpMan getblockhash()
{
return RPCHelpMan{"getblockhash",
@ -3021,6 +3027,7 @@ static const CRPCCommand commands[] =
{ "blockchain", &getbestblockhash, },
{ "blockchain", &getblockcount, },
{ "blockchain", &getblock, },
{ "blockchain", &getblockfrompeer, },
{ "blockchain", &getblockhash, },
{ "blockchain", &getblockheader, },
{ "blockchain", &getchaintips, },