aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/rpcdump.cpp
diff options
context:
space:
mode:
authorRussell Yanofsky <russ@yanofsky.org>2017-05-15 09:11:03 -0400
committerRussell Yanofsky <russ@yanofsky.org>2017-05-15 09:11:03 -0400
commit4d2d6045a4784d576d56299244b9f76a5909904b (patch)
tree1bdbce291ea8d01c9b47173f04b8fd0dae9ffd98 /src/wallet/rpcdump.cpp
parent41987aa92f0d6c0bee4d4b4889355fbd1dedeede (diff)
Fix importmulti failure to return rescan errors
An off-by-one-block bug in importmulti rescan logic could cause it to return success in an edge case even when a rescan was not successful. The case where this would happen is if there were multiple blocks in a row with the same GetBlockTimeMax() value, and the last block was scanned successfully, but one or more of the earlier blocks was not readable.
Diffstat (limited to 'src/wallet/rpcdump.cpp')
-rw-r--r--src/wallet/rpcdump.cpp21
1 files changed, 16 insertions, 5 deletions
diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp
index 82708dab26..37cdaf121e 100644
--- a/src/wallet/rpcdump.cpp
+++ b/src/wallet/rpcdump.cpp
@@ -1121,13 +1121,13 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
if (fRescan && fRunScan && requests.size()) {
CBlockIndex* pindex = nLowestTimestamp > minimumTimestamp ? chainActive.FindEarliestAtLeast(std::max<int64_t>(nLowestTimestamp - TIMESTAMP_WINDOW, 0)) : chainActive.Genesis();
- CBlockIndex* scannedRange = nullptr;
+ CBlockIndex* scanFailed = nullptr;
if (pindex) {
- scannedRange = pwallet->ScanForWalletTransactions(pindex, true);
+ scanFailed = pwallet->ScanForWalletTransactions(pindex, true);
pwallet->ReacceptWalletTransactions();
}
- if (!scannedRange || scannedRange->nHeight > pindex->nHeight) {
+ if (scanFailed) {
std::vector<UniValue> results = response.getValues();
response.clear();
response.setArray();
@@ -1137,12 +1137,23 @@ UniValue importmulti(const JSONRPCRequest& mainRequest)
// range, or if the import result already has an error set, let
// the result stand unmodified. Otherwise replace the result
// with an error message.
- if (GetImportTimestamp(request, now) - TIMESTAMP_WINDOW >= scannedRange->GetBlockTimeMax() || results.at(i).exists("error")) {
+ if (GetImportTimestamp(request, now) - TIMESTAMP_WINDOW > scanFailed->GetBlockTimeMax() || results.at(i).exists("error")) {
response.push_back(results.at(i));
} else {
UniValue result = UniValue(UniValue::VOBJ);
result.pushKV("success", UniValue(false));
- result.pushKV("error", JSONRPCError(RPC_MISC_ERROR, strprintf("Failed to rescan before time %d, transactions may be missing.", scannedRange->GetBlockTimeMax())));
+ result.pushKV(
+ "error",
+ JSONRPCError(
+ RPC_MISC_ERROR,
+ strprintf("Rescan failed for key with creation timestamp %d. There was an error reading a "
+ "block from time %d, which is after or within %d seconds of key creation, and "
+ "could contain transactions pertaining to the key. As a result, transactions "
+ "and coins using this key may not appear in the wallet. This error could be "
+ "caused by pruning or data corruption (see bitcoind log for details) and could "
+ "be dealt with by downloading and rescanning the relevant blocks (see -reindex "
+ "and -rescan options).",
+ GetImportTimestamp(request, now), scanFailed->GetBlockTimeMax(), TIMESTAMP_WINDOW)));
response.push_back(std::move(result));
}
++i;