Skip to content

Commit d3cdc63

Browse files
committed
wallet: add rescanblockchain <start_height> <stop_height> RPC command.
Adaptation of btc@c77170fbdbdfcd2ba830a1755450a2e5469f4e35
1 parent 4d0fa79 commit d3cdc63

File tree

6 files changed

+84
-11
lines changed

6 files changed

+84
-11
lines changed

src/qt/pivx/settings/settingsbittoolwidget.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ void SettingsBitToolWidget::importAddressFromDecKey()
312312

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

318318
ui->statusLabel_DEC->setStyleSheet("QLabel { color: green; }");

src/rpc/client.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ static const CRPCConvertParam vRPCConvertParams[] = {
149149
{ "getblockindexstats", 1 },
150150
{ "getfeeinfo", 0 },
151151
{ "getsupplyinfo", 0 },
152+
{ "rescanblockchain", 0},
153+
{ "rescanblockchain", 1},
152154
};
153155

154156
class CRPCConvertTable

src/wallet/rpcdump.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ UniValue importprivkey(const JSONRPCRequest& request)
144144
// cold staking was activated after nBlockTimeProtocolV2 (PIVX v4.0). No need to scan the whole chain
145145
pindex = chainActive[Params().GetConsensus().vUpgrades[Consensus::UPGRADE_V4_0].nActivationHeight];
146146
}
147-
pwalletMain->ScanForWalletTransactions(pindex, true);
147+
pwalletMain->ScanForWalletTransactions(pindex, nullptr, true);
148148
}
149149
}
150150

@@ -231,7 +231,7 @@ UniValue importaddress(const JSONRPCRequest& request)
231231
}
232232

233233
if (fRescan) {
234-
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
234+
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), nullptr, true);
235235
pwalletMain->ReacceptWalletTransactions();
236236
}
237237

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

277277
if (fRescan) {
278-
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
278+
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), nullptr, true);
279279
pwalletMain->ReacceptWalletTransactions();
280280
}
281281

@@ -697,7 +697,7 @@ UniValue bip38decrypt(const JSONRPCRequest& request)
697697

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

703703
return result;
@@ -791,7 +791,7 @@ UniValue importsaplingkey(const JSONRPCRequest& request)
791791

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

797797
return result;
@@ -884,7 +884,7 @@ UniValue importsaplingviewingkey(const JSONRPCRequest& request)
884884

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

890890
return result;

src/wallet/rpcwallet.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4179,6 +4179,67 @@ UniValue getsaplingnotescount(const JSONRPCRequest& request)
41794179
return count;
41804180
}
41814181

4182+
UniValue rescanblockchain(const JSONRPCRequest& request)
4183+
{
4184+
if (request.fHelp || request.params.size() > 2) {
4185+
throw std::runtime_error(
4186+
"rescanblockchain (start_height) (stop_height)\n"
4187+
"\nRescan the local blockchain for wallet related transactions.\n"
4188+
"\nArguments:\n"
4189+
"1. start_height (numeric, optional) block height where the rescan should start\n"
4190+
"2. stop_height (numeric, optional) the last block height that should be scanned\n"
4191+
"\nResult:\n"
4192+
"{\n"
4193+
" start_height (numeric) The block height where the rescan has started. If omitted, rescan started from the genesis block.\n"
4194+
" stop_height (numeric) The height of the last rescanned block. If omitted, rescan stopped at the chain tip.\n"
4195+
"}\n"
4196+
"\nExamples:\n"
4197+
+ HelpExampleCli("rescanblockchain", "100000 120000")
4198+
+ HelpExampleRpc("rescanblockchain", "100000 120000")
4199+
);
4200+
}
4201+
4202+
EnsureWallet();
4203+
LOCK2(cs_main, pwalletMain->cs_wallet);
4204+
4205+
CBlockIndex *pindexStart = chainActive.Genesis();
4206+
CBlockIndex *pindexStop = nullptr;
4207+
if (!request.params[0].isNull()) {
4208+
pindexStart = chainActive[request.params[0].get_int()];
4209+
if (!pindexStart) {
4210+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid start_height");
4211+
}
4212+
}
4213+
4214+
if (!request.params[1].isNull()) {
4215+
pindexStop = chainActive[request.params[1].get_int()];
4216+
if (!pindexStop) {
4217+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid stop_height");
4218+
}
4219+
else if (pindexStop->nHeight < pindexStart->nHeight) {
4220+
throw JSONRPCError(RPC_INVALID_PARAMETER, "stop_height must be greater then start_height");
4221+
}
4222+
}
4223+
4224+
CBlockIndex *stopBlock = pwalletMain->ScanForWalletTransactions(pindexStart, pindexStop, true);
4225+
if (!stopBlock) {
4226+
// future: backport abort rescan
4227+
//if (pwalletMain->IsAbortingRescan()) {
4228+
// throw JSONRPCError(RPC_MISC_ERROR, "Rescan aborted.");
4229+
//}
4230+
// if we got a nullptr returned, ScanForWalletTransactions did rescan up to the requested stopindex
4231+
stopBlock = pindexStop ? pindexStop : chainActive.Tip();
4232+
}
4233+
else {
4234+
throw JSONRPCError(RPC_MISC_ERROR, "Rescan failed. Potentially corrupted data files.");
4235+
}
4236+
4237+
UniValue response(UniValue::VOBJ);
4238+
response.pushKV("start_height", pindexStart->nHeight);
4239+
response.pushKV("stop_height", stopBlock->nHeight);
4240+
return response;
4241+
}
4242+
41824243
extern UniValue dumpprivkey(const JSONRPCRequest& request); // in rpcdump.cpp
41834244
extern UniValue importprivkey(const JSONRPCRequest& request);
41844245
extern UniValue importaddress(const JSONRPCRequest& request);
@@ -4243,6 +4304,7 @@ static const CRPCCommand commands[] =
42434304
{ "wallet", "walletlock", &walletlock, true },
42444305
{ "wallet", "walletpassphrasechange", &walletpassphrasechange, true },
42454306
{ "wallet", "walletpassphrase", &walletpassphrase, true },
4307+
{ "wallet", "rescanblockchain", &rescanblockchain, true },
42464308
{ "wallet", "delegatoradd", &delegatoradd, true },
42474309
{ "wallet", "delegatorremove", &delegatorremove, true },
42484310
{ "wallet", "bip38encrypt", &bip38encrypt, true },

