Skip to content

Commit f43f896

Browse files
committed
Wallet Repair Improved
Separates coin base / stake orphans from mismatched outputs. Makes sure there are no failed outputs in stake miner's cache.
1 parent 9d719d1 commit f43f896

File tree

4 files changed

+96
-66
lines changed

4 files changed

+96
-66
lines changed

src/init.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -418,11 +418,11 @@ bool AppInit2()
418418
nMinerSleep = GetArg("-minersleep", 2000);
419419
/* Minimal input time or depth in block chain for stake mining, in hours or confirmations */
420420
if(fTestNet) {
421-
nStakeMinTime = GetArg("-stakemintime", 1);
422-
nStakeMinDepth = GetArg("-stakemindepth", 0);
421+
nStakeMinTime = (uint)GetArg("-stakemintime", 1);
422+
nStakeMinDepth = (uint)GetArg("-stakemindepth", 0);
423423
} else {
424-
nStakeMinTime = GetArg("-stakemintime", 48);
425-
nStakeMinDepth = GetArg("-stakemindepth", 0);
424+
nStakeMinTime = (uint)GetArg("-stakemintime", 48);
425+
nStakeMinDepth = (uint)GetArg("-stakemindepth", 0);
426426
}
427427
/* Reset time if depth is specified */
428428
if(nStakeMinDepth) nStakeMinTime = 0;

src/qt/bitcoingui.cpp

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,21 +1160,22 @@ void BitcoinGUI::inspectWallet() {
11601160

11611161
walletModel->repairWallet(nMismatchSpent, nOrphansFound, nBalanceInQuestion, true);
11621162

1163-
if(!nMismatchSpent)
1163+
if(!nMismatchSpent && !nOrphansFound)
11641164
notificator->notify(Notificator::Warning,
11651165
tr("Wallet Inspection Report"),
11661166
tr("Integrity test passed, nothing to fix.\n"));
11671167
else
11681168
notificator->notify(Notificator::Warning,
11691169
tr("Wallet Inspection Report"),
11701170
tr("Integrity test failed!\n\n"
1171-
"Mismatched coins found: %1\n"
1172-
"Amount in question: %2\n"
1173-
"Orphans found: %3\n\n"
1171+
"Orphans found: %1\n"
1172+
"Mismatched outputs detected: %2\n"
1173+
"Amount in question: %3\n\n"
11741174
"Please clone your wallet and repair it.\n")
1175+
.arg(nOrphansFound)
11751176
.arg(nMismatchSpent)
1176-
.arg(BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), nBalanceInQuestion, true))
1177-
.arg(nOrphansFound));
1177+
.arg(BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(),
1178+
nBalanceInQuestion, true)));
11781179
}
11791180

11801181
void BitcoinGUI::repairWallet() {
@@ -1187,19 +1188,20 @@ void BitcoinGUI::repairWallet() {
11871188

11881189
walletModel->repairWallet(nMismatchSpent, nOrphansFound, nBalanceInQuestion, false);
11891190

1190-
if(!nMismatchSpent)
1191+
if(!nMismatchSpent && !nOrphansFound)
11911192
notificator->notify(Notificator::Warning,
11921193
tr("Wallet Repair Report"),
11931194
tr("Integrity test passed, nothing to fix.\n"));
11941195
else
11951196
notificator->notify(Notificator::Warning,
11961197
tr("Wallet Repair Report"),
11971198
tr("Wallet repaired successfully!\n\n"
1198-
"Mismatched coins found: %1\n"
1199-
"Amount affected by repair: %2\n"
1200-
"Orphans removed: %3\n")
1199+
"Orphans removed: %1\n"
1200+
"Mismatched outputs corrected: %2\n"
1201+
"Amount affected by repair: %3\n")
1202+
.arg(nOrphansFound)
12011203
.arg(nMismatchSpent)
1202-
.arg(BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), nBalanceInQuestion, true))
1203-
.arg(nOrphansFound));
1204+
.arg(BitcoinUnits::formatWithUnit(walletModel->getOptionsModel()->getDisplayUnit(),
1205+
nBalanceInQuestion, true)));
12041206
}
12051207

src/rpcwallet.cpp

Lines changed: 32 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,56 +1741,60 @@ Value reservebalance(const Array& params, bool fHelp)
17411741
return result;
17421742
}
17431743

