Add getspecialtxes rpc (#2668)
* Add getspecialtxes rpc Returns an array of special transactions found in the specified block * small help text tweak * add comments
This commit is contained in:
parent
34dee23386
commit
23eb70cb77
@ -9,6 +9,7 @@
|
|||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
#include "checkpoints.h"
|
#include "checkpoints.h"
|
||||||
#include "coins.h"
|
#include "coins.h"
|
||||||
|
#include "core_io.h"
|
||||||
#include "consensus/validation.h"
|
#include "consensus/validation.h"
|
||||||
#include "instantx.h"
|
#include "instantx.h"
|
||||||
#include "validation.h"
|
#include "validation.h"
|
||||||
@ -1620,6 +1621,113 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
|
|||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UniValue getspecialtxes(const JSONRPCRequest& request)
|
||||||
|
{
|
||||||
|
if (request.fHelp || request.params.size() < 1 || request.params.size() > 5)
|
||||||
|
throw std::runtime_error(
|
||||||
|
"getspecialtxes \"blockhash\" ( type count skip verbosity ) \n"
|
||||||
|
"Returns an array of special transactions found in the specified block\n"
|
||||||
|
"\nIf verbosity is 0, returns tx hash for each transaction.\n"
|
||||||
|
"If verbosity is 1, returns hex-encoded data for each transaction.\n"
|
||||||
|
"If verbosity is 2, returns an Object with information for each transaction.\n"
|
||||||
|
"\nArguments:\n"
|
||||||
|
"1. \"blockhash\" (string, required) The block hash\n"
|
||||||
|
"2. type (numeric, optional, default=-1) Filter special txes by type, -1 means all types\n"
|
||||||
|
"3. count (numeric, optional, default=10) The number of transactions to return\n"
|
||||||
|
"4. skip (numeric, optional, default=0) The number of transactions to skip\n"
|
||||||
|
"5. verbosity (numeric, optional, default=0) 0 for hashes, 1 for hex-encoded data, and 2 for json object\n"
|
||||||
|
"\nResult (for verbosity = 0):\n"
|
||||||
|
"[\n"
|
||||||
|
" \"txid\" : \"xxxx\", (string) The transaction id\n"
|
||||||
|
"]\n"
|
||||||
|
"\nResult (for verbosity = 1):\n"
|
||||||
|
"[\n"
|
||||||
|
" \"data\", (string) A string that is serialized, hex-encoded data for the transaction\n"
|
||||||
|
"]\n"
|
||||||
|
"\nResult (for verbosity = 2):\n"
|
||||||
|
"[ (array of Objects) The transactions in the format of the getrawtransaction RPC.\n"
|
||||||
|
" ...,\n"
|
||||||
|
"]\n"
|
||||||
|
"\nExamples:\n"
|
||||||
|
+ HelpExampleCli("getspecialtxes", "\"00000000000fd08c2fb661d2fcb0d49abb3a91e5f27082ce64feed3b4dede2e2\"")
|
||||||
|
+ HelpExampleRpc("getspecialtxes", "\"00000000000fd08c2fb661d2fcb0d49abb3a91e5f27082ce64feed3b4dede2e2\"")
|
||||||
|
);
|
||||||
|
|
||||||
|
LOCK(cs_main);
|
||||||
|
|
||||||
|
std::string strHash = request.params[0].get_str();
|
||||||
|
uint256 hash(uint256S(strHash));
|
||||||
|
|
||||||
|
int nTxType = -1;
|
||||||
|
if (request.params.size() > 1) {
|
||||||
|
nTxType = request.params[1].get_int();
|
||||||
|
}
|
||||||
|
|
||||||
|
int nCount = 10;
|
||||||
|
if (request.params.size() > 2) {
|
||||||
|
nCount = request.params[2].get_int();
|
||||||
|
if (nCount < 0)
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative count");
|
||||||
|
}
|
||||||
|
|
||||||
|
int nSkip = 0;
|
||||||
|
if (request.params.size() > 3) {
|
||||||
|
nSkip = request.params[3].get_int();
|
||||||
|
if (nSkip < 0)
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative skip");
|
||||||
|
}
|
||||||
|
|
||||||
|
int nVerbosity = 0;
|
||||||
|
if (request.params.size() > 4) {
|
||||||
|
nVerbosity = request.params[4].get_int();
|
||||||
|
if (nVerbosity < 0 || nVerbosity > 2) {
|
||||||
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Verbosity must be in range 0..2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapBlockIndex.count(hash) == 0)
|
||||||
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||||
|
|
||||||
|
CBlock block;
|
||||||
|
CBlockIndex* pblockindex = mapBlockIndex[hash];
|
||||||
|
|
||||||
|
if (fHavePruned && !(pblockindex->nStatus & BLOCK_HAVE_DATA) && pblockindex->nTx > 0)
|
||||||
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Block not available (pruned data)");
|
||||||
|
|
||||||
|
if(!ReadBlockFromDisk(block, pblockindex, Params().GetConsensus()))
|
||||||
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
|
||||||
|
|
||||||
|
int nTxNum = 0;
|
||||||
|
UniValue result(UniValue::VARR);
|
||||||
|
for(const auto& tx : block.vtx)
|
||||||
|
{
|
||||||
|
if (tx->nVersion != 3 || tx->nType == TRANSACTION_NORMAL // ensure it's in fact a special tx
|
||||||
|
|| (nTxType != -1 && tx->nType != nTxType)) { // ensure special tx type matches filter, if given
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nTxNum++;
|
||||||
|
if (nTxNum <= nSkip) continue;
|
||||||
|
if (nTxNum > nSkip + nCount) break;
|
||||||
|
|
||||||
|
switch (nVerbosity)
|
||||||
|
{
|
||||||
|
case 0 : result.push_back(tx->GetHash().GetHex()); break;
|
||||||
|
case 1 : result.push_back(EncodeHexTx(*tx)); break;
|
||||||
|
case 2 :
|
||||||
|
{
|
||||||
|
UniValue objTx(UniValue::VOBJ);
|
||||||
|
TxToJSON(*tx, uint256(), objTx);
|
||||||
|
result.push_back(objTx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default : throw JSONRPCError(RPC_INTERNAL_ERROR, "Unsupported verbosity");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static const CRPCCommand commands[] =
|
static const CRPCCommand commands[] =
|
||||||
{ // category name actor (function) okSafe argNames
|
{ // category name actor (function) okSafe argNames
|
||||||
// --------------------- ------------------------ ----------------------- ------ ----------
|
// --------------------- ------------------------ ----------------------- ------ ----------
|
||||||
@ -1638,6 +1746,7 @@ static const CRPCCommand commands[] =
|
|||||||
{ "blockchain", "getmempoolentry", &getmempoolentry, true, {"txid"} },
|
{ "blockchain", "getmempoolentry", &getmempoolentry, true, {"txid"} },
|
||||||
{ "blockchain", "getmempoolinfo", &getmempoolinfo, true, {} },
|
{ "blockchain", "getmempoolinfo", &getmempoolinfo, true, {} },
|
||||||
{ "blockchain", "getrawmempool", &getrawmempool, true, {"verbose"} },
|
{ "blockchain", "getrawmempool", &getrawmempool, true, {"verbose"} },
|
||||||
|
{ "blockchain", "getspecialtxes", &getspecialtxes, true, {"blockhash", "type", "count", "skip", "verbosity"} },
|
||||||
{ "blockchain", "gettxout", &gettxout, true, {"txid","n","include_mempool"} },
|
{ "blockchain", "gettxout", &gettxout, true, {"txid","n","include_mempool"} },
|
||||||
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, {} },
|
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, {} },
|
||||||
{ "blockchain", "pruneblockchain", &pruneblockchain, true, {"height"} },
|
{ "blockchain", "pruneblockchain", &pruneblockchain, true, {"height"} },
|
||||||
|
@ -154,6 +154,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "getaddressdeltas", 0, "addresses" },
|
{ "getaddressdeltas", 0, "addresses" },
|
||||||
{ "getaddressutxos", 0, "addresses" },
|
{ "getaddressutxos", 0, "addresses" },
|
||||||
{ "getaddressmempool", 0, "addresses" },
|
{ "getaddressmempool", 0, "addresses" },
|
||||||
|
{ "getspecialtxes", 1, "type" },
|
||||||
|
{ "getspecialtxes", 2, "count" },
|
||||||
|
{ "getspecialtxes", 3, "skip" },
|
||||||
|
{ "getspecialtxes", 4, "verbosity" },
|
||||||
// Echo with conversion (For testing only)
|
// Echo with conversion (For testing only)
|
||||||
{ "echojson", 0, "arg0" },
|
{ "echojson", 0, "arg0" },
|
||||||
{ "echojson", 1, "arg1" },
|
{ "echojson", 1, "arg1" },
|
||||||
|
Loading…
Reference in New Issue
Block a user