@@ -3169,6 +3169,81 @@ UniValue generate(const JSONRPCRequest& request)
31693169 return generateBlocks (coinbase_script, num_generate, max_tries, true );
31703170}
31713171
3172+ UniValue rescanblockchain (const JSONRPCRequest& request)
3173+ {
3174+ CWallet * const pwallet = GetWalletForJSONRPCRequest (request);
3175+ if (!EnsureWalletIsAvailable (pwallet, request.fHelp )) {
3176+ return NullUniValue;
3177+ }
3178+
3179+ if (request.fHelp || request.params .size () > 2 ) {
3180+ throw std::runtime_error (
3181+ " rescanblockchain (\" start_height\" ) (\" stop_height\" )\n "
3182+ " \n Rescan the local blockchain for wallet related transactions.\n "
3183+ " \n Arguments:\n "
3184+ " 1. \" start_height\" (numeric, optional) block height where the rescan should start\n "
3185+ " 2. \" stop_height\" (numeric, optional) the last block height that should be scanned\n "
3186+ " \n Result:\n "
3187+ " {\n "
3188+ " \" start_height\" (numeric) The block height where the rescan has started. If omitted, rescan started from the genesis block.\n "
3189+ " \" stop_height\" (numeric) The height of the last rescanned block. If omitted, rescan stopped at the chain tip.\n "
3190+ " }\n "
3191+ " \n Examples:\n "
3192+ + HelpExampleCli (" rescanblockchain" , " 100000 120000" )
3193+ + HelpExampleRpc (" rescanblockchain" , " 100000 120000" )
3194+ );
3195+ }
3196+
3197+ LOCK2 (cs_main, pwallet->cs_wallet );
3198+
3199+ CBlockIndex *pindexStart = chainActive.Genesis ();
3200+ CBlockIndex *pindexStop = nullptr ;
3201+ if (!request.params [0 ].isNull ()) {
3202+ pindexStart = chainActive[request.params [0 ].get_int ()];
3203+ if (!pindexStart) {
3204+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid start_height" );
3205+ }
3206+ }
3207+
3208+ if (!request.params [1 ].isNull ()) {
3209+ pindexStop = chainActive[request.params [1 ].get_int ()];
3210+ if (!pindexStop) {
3211+ throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid stop_height" );
3212+ }
3213+ else if (pindexStop->nHeight < pindexStart->nHeight ) {
3214+ throw JSONRPCError (RPC_INVALID_PARAMETER, " stop_height must be greater then start_height" );
3215+ }
3216+ }
3217+
3218+ // We can't rescan beyond non-pruned blocks, stop and throw an error
3219+ if (fPruneMode ) {
3220+ CBlockIndex *block = pindexStop ? pindexStop : chainActive.Tip ();
3221+ while (block && block->nHeight >= pindexStart->nHeight ) {
3222+ if (!(block->nStatus & BLOCK_HAVE_DATA)) {
3223+ throw JSONRPCError (RPC_MISC_ERROR, " Can't rescan beyond pruned data. Use RPC call getblockchaininfo to determine your pruned height." );
3224+ }
3225+ block = block->pprev ;
3226+ }
3227+ }
3228+
3229+ CBlockIndex *stopBlock = pwallet->ScanForWalletTransactions (pindexStart, pindexStop, true );
3230+ if (!stopBlock) {
3231+ if (pwallet->IsAbortingRescan ()) {
3232+ throw JSONRPCError (RPC_MISC_ERROR, " Rescan aborted." );
3233+ }
3234+ // if we got a nullptr returned, ScanForWalletTransactions did rescan up to the requested stopindex
3235+ stopBlock = pindexStop ? pindexStop : chainActive.Tip ();
3236+ }
3237+ else {
3238+ throw JSONRPCError (RPC_MISC_ERROR, " Rescan failed. Potentially corrupted data files." );
3239+ }
3240+
3241+ UniValue response (UniValue::VOBJ);
3242+ response.pushKV (" start_height" , pindexStart->nHeight );
3243+ response.pushKV (" stop_height" , stopBlock->nHeight );
3244+ return response;
3245+ }
3246+
31723247extern UniValue abortrescan (const JSONRPCRequest& request); // in rpcdump.cpp
31733248extern UniValue dumpprivkey (const JSONRPCRequest& request); // in rpcdump.cpp
31743249extern UniValue importprivkey (const JSONRPCRequest& request);
@@ -3179,6 +3254,7 @@ extern UniValue importwallet(const JSONRPCRequest& request);
31793254extern UniValue importprunedfunds (const JSONRPCRequest& request);
31803255extern UniValue removeprunedfunds (const JSONRPCRequest& request);
31813256extern UniValue importmulti (const JSONRPCRequest& request);
3257+ extern UniValue rescanblockchain (const JSONRPCRequest& request);
31823258
31833259static const CRPCCommand commands[] =
31843260{ // category name actor (function) argNames
@@ -3233,6 +3309,7 @@ static const CRPCCommand commands[] =
32333309 { " wallet" , " walletpassphrasechange" , &walletpassphrasechange, {" oldpassphrase" ," newpassphrase" } },
32343310 { " wallet" , " walletpassphrase" , &walletpassphrase, {" passphrase" ," timeout" } },
32353311 { " wallet" , " removeprunedfunds" , &removeprunedfunds, {" txid" } },
3312+ { " wallet" , " rescanblockchain" , &rescanblockchain, {" start_height" , " stop_height" } },
32363313
32373314 { " generating" , " generate" , &generate, {" nblocks" ," maxtries" } },
32383315};
0 commit comments