diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index fe628097a..6c005068d 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -292,6 +292,70 @@ UniValue getrawmempool(const UniValue& params, bool fHelp) return mempoolToJSON(fVerbose); } +UniValue getmempoolancestors(const UniValue& params, bool fHelp) +{ + if (fHelp || params.size() < 1 || params.size() > 2) { + throw runtime_error( + "getmempoolancestors txid (verbose)\n" + "\nIf txid is in the mempool, returns all in-mempool ancestors.\n" + "\nArguments:\n" + "1. \"txid\" (string, required) The transaction id (must be in mempool)\n" + "2. verbose (boolean, optional, default=false) true for a json object, false for array of transaction ids\n" + "\nResult (for verbose=false):\n" + "[ (json array of string)\n" + " \"transactionid\" (string) The transaction id of an in-mempool ancestor transaction\n" + " ,...\n" + "]\n" + "\nResult (for verbose=true):\n" + "{ (json object)\n" + " \"transactionid\" : { (json object)\n" + + EntryDescriptionString() + + " }, ...\n" + "}\n" + "\nExamples\n" + + HelpExampleCli("getmempoolancestors", "\"mytxid\"") + + HelpExampleRpc("getmempoolancestors", "\"mytxid\"") + ); + } + + bool fVerbose = false; + if (params.size() > 1) + fVerbose = params[1].get_bool(); + + uint256 hash = ParseHashV(params[0], "parameter 1"); + + LOCK(mempool.cs); + + CTxMemPool::txiter it = mempool.mapTx.find(hash); + if (it == mempool.mapTx.end()) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not in mempool"); + } + + CTxMemPool::setEntries setAncestors; + uint64_t noLimit = std::numeric_limits::max(); + std::string dummy; + mempool.CalculateMemPoolAncestors(*it, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false); + + if (!fVerbose) { + UniValue o(UniValue::VARR); + BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) { + o.push_back(ancestorIt->GetTx().GetHash().ToString()); + } + + return o; + } else { + UniValue o(UniValue::VOBJ); + BOOST_FOREACH(CTxMemPool::txiter ancestorIt, setAncestors) { + const CTxMemPoolEntry &e = *ancestorIt; + const uint256& hash = e.GetTx().GetHash(); + UniValue info(UniValue::VOBJ); + entryToJSON(info, e); + o.push_back(Pair(hash.ToString(), info)); + } + return o; + } +} + UniValue getblockhash(const UniValue& params, bool fHelp) { if (fHelp || params.size() != 1) @@ -1016,6 +1080,7 @@ static const CRPCCommand commands[] = { "blockchain", "getblockheader", &getblockheader, true }, { "blockchain", "getchaintips", &getchaintips, true }, { "blockchain", "getdifficulty", &getdifficulty, true }, + { "blockchain", "getmempoolancestors", &getmempoolancestors, true }, { "blockchain", "getmempoolinfo", &getmempoolinfo, true }, { "blockchain", "getrawmempool", &getrawmempool, true }, { "blockchain", "gettxout", &gettxout, true }, diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index c89af6bfa..3dfc27fff 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -102,6 +102,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "prioritisetransaction", 2 }, { "setban", 2 }, { "setban", 3 }, + { "getmempoolancestors", 1 }, }; class CRPCConvertTable