Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/rpcwallet.cpp
Show First 20 Lines • Show All 1,757 Lines • ▼ Show 20 Lines | UniValue listtransactions(const Config &config, const JSONRPCRequest &request) { | ||||
UniValue result{UniValue::VARR}; | UniValue result{UniValue::VARR}; | ||||
// Return oldest to newest | // Return oldest to newest | ||||
result.push_backV({txs.rend() - nFrom - nCount, txs.rend() - nFrom}); | result.push_backV({txs.rend() - nFrom - nCount, txs.rend() - nFrom}); | ||||
return result; | return result; | ||||
} | } | ||||
static UniValue listsinceblock(const Config &config, | static UniValue listsinceblock(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); | std::shared_ptr<CWallet> const pwallet = | ||||
const CWallet *const pwallet = wallet.get(); | GetWalletForJSONRPCRequest(request); | ||||
if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { | if (!EnsureWalletIsAvailable(pwallet.get(), request.fHelp)) { | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
RPCHelpMan{ | RPCHelpMan{ | ||||
"listsinceblock", | "listsinceblock", | ||||
"Get all transactions in blocks since block [blockhash], or all " | "Get all transactions in blocks since block [blockhash], or all " | ||||
"transactions if omitted.\n" | "transactions if omitted.\n" | ||||
"If \"blockhash\" is no longer a part of the main chain, transactions " | "If \"blockhash\" is no longer a part of the main chain, transactions " | ||||
▲ Show 20 Lines • Show All 103 Lines • ▼ Show 20 Lines | RPCHelpMan{ | ||||
"\"000000000000000bacf66f7497b7dc45ef753ee9a" | "\"000000000000000bacf66f7497b7dc45ef753ee9a" | ||||
"7d38571037cdb1a57f663ad\" 6") + | "7d38571037cdb1a57f663ad\" 6") + | ||||
HelpExampleRpc("listsinceblock", | HelpExampleRpc("listsinceblock", | ||||
"\"000000000000000bacf66f7497b7dc45ef753ee9a" | "\"000000000000000bacf66f7497b7dc45ef753ee9a" | ||||
"7d38571037cdb1a57f663ad\", 6")}, | "7d38571037cdb1a57f663ad\", 6")}, | ||||
} | } | ||||
.Check(request); | .Check(request); | ||||
const CWallet &wallet = *pwallet; | |||||
// Make sure the results are valid at least up to the most recent block | // Make sure the results are valid at least up to the most recent block | ||||
// the user could have gotten from another RPC command prior to now | // the user could have gotten from another RPC command prior to now | ||||
pwallet->BlockUntilSyncedToCurrentChain(); | wallet.BlockUntilSyncedToCurrentChain(); | ||||
LOCK(pwallet->cs_wallet); | LOCK(wallet.cs_wallet); | ||||
// Height of the specified block or the common ancestor, if the block | // Height of the specified block or the common ancestor, if the block | ||||
// provided was in a deactivated chain. | // provided was in a deactivated chain. | ||||
std::optional<int> height; | std::optional<int> height; | ||||
// Height of the specified block, even if it's in a deactivated chain. | // Height of the specified block, even if it's in a deactivated chain. | ||||
std::optional<int> altheight; | std::optional<int> altheight; | ||||
int target_confirms = 1; | int target_confirms = 1; | ||||
isminefilter filter = ISMINE_SPENDABLE; | isminefilter filter = ISMINE_SPENDABLE; | ||||
BlockHash blockId; | BlockHash blockId; | ||||
if (!request.params[0].isNull() && !request.params[0].get_str().empty()) { | if (!request.params[0].isNull() && !request.params[0].get_str().empty()) { | ||||
blockId = BlockHash(ParseHashV(request.params[0], "blockhash")); | blockId = BlockHash(ParseHashV(request.params[0], "blockhash")); | ||||
height.emplace(); | height = int{}; | ||||
altheight.emplace(); | altheight = int{}; | ||||
if (!pwallet->chain().findCommonAncestor( | if (!wallet.chain().findCommonAncestor( | ||||
blockId, pwallet->GetLastBlockHash(), | blockId, wallet.GetLastBlockHash(), | ||||
/* ancestor out */ FoundBlock().height(*height), | /* ancestor out */ FoundBlock().height(*height), | ||||
/* blockId out */ FoundBlock().height(*altheight))) { | /* blockId out */ FoundBlock().height(*altheight))) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | ||||
} | } | ||||
} | } | ||||
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 (ParseIncludeWatchonly(request.params[2], *pwallet)) { | if (ParseIncludeWatchonly(request.params[2], wallet)) { | ||||
filter |= ISMINE_WATCH_ONLY; | filter |= ISMINE_WATCH_ONLY; | ||||
} | } | ||||
bool include_removed = | bool include_removed = | ||||
(request.params[3].isNull() || request.params[3].get_bool()); | (request.params[3].isNull() || request.params[3].get_bool()); | ||||
int depth = height ? pwallet->GetLastBlockHeight() + 1 - *height : -1; | int depth = height ? wallet.GetLastBlockHeight() + 1 - *height : -1; | ||||
UniValue transactions(UniValue::VARR); | UniValue transactions(UniValue::VARR); | ||||
for (const std::pair<const TxId, CWalletTx> &pairWtx : pwallet->mapWallet) { | for (const std::pair<const TxId, CWalletTx> &pairWtx : wallet.mapWallet) { | ||||
const CWalletTx &tx = pairWtx.second; | const CWalletTx &tx = pairWtx.second; | ||||
if (depth == -1 || tx.GetDepthInMainChain() < depth) { | if (depth == -1 || tx.GetDepthInMainChain() < depth) { | ||||
ListTransactions(pwallet, tx, 0, true, transactions, filter, | ListTransactions(&wallet, tx, 0, true, transactions, filter, | ||||
nullptr /* filter_label */); | nullptr /* filter_label */); | ||||
} | } | ||||
} | } | ||||
// when a reorg'd block is requested, we also list any relevant transactions | // when a reorg'd block is requested, we also list any relevant transactions | ||||
// in the blocks of the chain that was detached | // in the blocks of the chain that was detached | ||||
UniValue removed(UniValue::VARR); | UniValue removed(UniValue::VARR); | ||||
while (include_removed && altheight && *altheight > *height) { | while (include_removed && altheight && *altheight > *height) { | ||||
CBlock block; | CBlock block; | ||||
if (!pwallet->chain().findBlock(blockId, FoundBlock().data(block)) || | if (!wallet.chain().findBlock(blockId, FoundBlock().data(block)) || | ||||
block.IsNull()) { | block.IsNull()) { | ||||
throw JSONRPCError(RPC_INTERNAL_ERROR, | throw JSONRPCError(RPC_INTERNAL_ERROR, | ||||
"Can't read block from disk"); | "Can't read block from disk"); | ||||
} | } | ||||
for (const CTransactionRef &tx : block.vtx) { | for (const CTransactionRef &tx : block.vtx) { | ||||
auto it = pwallet->mapWallet.find(tx->GetId()); | auto it = wallet.mapWallet.find(tx->GetId()); | ||||
if (it != pwallet->mapWallet.end()) { | if (it != wallet.mapWallet.end()) { | ||||
// We want all transactions regardless of confirmation count to | // We want all transactions regardless of confirmation count to | ||||
// appear here, even negative confirmation ones, hence the big | // appear here, even negative confirmation ones, hence the big | ||||
// negative. | // negative. | ||||
ListTransactions(pwallet, it->second, -100000000, true, removed, | ListTransactions(&wallet, it->second, -100000000, true, removed, | ||||
filter, nullptr /* filter_label */); | filter, nullptr /* filter_label */); | ||||
} | } | ||||
} | } | ||||
blockId = block.hashPrevBlock; | blockId = block.hashPrevBlock; | ||||
--*altheight; | --*altheight; | ||||
} | } | ||||
BlockHash lastblock; | BlockHash lastblock; | ||||
CHECK_NONFATAL(pwallet->chain().findAncestorByHeight( | CHECK_NONFATAL(wallet.chain().findAncestorByHeight( | ||||
pwallet->GetLastBlockHash(), | wallet.GetLastBlockHash(), | ||||
pwallet->GetLastBlockHeight() + 1 - target_confirms, | wallet.GetLastBlockHeight() + 1 - target_confirms, | ||||
FoundBlock().hash(lastblock))); | FoundBlock().hash(lastblock))); | ||||
UniValue ret(UniValue::VOBJ); | UniValue ret(UniValue::VOBJ); | ||||
ret.pushKV("transactions", transactions); | ret.pushKV("transactions", transactions); | ||||
if (include_removed) { | if (include_removed) { | ||||
ret.pushKV("removed", removed); | ret.pushKV("removed", removed); | ||||
} | } | ||||
ret.pushKV("lastblock", lastblock.GetHex()); | ret.pushKV("lastblock", lastblock.GetHex()); | ||||
▲ Show 20 Lines • Show All 3,115 Lines • Show Last 20 Lines |