From: Sunny King Date: Thu, 22 Mar 2012 18:02:37 +0000 (+0000) Subject: PPCoin: Add RPC command 'repairwallet' X-Git-Tag: v0.4.0-unstable~201 X-Git-Url: https://git.novaco.in/?p=novacoin.git;a=commitdiff_plain;h=c9d655232500a0b4e085fb6a9cc0ba1966db027a PPCoin: Add RPC command 'repairwallet' --- diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp index e9b9dfb..ecd35ac 100644 --- a/src/bitcoinrpc.cpp +++ b/src/bitcoinrpc.cpp @@ -1906,6 +1906,31 @@ Value checkwallet(const Array& params, bool fHelp) } +// ppcoin: repair wallet +Value repairwallet(const Array& params, bool fHelp) +{ + if (fHelp || params.size() > 0) + throw runtime_error( + "repairwallet\n" + "Repair wallet if checkwallet reports any problem.\n"); + + int nMismatchSpent; + int64 nBalanceInQuestion; + pwalletMain->FixSpentCoins(nMismatchSpent, nBalanceInQuestion); + Object result; + if (nMismatchSpent == 0) + { + result.push_back(Pair("wallet check passed", true)); + } + else + { + result.push_back(Pair("mismatched spent coins", nMismatchSpent)); + result.push_back(Pair("amount affected by repair", ValueFromAmount(nBalanceInQuestion))); + } + return result; +} + + @@ -1960,6 +1985,7 @@ pair pCallTable[] = make_pair("getbranchpoint", &getbranchpoint), make_pair("reservebalance", &reservebalance), make_pair("checkwallet", &checkwallet), + make_pair("repairwallet", &repairwallet), }; map mapCallTable(pCallTable, pCallTable + sizeof(pCallTable)/sizeof(pCallTable[0])); diff --git a/src/wallet.cpp b/src/wallet.cpp index e469803..29cc87a 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -1510,6 +1510,48 @@ bool CWallet::CheckSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion) return (nMismatchFound == 0); } +// ppcoin: fix wallet spent state according to txindex +void CWallet::FixSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion) +{ + nMismatchFound = 0; + nBalanceInQuestion = 0; + CRITICAL_BLOCK(cs_wallet) + { + vector vCoins; + vCoins.reserve(mapWallet.size()); + for (map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + vCoins.push_back(&(*it).second); + + CTxDB txdb("r"); + BOOST_FOREACH(CWalletTx* pcoin, vCoins) + { + // Find the corresponding transaction index + CTxIndex txindex; + if (!txdb.ReadTxIndex(pcoin->GetHash(), txindex)) + continue; + for (int n=0; n < pcoin->vout.size(); n++) + { + if (pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull())) + { + printf("FixSpentCoins found lost coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n); + nMismatchFound++; + nBalanceInQuestion += pcoin->vout[n].nValue; + pcoin->MarkUnspent(n); + pcoin->WriteToDisk(); + } + else if (!pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull())) + { + printf("FixSpentCoins found spent coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n); + nMismatchFound++; + nBalanceInQuestion += pcoin->vout[n].nValue; + pcoin->MarkSpent(n); + pcoin->WriteToDisk(); + } + } + } + } +} + vector CReserveKey::GetReservedKey() { if (nIndex == -1) diff --git a/src/wallet.h b/src/wallet.h index 970f2e4..2fb41db 100644 --- a/src/wallet.h +++ b/src/wallet.h @@ -215,6 +215,7 @@ public: bool SetDefaultKey(const std::vector &vchPubKey); bool CheckSpentCoins(int& nMismatchSpent, int64& nBalanceInQuestion); + void FixSpentCoins(int& nMismatchSpent, int64& nBalanceInQuestion); }; @@ -408,6 +409,18 @@ public: } } + void MarkUnspent(unsigned int nOut) + { + if (nOut >= vout.size()) + throw std::runtime_error("CWalletTx::MarkUnspent() : nOut out of range"); + vfSpent.resize(vout.size()); + if (vfSpent[nOut]) + { + vfSpent[nOut] = false; + fAvailableCreditCached = false; + } + } + bool IsSpent(unsigned int nOut) const { if (nOut >= vout.size())