mirror of
https://github.com/kvazar-network/kevacoin.git
synced 2025-01-23 21:34:45 +00:00
listsinceblock: optionally find and list any transactions that were undone due to reorg when requesting a non-main chain block in a new 'removed' array.
This commit is contained in:
parent
6adc3a3732
commit
f999c46cae
@ -68,6 +68,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
|
|||||||
{ "getblocktemplate", 0, "template_request" },
|
{ "getblocktemplate", 0, "template_request" },
|
||||||
{ "listsinceblock", 1, "target_confirmations" },
|
{ "listsinceblock", 1, "target_confirmations" },
|
||||||
{ "listsinceblock", 2, "include_watchonly" },
|
{ "listsinceblock", 2, "include_watchonly" },
|
||||||
|
{ "listsinceblock", 3, "include_removed" },
|
||||||
{ "sendmany", 1, "amounts" },
|
{ "sendmany", 1, "amounts" },
|
||||||
{ "sendmany", 2, "minconf" },
|
{ "sendmany", 2, "minconf" },
|
||||||
{ "sendmany", 4, "subtractfeefrom" },
|
{ "sendmany", 4, "subtractfeefrom" },
|
||||||
|
@ -1426,6 +1426,17 @@ static void MaybePushAddress(UniValue & entry, const CTxDestination &dest)
|
|||||||
entry.push_back(Pair("address", addr.ToString()));
|
entry.push_back(Pair("address", addr.ToString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List transactions based on the given criteria.
|
||||||
|
*
|
||||||
|
* @param pwallet The wallet.
|
||||||
|
* @param wtx The wallet transaction.
|
||||||
|
* @param strAccount The account, if any, or "*" for all.
|
||||||
|
* @param nMinDepth The minimum confirmation depth.
|
||||||
|
* @param fLong Whether to include the JSON version of the transaction.
|
||||||
|
* @param ret The UniValue into which the result is stored.
|
||||||
|
* @param filter The "is mine" filter bool.
|
||||||
|
*/
|
||||||
void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
|
void ListTransactions(CWallet* const pwallet, const CWalletTx& wtx, const std::string& strAccount, int nMinDepth, bool fLong, UniValue& ret, const isminefilter& filter)
|
||||||
{
|
{
|
||||||
CAmount nFee;
|
CAmount nFee;
|
||||||
@ -1742,14 +1753,18 @@ UniValue listsinceblock(const JSONRPCRequest& request)
|
|||||||
return NullUniValue;
|
return NullUniValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.fHelp || request.params.size() > 3)
|
if (request.fHelp || request.params.size() > 4)
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
"listsinceblock ( \"blockhash\" target_confirmations include_watchonly)\n"
|
"listsinceblock ( \"blockhash\" target_confirmations include_watchonly include_removed )\n"
|
||||||
"\nGet all transactions in blocks since block [blockhash], or all transactions if omitted\n"
|
"\nGet all transactions in blocks since block [blockhash], or all transactions if omitted.\n"
|
||||||
|
"If \"blockhash\" is no longer a part of the main chain, transactions from the fork point onward are included.\n"
|
||||||
|
"Additionally, if include_removed is set, transactions affecting the wallet which were removed are returned in the \"removed\" array.\n"
|
||||||
"\nArguments:\n"
|
"\nArguments:\n"
|
||||||
"1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
|
"1. \"blockhash\" (string, optional) The block hash to list transactions since\n"
|
||||||
"2. target_confirmations: (numeric, optional) The confirmations required, must be 1 or more\n"
|
"2. target_confirmations: (numeric, optional, default=1) The confirmations required, must be 1 or more\n"
|
||||||
"3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')"
|
"3. include_watchonly: (bool, optional, default=false) Include transactions to watch-only addresses (see 'importaddress')\n"
|
||||||
|
"4. include_removed: (bool, optional, default=true) Show transactions that were removed due to a reorg in the \"removed\" array\n"
|
||||||
|
" (not guaranteed to work on pruned nodes)\n"
|
||||||
"\nResult:\n"
|
"\nResult:\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" \"transactions\": [\n"
|
" \"transactions\": [\n"
|
||||||
@ -1774,7 +1789,11 @@ UniValue listsinceblock(const JSONRPCRequest& request)
|
|||||||
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
|
" \"comment\": \"...\", (string) If a comment is associated with the transaction.\n"
|
||||||
" \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
|
" \"label\" : \"label\" (string) A comment for the address/transaction, if any\n"
|
||||||
" \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
|
" \"to\": \"...\", (string) If a comment to is associated with the transaction.\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
|
" \"removed\": [\n"
|
||||||
|
" <structure is the same as \"transactions\" above, only present if include_removed=true>\n"
|
||||||
|
" Note: transactions that were readded in the active chain will appear as-is in this array, and may thus have a positive confirmation count.\n"
|
||||||
|
" ],\n"
|
||||||
" \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
|
" \"lastblock\": \"lastblockhash\" (string) The hash of the last block\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\nExamples:\n"
|
"\nExamples:\n"
|
||||||
@ -1785,21 +1804,19 @@ UniValue listsinceblock(const JSONRPCRequest& request)
|
|||||||
|
|
||||||
LOCK2(cs_main, pwallet->cs_wallet);
|
LOCK2(cs_main, pwallet->cs_wallet);
|
||||||
|
|
||||||
const CBlockIndex *pindex = NULL;
|
const CBlockIndex* pindex = NULL; // Block index of the specified block or the common ancestor, if the block provided was in a deactivated chain.
|
||||||
|
const CBlockIndex* paltindex = NULL; // Block index of the specified block, even if it's in a deactivated chain.
|
||||||
int target_confirms = 1;
|
int target_confirms = 1;
|
||||||
isminefilter filter = ISMINE_SPENDABLE;
|
isminefilter filter = ISMINE_SPENDABLE;
|
||||||
|
|
||||||
if (!request.params[0].isNull())
|
if (!request.params[0].isNull()) {
|
||||||
{
|
|
||||||
uint256 blockId;
|
uint256 blockId;
|
||||||
|
|
||||||
blockId.SetHex(request.params[0].get_str());
|
blockId.SetHex(request.params[0].get_str());
|
||||||
BlockMap::iterator it = mapBlockIndex.find(blockId);
|
BlockMap::iterator it = mapBlockIndex.find(blockId);
|
||||||
if (it != mapBlockIndex.end())
|
if (it != mapBlockIndex.end()) {
|
||||||
{
|
paltindex = pindex = it->second;
|
||||||
pindex = it->second;
|
if (chainActive[pindex->nHeight] != pindex) {
|
||||||
if (chainActive[pindex->nHeight] != pindex)
|
|
||||||
{
|
|
||||||
// the block being asked for is a part of a deactivated chain;
|
// the block being asked for is a part of a deactivated chain;
|
||||||
// we don't want to depend on its perceived height in the block
|
// we don't want to depend on its perceived height in the block
|
||||||
// chain, we want to instead use the last common ancestor
|
// chain, we want to instead use the last common ancestor
|
||||||
@ -1808,19 +1825,20 @@ UniValue listsinceblock(const JSONRPCRequest& request)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!request.params[1].isNull())
|
if (!request.params[1].isNull()) {
|
||||||
{
|
|
||||||
target_confirms = request.params[1].get_int();
|
target_confirms = request.params[1].get_int();
|
||||||
|
|
||||||
if (target_confirms < 1)
|
if (target_confirms < 1) {
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.params.size() > 2 && request.params[2].get_bool())
|
if (!request.params[2].isNull() && request.params[2].get_bool()) {
|
||||||
{
|
|
||||||
filter = filter | ISMINE_WATCH_ONLY;
|
filter = filter | ISMINE_WATCH_ONLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool include_removed = (request.params[3].isNull() || request.params[3].get_bool());
|
||||||
|
|
||||||
int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
|
int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
|
||||||
|
|
||||||
UniValue transactions(UniValue::VARR);
|
UniValue transactions(UniValue::VARR);
|
||||||
@ -1828,8 +1846,27 @@ UniValue listsinceblock(const JSONRPCRequest& request)
|
|||||||
for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
|
for (const std::pair<uint256, CWalletTx>& pairWtx : pwallet->mapWallet) {
|
||||||
CWalletTx tx = pairWtx.second;
|
CWalletTx tx = pairWtx.second;
|
||||||
|
|
||||||
if (depth == -1 || tx.GetDepthInMainChain() < depth)
|
if (depth == -1 || tx.GetDepthInMainChain() < depth) {
|
||||||
ListTransactions(pwallet, tx, "*", 0, true, transactions, filter);
|
ListTransactions(pwallet, tx, "*", 0, true, transactions, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// when a reorg'd block is requested, we also list any relevant transactions
|
||||||
|
// in the blocks of the chain that was detached
|
||||||
|
UniValue removed(UniValue::VARR);
|
||||||
|
while (include_removed && paltindex && paltindex != pindex) {
|
||||||
|
CBlock block;
|
||||||
|
if (!ReadBlockFromDisk(block, paltindex, Params().GetConsensus())) {
|
||||||
|
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
|
||||||
|
}
|
||||||
|
for (const CTransactionRef& tx : block.vtx) {
|
||||||
|
if (pwallet->mapWallet.count(tx->GetHash()) > 0) {
|
||||||
|
// We want all transactions regardless of confirmation count to appear here,
|
||||||
|
// even negative confirmation ones, hence the big negative.
|
||||||
|
ListTransactions(pwallet, pwallet->mapWallet[tx->GetHash()], "*", -100000000, true, removed, filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paltindex = paltindex->pprev;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
|
CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
|
||||||
@ -1837,6 +1874,7 @@ UniValue listsinceblock(const JSONRPCRequest& request)
|
|||||||
|
|
||||||
UniValue ret(UniValue::VOBJ);
|
UniValue ret(UniValue::VOBJ);
|
||||||
ret.push_back(Pair("transactions", transactions));
|
ret.push_back(Pair("transactions", transactions));
|
||||||
|
if (include_removed) ret.push_back(Pair("removed", removed));
|
||||||
ret.push_back(Pair("lastblock", lastblock.GetHex()));
|
ret.push_back(Pair("lastblock", lastblock.GetHex()));
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -3082,7 +3120,7 @@ static const CRPCCommand commands[] =
|
|||||||
{ "wallet", "listlockunspent", &listlockunspent, false, {} },
|
{ "wallet", "listlockunspent", &listlockunspent, false, {} },
|
||||||
{ "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, {"minconf","include_empty","include_watchonly"} },
|
{ "wallet", "listreceivedbyaccount", &listreceivedbyaccount, false, {"minconf","include_empty","include_watchonly"} },
|
||||||
{ "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","include_empty","include_watchonly"} },
|
{ "wallet", "listreceivedbyaddress", &listreceivedbyaddress, false, {"minconf","include_empty","include_watchonly"} },
|
||||||
{ "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly"} },
|
{ "wallet", "listsinceblock", &listsinceblock, false, {"blockhash","target_confirmations","include_watchonly","include_removed"} },
|
||||||
{ "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} },
|
{ "wallet", "listtransactions", &listtransactions, false, {"account","count","skip","include_watchonly"} },
|
||||||
{ "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
|
{ "wallet", "listunspent", &listunspent, false, {"minconf","maxconf","addresses","include_unsafe","query_options"} },
|
||||||
{ "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
|
{ "wallet", "lockunspent", &lockunspent, true, {"unlock","transactions"} },
|
||||||
|
Loading…
x
Reference in New Issue
Block a user