@@ -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+ " \n Rescan the local blockchain for wallet related transactions.\n "
4188+ " \n Arguments:\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+ " \n Result:\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+ " \n Examples:\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+
41824243extern UniValue dumpprivkey (const JSONRPCRequest& request); // in rpcdump.cpp
41834244extern UniValue importprivkey (const JSONRPCRequest& request);
41844245extern 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 },
0 commit comments