Skip to content

Commit

Permalink
wallet: add rescanblockchain <start_height> <stop_height> RPC command.
Browse files Browse the repository at this point in the history
Adaptation of btc@c77170fbdbdfcd2ba830a1755450a2e5469f4e35
  • Loading branch information
furszy committed Mar 10, 2021
1 parent 4d0fa79 commit d3cdc63
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/qt/pivx/settings/settingsbittoolwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ void SettingsBitToolWidget::importAddressFromDecKey()

// whenever a key is imported, we need to scan the whole chain
pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value'
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), nullptr, true);
}

ui->statusLabel_DEC->setStyleSheet("QLabel { color: green; }");
Expand Down
2 changes: 2 additions & 0 deletions src/rpc/client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ static const CRPCConvertParam vRPCConvertParams[] = {
{ "getblockindexstats", 1 },
{ "getfeeinfo", 0 },
{ "getsupplyinfo", 0 },
{ "rescanblockchain", 0},
{ "rescanblockchain", 1},
};

class CRPCConvertTable
Expand Down
12 changes: 6 additions & 6 deletions src/wallet/rpcdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
// cold staking was activated after nBlockTimeProtocolV2 (PIVX v4.0). No need to scan the whole chain
pindex = chainActive[Params().GetConsensus().vUpgrades[Consensus::UPGRADE_V4_0].nActivationHeight];
}
pwalletMain->ScanForWalletTransactions(pindex, true);
pwalletMain->ScanForWalletTransactions(pindex, nullptr, true);
}
}

Expand Down Expand Up @@ -231,7 +231,7 @@ UniValue importaddress(const JSONRPCRequest& request)
}

if (fRescan) {
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), nullptr, true);
pwalletMain->ReacceptWalletTransactions();
}

Expand Down Expand Up @@ -275,7 +275,7 @@ UniValue importpubkey(const JSONRPCRequest& request)
ImportScript(GetScriptForRawPubKey(pubKey), strLabel, false);

if (fRescan) {
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), nullptr, true);
pwalletMain->ReacceptWalletTransactions();
}

Expand Down Expand Up @@ -697,7 +697,7 @@ UniValue bip38decrypt(const JSONRPCRequest& request)

// whenever a key is imported, we need to scan the whole chain
pwalletMain->nTimeFirstKey = 1; // 0 would be considered 'no value'
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), nullptr, true);
}

return result;
Expand Down Expand Up @@ -791,7 +791,7 @@ UniValue importsaplingkey(const JSONRPCRequest& request)

// We want to scan for transactions and notes
if (fRescan) {
pwalletMain->ScanForWalletTransactions(chainActive[nRescanHeight], true);
pwalletMain->ScanForWalletTransactions(chainActive[nRescanHeight], nullptr, true);
}

return result;
Expand Down Expand Up @@ -884,7 +884,7 @@ UniValue importsaplingviewingkey(const JSONRPCRequest& request)

// We want to scan for transactions and notes
if (fRescan) {
pwalletMain->ScanForWalletTransactions(chainActive[nRescanHeight], true);
pwalletMain->ScanForWalletTransactions(chainActive[nRescanHeight], nullptr, true);
}

return result;
Expand Down
62 changes: 62 additions & 0 deletions src/wallet/rpcwallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4179,6 +4179,67 @@ UniValue getsaplingnotescount(const JSONRPCRequest& request)
return count;
}

UniValue rescanblockchain(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() > 2) {
throw std::runtime_error(
"rescanblockchain (start_height) (stop_height)\n"
"\nRescan the local blockchain for wallet related transactions.\n"
"\nArguments:\n"
"1. start_height (numeric, optional) block height where the rescan should start\n"
"2. stop_height (numeric, optional) the last block height that should be scanned\n"
"\nResult:\n"
"{\n"
" start_height (numeric) The block height where the rescan has started. If omitted, rescan started from the genesis block.\n"
" stop_height (numeric) The height of the last rescanned block. If omitted, rescan stopped at the chain tip.\n"
"}\n"
"\nExamples:\n"
+ HelpExampleCli("rescanblockchain", "100000 120000")
+ HelpExampleRpc("rescanblockchain", "100000 120000")
);
}

