Skip to content

Commit

Permalink
Add getspecialtxes rpc (#2668)
Browse files Browse the repository at this point in the history
* Add getspecialtxes rpc

Returns an array of special transactions found in the specified block

* small help text tweak

* add comments
  • Loading branch information
UdjinM6 committed Jan 30, 2019
1 parent ca6c8f5 commit 5d1c97d
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 0 deletions.
109 changes: 109 additions & 0 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -1633,6 +1634,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
// --------------------- ------------------------ ----------------------- ------ ----------
Expand All @@ -1651,6 +1759,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"} },
Expand Down
4 changes: 4 additions & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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" },
Expand Down

0 comments on commit 5d1c97d

Please sign in to comment.