@@ -3150,6 +3150,81 @@ UniValue generate(const JSONRPCRequest& request)
31503150}
31513151#endif // ENABLE_MINING
31523152
3153+ UniValue rescanblockchain (const JSONRPCRequest& request)
3154+ {
3155+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
3156+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
3157+ return NullUniValue;
3158+ }
3159+
3160+ if (request.fHelp || request.params .size () > 2 ) {
3161+ throw std::runtime_error (
3162+ " rescanblockchain (\" start_height\" ) (\" stop_height\" )\n "
3163+ " \n Rescan the local blockchain for wallet related transactions.\n "
3164+ " \n Arguments:\n "
3165+ " 1. \" start_height\" (numeric, optional) block height where the rescan should start\n "
3166+ " 2. \" stop_height\" (numeric, optional) the last block height that should be scanned\n "
3167+ " \n Result:\n "
3168+ " {\n "
3169+ " \" start_height\" (numeric) The block height where the rescan has started. If omitted, rescan started from the genesis block.\n "
3170+ " \" stop_height\" (numeric) The height of the last rescanned block. If omitted, rescan stopped at the chain tip.\n "
3171+ " }\n "
3172+ " \n Examples:\n "
3173+ + HelpExampleCli (" rescanblockchain" , " 100000 120000" )
3174+ + HelpExampleRpc (" rescanblockchain" , " 100000 120000" )
3175+ );
3176+ }
3177+
3178+ LOCK2 (cs_main, pwallet->cs_wallet );
3179+
3180+ CBlockIndex *pindexStart = chainActive.Genesis ();
3181+ CBlockIndex *pindexStop = nullptr ;
3182+ if (!request.params [0 ].isNull ()) {
3183+ pindexStart = chainActive[request.params [0 ].get_int ()];
3184+ if (!pindexStart) {
3185+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid start_height" );
3186+ }
3187+ }
3188+
3189+ if (!request.params [1 ].isNull ()) {
3190+ pindexStop = chainActive[request.params [1 ].get_int ()];
3191+ if (!pindexStop) {
3192+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid stop_height" );
3193+ }
3194+ else if (pindexStop->nHeight < pindexStart->nHeight ) {
3195+ throw JSONRPCError (RPC_INVALID_PARAMETER, " stop_height must be greater then start_height" );
3196+ }
3197+ }
3198+
3199+ // We can't rescan beyond non-pruned blocks, stop and throw an error
3200+ if (fPruneMode ) {
3201+ CBlockIndex *block = pindexStop ? pindexStop : chainActive.Tip ();
3202+ while (block && block->nHeight >= pindexStart->nHeight ) {
3203+ if (!(block->nStatus & BLOCK_HAVE_DATA)) {
3204+ throw JSONRPCError (RPC_MISC_ERROR, " Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height." );
3205+ }
3206+ block = block->pprev ;
3207+ }
3208+ }
3209+
3210+ CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions (pindexStart, pindexStop, true );
3211+ if (!stopBlock) {
3212+ if (pwallet->IsAbortingRescan ()) {
3213+ throw JSONRPCError (RPC_MISC_ERROR, " Rescan aborted." );
3214+ }
3215+ // if we got a nullptr returned, ScanForWalletTransactions did rescan up to the requested stopindex
3216+ stopBlock = pindexStop ? pindexStop : chainActive.Tip ();
3217+ }
3218+ else {
3219+ throw JSONRPCError (RPC_MISC_ERROR, " Rescan failed. Potentially corrupted data files." );
3220+ }
3221+
3222+ UniValue response (UniValue::VOBJ);
3223+ response.pushKV (" start_height" , pindexStart->nHeight );
3224+ response.pushKV (" stop_height" , stopBlock->nHeight );
3225+ return response;
3226+ }
3227+
31533228extern UniValue abortrescan (const JSONRPCRequest& request); // in rpcdump.cpp
31543229extern UniValue dumpprivkey (const JSONRPCRequest& request); // in rpcdump.cpp
31553230extern UniValue importprivkey (const JSONRPCRequest& request);
@@ -3160,6 +3235,7 @@ extern UniValue importwallet(const JSONRPCRequest& request);
31603235extern UniValue importprunedfunds (const JSONRPCRequest& request);
31613236extern UniValue removeprunedfunds (const JSONRPCRequest& request);
31623237extern UniValue importmulti (const JSONRPCRequest& request);
3238+ extern UniValue rescanblockchain (const JSONRPCRequest& request);
31633239
31643240extern UniValue dumphdinfo (const JSONRPCRequest& request);
31653241extern UniValue importelectrumwallet (const JSONRPCRequest& request);
@@ -3218,6 +3294,7 @@ static const CRPCCommand commands[] =
32183294 { " wallet" , " walletpassphrasechange" , &walletpassphrasechange, {" oldpassphrase" ," newpassphrase" } },
32193295 { " wallet" , " walletpassphrase" , &walletpassphrase, {" passphrase" ," timeout" ," mixingonly" } },
32203296 { " wallet" , " removeprunedfunds" , &removeprunedfunds, {" txid" } },
3297+ { " wallet" , " rescanblockchain" , &rescanblockchain, {" start_height" , " stop_height" } },
32213298
32223299#if ENABLE_MINER
32233300 { " generating" , " generate" , &generate, {" nblocks" ," maxtries" } },
0 commit comments