EnsureWallet();
LOCK2(cs_main, pwalletMain->cs_wallet);

CBlockIndex *pindexStart = chainActive.Genesis();
CBlockIndex *pindexStop = nullptr;
if (!request.params[0].isNull()) {
pindexStart = chainActive[request.params[0].get_int()];
if (!pindexStart) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
}
}

if (!request.params[1].isNull()) {
pindexStop = chainActive[request.params[1].get_int()];
if (!pindexStop) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
}
else if (pindexStop->nHeight < pindexStart->nHeight) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater then start_height");
}
}

CBlockIndex *stopBlock = pwalletMain->ScanForWalletTransactions(pindexStart, pindexStop, true);
if (!stopBlock) {
// future: backport abort rescan
//if (pwalletMain->IsAbortingRescan()) {
// throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
//}
// if we got a nullptr returned, ScanForWalletTransactions did rescan up to the requested stopindex
stopBlock = pindexStop ? pindexStop : chainActive.Tip();
}
else {
throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
}

UniValue response(UniValue::VOBJ);
response.pushKV("start_height", pindexStart->nHeight);
response.pushKV("stop_height", stopBlock->nHeight);
return response;
}

extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
extern UniValue importprivkey(const JSONRPCRequest& request);
extern UniValue importaddress(const JSONRPCRequest& request);
Expand Down Expand Up @@ -4243,6 +4304,7 @@ static const CRPCCommand commands[] =
{ "wallet", "walletlock", &walletlock, true },
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
{ "wallet", "walletpassphrase", &walletpassphrase, true },
{ "wallet", "rescanblockchain", &rescanblockchain, true },
{ "wallet", "delegatoradd", &delegatoradd, true },
{ "wallet", "delegatorremove", &delegatorremove, true },
{ "wallet", "bip38encrypt", &bip38encrypt, true },
Expand Down
15 changes: 12 additions & 3 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1776,17 +1776,23 @@ bool CWallet::Upgrade(std::string& error, const int& prevVersion)
* from or to us. If fUpdate is true, found transactions that already
* exist in the wallet will be updated.
*
* If pindexStop is not a nullptr, the scan will stop at the block-index
* defined by pindexStop
*
* Returns null if scan was successful. Otherwise, if a complete rescan was not
* possible (due to pruning or corruption), returns pointer to the most recent
* block that could not be scanned.
*/
CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, bool fromStartup)
CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, bool fUpdate, bool fromStartup)
{
CBlockIndex* ret = nullptr;
int64_t nNow = GetTime();

const Consensus::Params& consensus = Params().GetConsensus();

if (pindexStop) {
assert(pindexStop->nHeight >= pindexStart->nHeight);
}

CBlockIndex* pindex = pindexStart;
{
LOCK(cs_main);
Expand Down Expand Up @@ -1858,6 +1864,9 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
ChainTipAdded(pindex, &block, saplingTree);
}
}
if (pindex == pindexStop) {
break;
}
pindex = chainActive.Next(pindex);
}
}
Expand Down Expand Up @@ -4201,7 +4210,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
uiInterface.InitMessage(_("Rescanning..."));
LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
const int64_t nWalletRescanTime = GetTimeMillis();
if (walletInstance->ScanForWalletTransactions(pindexRescan, true, true) != nullptr) {
if (walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, true, true) != nullptr) {
UIError(_("Shutdown requested over the txs scan. Exiting."));
return nullptr;
}
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
bool Upgrade(std::string& error, const int& prevVersion);
bool ActivateSaplingWallet(bool memOnly = false);

CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false, bool fromStartup = false);
CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop = nullptr, bool fUpdate = false, bool fromStartup = false);
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
void ReacceptWalletTransactions(bool fFirstLoad = false);
void ResendWalletTransactions(CConnman* connman) override;
Expand Down

0 comments on commit d3cdc63

Please sign in to comment.