Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/blockchain.cpp
Show First 20 Lines • Show All 170 Lines • ▼ Show 20 Lines | UniValue blockToJSON(const CBlock &block, const CBlockIndex *tip, | ||||
if (pnext) { | if (pnext) { | ||||
result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex()); | result.pushKV("nextblockhash", pnext->GetBlockHash().GetHex()); | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
static UniValue getblockcount(const Config &config, | static UniValue getblockcount(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getblockcount", | "getblockcount", | ||||
"\nReturns the number of blocks in the longest blockchain.\n", | "\nReturns the number of blocks in the longest blockchain.\n", | ||||
{}, | {}, | ||||
RPCResult{"n (numeric) The current block count\n"}, | RPCResult{"n (numeric) The current block count\n"}, | ||||
RPCExamples{HelpExampleCli("getblockcount", "") + | RPCExamples{HelpExampleCli("getblockcount", "") + | ||||
HelpExampleRpc("getblockcount", "")}, | HelpExampleRpc("getblockcount", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return ::ChainActive().Height(); | return ::ChainActive().Height(); | ||||
} | } | ||||
static UniValue getbestblockhash(const Config &config, | static UniValue getbestblockhash(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getbestblockhash", | "getbestblockhash", | ||||
"\nReturns the hash of the best (tip) block in the " | "\nReturns the hash of the best (tip) block in the longest " | ||||
"longest blockchain.\n", | "blockchain.\n", | ||||
{}, | {}, | ||||
RPCResult{"\"hex\" (string) the block hash, hex-encoded\n"}, | RPCResult{"\"hex\" (string) the block hash, hex-encoded\n"}, | ||||
RPCExamples{HelpExampleCli("getbestblockhash", "") + | RPCExamples{HelpExampleCli("getbestblockhash", "") + | ||||
HelpExampleRpc("getbestblockhash", "")}, | HelpExampleRpc("getbestblockhash", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return ::ChainActive().Tip()->GetBlockHash().GetHex(); | return ::ChainActive().Tip()->GetBlockHash().GetHex(); | ||||
} | } | ||||
UniValue getfinalizedblockhash(const Config &config, | UniValue getfinalizedblockhash(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getfinalizedblockhash", | "getfinalizedblockhash", | ||||
"\nReturns the hash of the currently finalized block\n", | "\nReturns the hash of the currently finalized block\n", | ||||
{}, | {}, | ||||
RPCResult{"\"hex\" (string) the block hash hex-encoded\n"}, | RPCResult{"\"hex\" (string) the block hash hex-encoded\n"}, | ||||
RPCExamples{HelpExampleCli("getfinalizedblockhash", "") + | RPCExamples{HelpExampleCli("getfinalizedblockhash", "") + | ||||
HelpExampleRpc("getfinalizedblockhash", "")}, | HelpExampleRpc("getfinalizedblockhash", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CBlockIndex *blockIndexFinalized = GetFinalizedBlock(); | const CBlockIndex *blockIndexFinalized = GetFinalizedBlock(); | ||||
if (blockIndexFinalized) { | if (blockIndexFinalized) { | ||||
return blockIndexFinalized->GetBlockHash().GetHex(); | return blockIndexFinalized->GetBlockHash().GetHex(); | ||||
} | } | ||||
return UniValue(UniValue::VSTR); | return UniValue(UniValue::VSTR); | ||||
} | } | ||||
void RPCNotifyBlockChange(bool ibd, const CBlockIndex *pindex) { | void RPCNotifyBlockChange(bool ibd, const CBlockIndex *pindex) { | ||||
if (pindex) { | if (pindex) { | ||||
std::lock_guard<std::mutex> lock(cs_blockchange); | std::lock_guard<std::mutex> lock(cs_blockchange); | ||||
latestblock.hash = pindex->GetBlockHash(); | latestblock.hash = pindex->GetBlockHash(); | ||||
latestblock.height = pindex->nHeight; | latestblock.height = pindex->nHeight; | ||||
} | } | ||||
cond_blockchange.notify_all(); | cond_blockchange.notify_all(); | ||||
} | } | ||||
static UniValue waitfornewblock(const Config &config, | static UniValue waitfornewblock(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() > 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"waitfornewblock", | "waitfornewblock", | ||||
"\nWaits for a specific new block and returns useful " | "\nWaits for a specific new block and returns useful info about it.\n" | ||||
"info about it.\n" | |||||
"\nReturns the current block on timeout or exit.\n", | "\nReturns the current block on timeout or exit.\n", | ||||
{ | { | ||||
{"timeout", RPCArg::Type::NUM, /* default */ "0", | {"timeout", RPCArg::Type::NUM, /* default */ "0", | ||||
"Time in milliseconds to wait for a response. 0 indicates no " | "Time in milliseconds to wait for a response. 0 indicates no " | ||||
"timeout."}, | "timeout."}, | ||||
}, | }, | ||||
RPCResult{"{ (json object)\n" | RPCResult{"{ (json object)\n" | ||||
" \"hash\" : { (string) The blockhash\n" | " \"hash\" : { (string) The blockhash\n" | ||||
" \"height\" : { (int) Block height\n" | " \"height\" : { (int) Block height\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("waitfornewblock", "1000") + | RPCExamples{HelpExampleCli("waitfornewblock", "1000") + | ||||
HelpExampleRpc("waitfornewblock", "1000")}, | HelpExampleRpc("waitfornewblock", "1000")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
int timeout = 0; | int timeout = 0; | ||||
if (!request.params[0].isNull()) { | if (!request.params[0].isNull()) { | ||||
timeout = request.params[0].get_int(); | timeout = request.params[0].get_int(); | ||||
} | } | ||||
CUpdatedBlock block; | CUpdatedBlock block; | ||||
{ | { | ||||
WAIT_LOCK(cs_blockchange, lock); | WAIT_LOCK(cs_blockchange, lock); | ||||
Show All 15 Lines | static UniValue waitfornewblock(const Config &config, | ||||
UniValue ret(UniValue::VOBJ); | UniValue ret(UniValue::VOBJ); | ||||
ret.pushKV("hash", block.hash.GetHex()); | ret.pushKV("hash", block.hash.GetHex()); | ||||
ret.pushKV("height", block.height); | ret.pushKV("height", block.height); | ||||
return ret; | return ret; | ||||
} | } | ||||
static UniValue waitforblock(const Config &config, | static UniValue waitforblock(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | RPCHelpMan{ | ||||
request.params.size() > 2) { | |||||
throw std::runtime_error(RPCHelpMan{ | |||||
"waitforblock", | "waitforblock", | ||||
"\nWaits for a specific new block and returns useful " | "\nWaits for a specific new block and returns useful info about it.\n" | ||||
"info about it.\n" | |||||
"\nReturns the current block on timeout or exit.\n", | "\nReturns the current block on timeout or exit.\n", | ||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"Block hash to wait for."}, | "Block hash to wait for."}, | ||||
{"timeout", RPCArg::Type::NUM, /* default */ "0", | {"timeout", RPCArg::Type::NUM, /* default */ "0", | ||||
"Time in milliseconds to wait for a response. 0 " | "Time in milliseconds to wait for a response. 0 indicates no " | ||||
"indicates no timeout."}, | "timeout."}, | ||||
}, | }, | ||||
RPCResult{"{ (json object)\n" | RPCResult{"{ (json object)\n" | ||||
" \"hash\" : { (string) The blockhash\n" | " \"hash\" : { (string) The blockhash\n" | ||||
" \"height\" : { (int) Block height\n" | " \"height\" : { (int) Block height\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("waitforblock", | RPCExamples{HelpExampleCli("waitforblock", | ||||
"\"0000000000079f8ef3d2c688c244eb7a4" | "\"0000000000079f8ef3d2c688c244eb7a4570b24c9" | ||||
"570b24c9ed7b4a8c619eb02596f8862\", " | "ed7b4a8c619eb02596f8862\", 1000") + | ||||
"1000") + | |||||
HelpExampleRpc("waitforblock", | HelpExampleRpc("waitforblock", | ||||
"\"0000000000079f8ef3d2c688c244eb7a4" | "\"0000000000079f8ef3d2c688c244eb7a4570b24c9" | ||||
"570b24c9ed7b4a8c619eb02596f8862\", " | "ed7b4a8c619eb02596f8862\", 1000")}, | ||||
"1000")}, | |||||
} | |||||
.ToString()); | |||||
} | } | ||||
.Check(request); | |||||
int timeout = 0; | int timeout = 0; | ||||
BlockHash hash(ParseHashV(request.params[0], "blockhash")); | BlockHash hash(ParseHashV(request.params[0], "blockhash")); | ||||
if (!request.params[1].isNull()) { | if (!request.params[1].isNull()) { | ||||
timeout = request.params[1].get_int(); | timeout = request.params[1].get_int(); | ||||
} | } | ||||
Show All 17 Lines | static UniValue waitforblock(const Config &config, | ||||
UniValue ret(UniValue::VOBJ); | UniValue ret(UniValue::VOBJ); | ||||
ret.pushKV("hash", block.hash.GetHex()); | ret.pushKV("hash", block.hash.GetHex()); | ||||
ret.pushKV("height", block.height); | ret.pushKV("height", block.height); | ||||
return ret; | return ret; | ||||
} | } | ||||
static UniValue waitforblockheight(const Config &config, | static UniValue waitforblockheight(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | RPCHelpMan{ | ||||
request.params.size() > 2) { | |||||
throw std::runtime_error(RPCHelpMan{ | |||||
"waitforblockheight", | "waitforblockheight", | ||||
"\nWaits for (at least) block height and returns the " | "\nWaits for (at least) block height and returns the height and " | ||||
"height and hash\nof the current tip.\n" | "hash\nof the current tip.\n" | ||||
"\nReturns the current block on timeout or exit.\n", | "\nReturns the current block on timeout or exit.\n", | ||||
{ | { | ||||
{"height", RPCArg::Type::NUM, RPCArg::Optional::NO, | {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, | ||||
"Block height to wait for."}, | "Block height to wait for."}, | ||||
{"timeout", RPCArg::Type::NUM, /* default */ "0", | {"timeout", RPCArg::Type::NUM, /* default */ "0", | ||||
"Time in milliseconds to wait for a response. 0 " | "Time in milliseconds to wait for a response. 0 indicates no " | ||||
"indicates no timeout."}, | "timeout."}, | ||||
}, | }, | ||||
RPCResult{"{ (json object)\n" | RPCResult{"{ (json object)\n" | ||||
" \"hash\" : { (string) The blockhash\n" | " \"hash\" : { (string) The blockhash\n" | ||||
" \"height\" : { (int) Block height\n" | " \"height\" : { (int) Block height\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("waitforblockheight", "\"100\", 1000") + | RPCExamples{HelpExampleCli("waitforblockheight", "\"100\", 1000") + | ||||
HelpExampleRpc("waitforblockheight", "\"100\", 1000")}, | HelpExampleRpc("waitforblockheight", "\"100\", 1000")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
int timeout = 0; | int timeout = 0; | ||||
int height = request.params[0].get_int(); | int height = request.params[0].get_int(); | ||||
if (!request.params[1].isNull()) { | if (!request.params[1].isNull()) { | ||||
timeout = request.params[1].get_int(); | timeout = request.params[1].get_int(); | ||||
} | } | ||||
Show All 17 Lines | static UniValue waitforblockheight(const Config &config, | ||||
ret.pushKV("hash", block.hash.GetHex()); | ret.pushKV("hash", block.hash.GetHex()); | ||||
ret.pushKV("height", block.height); | ret.pushKV("height", block.height); | ||||
return ret; | return ret; | ||||
} | } | ||||
static UniValue | static UniValue | ||||
syncwithvalidationinterfacequeue(const Config &config, | syncwithvalidationinterfacequeue(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() > 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"syncwithvalidationinterfacequeue", | "syncwithvalidationinterfacequeue", | ||||
"\nWaits for the validation interface queue to catch up on " | "\nWaits for the validation interface queue to catch up on everything " | ||||
"everything that was there when we entered this function.\n", | "that was there when we entered this function.\n", | ||||
{}, | {}, | ||||
RPCResults{}, | RPCResults{}, | ||||
RPCExamples{HelpExampleCli("syncwithvalidationinterfacequeue", "") + | RPCExamples{HelpExampleCli("syncwithvalidationinterfacequeue", "") + | ||||
HelpExampleRpc("syncwithvalidationinterfacequeue", "")}, | HelpExampleRpc("syncwithvalidationinterfacequeue", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
SyncWithValidationInterfaceQueue(); | SyncWithValidationInterfaceQueue(); | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
static UniValue getdifficulty(const Config &config, | static UniValue getdifficulty(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getdifficulty", | "getdifficulty", | ||||
"\nReturns the proof-of-work difficulty as a multiple of the " | "\nReturns the proof-of-work difficulty as a multiple of the minimum " | ||||
"minimum difficulty.\n", | "difficulty.\n", | ||||
{}, | {}, | ||||
RPCResult{"n.nnn (numeric) the proof-of-work difficulty as a " | RPCResult{"n.nnn (numeric) the proof-of-work difficulty as a " | ||||
"multiple of the minimum difficulty.\n"}, | "multiple of the minimum difficulty.\n"}, | ||||
RPCExamples{HelpExampleCli("getdifficulty", "") + | RPCExamples{HelpExampleCli("getdifficulty", "") + | ||||
HelpExampleRpc("getdifficulty", "")}, | HelpExampleRpc("getdifficulty", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return GetDifficulty(::ChainActive().Tip()); | return GetDifficulty(::ChainActive().Tip()); | ||||
} | } | ||||
static std::string EntryDescriptionString() { | static std::string EntryDescriptionString() { | ||||
return " \"size\" : n, (numeric) transaction size.\n" | return " \"size\" : n, (numeric) transaction size.\n" | ||||
" \"fee\" : n, (numeric) transaction fee in " + | " \"fee\" : n, (numeric) transaction fee in " + | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | if (verbose) { | ||||
} | } | ||||
return a; | return a; | ||||
} | } | ||||
} | } | ||||
static UniValue getrawmempool(const Config &config, | static UniValue getrawmempool(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() > 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getrawmempool", | "getrawmempool", | ||||
"\nReturns all transaction ids in memory pool as a json " | "\nReturns all transaction ids in memory pool as a json array of " | ||||
"array of string transaction ids.\n" | "string transaction ids.\n" | ||||
"\nHint: use getmempoolentry to fetch a specific " | "\nHint: use getmempoolentry to fetch a specific transaction from the " | ||||
"transaction from the mempool.\n", | "mempool.\n", | ||||
{ | { | ||||
{"verbose", RPCArg::Type::BOOL, /* default */ "false", | {"verbose", RPCArg::Type::BOOL, /* default */ "false", | ||||
"True for a json object, false for array of " | "True for a json object, false for array of transaction ids"}, | ||||
"transaction ids"}, | |||||
}, | }, | ||||
RPCResult{"for verbose = false", | RPCResult{"for verbose = false", | ||||
"[ (json array of string)\n" | "[ (json array of string)\n" | ||||
" \"transactionid\" (string) The transaction id\n" | " \"transactionid\" (string) The transaction id\n" | ||||
" ,...\n" | " ,...\n" | ||||
"]\n" | "]\n" | ||||
"\nResult: (for verbose = true):\n" | "\nResult: (for verbose = true):\n" | ||||
"{ (json object)\n" | "{ (json object)\n" | ||||
" \"transactionid\" : { (json object)\n" + | " \"transactionid\" : { (json object)\n" + | ||||
EntryDescriptionString() + | EntryDescriptionString() + | ||||
" }, ...\n" | " }, ...\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("getrawmempool", "true") + | RPCExamples{HelpExampleCli("getrawmempool", "true") + | ||||
HelpExampleRpc("getrawmempool", "true")}, | HelpExampleRpc("getrawmempool", "true")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
bool fVerbose = false; | bool fVerbose = false; | ||||
if (!request.params[0].isNull()) { | if (!request.params[0].isNull()) { | ||||
fVerbose = request.params[0].get_bool(); | fVerbose = request.params[0].get_bool(); | ||||
} | } | ||||
return MempoolToJSON(::g_mempool, fVerbose); | return MempoolToJSON(::g_mempool, fVerbose); | ||||
} | } | ||||
static UniValue getmempoolancestors(const Config &config, | static UniValue getmempoolancestors(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | RPCHelpMan{ | ||||
request.params.size() > 2) { | |||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getmempoolancestors", | "getmempoolancestors", | ||||
"\nIf txid is in the mempool, returns all in-mempool " | "\nIf txid is in the mempool, returns all in-mempool ancestors.\n", | ||||
"ancestors.\n", | |||||
{ | { | ||||
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"The transaction id (must be in mempool)"}, | "The transaction id (must be in mempool)"}, | ||||
{"verbose", RPCArg::Type::BOOL, /* default */ "false", | {"verbose", RPCArg::Type::BOOL, /* default */ "false", | ||||
"True for a json object, false for array of " | "True for a json object, false for array of transaction ids"}, | ||||
"transaction ids"}, | |||||
}, | }, | ||||
{ | { | ||||
RPCResult{ | RPCResult{"for verbose = false", | ||||
"for verbose = false", | |||||
"[ (json array of strings)\n" | "[ (json array of strings)\n" | ||||
" \"transactionid\" (string) The transaction id " | " \"transactionid\" (string) The transaction " | ||||
"of an in-mempool ancestor transaction\n" | "id of an in-mempool ancestor transaction\n" | ||||
" ,...\n" | " ,...\n" | ||||
"]\n"}, | "]\n"}, | ||||
RPCResult{"for verbose = true", | RPCResult{"for verbose = true", | ||||
"{ (json object)\n" | "{ (json object)\n" | ||||
" \"transactionid\" : { (json object)\n" + | " \"transactionid\" : { (json object)\n" + | ||||
EntryDescriptionString() + | EntryDescriptionString() + | ||||
" }, ...\n" | " }, ...\n" | ||||
"}\n"}, | "}\n"}, | ||||
}, | }, | ||||
RPCExamples{HelpExampleCli("getmempoolancestors", "\"mytxid\"") + | RPCExamples{HelpExampleCli("getmempoolancestors", "\"mytxid\"") + | ||||
HelpExampleRpc("getmempoolancestors", "\"mytxid\"")}, | HelpExampleRpc("getmempoolancestors", "\"mytxid\"")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
bool fVerbose = false; | bool fVerbose = false; | ||||
if (!request.params[1].isNull()) { | if (!request.params[1].isNull()) { | ||||
fVerbose = request.params[1].get_bool(); | fVerbose = request.params[1].get_bool(); | ||||
} | } | ||||
TxId txid(ParseHashV(request.params[0], "parameter 1")); | TxId txid(ParseHashV(request.params[0], "parameter 1")); | ||||
Show All 28 Lines | if (!fVerbose) { | ||||
o.pushKV(_txid.ToString(), info); | o.pushKV(_txid.ToString(), info); | ||||
} | } | ||||
return o; | return o; | ||||
} | } | ||||
} | } | ||||
static UniValue getmempooldescendants(const Config &config, | static UniValue getmempooldescendants(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | RPCHelpMan{ | ||||
request.params.size() > 2) { | |||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getmempooldescendants", | "getmempooldescendants", | ||||
"\nIf txid is in the mempool, returns all in-mempool " | "\nIf txid is in the mempool, returns all in-mempool descendants.\n", | ||||
"descendants.\n", | |||||
{ | { | ||||
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"The transaction id (must be in mempool)"}, | "The transaction id (must be in mempool)"}, | ||||
{"verbose", RPCArg::Type::BOOL, /* default */ "false", | {"verbose", RPCArg::Type::BOOL, /* default */ "false", | ||||
"True for a json object, false for array of " | "True for a json object, false for array of transaction ids"}, | ||||
"transaction ids"}, | |||||
}, | }, | ||||
{ | { | ||||
RPCResult{ | RPCResult{"for verbose = false", | ||||
"for verbose = false", | |||||
"[ (json array of strings)\n" | "[ (json array of strings)\n" | ||||
" \"transactionid\" (string) The transaction id " | " \"transactionid\" (string) The transaction " | ||||
"of an in-mempool descendant transaction\n" | "id of an in-mempool descendant transaction\n" | ||||
" ,...\n" | " ,...\n" | ||||
"]\n"}, | "]\n"}, | ||||
RPCResult{"for verbose = true", | RPCResult{"for verbose = true", | ||||
"{ (json object)\n" | "{ (json object)\n" | ||||
" \"transactionid\" : { (json object)\n" + | " \"transactionid\" : { (json object)\n" + | ||||
EntryDescriptionString() + | EntryDescriptionString() + | ||||
" }, ...\n" | " }, ...\n" | ||||
"}\n"}, | "}\n"}, | ||||
}, | }, | ||||
RPCExamples{HelpExampleCli("getmempooldescendants", "\"mytxid\"") + | RPCExamples{HelpExampleCli("getmempooldescendants", "\"mytxid\"") + | ||||
HelpExampleRpc("getmempooldescendants", "\"mytxid\"")}, | HelpExampleRpc("getmempooldescendants", "\"mytxid\"")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
bool fVerbose = false; | bool fVerbose = false; | ||||
if (!request.params[1].isNull()) { | if (!request.params[1].isNull()) { | ||||
fVerbose = request.params[1].get_bool(); | fVerbose = request.params[1].get_bool(); | ||||
} | } | ||||
TxId txid(ParseHashV(request.params[0], "parameter 1")); | TxId txid(ParseHashV(request.params[0], "parameter 1")); | ||||
Show All 27 Lines | if (!fVerbose) { | ||||
o.pushKV(_txid.ToString(), info); | o.pushKV(_txid.ToString(), info); | ||||
} | } | ||||
return o; | return o; | ||||
} | } | ||||
} | } | ||||
static UniValue getmempoolentry(const Config &config, | static UniValue getmempoolentry(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getmempoolentry", | "getmempoolentry", | ||||
"\nReturns mempool data for given transaction\n", | "\nReturns mempool data for given transaction\n", | ||||
{ | { | ||||
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"The transaction id (must be in mempool)"}, | "The transaction id (must be in mempool)"}, | ||||
}, | }, | ||||
RPCResult{"{ (json object)\n" + | RPCResult{"{ (json object)\n" + | ||||
EntryDescriptionString() + "}\n"}, | EntryDescriptionString() + "}\n"}, | ||||
RPCExamples{HelpExampleCli("getmempoolentry", "\"mytxid\"") + | RPCExamples{HelpExampleCli("getmempoolentry", "\"mytxid\"") + | ||||
HelpExampleRpc("getmempoolentry", "\"mytxid\"")}, | HelpExampleRpc("getmempoolentry", "\"mytxid\"")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
TxId txid(ParseHashV(request.params[0], "parameter 1")); | TxId txid(ParseHashV(request.params[0], "parameter 1")); | ||||
LOCK(g_mempool.cs); | LOCK(g_mempool.cs); | ||||
CTxMemPool::txiter it = g_mempool.mapTx.find(txid); | CTxMemPool::txiter it = g_mempool.mapTx.find(txid); | ||||
if (it == g_mempool.mapTx.end()) { | if (it == g_mempool.mapTx.end()) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Transaction not in mempool"); | "Transaction not in mempool"); | ||||
} | } | ||||
const CTxMemPoolEntry &e = *it; | const CTxMemPoolEntry &e = *it; | ||||
UniValue info(UniValue::VOBJ); | UniValue info(UniValue::VOBJ); | ||||
entryToJSON(::g_mempool, info, e); | entryToJSON(::g_mempool, info, e); | ||||
return info; | return info; | ||||
} | } | ||||
static UniValue getblockhash(const Config &config, | static UniValue getblockhash(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getblockhash", | "getblockhash", | ||||
"\nReturns hash of block in best-block-chain at height " | "\nReturns hash of block in best-block-chain at height provided.\n", | ||||
"provided.\n", | |||||
{ | { | ||||
{"height", RPCArg::Type::NUM, RPCArg::Optional::NO, | {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, | ||||
"The height index"}, | "The height index"}, | ||||
}, | }, | ||||
RPCResult{"\"hash\" (string) The block hash\n"}, | RPCResult{"\"hash\" (string) The block hash\n"}, | ||||
RPCExamples{HelpExampleCli("getblockhash", "1000") + | RPCExamples{HelpExampleCli("getblockhash", "1000") + | ||||
HelpExampleRpc("getblockhash", "1000")}, | HelpExampleRpc("getblockhash", "1000")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
int nHeight = request.params[0].get_int(); | int nHeight = request.params[0].get_int(); | ||||
if (nHeight < 0 || nHeight > ::ChainActive().Height()) { | if (nHeight < 0 || nHeight > ::ChainActive().Height()) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); | throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); | ||||
} | } | ||||
CBlockIndex *pblockindex = ::ChainActive()[nHeight]; | CBlockIndex *pblockindex = ::ChainActive()[nHeight]; | ||||
return pblockindex->GetBlockHash().GetHex(); | return pblockindex->GetBlockHash().GetHex(); | ||||
} | } | ||||
static UniValue getblockheader(const Config &config, | static UniValue getblockheader(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | RPCHelpMan{ | ||||
request.params.size() > 2) { | |||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getblockheader", | "getblockheader", | ||||
"\nIf verbose is false, returns a string that is " | "\nIf verbose is false, returns a string that is serialized, " | ||||
"serialized, hex-encoded data for blockheader 'hash'.\n" | "hex-encoded data for blockheader 'hash'.\n" | ||||
"If verbose is true, returns an Object with information " | "If verbose is true, returns an Object with information about " | ||||
"about blockheader <hash>.\n", | "blockheader <hash>.\n", | ||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"The block hash"}, | "The block hash"}, | ||||
{"verbose", RPCArg::Type::BOOL, /* default */ "true", | {"verbose", RPCArg::Type::BOOL, /* default */ "true", | ||||
"true for a json object, false for the hex-encoded data"}, | "true for a json object, false for the hex-encoded data"}, | ||||
}, | }, | ||||
{ | { | ||||
RPCResult{ | RPCResult{ | ||||
"for verbose = true", | "for verbose = true", | ||||
"{\n" | "{\n" | ||||
" \"hash\" : \"hash\", (string) the block hash (same " | " \"hash\" : \"hash\", (string) the block hash (same as " | ||||
"as provided)\n" | "provided)\n" | ||||
" \"confirmations\" : n, (numeric) The number of " | " \"confirmations\" : n, (numeric) The number of " | ||||
"confirmations, or -1 if the block is not on the main " | "confirmations, or -1 if the block is not on the main chain\n" | ||||
"chain\n" | |||||
" \"height\" : n, (numeric) The block height or " | " \"height\" : n, (numeric) The block height or " | ||||
"index\n" | "index\n" | ||||
" \"version\" : n, (numeric) The block version\n" | " \"version\" : n, (numeric) The block version\n" | ||||
" \"versionHex\" : \"00000000\", (string) The block " | " \"versionHex\" : \"00000000\", (string) The block version " | ||||
"version formatted in hexadecimal\n" | "formatted in hexadecimal\n" | ||||
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n" | " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" | ||||
" \"time\" : ttt, (numeric) The block time in " | " \"time\" : ttt, (numeric) The block time in " | ||||
"seconds since epoch (Jan 1 1970 GMT)\n" | "seconds since epoch (Jan 1 1970 GMT)\n" | ||||
" \"mediantime\" : ttt, (numeric) The median block " | " \"mediantime\" : ttt, (numeric) The median block time in " | ||||
"time in seconds since epoch (Jan 1 1970 GMT)\n" | "seconds since epoch (Jan 1 1970 GMT)\n" | ||||
" \"nonce\" : n, (numeric) The nonce\n" | " \"nonce\" : n, (numeric) The nonce\n" | ||||
" \"bits\" : \"1d00ffff\", (string) The bits\n" | " \"bits\" : \"1d00ffff\", (string) The bits\n" | ||||
" \"difficulty\" : x.xxx, (numeric) The difficulty\n" | " \"difficulty\" : x.xxx, (numeric) The difficulty\n" | ||||
" \"chainwork\" : \"0000...1f3\" (string) Expected " | " \"chainwork\" : \"0000...1f3\" (string) Expected number " | ||||
"number of hashes required to produce the current chain " | "of hashes required to produce the current chain (in hex)\n" | ||||
"(in hex)\n" | |||||
" \"nTx\" : n, (numeric) The number of " | " \"nTx\" : n, (numeric) The number of " | ||||
"transactions in the block.\n" | "transactions in the block.\n" | ||||
" \"previousblockhash\" : \"hash\", (string) The hash of " | " \"previousblockhash\" : \"hash\", (string) The hash of the " | ||||
"the previous block\n" | "previous block\n" | ||||
" \"nextblockhash\" : \"hash\", (string) The hash of " | " \"nextblockhash\" : \"hash\", (string) The hash of the " | ||||
"the next block\n" | "next block\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCResult{"for verbose=false", | RPCResult{"for verbose=false", | ||||
"\"data\" (string) A string that is " | "\"data\" (string) A string that is " | ||||
"serialized, hex-encoded data for block 'hash'.\n"}, | "serialized, hex-encoded data for block 'hash'.\n"}, | ||||
}, | }, | ||||
RPCExamples{HelpExampleCli("getblockheader", | RPCExamples{HelpExampleCli("getblockheader", | ||||
"\"00000000c937983704a73af28acdec3" | "\"00000000c937983704a73af28acdec37b049d214a" | ||||
"7b049d214adbda81d7e2a3dd146f6ed09" | "dbda81d7e2a3dd146f6ed09\"") + | ||||
"\"") + | |||||
HelpExampleRpc("getblockheader", | HelpExampleRpc("getblockheader", | ||||
"\"00000000c937983704a73af28acdec3" | "\"00000000c937983704a73af28acdec37b049d214a" | ||||
"7b049d214adbda81d7e2a3dd146f6ed09" | "dbda81d7e2a3dd146f6ed09\"")}, | ||||
"\"")}, | |||||
} | |||||
.ToString()); | |||||
} | } | ||||
.Check(request); | |||||
BlockHash hash(ParseHashV(request.params[0], "hash")); | BlockHash hash(ParseHashV(request.params[0], "hash")); | ||||
bool fVerbose = true; | bool fVerbose = true; | ||||
if (!request.params[1].isNull()) { | if (!request.params[1].isNull()) { | ||||
fVerbose = request.params[1].get_bool(); | fVerbose = request.params[1].get_bool(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | static CBlockUndo GetUndoChecked(const CBlockIndex *pblockindex) { | ||||
if (!UndoReadFromDisk(blockUndo, pblockindex)) { | if (!UndoReadFromDisk(blockUndo, pblockindex)) { | ||||
throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk"); | throw JSONRPCError(RPC_MISC_ERROR, "Can't read undo data from disk"); | ||||
} | } | ||||
return blockUndo; | return blockUndo; | ||||
} | } | ||||
static UniValue getblock(const Config &config, const JSONRPCRequest &request) { | static UniValue getblock(const Config &config, const JSONRPCRequest &request) { | ||||
const RPCHelpMan help{ | RPCHelpMan{ | ||||
"getblock", | "getblock", | ||||
"\nIf verbosity is 0 or false, returns a string that is " | "\nIf verbosity is 0 or false, returns a string that is serialized, " | ||||
"serialized, hex-encoded data for block 'hash'.\n" | "hex-encoded data for block 'hash'.\n" | ||||
"If verbosity is 1 or true, returns an Object with information " | "If verbosity is 1 or true, returns an Object with information about " | ||||
"about block <hash>.\n" | "block <hash>.\n" | ||||
"If verbosity is 2, returns an Object with information about " | "If verbosity is 2, returns an Object with information about block " | ||||
"block <hash> and information about each transaction.\n", | "<hash> and information about each transaction.\n", | ||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"The block hash"}, | "The block hash"}, | ||||
{"verbosity", RPCArg::Type::NUM, /* default */ "1", | {"verbosity", RPCArg::Type::NUM, /* default */ "1", | ||||
"0 for hex-encoded data, 1 for a json object, and 2 for " | "0 for hex-encoded data, 1 for a json object, and 2 for json " | ||||
"json object with transaction data"}, | "object with transaction data"}, | ||||
}, | }, | ||||
{ | { | ||||
RPCResult{"for verbosity = 0", | RPCResult{"for verbosity = 0", | ||||
"\"data\" (string) A string that is " | "\"data\" (string) A string that is " | ||||
"serialized, hex-encoded data for block 'hash'.\n"}, | "serialized, hex-encoded data for block 'hash'.\n"}, | ||||
RPCResult{ | RPCResult{ | ||||
"for verbosity = 1", | "for verbosity = 1", | ||||
"{\n" | "{\n" | ||||
" \"hash\" : \"hash\", (string) The block hash " | " \"hash\" : \"hash\", (string) The block hash (same as " | ||||
"(same as provided)\n" | "provided)\n" | ||||
" \"confirmations\" : n, (numeric) The number of " | " \"confirmations\" : n, (numeric) The number of " | ||||
"confirmations, or -1 if the block is not on the main " | "confirmations, or -1 if the block is not on the main chain\n" | ||||
"chain\n" | |||||
" \"size\" : n, (numeric) The block size\n" | " \"size\" : n, (numeric) The block size\n" | ||||
" \"height\" : n, (numeric) The block height or " | " \"height\" : n, (numeric) The block height or " | ||||
"index\n" | "index\n" | ||||
" \"version\" : n, (numeric) The block version\n" | " \"version\" : n, (numeric) The block version\n" | ||||
" \"versionHex\" : \"00000000\", (string) The block " | " \"versionHex\" : \"00000000\", (string) The block version " | ||||
"version formatted in hexadecimal\n" | "formatted in hexadecimal\n" | ||||
" \"merkleroot\" : \"xxxx\", (string) The merkle root\n" | " \"merkleroot\" : \"xxxx\", (string) The merkle root\n" | ||||
" \"tx\" : [ (array of string) The " | " \"tx\" : [ (array of string) The transaction " | ||||
"transaction ids\n" | "ids\n" | ||||
" \"transactionid\" (string) The transaction id\n" | " \"transactionid\" (string) The transaction id\n" | ||||
" ,...\n" | " ,...\n" | ||||
" ],\n" | " ],\n" | ||||
" \"time\" : ttt, (numeric) The block time in " | " \"time\" : ttt, (numeric) The block time in " | ||||
"seconds since epoch (Jan 1 1970 GMT)\n" | "seconds since epoch (Jan 1 1970 GMT)\n" | ||||
" \"mediantime\" : ttt, (numeric) The median block " | " \"mediantime\" : ttt, (numeric) The median block time in " | ||||
"time in seconds since epoch (Jan 1 1970 GMT)\n" | "seconds since epoch (Jan 1 1970 GMT)\n" | ||||
" \"nonce\" : n, (numeric) The nonce\n" | " \"nonce\" : n, (numeric) The nonce\n" | ||||
" \"bits\" : \"1d00ffff\", (string) The bits\n" | " \"bits\" : \"1d00ffff\", (string) The bits\n" | ||||
" \"difficulty\" : x.xxx, (numeric) The difficulty\n" | " \"difficulty\" : x.xxx, (numeric) The difficulty\n" | ||||
" \"chainwork\" : \"xxxx\", (string) Expected number of " | " \"chainwork\" : \"xxxx\", (string) Expected number of " | ||||
"hashes required to produce the chain up to this block (in " | "hashes required to produce the chain up to this block (in " | ||||
"hex)\n" | "hex)\n" | ||||
" \"nTx\" : n, (numeric) The number of " | " \"nTx\" : n, (numeric) The number of " | ||||
"transactions in the block.\n" | "transactions in the block.\n" | ||||
" \"previousblockhash\" : \"hash\", (string) The hash of " | " \"previousblockhash\" : \"hash\", (string) The hash of the " | ||||
"the previous block\n" | "previous block\n" | ||||
" \"nextblockhash\" : \"hash\" (string) The hash of " | " \"nextblockhash\" : \"hash\" (string) The hash of the " | ||||
"the next block\n" | "next block\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCResult{ | RPCResult{ | ||||
"for verbosity = 2", | "for verbosity = 2", | ||||
"{\n" | "{\n" | ||||
" ..., Same output as verbosity = 1\n" | " ..., Same output as verbosity = 1\n" | ||||
" \"tx\" : [ (array of Objects) The " | " \"tx\" : [ (array of Objects) The " | ||||
"transactions in the format of the getrawtransaction RPC; " | "transactions in the format of the getrawtransaction RPC; " | ||||
"different from verbosity = 1 \"tx\" result\n" | "different from verbosity = 1 \"tx\" result\n" | ||||
" ...\n" | " ...\n" | ||||
" ],\n" | " ],\n" | ||||
" ... Same output as verbosity = 1\n" | " ... Same output as verbosity = 1\n" | ||||
"}\n"}, | "}\n"}, | ||||
}, | }, | ||||
RPCExamples{ | RPCExamples{ | ||||
HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d" | HelpExampleCli("getblock", "\"00000000c937983704a73af28acdec37b049d" | ||||
"214adbda81d7e2a3dd146f6ed09\"") + | "214adbda81d7e2a3dd146f6ed09\"") + | ||||
HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d" | HelpExampleRpc("getblock", "\"00000000c937983704a73af28acdec37b049d" | ||||
"214adbda81d7e2a3dd146f6ed09\"")}, | "214adbda81d7e2a3dd146f6ed09\"")}, | ||||
}; | |||||
if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { | |||||
throw std::runtime_error(help.ToString()); | |||||
} | } | ||||
.Check(request); | |||||
BlockHash hash(ParseHashV(request.params[0], "blockhash")); | BlockHash hash(ParseHashV(request.params[0], "blockhash")); | ||||
int verbosity = 1; | int verbosity = 1; | ||||
if (!request.params[1].isNull()) { | if (!request.params[1].isNull()) { | ||||
if (request.params[1].isNum()) { | if (request.params[1].isNum()) { | ||||
verbosity = request.params[1].get_int(); | verbosity = request.params[1].get_int(); | ||||
} else { | } else { | ||||
Show All 24 Lines | if (verbosity <= 0) { | ||||
return strHex; | return strHex; | ||||
} | } | ||||
return blockToJSON(block, tip, pblockindex, verbosity >= 2); | return blockToJSON(block, tip, pblockindex, verbosity >= 2); | ||||
} | } | ||||
static UniValue pruneblockchain(const Config &config, | static UniValue pruneblockchain(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"pruneblockchain", | "pruneblockchain", | ||||
"", | "", | ||||
{ | { | ||||
{"height", RPCArg::Type::NUM, RPCArg::Optional::NO, | {"height", RPCArg::Type::NUM, RPCArg::Optional::NO, | ||||
"The block height to prune up to. May be set to a discrete " | "The block height to prune up to. May be set to a discrete " | ||||
"height, or a unix timestamp\n" | "height, or a unix timestamp\n" | ||||
" to prune blocks whose block time is at " | " to prune blocks whose block time is at least 2 " | ||||
"least 2 hours older than the provided timestamp."}, | "hours older than the provided timestamp."}, | ||||
}, | }, | ||||
RPCResult{"n (numeric) Height of the last block pruned.\n"}, | RPCResult{"n (numeric) Height of the last block pruned.\n"}, | ||||
RPCExamples{HelpExampleCli("pruneblockchain", "1000") + | RPCExamples{HelpExampleCli("pruneblockchain", "1000") + | ||||
HelpExampleRpc("pruneblockchain", "1000")}, | HelpExampleRpc("pruneblockchain", "1000")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
if (!fPruneMode) { | if (!fPruneMode) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_MISC_ERROR, | RPC_MISC_ERROR, | ||||
"Cannot prune blocks because node is not in prune mode."); | "Cannot prune blocks because node is not in prune mode."); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Show All 34 Lines | static UniValue pruneblockchain(const Config &config, | ||||
} | } | ||||
PruneBlockFilesManual(height); | PruneBlockFilesManual(height); | ||||
return uint64_t(height); | return uint64_t(height); | ||||
} | } | ||||
static UniValue gettxoutsetinfo(const Config &config, | static UniValue gettxoutsetinfo(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"gettxoutsetinfo", | "gettxoutsetinfo", | ||||
"\nReturns statistics about the unspent transaction output set.\n" | "\nReturns statistics about the unspent transaction output set.\n" | ||||
"Note this call may take some time.\n", | "Note this call may take some time.\n", | ||||
{}, | {}, | ||||
RPCResult{ | RPCResult{ | ||||
"{\n" | "{\n" | ||||
" \"height\":n, (numeric) The current block height " | " \"height\":n, (numeric) The current block height (index)\n" | ||||
"(index)\n" | |||||
" \"bestblock\": \"hex\", (string) the best block hash hex\n" | " \"bestblock\": \"hex\", (string) the best block hash hex\n" | ||||
" \"transactions\": n, (numeric) The number of " | " \"transactions\": n, (numeric) The number of transactions\n" | ||||
"transactions\n" | |||||
" \"txouts\": n, (numeric) The number of output " | " \"txouts\": n, (numeric) The number of output " | ||||
"transactions\n" | "transactions\n" | ||||
" \"bogosize\": n, (numeric) A database-independent " | " \"bogosize\": n, (numeric) A database-independent " | ||||
"metric for UTXO set size\n" | "metric for UTXO set size\n" | ||||
" \"hash_serialized\": \"hash\", (string) The serialized " | " \"hash_serialized\": \"hash\", (string) The serialized hash\n" | ||||
"hash\n" | " \"disk_size\": n, (numeric) The estimated size of the " | ||||
" \"disk_size\": n, (numeric) The estimated size of " | "chainstate on disk\n" | ||||
"the chainstate on disk\n" | " \"total_amount\": x.xxx (numeric) The total amount\n" | ||||
" \"total_amount\": x.xxx (numeric) The total " | |||||
"amount\n" | |||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("gettxoutsetinfo", "") + | RPCExamples{HelpExampleCli("gettxoutsetinfo", "") + | ||||
HelpExampleRpc("gettxoutsetinfo", "")}, | HelpExampleRpc("gettxoutsetinfo", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
UniValue ret(UniValue::VOBJ); | UniValue ret(UniValue::VOBJ); | ||||
CCoinsStats stats; | CCoinsStats stats; | ||||
::ChainstateActive().ForceFlushStateToDisk(); | ::ChainstateActive().ForceFlushStateToDisk(); | ||||
if (GetUTXOStats(pcoinsdbview.get(), stats)) { | if (GetUTXOStats(pcoinsdbview.get(), stats)) { | ||||
ret.pushKV("height", int64_t(stats.nHeight)); | ret.pushKV("height", int64_t(stats.nHeight)); | ||||
ret.pushKV("bestblock", stats.hashBlock.GetHex()); | ret.pushKV("bestblock", stats.hashBlock.GetHex()); | ||||
ret.pushKV("transactions", int64_t(stats.nTransactions)); | ret.pushKV("transactions", int64_t(stats.nTransactions)); | ||||
ret.pushKV("txouts", int64_t(stats.nTransactionOutputs)); | ret.pushKV("txouts", int64_t(stats.nTransactionOutputs)); | ||||
ret.pushKV("bogosize", int64_t(stats.nBogoSize)); | ret.pushKV("bogosize", int64_t(stats.nBogoSize)); | ||||
ret.pushKV("hash_serialized", stats.hashSerialized.GetHex()); | ret.pushKV("hash_serialized", stats.hashSerialized.GetHex()); | ||||
ret.pushKV("disk_size", stats.nDiskSize); | ret.pushKV("disk_size", stats.nDiskSize); | ||||
ret.pushKV("total_amount", ValueFromAmount(stats.nTotalAmount)); | ret.pushKV("total_amount", ValueFromAmount(stats.nTotalAmount)); | ||||
} else { | } else { | ||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set"); | throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set"); | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
UniValue gettxout(const Config &config, const JSONRPCRequest &request) { | UniValue gettxout(const Config &config, const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 2 || | RPCHelpMan{ | ||||
request.params.size() > 3) { | |||||
throw std::runtime_error(RPCHelpMan{ | |||||
"gettxout", | "gettxout", | ||||
"\nReturns details about an unspent transaction output.\n", | "\nReturns details about an unspent transaction output.\n", | ||||
{ | { | ||||
{"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"txid", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"The transaction id"}, | "The transaction id"}, | ||||
{"n", RPCArg::Type::NUM, RPCArg::Optional::NO, "vout number"}, | {"n", RPCArg::Type::NUM, RPCArg::Optional::NO, "vout number"}, | ||||
{"include_mempool", RPCArg::Type::BOOL, /* default */ "true", | {"include_mempool", RPCArg::Type::BOOL, /* default */ "true", | ||||
"Whether to include the mempool. Note that an unspent " | "Whether to include the mempool. Note that an unspent output that " | ||||
"output that is spent in the mempool won't appear."}, | "is spent in the mempool won't appear."}, | ||||
}, | }, | ||||
RPCResult{ | RPCResult{ | ||||
"{\n" | "{\n" | ||||
" \"bestblock\" : \"hash\", (string) the block hash\n" | " \"bestblock\" : \"hash\", (string) the block hash\n" | ||||
" \"confirmations\" : n, (numeric) The number of " | " \"confirmations\" : n, (numeric) The number of " | ||||
"confirmations\n" | "confirmations\n" | ||||
" \"value\" : x.xxx, (numeric) The transaction " | " \"value\" : x.xxx, (numeric) The transaction value " | ||||
"value in " + | "in " + | ||||
CURRENCY_UNIT + | CURRENCY_UNIT + | ||||
"\n" | "\n" | ||||
" \"scriptPubKey\" : { (json object)\n" | " \"scriptPubKey\" : { (json object)\n" | ||||
" \"asm\" : \"code\", (string) \n" | " \"asm\" : \"code\", (string) \n" | ||||
" \"hex\" : \"hex\", (string) \n" | " \"hex\" : \"hex\", (string) \n" | ||||
" \"reqSigs\" : n, (numeric) Number of required " | " \"reqSigs\" : n, (numeric) Number of required " | ||||
"signatures\n" | "signatures\n" | ||||
" \"type\" : \"pubkeyhash\", (string) The type, eg " | " \"type\" : \"pubkeyhash\", (string) The type, eg pubkeyhash\n" | ||||
"pubkeyhash\n" | |||||
" \"addresses\" : [ (array of string) array of " | " \"addresses\" : [ (array of string) array of " | ||||
"bitcoin addresses\n" | "bitcoin addresses\n" | ||||
" \"address\" (string) bitcoin address\n" | " \"address\" (string) bitcoin address\n" | ||||
" ,...\n" | " ,...\n" | ||||
" ]\n" | " ]\n" | ||||
" },\n" | " },\n" | ||||
" \"coinbase\" : true|false (boolean) Coinbase or not\n" | " \"coinbase\" : true|false (boolean) Coinbase or not\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{"\nGet unspent transactions\n" + | RPCExamples{"\nGet unspent transactions\n" + | ||||
HelpExampleCli("listunspent", "") + | HelpExampleCli("listunspent", "") + "\nView the details\n" + | ||||
"\nView the details\n" + | |||||
HelpExampleCli("gettxout", "\"txid\" 1") + | HelpExampleCli("gettxout", "\"txid\" 1") + | ||||
"\nAs a JSON-RPC call\n" + | "\nAs a JSON-RPC call\n" + | ||||
HelpExampleRpc("gettxout", "\"txid\", 1")}, | HelpExampleRpc("gettxout", "\"txid\", 1")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
UniValue ret(UniValue::VOBJ); | UniValue ret(UniValue::VOBJ); | ||||
TxId txid(ParseHashV(request.params[0], "txid")); | TxId txid(ParseHashV(request.params[0], "txid")); | ||||
int n = request.params[1].get_int(); | int n = request.params[1].get_int(); | ||||
COutPoint out(txid, n); | COutPoint out(txid, n); | ||||
Show All 31 Lines | UniValue gettxout(const Config &config, const JSONRPCRequest &request) { | ||||
return ret; | return ret; | ||||
} | } | ||||
static UniValue verifychain(const Config &config, | static UniValue verifychain(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL); | int nCheckLevel = gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL); | ||||
int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); | int nCheckDepth = gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS); | ||||
if (request.fHelp || request.params.size() > 2) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"verifychain", | "verifychain", | ||||
"\nVerifies blockchain database.\n", | "\nVerifies blockchain database.\n", | ||||
{ | { | ||||
{"checklevel", RPCArg::Type::NUM, | {"checklevel", RPCArg::Type::NUM, | ||||
/* default */ strprintf("%d, range=0-4", nCheckLevel), | /* default */ strprintf("%d, range=0-4", nCheckLevel), | ||||
"How thorough the block verification is."}, | "How thorough the block verification is."}, | ||||
{"nblocks", RPCArg::Type::NUM, | {"nblocks", RPCArg::Type::NUM, | ||||
/* default */ strprintf("%d, 0=all", nCheckDepth), | /* default */ strprintf("%d, 0=all", nCheckDepth), | ||||
"The number of blocks to check."}, | "The number of blocks to check."}, | ||||
}, | }, | ||||
RPCResult{"true|false (boolean) Verified or not\n"}, | RPCResult{"true|false (boolean) Verified or not\n"}, | ||||
RPCExamples{HelpExampleCli("verifychain", "") + | RPCExamples{HelpExampleCli("verifychain", "") + | ||||
HelpExampleRpc("verifychain", "")}, | HelpExampleRpc("verifychain", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (!request.params[0].isNull()) { | if (!request.params[0].isNull()) { | ||||
nCheckLevel = request.params[0].get_int(); | nCheckLevel = request.params[0].get_int(); | ||||
} | } | ||||
if (!request.params[1].isNull()) { | if (!request.params[1].isNull()) { | ||||
nCheckDepth = request.params[1].get_int(); | nCheckDepth = request.params[1].get_int(); | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | static void BIP9SoftForkDescPushBack(UniValue &softforks, | ||||
} | } | ||||
rv.pushKV("active", ThresholdState::ACTIVE == thresholdState); | rv.pushKV("active", ThresholdState::ACTIVE == thresholdState); | ||||
softforks.pushKV(VersionBitsDeploymentInfo[id].name, rv); | softforks.pushKV(VersionBitsDeploymentInfo[id].name, rv); | ||||
} | } | ||||
UniValue getblockchaininfo(const Config &config, | UniValue getblockchaininfo(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getblockchaininfo", | "getblockchaininfo", | ||||
"Returns an object containing various state info " | "Returns an object containing various state info regarding blockchain " | ||||
"regarding blockchain processing.\n", | "processing.\n", | ||||
{}, | {}, | ||||
RPCResult{ | RPCResult{ | ||||
"{\n" | "{\n" | ||||
" \"chain\": \"xxxx\", (string) current network " | " \"chain\": \"xxxx\", (string) current network name " | ||||
"name as defined in BIP70 (main, test, regtest)\n" | "as defined in BIP70 (main, test, regtest)\n" | ||||
" \"blocks\": xxxxxx, (numeric) the current " | " \"blocks\": xxxxxx, (numeric) the current number of " | ||||
"number of blocks processed in the server\n" | "blocks processed in the server\n" | ||||
" \"headers\": xxxxxx, (numeric) the current " | " \"headers\": xxxxxx, (numeric) the current number of " | ||||
"number of headers we have validated\n" | "headers we have validated\n" | ||||
" \"bestblockhash\": \"...\", (string) the hash of the " | " \"bestblockhash\": \"...\", (string) the hash of the " | ||||
"currently best block\n" | "currently best block\n" | ||||
" \"difficulty\": xxxxxx, (numeric) the current " | " \"difficulty\": xxxxxx, (numeric) the current " | ||||
"difficulty\n" | "difficulty\n" | ||||
" \"mediantime\": xxxxxx, (numeric) median time for " | " \"mediantime\": xxxxxx, (numeric) median time for the " | ||||
"the current best block\n" | "current best block\n" | ||||
" \"verificationprogress\": xxxx, (numeric) estimate of " | " \"verificationprogress\": xxxx, (numeric) estimate of " | ||||
"verification progress [0..1]\n" | "verification progress [0..1]\n" | ||||
" \"initialblockdownload\": xxxx, (bool) (debug information) " | " \"initialblockdownload\": xxxx, (bool) (debug information) " | ||||
"estimate of whether this node is in Initial Block Download " | "estimate of whether this node is in Initial Block Download mode.\n" | ||||
"mode.\n" | " \"chainwork\": \"xxxx\" (string) total amount of work " | ||||
" \"chainwork\": \"xxxx\" (string) total amount of " | "in active chain, in hexadecimal\n" | ||||
"work in active chain, in hexadecimal\n" | " \"size_on_disk\": xxxxxx, (numeric) the estimated size of " | ||||
" \"size_on_disk\": xxxxxx, (numeric) the estimated " | "the block and undo files on disk\n" | ||||
"size of the block and undo files on disk\n" | |||||
" \"pruned\": xx, (boolean) if the blocks are " | " \"pruned\": xx, (boolean) if the blocks are " | ||||
"subject to pruning\n" | "subject to pruning\n" | ||||
" \"pruneheight\": xxxxxx, (numeric) lowest-height " | " \"pruneheight\": xxxxxx, (numeric) lowest-height " | ||||
"complete block stored (only present if pruning is enabled)\n" | "complete block stored (only present if pruning is enabled)\n" | ||||
" \"automatic_pruning\": xx, (boolean) whether automatic " | " \"automatic_pruning\": xx, (boolean) whether automatic " | ||||
"pruning is enabled (only present if pruning is enabled)\n" | "pruning is enabled (only present if pruning is enabled)\n" | ||||
" \"prune_target_size\": xxxxxx, (numeric) the target size " | " \"prune_target_size\": xxxxxx, (numeric) the target size used " | ||||
"used by pruning (only present if automatic pruning is " | "by pruning (only present if automatic pruning is enabled)\n" | ||||
"enabled)\n" | " \"softforks\": { (object) status of softforks in " | ||||
" \"softforks\": { (object) status of " | "progress\n" | ||||
"softforks in progress\n" | " \"xxxx\" : { (string) name of the softfork\n" | ||||
" \"xxxx\" : { (string) name of the " | " \"type\" : \"bip9\", (string) currently only set to " | ||||
"softfork\n" | "\"bip9\"\n" | ||||
" \"type\" : \"bip9\", (string) currently only set " | |||||
"to \"bip9\"\n" | |||||
" \"bip9\" : { (object) status of bip9 " | " \"bip9\" : { (object) status of bip9 " | ||||
"softforks (only for \"bip9\" type)\n" | "softforks (only for \"bip9\" type)\n" | ||||
" \"status\": \"xxxx\", (string) one of " | " \"status\": \"xxxx\", (string) one of \"defined\", " | ||||
"\"defined\", \"started\", \"locked_in\", \"active\", " | "\"started\", \"locked_in\", \"active\", \"failed\"\n" | ||||
"\"failed\"\n" | " \"bit\": xx, (numeric) the bit (0-28) in the " | ||||
" \"bit\": xx, (numeric) the bit (0-28) in " | "block version field used to signal this softfork (only for " | ||||
"the block version field used to signal this softfork (only " | "\"started\" status)\n" | ||||
"for \"started\" status)\n" | " \"startTime\": xx, (numeric) the minimum median " | ||||
" \"startTime\": xx, (numeric) the minimum " | "time past of a block at which the bit gains its meaning\n" | ||||
"median time past of a block at which the bit gains its " | " \"timeout\": xx, (numeric) the median time past " | ||||
"meaning\n" | "of a block at which the deployment is considered failed if not " | ||||
" \"timeout\": xx, (numeric) the median time " | |||||
"past of a block at which the deployment is considered failed " | |||||
"if not " | |||||
"yet locked in\n" | "yet locked in\n" | ||||
" \"since\": xx, (numeric) height of the " | " \"since\": xx, (numeric) height of the first " | ||||
"first block to which the status applies\n" | "block to which the status applies\n" | ||||
" \"statistics\": { (object) numeric statistics " | " \"statistics\": { (object) numeric statistics " | ||||
"about BIP9 signalling for a softfork (only for \"started\" " | "about BIP9 signalling for a softfork (only for \"started\" " | ||||
"status)\n" | "status)\n" | ||||
" \"period\": xx, (numeric) the length in " | " \"period\": xx, (numeric) the length in blocks " | ||||
"blocks of the BIP9 signalling period \n" | "of the BIP9 signalling period \n" | ||||
" \"threshold\": xx, (numeric) the number of " | " \"threshold\": xx, (numeric) the number of blocks " | ||||
"blocks with the version bit set required to activate the " | "with the version bit set required to activate the feature \n" | ||||
"feature \n" | " \"elapsed\": xx, (numeric) the number of blocks " | ||||
" \"elapsed\": xx, (numeric) the number of " | "elapsed since the beginning of the current period \n" | ||||
"blocks elapsed since the beginning of the current period \n" | " \"count\": xx, (numeric) the number of blocks " | ||||
" \"count\": xx, (numeric) the number of " | "with the version bit set in the current period \n" | ||||
"blocks with the version bit set in the current period \n" | |||||
" \"possible\": xx (boolean) returns false if " | " \"possible\": xx (boolean) returns false if " | ||||
"there are not enough blocks left in this period to pass " | "there are not enough blocks left in this period to pass " | ||||
"activation threshold\n" | "activation threshold\n" | ||||
" },\n" | " },\n" | ||||
" \"active\": xx, (boolean) true if the rules " | " \"active\": xx, (boolean) true if the rules are " | ||||
"are enforced for the mempool and the next block\n" | "enforced for the mempool and the next block\n" | ||||
" }\n" | " }\n" | ||||
" }\n" | " }\n" | ||||
" }\n" | " }\n" | ||||
" \"warnings\" : \"...\", (string) any network and " | " \"warnings\" : \"...\", (string) any network and " | ||||
"blockchain warnings.\n" | "blockchain warnings.\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("getblockchaininfo", "") + | RPCExamples{HelpExampleCli("getblockchaininfo", "") + | ||||
HelpExampleRpc("getblockchaininfo", "")}, | HelpExampleRpc("getblockchaininfo", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CChainParams &chainparams = config.GetChainParams(); | const CChainParams &chainparams = config.GetChainParams(); | ||||
const CBlockIndex *tip = ::ChainActive().Tip(); | const CBlockIndex *tip = ::ChainActive().Tip(); | ||||
UniValue obj(UniValue::VOBJ); | UniValue obj(UniValue::VOBJ); | ||||
obj.pushKV("chain", chainparams.NetworkIDString()); | obj.pushKV("chain", chainparams.NetworkIDString()); | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | bool operator()(const CBlockIndex *a, const CBlockIndex *b) const { | ||||
} | } | ||||
return a < b; | return a < b; | ||||
} | } | ||||
}; | }; | ||||
static UniValue getchaintips(const Config &config, | static UniValue getchaintips(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getchaintips", | "getchaintips", | ||||
"Return information about all known tips in the block tree, " | "Return information about all known tips in the block tree, including " | ||||
"including the main chain as well as orphaned branches.\n", | "the main chain as well as orphaned branches.\n", | ||||
{}, | {}, | ||||
RPCResult{ | RPCResult{ | ||||
"[\n" | "[\n" | ||||
" {\n" | " {\n" | ||||
" \"height\": xxxx, (numeric) height of the chain " | " \"height\": xxxx, (numeric) height of the chain tip\n" | ||||
"tip\n" | " \"hash\": \"xxxx\", (string) block hash of the tip\n" | ||||
" \"hash\": \"xxxx\", (string) block hash of the " | |||||
"tip\n" | |||||
" \"branchlen\": 0 (numeric) zero for main chain\n" | " \"branchlen\": 0 (numeric) zero for main chain\n" | ||||
" \"status\": \"active\" (string) \"active\" for the " | " \"status\": \"active\" (string) \"active\" for the main " | ||||
"main chain\n" | "chain\n" | ||||
" },\n" | " },\n" | ||||
" {\n" | " {\n" | ||||
" \"height\": xxxx,\n" | " \"height\": xxxx,\n" | ||||
" \"hash\": \"xxxx\",\n" | " \"hash\": \"xxxx\",\n" | ||||
" \"branchlen\": 1 (numeric) length of branch " | " \"branchlen\": 1 (numeric) length of branch " | ||||
"connecting the tip to the main chain\n" | "connecting the tip to the main chain\n" | ||||
" \"status\": \"xxxx\" (string) status of the chain " | " \"status\": \"xxxx\" (string) status of the chain " | ||||
"(active, valid-fork, valid-headers, headers-only, invalid)\n" | "(active, valid-fork, valid-headers, headers-only, invalid)\n" | ||||
" }\n" | " }\n" | ||||
"]\n" | "]\n" | ||||
"Possible values for status:\n" | "Possible values for status:\n" | ||||
"1. \"invalid\" This branch contains at least " | "1. \"invalid\" This branch contains at least one " | ||||
"one invalid block\n" | "invalid block\n" | ||||
"2. \"parked\" This branch contains at least " | "2. \"parked\" This branch contains at least one " | ||||
"one parked block\n" | "parked block\n" | ||||
"3. \"headers-only\" Not all blocks for this branch " | "3. \"headers-only\" Not all blocks for this branch are " | ||||
"are available, but the headers are valid\n" | "available, but the headers are valid\n" | ||||
"4. \"valid-headers\" All blocks are available for " | "4. \"valid-headers\" All blocks are available for this " | ||||
"this branch, but they were never fully validated\n" | "branch, but they were never fully validated\n" | ||||
"5. \"valid-fork\" This branch is not part of the " | "5. \"valid-fork\" This branch is not part of the " | ||||
"active chain, but is fully validated\n" | "active chain, but is fully validated\n" | ||||
"6. \"active\" This is the tip of the active " | "6. \"active\" This is the tip of the active main " | ||||
"main chain, which is certainly valid\n"}, | "chain, which is certainly valid\n"}, | ||||
RPCExamples{HelpExampleCli("getchaintips", "") + | RPCExamples{HelpExampleCli("getchaintips", "") + | ||||
HelpExampleRpc("getchaintips", "")}, | HelpExampleRpc("getchaintips", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
/** | /** | ||||
* Idea: the set of chain tips is ::ChainActive().tip, plus orphan blocks | * Idea: the set of chain tips is ::ChainActive().tip, plus orphan blocks | ||||
* which do not have another orphan building off of them. Algorithm: | * which do not have another orphan building off of them. Algorithm: | ||||
* - Make one pass through mapBlockIndex, picking out the orphan blocks, | * - Make one pass through mapBlockIndex, picking out the orphan blocks, | ||||
* and also storing a set of the orphan block's pprev pointers. | * and also storing a set of the orphan block's pprev pointers. | ||||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Lines | ret.pushKV( | ||||
.GetFeePerK())); | .GetFeePerK())); | ||||
ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())); | ret.pushKV("minrelaytxfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())); | ||||
return ret; | return ret; | ||||
} | } | ||||
static UniValue getmempoolinfo(const Config &config, | static UniValue getmempoolinfo(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getmempoolinfo", | "getmempoolinfo", | ||||
"\nReturns details on the active state of the TX memory " | "\nReturns details on the active state of the TX memory pool.\n", | ||||
"pool.\n", | |||||
{}, | {}, | ||||
RPCResult{ | RPCResult{ | ||||
"{\n" | "{\n" | ||||
" \"loaded\": true|false (boolean) True if the " | " \"loaded\": true|false (boolean) True if the mempool is " | ||||
"mempool is fully loaded\n" | "fully loaded\n" | ||||
" \"size\": xxxxx, (numeric) Current tx count\n" | " \"size\": xxxxx, (numeric) Current tx count\n" | ||||
" \"bytes\": xxxxx, (numeric) Transaction size.\n" | " \"bytes\": xxxxx, (numeric) Transaction size.\n" | ||||
" \"usage\": xxxxx, (numeric) Total memory usage " | " \"usage\": xxxxx, (numeric) Total memory usage for " | ||||
"the mempool\n" | |||||
" \"maxmempool\": xxxxx, (numeric) Maximum memory usage " | |||||
"for the mempool\n" | "for the mempool\n" | ||||
" \"maxmempool\": xxxxx, (numeric) Maximum memory " | " \"mempoolminfee\": xxxxx (numeric) Minimum fee rate in " + | ||||
"usage for the mempool\n" | |||||
" \"mempoolminfee\": xxxxx (numeric) Minimum fee rate " | |||||
"in " + | |||||
CURRENCY_UNIT + | CURRENCY_UNIT + | ||||
"/kB for tx to be accepted. Is the maximum of minrelaytxfee " | "/kB for tx to be accepted. Is the maximum of minrelaytxfee and " | ||||
"and minimum mempool fee\n" | "minimum mempool fee\n" | ||||
" \"minrelaytxfee\": xxxxx (numeric) Current minimum " | " \"minrelaytxfee\": xxxxx (numeric) Current minimum relay " | ||||
"relay fee for transactions\n" | "fee for transactions\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("getmempoolinfo", "") + | RPCExamples{HelpExampleCli("getmempoolinfo", "") + | ||||
HelpExampleRpc("getmempoolinfo", "")}, | HelpExampleRpc("getmempoolinfo", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
return MempoolInfoToJSON(::g_mempool); | return MempoolInfoToJSON(::g_mempool); | ||||
} | } | ||||
static UniValue preciousblock(const Config &config, | static UniValue preciousblock(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"preciousblock", | "preciousblock", | ||||
"\nTreats a block as if it were received before others " | "\nTreats a block as if it were received before others with the same " | ||||
"with the same work.\n" | "work.\n" | ||||
"\nA later preciousblock call can override the effect " | "\nA later preciousblock call can override the effect of an earlier " | ||||
"of an earlier one.\n" | "one.\n" | ||||
"\nThe effects of preciousblock are not retained across " | "\nThe effects of preciousblock are not retained across restarts.\n", | ||||
"restarts.\n", | |||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"the hash of the block to mark as precious"}, | "the hash of the block to mark as precious"}, | ||||
}, | }, | ||||
RPCResults{}, | RPCResults{}, | ||||
RPCExamples{HelpExampleCli("preciousblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("preciousblock", "\"blockhash\"") + | ||||
HelpExampleRpc("preciousblock", "\"blockhash\"")}, | HelpExampleRpc("preciousblock", "\"blockhash\"")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
BlockHash hash(ParseHashV(request.params[0], "blockhash")); | BlockHash hash(ParseHashV(request.params[0], "blockhash")); | ||||
CBlockIndex *pblockindex; | CBlockIndex *pblockindex; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pblockindex = LookupBlockIndex(hash); | pblockindex = LookupBlockIndex(hash); | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | ||||
} | } | ||||
} | } | ||||
CValidationState state; | CValidationState state; | ||||
PreciousBlock(config, state, pblockindex); | PreciousBlock(config, state, pblockindex); | ||||
if (!state.IsValid()) { | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
UniValue finalizeblock(const Config &config, const JSONRPCRequest &request) { | UniValue finalizeblock(const Config &config, const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"finalizeblock", | "finalizeblock", | ||||
"\nTreats a block as final. It cannot be reorged. Any chain\n" | "\nTreats a block as final. It cannot be reorged. Any chain\n" | ||||
"that does not contain this block is invalid. Used on a less\n" | "that does not contain this block is invalid. Used on a less\n" | ||||
"work chain, it can effectively PUTS YOU OUT OF CONSENSUS.\n" | "work chain, it can effectively PUTS YOU OUT OF CONSENSUS.\n" | ||||
"USE WITH CAUTION!\n", | "USE WITH CAUTION!\n", | ||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"the hash of the block to mark as invalid"}, | "the hash of the block to mark as invalid"}, | ||||
}, | }, | ||||
RPCResults{}, | RPCResults{}, | ||||
RPCExamples{HelpExampleCli("invalidateblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("invalidateblock", "\"blockhash\"") + | ||||
HelpExampleRpc("invalidateblock", "\"blockhash\"")}, | HelpExampleRpc("invalidateblock", "\"blockhash\"")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
std::string strHash = request.params[0].get_str(); | std::string strHash = request.params[0].get_str(); | ||||
BlockHash hash(uint256S(strHash)); | BlockHash hash(uint256S(strHash)); | ||||
CValidationState state; | CValidationState state; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *pblockindex = LookupBlockIndex(hash); | CBlockIndex *pblockindex = LookupBlockIndex(hash); | ||||
Show All 12 Lines | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state)); | throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state)); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
static UniValue invalidateblock(const Config &config, | static UniValue invalidateblock(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"invalidateblock", | "invalidateblock", | ||||
"\nPermanently marks a block as invalid, as if it " | "\nPermanently marks a block as invalid, as if it violated a consensus " | ||||
"violated a consensus rule.\n", | "rule.\n", | ||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"the hash of the block to mark as invalid"}, | "the hash of the block to mark as invalid"}, | ||||
}, | }, | ||||
RPCResults{}, | RPCResults{}, | ||||
RPCExamples{HelpExampleCli("invalidateblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("invalidateblock", "\"blockhash\"") + | ||||
HelpExampleRpc("invalidateblock", "\"blockhash\"")}, | HelpExampleRpc("invalidateblock", "\"blockhash\"")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
const BlockHash hash(ParseHashV(request.params[0], "blockhash")); | const BlockHash hash(ParseHashV(request.params[0], "blockhash")); | ||||
CValidationState state; | CValidationState state; | ||||
CBlockIndex *pblockindex; | CBlockIndex *pblockindex; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pblockindex = LookupBlockIndex(hash); | pblockindex = LookupBlockIndex(hash); | ||||
Show All 10 Lines | static UniValue invalidateblock(const Config &config, | ||||
if (!state.IsValid()) { | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state)); | throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state)); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
UniValue parkblock(const Config &config, const JSONRPCRequest &request) { | UniValue parkblock(const Config &config, const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"parkblock", | "parkblock", | ||||
"\nMarks a block as parked.\n", | "\nMarks a block as parked.\n", | ||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"the hash of the block to park"}, | "the hash of the block to park"}, | ||||
}, | }, | ||||
RPCResults{}, | RPCResults{}, | ||||
RPCExamples{HelpExampleCli("parkblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("parkblock", "\"blockhash\"") + | ||||
HelpExampleRpc("parkblock", "\"blockhash\"")}, | HelpExampleRpc("parkblock", "\"blockhash\"")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
const std::string strHash = request.params[0].get_str(); | const std::string strHash = request.params[0].get_str(); | ||||
const BlockHash hash(uint256S(strHash)); | const BlockHash hash(uint256S(strHash)); | ||||
CValidationState state; | CValidationState state; | ||||
CBlockIndex *pblockindex; | CBlockIndex *pblockindex; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
Show All 13 Lines | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
static UniValue reconsiderblock(const Config &config, | static UniValue reconsiderblock(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"reconsiderblock", | "reconsiderblock", | ||||
"\nRemoves invalidity status of a block and its descendants, " | "\nRemoves invalidity status of a block and its descendants, " | ||||
"reconsider them for activation.\n" | "reconsider them for activation.\n" | ||||
"This can be used to undo the effects of invalidateblock.\n", | "This can be used to undo the effects of invalidateblock.\n", | ||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"the hash of the block to reconsider"}, | "the hash of the block to reconsider"}, | ||||
}, | }, | ||||
RPCResults{}, | RPCResults{}, | ||||
RPCExamples{HelpExampleCli("reconsiderblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("reconsiderblock", "\"blockhash\"") + | ||||
HelpExampleRpc("reconsiderblock", "\"blockhash\"")}, | HelpExampleRpc("reconsiderblock", "\"blockhash\"")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
const BlockHash hash(ParseHashV(request.params[0], "blockhash")); | const BlockHash hash(ParseHashV(request.params[0], "blockhash")); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *pblockindex = LookupBlockIndex(hash); | CBlockIndex *pblockindex = LookupBlockIndex(hash); | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | ||||
} | } | ||||
ResetBlockFailureFlags(pblockindex); | ResetBlockFailureFlags(pblockindex); | ||||
} | } | ||||
CValidationState state; | CValidationState state; | ||||
ActivateBestChain(config, state); | ActivateBestChain(config, state); | ||||
if (!state.IsValid()) { | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state)); | throw JSONRPCError(RPC_DATABASE_ERROR, FormatStateMessage(state)); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
UniValue unparkblock(const Config &config, const JSONRPCRequest &request) { | UniValue unparkblock(const Config &config, const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 1) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"unparkblock", | "unparkblock", | ||||
"\nRemoves parked status of a block and its descendants, " | "\nRemoves parked status of a block and its descendants, reconsider " | ||||
"reconsider them for activation.\n" | "them for activation.\n" | ||||
"This can be used to undo the effects of parkblock.\n", | "This can be used to undo the effects of parkblock.\n", | ||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"the hash of the block to unpark"}, | "the hash of the block to unpark"}, | ||||
}, | }, | ||||
RPCResults{}, | RPCResults{}, | ||||
RPCExamples{HelpExampleCli("unparkblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("unparkblock", "\"blockhash\"") + | ||||
HelpExampleRpc("unparkblock", "\"blockhash\"")}, | HelpExampleRpc("unparkblock", "\"blockhash\"")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
const std::string strHash = request.params[0].get_str(); | const std::string strHash = request.params[0].get_str(); | ||||
const BlockHash hash(uint256S(strHash)); | const BlockHash hash(uint256S(strHash)); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (mapBlockIndex.count(hash) == 0) { | if (mapBlockIndex.count(hash) == 0) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | ||||
Show All 10 Lines | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
static UniValue getchaintxstats(const Config &config, | static UniValue getchaintxstats(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() > 2) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getchaintxstats", | "getchaintxstats", | ||||
"\nCompute statistics about the total number and rate " | "\nCompute statistics about the total number and rate of transactions " | ||||
"of transactions in the chain.\n", | "in the chain.\n", | ||||
{ | { | ||||
{"nblocks", RPCArg::Type::NUM, /* default */ "one month", | {"nblocks", RPCArg::Type::NUM, /* default */ "one month", | ||||
"Size of the window in number of blocks"}, | "Size of the window in number of blocks"}, | ||||
{"blockhash", RPCArg::Type::STR_HEX, /* default */ "chain tip", | {"blockhash", RPCArg::Type::STR_HEX, /* default */ "chain tip", | ||||
"The hash of the block that ends the window."}, | "The hash of the block that ends the window."}, | ||||
}, | }, | ||||
RPCResult{ | RPCResult{ | ||||
"{\n" | "{\n" | ||||
" \"time\": xxxxx, (numeric) The " | " \"time\": xxxxx, (numeric) The " | ||||
"timestamp for the final block in the window in UNIX format.\n" | "timestamp for the final block in the window in UNIX format.\n" | ||||
" \"txcount\": xxxxx, (numeric) The " | " \"txcount\": xxxxx, (numeric) The total " | ||||
"total number of transactions in the chain up to that point.\n" | "number of transactions in the chain up to that point.\n" | ||||
" \"window_final_block_hash\": \"...\", (string) The " | " \"window_final_block_hash\": \"...\", (string) The hash of " | ||||
"hash of the final block in the window.\n" | "the final block in the window.\n" | ||||
" \"window_block_count\": xxxxx, (numeric) Size of " | " \"window_block_count\": xxxxx, (numeric) Size of the " | ||||
"the window in number of blocks.\n" | "window in number of blocks.\n" | ||||
" \"window_tx_count\": xxxxx, (numeric) The " | " \"window_tx_count\": xxxxx, (numeric) The number " | ||||
"number of transactions in the window. Only returned if " | "of transactions in the window. Only returned if " | ||||
"\"window_block_count\" is > 0.\n" | "\"window_block_count\" is > 0.\n" | ||||
" \"window_interval\": xxxxx, (numeric) The " | " \"window_interval\": xxxxx, (numeric) The elapsed " | ||||
"elapsed time in the window in seconds. Only returned if " | "time in the window in seconds. Only returned if " | ||||
"\"window_block_count\" is > 0.\n" | "\"window_block_count\" is > 0.\n" | ||||
" \"txrate\": x.xx, (numeric) The " | " \"txrate\": x.xx, (numeric) The average " | ||||
"average rate of transactions per second in the window. Only " | "rate of transactions per second in the window. Only returned if " | ||||
"returned if \"window_interval\" is > 0.\n" | "\"window_interval\" is > 0.\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("getchaintxstats", "") + | RPCExamples{HelpExampleCli("getchaintxstats", "") + | ||||
HelpExampleRpc("getchaintxstats", "2016")}, | HelpExampleRpc("getchaintxstats", "2016")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
const CBlockIndex *pindex; | const CBlockIndex *pindex; | ||||
// By default: 1 month | // By default: 1 month | ||||
int blockcount = 30 * 24 * 60 * 60 / | int blockcount = 30 * 24 * 60 * 60 / | ||||
config.GetChainParams().GetConsensus().nPowTargetSpacing; | config.GetChainParams().GetConsensus().nPowTargetSpacing; | ||||
if (request.params[1].isNull()) { | if (request.params[1].isNull()) { | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
// outpoint (needed for the utxo index) + nHeight + fCoinBase | // outpoint (needed for the utxo index) + nHeight + fCoinBase | ||||
static constexpr size_t PER_UTXO_OVERHEAD = | static constexpr size_t PER_UTXO_OVERHEAD = | ||||
sizeof(COutPoint) + sizeof(uint32_t) + sizeof(bool); | sizeof(COutPoint) + sizeof(uint32_t) + sizeof(bool); | ||||
static UniValue getblockstats(const Config &config, | static UniValue getblockstats(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
const RPCHelpMan help{ | RPCHelpMan{ | ||||
"getblockstats", | "getblockstats", | ||||
"\nCompute per block statistics for a given window. All amounts are " | "\nCompute per block statistics for a given window. All amounts are " | ||||
"in " + | "in " + | ||||
CURRENCY_UNIT + | CURRENCY_UNIT + | ||||
".\n" | ".\n" | ||||
"It won't work for some heights with pruning.\n", | "It won't work for some heights with pruning.\n", | ||||
{ | { | ||||
{"hash_or_height", | {"hash_or_height", | ||||
▲ Show 20 Lines • Show All 61 Lines • ▼ Show 20 Lines | RPCHelpMan{ | ||||
"the number of unspent outputs\n" | "the number of unspent outputs\n" | ||||
" \"utxo_size_inc\": xxxxx, (numeric) The increase/decrease in " | " \"utxo_size_inc\": xxxxx, (numeric) The increase/decrease in " | ||||
"size for the utxo index (not discounting op_return and similar)\n" | "size for the utxo index (not discounting op_return and similar)\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli("getblockstats", | RPCExamples{HelpExampleCli("getblockstats", | ||||
"1000 '[\"minfeerate\",\"avgfeerate\"]'") + | "1000 '[\"minfeerate\",\"avgfeerate\"]'") + | ||||
HelpExampleRpc("getblockstats", | HelpExampleRpc("getblockstats", | ||||
"1000 '[\"minfeerate\",\"avgfeerate\"]'")}, | "1000 '[\"minfeerate\",\"avgfeerate\"]'")}, | ||||
}; | |||||
if (request.fHelp || !help.IsValidNumArgs(request.params.size())) { | |||||
throw std::runtime_error(help.ToString()); | |||||
} | } | ||||
.Check(request); | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *pindex; | CBlockIndex *pindex; | ||||
if (request.params[0].isNum()) { | if (request.params[0].isNum()) { | ||||
const int height = request.params[0].get_int(); | const int height = request.params[0].get_int(); | ||||
const int current_tip = ::ChainActive().Height(); | const int current_tip = ::ChainActive().Height(); | ||||
if (height < 0) { | if (height < 0) { | ||||
▲ Show 20 Lines • Show All 184 Lines • ▼ Show 20 Lines | for (const std::string &stat : stats) { | ||||
} | } | ||||
ret.pushKV(stat, value); | ret.pushKV(stat, value); | ||||
} | } | ||||
return ret; | return ret; | ||||
} | } | ||||
static UniValue savemempool(const Config &config, | static UniValue savemempool(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | RPCHelpMan{ | ||||
throw std::runtime_error(RPCHelpMan{ | |||||
"savemempool", | "savemempool", | ||||
"\nDumps the mempool to disk. It will fail until the " | "\nDumps the mempool to disk. It will fail until the previous dump is " | ||||
"previous dump is fully loaded.\n", | "fully loaded.\n", | ||||
{}, | {}, | ||||
RPCResults{}, | RPCResults{}, | ||||
RPCExamples{HelpExampleCli("savemempool", "") + | RPCExamples{HelpExampleCli("savemempool", "") + | ||||
HelpExampleRpc("savemempool", "")}, | HelpExampleRpc("savemempool", "")}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
if (!::g_mempool.IsLoaded()) { | if (!::g_mempool.IsLoaded()) { | ||||
throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet"); | throw JSONRPCError(RPC_MISC_ERROR, "The mempool was not loaded yet"); | ||||
} | } | ||||
if (!DumpMempool(::g_mempool)) { | if (!DumpMempool(::g_mempool)) { | ||||
throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk"); | throw JSONRPCError(RPC_MISC_ERROR, "Unable to dump mempool to disk"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | ~CoinsViewScanReserver() { | ||||
std::lock_guard<std::mutex> lock(g_utxosetscan); | std::lock_guard<std::mutex> lock(g_utxosetscan); | ||||
g_scan_in_progress = false; | g_scan_in_progress = false; | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
static UniValue scantxoutset(const Config &config, | static UniValue scantxoutset(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | RPCHelpMan{ | ||||
request.params.size() > 2) { | |||||
throw std::runtime_error(RPCHelpMan{ | |||||
"scantxoutset", | "scantxoutset", | ||||
"\nEXPERIMENTAL warning: this call may be removed or changed " | "\nEXPERIMENTAL warning: this call may be removed or changed in future " | ||||
"in future releases.\n" | "releases.\n" | ||||
"\nScans the unspent transaction output set for entries that " | "\nScans the unspent transaction output set for entries that match " | ||||
"match certain output descriptors.\n" | "certain output descriptors.\n" | ||||
"Examples of output descriptors are:\n" | "Examples of output descriptors are:\n" | ||||
" addr(<address>) Outputs whose " | " addr(<address>) Outputs whose scriptPubKey " | ||||
"scriptPubKey corresponds to the specified address (does not " | "corresponds to the specified address (does not include P2PK)\n" | ||||
"include P2PK)\n" | " raw(<hex script>) Outputs whose scriptPubKey " | ||||
" raw(<hex script>) Outputs whose " | "equals the specified hex scripts\n" | ||||
"scriptPubKey equals the specified hex scripts\n" | " combo(<pubkey>) P2PK and P2PKH outputs for " | ||||
" combo(<pubkey>) P2PK and P2PKH " | |||||
"outputs for the given pubkey\n" | |||||
" pkh(<pubkey>) P2PKH outputs for " | |||||
"the given pubkey\n" | "the given pubkey\n" | ||||
" sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig " | " pkh(<pubkey>) P2PKH outputs for the given " | ||||
"outputs for the given threshold and pubkeys\n" | "pubkey\n" | ||||
"\nIn the above, <pubkey> either refers to a fixed public key " | " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for " | ||||
"in hexadecimal notation, or to an xpub/xprv optionally " | "the given threshold and pubkeys\n" | ||||
"followed by one\n" | "\nIn the above, <pubkey> either refers to a fixed public key in " | ||||
"or more path elements separated by \"/\", and optionally " | "hexadecimal notation, or to an xpub/xprv optionally followed by one\n" | ||||
"ending in \"/*\" (unhardened), or \"/*'\" or \"/*h\" " | "or more path elements separated by \"/\", and optionally ending in " | ||||
"(hardened) to specify all\n" | "\"/*\" (unhardened), or \"/*'\" or \"/*h\" (hardened) to specify all\n" | ||||
"unhardened or hardened child keys.\n" | "unhardened or hardened child keys.\n" | ||||
"In the latter case, a range needs to be specified by below if " | "In the latter case, a range needs to be specified by below if " | ||||
"different from 1000.\n" | "different from 1000.\n" | ||||
"For more information on output descriptors, see the " | "For more information on output descriptors, see the documentation in " | ||||
"documentation in the doc/descriptors.md file.\n", | "the doc/descriptors.md file.\n", | ||||
{ | { | ||||
{"action", RPCArg::Type::STR, RPCArg::Optional::NO, | {"action", RPCArg::Type::STR, RPCArg::Optional::NO, | ||||
"The action to execute\n" | "The action to execute\n" | ||||
" \"start\" for " | " \"start\" for starting a " | ||||
"starting a scan\n" | "scan\n" | ||||
" \"abort\" for " | " \"abort\" for aborting the " | ||||
"aborting the current scan (returns true when abort was " | "current scan (returns true when abort was successful)\n" | ||||
"successful)\n" | |||||
" \"status\" for " | " \"status\" for " | ||||
"progress report (in %) of the current scan"}, | "progress report (in %) of the current scan"}, | ||||
{"scanobjects", | {"scanobjects", | ||||
RPCArg::Type::ARR, | RPCArg::Type::ARR, | ||||
RPCArg::Optional::NO, | RPCArg::Optional::NO, | ||||
"Array of scan objects\n" | "Array of scan objects\n" | ||||
" Every scan object is " | " Every scan object is either a " | ||||
"either a string descriptor or an object:", | "string descriptor or an object:", | ||||
{ | { | ||||
{"descriptor", RPCArg::Type::STR, | {"descriptor", RPCArg::Type::STR, RPCArg::Optional::OMITTED, | ||||
RPCArg::Optional::OMITTED, "An output descriptor"}, | "An output descriptor"}, | ||||
{ | { | ||||
"", | "", | ||||
RPCArg::Type::OBJ, | RPCArg::Type::OBJ, | ||||
RPCArg::Optional::OMITTED, | RPCArg::Optional::OMITTED, | ||||
"An object with output descriptor and metadata", | "An object with output descriptor and metadata", | ||||
{ | { | ||||
{"desc", RPCArg::Type::STR, RPCArg::Optional::NO, | {"desc", RPCArg::Type::STR, RPCArg::Optional::NO, | ||||
"An output descriptor"}, | "An output descriptor"}, | ||||
{"range", RPCArg::Type::NUM, /* default */ "1000", | {"range", RPCArg::Type::NUM, /* default */ "1000", | ||||
"Up to what child index HD chains should be " | "Up to what child index HD chains should be " | ||||
"explored"}, | "explored"}, | ||||
}, | }, | ||||
}, | }, | ||||
}, | }, | ||||
"[scanobjects,...]"}, | "[scanobjects,...]"}, | ||||
}, | }, | ||||
RPCResult{ | RPCResult{ | ||||
"{\n" | "{\n" | ||||
" \"unspents\": [\n" | " \"unspents\": [\n" | ||||
" {\n" | " {\n" | ||||
" \"txid\" : \"transactionid\", (string) The " | " \"txid\" : \"transactionid\", (string) The transaction id\n" | ||||
"transaction id\n" | |||||
" \"vout\": n, (numeric) the vout value\n" | " \"vout\": n, (numeric) the vout value\n" | ||||
" \"scriptPubKey\" : \"script\", (string) the script " | " \"scriptPubKey\" : \"script\", (string) the script key\n" | ||||
"key\n" | |||||
" \"desc\" : \"descriptor\", (string) A specialized " | " \"desc\" : \"descriptor\", (string) A specialized " | ||||
"descriptor for the matched scriptPubKey\n" | "descriptor for the matched scriptPubKey\n" | ||||
" \"amount\" : x.xxx, (numeric) The total " | " \"amount\" : x.xxx, (numeric) The total amount " | ||||
"amount in " + | "in " + | ||||
CURRENCY_UNIT + | CURRENCY_UNIT + | ||||
" of the unspent output\n" | " of the unspent output\n" | ||||
" \"height\" : n, (numeric) Height of the " | " \"height\" : n, (numeric) Height of the " | ||||
"unspent transaction output\n" | "unspent transaction output\n" | ||||
" }\n" | " }\n" | ||||
" ,...], \n" | " ,...], \n" | ||||
" \"total_amount\" : x.xxx, (numeric) The total " | " \"total_amount\" : x.xxx, (numeric) The total amount of " | ||||
"amount of all found unspent outputs in " + | "all found unspent outputs in " + | ||||
CURRENCY_UNIT + | CURRENCY_UNIT + | ||||
"\n" | "\n" | ||||
"]\n"}, | "]\n"}, | ||||
RPCExamples{""}, | RPCExamples{""}, | ||||
} | } | ||||
.ToString()); | .Check(request); | ||||
} | |||||
RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}); | RPCTypeCheck(request.params, {UniValue::VSTR, UniValue::VARR}); | ||||
UniValue result(UniValue::VOBJ); | UniValue result(UniValue::VOBJ); | ||||
if (request.params[0].get_str() == "status") { | if (request.params[0].get_str() == "status") { | ||||
CoinsViewScanReserver reserver; | CoinsViewScanReserver reserver; | ||||
if (reserver.reserve()) { | if (reserver.reserve()) { | ||||
// no scan in progress | // no scan in progress | ||||
▲ Show 20 Lines • Show All 120 Lines • ▼ Show 20 Lines | static UniValue scantxoutset(const Config &config, | ||||
} else { | } else { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid command"); | throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid command"); | ||||
} | } | ||||
return result; | return result; | ||||
} | } | ||||
static UniValue getblockfilter(const Config &config, | static UniValue getblockfilter(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | RPCHelpMan{ | ||||
request.params.size() > 2) { | |||||
throw std::runtime_error(RPCHelpMan{ | |||||
"getblockfilter", | "getblockfilter", | ||||
"\nRetrieve a BIP 157 content filter for a particular block.\n", | "\nRetrieve a BIP 157 content filter for a particular block.\n", | ||||
{ | { | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"The hash of the block"}, | "The hash of the block"}, | ||||
{"filtertype", RPCArg::Type::STR, /*default*/ "basic", | {"filtertype", RPCArg::Type::STR, /*default*/ "basic", | ||||
"The type name of the filter"}, | "The type name of the filter"}, | ||||
}, | }, | ||||
RPCResult{"{\n" | RPCResult{"{\n" | ||||
" \"filter\" : (string) the hex-encoded filter data\n" | " \"filter\" : (string) the hex-encoded filter data\n" | ||||
" \"header\" : (string) the hex-encoded filter header\n" | " \"header\" : (string) the hex-encoded filter header\n" | ||||
"}\n"}, | "}\n"}, | ||||
RPCExamples{HelpExampleCli( | RPCExamples{HelpExampleCli("getblockfilter", | ||||
"getblockfilter", | "\"00000000c937983704a73af28acdec37b049d214a" | ||||
"\"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6" | "dbda81d7e2a3dd146f6ed09\" \"basic\"")}} | ||||
"ed09\" \"basic\"")}}.ToString()); | .Check(request); | ||||
} | |||||
const BlockHash block_hash(ParseHashV(request.params[0], "blockhash")); | const BlockHash block_hash(ParseHashV(request.params[0], "blockhash")); | ||||
std::string filtertype_name = "basic"; | std::string filtertype_name = "basic"; | ||||
if (!request.params[1].isNull()) { | if (!request.params[1].isNull()) { | ||||
filtertype_name = request.params[1].get_str(); | filtertype_name = request.params[1].get_str(); | ||||
} | } | ||||
BlockFilterType filtertype; | BlockFilterType filtertype; | ||||
▲ Show 20 Lines • Show All 102 Lines • Show Last 20 Lines |