1744+
/* Wallet integrity check */
1745+
Value checkwallet(const Array &params, bool fHelp) {
17441746

1745-
// check wallet integrity
1746-
Value checkwallet(const Array& params, bool fHelp)
1747-
{
1748-
if (fHelp || params.size() > 0)
1749-
throw runtime_error(
1750-
"checkwallet\n"
1751-
"Check wallet for integrity.\n");
1747+
if(fHelp || (params.size() > 0)) throw(runtime_error(
1748+
"checkwallet\n"
1749+
"Wallet integrity check.\n"));
17521750

17531751
int nMismatchSpent;
17541752
int nOrphansFound;
17551753
int64 nBalanceInQuestion;
1754+
17561755
pwalletMain->FixSpentCoins(nMismatchSpent, nOrphansFound, nBalanceInQuestion, true);
1756+
17571757
Object result;
1758-
if (nMismatchSpent == 0)
1758+
if(!nMismatchSpent && !nOrphansFound) {
17591759
result.push_back(Pair("wallet check passed", true));
1760-
else
1761-
{
1762-
result.push_back(Pair("mismatched spent coins", nMismatchSpent));
1760+
} else {
1761+
if(nOrphansFound) {
1762+
result.push_back(Pair("orphans found", nOrphansFound));
1763+
}
1764+
if(nMismatchSpent) {
1765+
result.push_back(Pair("mismatched outputs detected", nMismatchSpent));
1766+
}
17631767
result.push_back(Pair("amount in question", ValueFromAmount(nBalanceInQuestion)));
1764-
if(!nOrphansFound)
1765-
result.push_back(Pair("orphans found", nOrphansFound));
17661768
}
1767-
return result;
1769+
return(result);
17681770
}
17691771

1772+
/* Wallet repair (removal of failed and orphaned transactions) */
1773+
Value repairwallet(const Array &params, bool fHelp) {
17701774

1771-
// repair wallet
1772-
Value repairwallet(const Array& params, bool fHelp)
1773-
{
1774-
if (fHelp || params.size() > 0)
1775-
throw runtime_error(
1776-
"repairwallet\n"
1777-
"Repair wallet if checkwallet reports any problem.\n");
1775+
if(fHelp || (params.size() > 0)) throw(runtime_error(
1776+
"repairwallet\n"
1777+
"Wallet repair if any mismatches found.\n"));
17781778

17791779
int nMismatchSpent;
17801780
int nOrphansFound;
17811781
int64 nBalanceInQuestion;
1782+
17821783
pwalletMain->FixSpentCoins(nMismatchSpent, nOrphansFound, nBalanceInQuestion, false);
1784+
17831785
Object result;
1784-
if (nMismatchSpent == 0)
1786+
if(!nMismatchSpent && !nOrphansFound) {
17851787
result.push_back(Pair("wallet check passed", true));
1786-
else
1787-
{
1788-
result.push_back(Pair("mismatched spent coins", nMismatchSpent));
1788+
} else {
1789+
if(nOrphansFound) {
1790+
result.push_back(Pair("orphans removed", nOrphansFound));
1791+
}
1792+
if(nMismatchSpent) {
1793+
result.push_back(Pair("mismatched outputs corrected", nMismatchSpent));
1794+
}
17891795
result.push_back(Pair("amount affected by repair", ValueFromAmount(nBalanceInQuestion)));
1790-
if(!nOrphansFound)
1791-
result.push_back(Pair("orphans removed", nOrphansFound));
17921796
}
1793-
return result;
1797+
return(result);
17941798
}
17951799

17961800
// resend unconfirmed wallet transactions

src/wallet.cpp

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,10 +1246,15 @@ bool CWallet::SelectCoinsStaking(int64 nTargetValue,
12461246
nDepth = pcoin->GetDepthInMainChain();
12471247

12481248
/* Discard if the time (depth) requirement is unmet */
1249-
if(nStakeMinTime && ((nCurrentTime - nStakeMinTime * 60 * 60) < pcoin->nTime))
1250-
continue;
1251-
if(!nStakeMinTime && (nDepth < (int)nStakeMinDepth))
1252-
continue;
1249+
if(nStakeMinTime) {
1250+
if(nDepth < nBaseMaturity)
1251+
continue;
1252+
if(nCurrentTime < (pcoin->nTime + nStakeMinTime * 60 * 60))
1253+
continue;
1254+
} else {
1255+
if(nDepth < (int)nStakeMinDepth)
1256+
continue;
1257+
}
12531258

12541259
for(i = 0; i < pcoin->vout.size(); i++) {
12551260
/* Must be unspent and above the limit in value */
@@ -2274,31 +2279,60 @@ void CWallet::FixSpentCoins(int& nMismatchFound, int& nOrphansFound, int64& nBal
22742279
nBalanceInQuestion = 0;
22752280
nOrphansFound = 0;
22762281

2282+
/* If repairing, don't bother to put the stake miner on hold and invalidate its cache
2283+
* as there shouldn't be any failed transactions by design */
2284+
22772285
LOCK(cs_wallet);
22782286
vector<CWalletTx*> vCoins;
22792287
vCoins.reserve(mapWallet.size());
22802288
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
22812289
vCoins.push_back(&(*it).second);
22822290

2291+
uint n;
22832292
CCoinsViewCache &view = *pcoinsTip;
22842293
BOOST_FOREACH(CWalletTx* pcoin, vCoins)
22852294
{
22862295
uint256 hash = pcoin->GetHash();
22872296
if(!view.HaveCoins(hash))
22882297
continue;
22892298

2299+
if((pcoin->IsCoinBase() || pcoin->IsCoinStake()) &&
2300+
(pcoin->GetDepthInMainChain() < 0)) {
2301+
int64 nCurrentValue = 0;
2302+
2303+
nOrphansFound++;
2304+
2305+
for(n = 0; n < pcoin->vout.size(); n++)
2306+
nCurrentValue += pcoin->vout[n].nValue;
2307+
nBalanceInQuestion += nCurrentValue;
2308+
2309+
printf("FixSpentCoins() : %s orphaned coin %s %s of value %s\n",
2310+
fCheckOnly ? "found" : "removed",
2311+
pcoin->IsCoinBase() ? "base" : "stake",
2312+
hash.ToString().c_str(),
2313+
FormatMoney(nCurrentValue).c_str());
2314+
2315+
if(!fCheckOnly) {
2316+
EraseFromWallet(hash);
2317+
NotifyTransactionChanged(this, hash, CT_DELETED);
2318+
}
2319+
2320+
continue;
2321+
}
2322+
22902323
// Find the corresponding transaction index
22912324
CCoins &coins = view.GetCoins(hash);
22922325

2293-
for (unsigned int n=0; n < pcoin->vout.size(); n++)
2294-
{
2326+
for(n = 0; n < pcoin->vout.size(); n++) {
22952327
bool fUpdated = false;
22962328
if (IsMine(pcoin->vout[n]))
22972329
{
22982330
if (pcoin->IsSpent(n) && coins.IsAvailable(n))
22992331
{
2300-
printf("FixSpentCoins found lost coin %sorb %s[%d], %s\n",
2301-
FormatMoney(pcoin->vout[n].nValue).c_str(), hash.ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
2332+
printf("FixSpentCoins() : %s lost output %s-%u of value %s\n",
2333+
fCheckOnly ? "found" : "added",
2334+
hash.ToString().c_str(), n,
2335+
FormatMoney(pcoin->vout[n].nValue).c_str());
23022336
nMismatchFound++;
23032337
nBalanceInQuestion += pcoin->vout[n].nValue;
23042338
if (!fCheckOnly)
@@ -2310,8 +2344,10 @@ void CWallet::FixSpentCoins(int& nMismatchFound, int& nOrphansFound, int64& nBal
23102344
}
23112345
else if (!pcoin->IsSpent(n) && !coins.IsAvailable(n))
23122346
{
2313-
printf("FixSpentCoins found spent coin %sorb %s[%d], %s\n",
2314-
FormatMoney(pcoin->vout[n].nValue).c_str(), hash.ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
2347+
printf("FixSpentCoins() : %s spent output %s-%u of value %s\n",
2348+
fCheckOnly ? "found" : "removed",
2349+
hash.ToString().c_str(), n,
2350+
FormatMoney(pcoin->vout[n].nValue).c_str());
23152351
nMismatchFound++;
23162352
nBalanceInQuestion += pcoin->vout[n].nValue;
23172353
if (!fCheckOnly)
@@ -2326,18 +2362,6 @@ void CWallet::FixSpentCoins(int& nMismatchFound, int& nOrphansFound, int64& nBal
23262362
NotifyTransactionChanged(this, hash, CT_UPDATED);
23272363
}
23282364
}
2329-
2330-
if((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && (pcoin->GetDepthInMainChain() < 0)) {
2331-
nOrphansFound++;
2332-
2333-
if (!fCheckOnly)
2334-
{
2335-
EraseFromWallet(hash);
2336-
NotifyTransactionChanged(this, hash, CT_DELETED);
2337-
}
2338-
2339-
printf("FixSpentCoins %s orphaned generation tx %s\n", fCheckOnly ? "found" : "removed", hash.ToString().c_str());
2340-
}
23412365
}
23422366
}
23432367

0 commit comments

Comments
 (0)