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:
UdjinM6 2019-01-30 21:53:22 +03:00 committed by Alexander Block
parent 34dee23386
commit 23eb70cb77
2 changed files with 113 additions and 0 deletions

View File

@ -9,6 +9,7 @@
#include "chainparams.h"
#include "checkpoints.h"
#include "coins.h"
#include "core_io.h"
#include "consensus/validation.h"
#include "instantx.h"
#include "validation.h"
@ -1620,6 +1621,113 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
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[] =
{ // category name actor (function) okSafe argNames
// --------------------- ------------------------ ----------------------- ------ ----------
@ -1638,6 +1746,7 @@ static const CRPCCommand commands[] =
{ "blockchain", "getmempoolentry", &getmempoolentry, true, {"txid"} },
{ "blockchain", "getmempoolinfo", &getmempoolinfo, true, {} },
{ "blockchain", "getrawmempool", &getrawmempool, true, {"verbose"} },
{ "blockchain", "getspecialtxes", &getspecialtxes, true, {"blockhash", "type", "count", "skip", "verbosity"} },
{ "blockchain", "gettxout", &gettxout, true, {"txid","n","include_mempool"} },
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, {} },
{ "blockchain", "pruneblockchain", &pruneblockchain, true, {"height"} },

View File

@ -154,6 +154,10 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "getaddressdeltas", 0, "addresses" },
{ "getaddressutxos", 0, "addresses" },
{ "getaddressmempool", 0, "addresses" },
{ "getspecialtxes", 1, "type" },
{ "getspecialtxes", 2, "count" },
{ "getspecialtxes", 3, "skip" },
{ "getspecialtxes", 4, "verbosity" },
// Echo with conversion (For testing only)
{ "echojson", 0, "arg0" },
{ "echojson", 1, "arg1" },