src/wallet/wallet.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,17 +1776,23 @@ bool CWallet::Upgrade(std::string& error, const int& prevVersion)
17761776
* from or to us. If fUpdate is true, found transactions that already
17771777
* exist in the wallet will be updated.
17781778
*
1779+
* If pindexStop is not a nullptr, the scan will stop at the block-index
1780+
* defined by pindexStop
1781+
*
17791782
* Returns null if scan was successful. Otherwise, if a complete rescan was not
17801783
* possible (due to pruning or corruption), returns pointer to the most recent
17811784
* block that could not be scanned.
17821785
*/
1783-
CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate, bool fromStartup)
1786+
CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop, bool fUpdate, bool fromStartup)
17841787
{
17851788
CBlockIndex* ret = nullptr;
17861789
int64_t nNow = GetTime();
1787-
17881790
const Consensus::Params& consensus = Params().GetConsensus();
17891791

1792+
if (pindexStop) {
1793+
assert(pindexStop->nHeight >= pindexStart->nHeight);
1794+
}
1795+
17901796
CBlockIndex* pindex = pindexStart;
17911797
{
17921798
LOCK(cs_main);
@@ -1858,6 +1864,9 @@ CBlockIndex* CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool f
18581864
ChainTipAdded(pindex, &block, saplingTree);
18591865
}
18601866
}
1867+
if (pindex == pindexStop) {
1868+
break;
1869+
}
18611870
pindex = chainActive.Next(pindex);
18621871
}
18631872
}
@@ -4201,7 +4210,7 @@ CWallet* CWallet::CreateWalletFromFile(const std::string walletFile)
42014210
uiInterface.InitMessage(_("Rescanning..."));
42024211
LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
42034212
const int64_t nWalletRescanTime = GetTimeMillis();
4204-
if (walletInstance->ScanForWalletTransactions(pindexRescan, true, true) != nullptr) {
4213+
if (walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, true, true) != nullptr) {
42054214
UIError(_("Shutdown requested over the txs scan. Exiting."));
42064215
return nullptr;
42074216
}

src/wallet/wallet.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,7 +863,7 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
863863
bool Upgrade(std::string& error, const int& prevVersion);
864864
bool ActivateSaplingWallet(bool memOnly = false);
865865

866-
CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false, bool fromStartup = false);
866+
CBlockIndex* ScanForWalletTransactions(CBlockIndex* pindexStart, CBlockIndex* pindexStop = nullptr, bool fUpdate = false, bool fromStartup = false);
867867
void TransactionRemovedFromMempool(const CTransactionRef &ptx) override;
868868
void ReacceptWalletTransactions(bool fFirstLoad = false);
869869
void ResendWalletTransactions(CConnman* connman) override;

0 commit comments

Comments
 (0)