|
18 | 18 | #include <hash.h> |
19 | 19 | #include <index/blockfilterindex.h> |
20 | 20 | #include <index/coinstatsindex.h> |
| 21 | +#include <net.h> |
| 22 | +#include <net_processing.h> |
21 | 23 | #include <node/blockstorage.h> |
22 | 24 | #include <node/coinstats.h> |
23 | 25 | #include <node/context.h> |
@@ -748,6 +750,52 @@ static RPCHelpMan getmempoolentry() |
748 | 750 | }; |
749 | 751 | } |
750 | 752 |
|
| 753 | +static RPCHelpMan getblockfrompeer() |
| 754 | +{ |
| 755 | + return RPCHelpMan{"getblockfrompeer", |
| 756 | + "\nAttempt to fetch block from a given peer.\n" |
| 757 | + "\nWe must have the header for this block, e.g. using submitheader.\n" |
| 758 | + "\nReturns {} if a block-request was successfully scheduled\n", |
| 759 | + { |
| 760 | + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, "The block hash"}, |
| 761 | + {"nodeid", RPCArg::Type::NUM, RPCArg::Optional::NO, "The node ID (see getpeerinfo for node IDs)"}, |
| 762 | + }, |
| 763 | + RPCResult{RPCResult::Type::OBJ, "", "", |
| 764 | + { |
| 765 | + {RPCResult::Type::STR, "warnings", "any warnings"} |
| 766 | + }}, |
| 767 | + RPCExamples{ |
| 768 | + HelpExampleCli("getblockfrompeer", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 0") |
| 769 | + + HelpExampleRpc("getblockfrompeer", "\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09\" 0") |
| 770 | + }, |
| 771 | + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue |
| 772 | +{ |
| 773 | + const NodeContext& node = EnsureAnyNodeContext(request.context); |
| 774 | + ChainstateManager& chainman = EnsureChainman(node); |
| 775 | + PeerManager& peerman = EnsurePeerman(node); |
| 776 | + |
| 777 | + uint256 hash(ParseHashV(request.params[0], "hash")); |
| 778 | + |
| 779 | + const NodeId nodeid = static_cast<NodeId>(request.params[1].get_int64()); |
| 780 | + |
| 781 | + const CBlockIndex* const index = WITH_LOCK(cs_main, return chainman.m_blockman.LookupBlockIndex(hash);); |
| 782 | + |
| 783 | + if (!index) { |
| 784 | + throw JSONRPCError(RPC_MISC_ERROR, "Block header missing"); |
| 785 | + } |
| 786 | + |
| 787 | + UniValue result = UniValue::VOBJ; |
| 788 | + |
| 789 | + if (index->nStatus & BLOCK_HAVE_DATA) { |
| 790 | + result.pushKV("warnings", "Block already downloaded"); |
| 791 | + } else if (!peerman.FetchBlock(nodeid, hash, *index)) { |
| 792 | + throw JSONRPCError(RPC_MISC_ERROR, "Failed to fetch block from peer"); |
| 793 | + } |
| 794 | + return result; |
| 795 | +}, |
| 796 | + }; |
| 797 | +} |
| 798 | + |
751 | 799 | static RPCHelpMan getblockhash() |
752 | 800 | { |
753 | 801 | return RPCHelpMan{"getblockhash", |
@@ -2586,6 +2634,7 @@ static const CRPCCommand commands[] = |
2586 | 2634 | { "blockchain", &getbestblockhash, }, |
2587 | 2635 | { "blockchain", &getblockcount, }, |
2588 | 2636 | { "blockchain", &getblock, }, |
| 2637 | + { "blockchain", &getblockfrompeer, }, |
2589 | 2638 | { "blockchain", &getblockhash, }, |
2590 | 2639 | { "blockchain", &getblockheader, }, |
2591 | 2640 | { "blockchain", &getchaintips, }, |
|
0 commit comments