return txOrdered;
}
-void CWallet::WalletUpdateSpent(const CTransaction &tx)
+void CWallet::WalletUpdateSpent(const CTransaction &tx, bool fBlock)
{
// Anytime a signature is successfully verified, it's proof the outpoint is spent.
// Update the wallet spent flag if it doesn't know due to wallet.dat being
}
}
}
+
+ if (fBlock)
+ {
+ uint256 hash = tx.GetHash();
+ map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
+ CWalletTx& wtx = (*mi).second;
+
+ BOOST_FOREACH(const CTxOut& txout, tx.vout)
+ {
+ if (IsMine(txout))
+ {
+ wtx.MarkUnspent(&txout - &tx.vout[0]);
+ wtx.WriteToDisk();
+ NotifyTransactionChanged(this, hash, CT_UPDATED);
+ }
+ }
+ }
}
}
}
else
printf("AddToWallet() : found %s in block %s not in index\n",
- wtxIn.GetHash().ToString().substr(0,10).c_str(),
+ hash.ToString().substr(0,10).c_str(),
wtxIn.hashBlock.ToString().c_str());
}
}
}
//// debug print
- printf("AddToWallet %s %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
+ printf("AddToWallet %s %s%s\n", hash.ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
// Write to disk
if (fInsertedNew || fUpdated)
}
#endif
// since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
- WalletUpdateSpent(wtx);
+ WalletUpdateSpent(wtx, (wtxIn.hashBlock != 0));
// Notify UI of new or updated transaction
NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
if ( !strCmd.empty())
{
- boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
+ boost::replace_all(strCmd, "%s", hash.GetHex());
boost::thread t(runCommand, strCmd); // thread runs free
}
// Add a transaction to the wallet, or update it.
// pblock is optional, but should be provided if the transaction is known to be in a block.
// If fUpdate is true, existing transactions will be updated.
-bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
+bool CWallet::AddToWalletIfInvolvingMe(const uint256 &hash, const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
{
- uint256 hash = tx.GetHash();
{
LOCK(cs_wallet);
bool fExisted = mapWallet.count(hash);
block.ReadFromDisk(pindex, true);
BOOST_FOREACH(CTransaction& tx, block.vtx)
{
- if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
+ if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
ret++;
}
pindex = pindex->pnext;
}
if (fUpdated)
{
- printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+ printf("ReacceptWalletTransactions found spent coin %snvc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
wtx.MarkDirty();
wtx.WriteToDisk();
}
CCoins coins;
{
LOCK2(cs_main, cs_wallet);
- if (!view.GetCoins(pcoin.first->GetHash(), coins))
+ if (!view.GetCoinsReadOnly(pcoin.first->GetHash(), coins))
continue;
}
CCoins coins;
{
LOCK2(cs_main, cs_wallet);
- if (!view.GetCoins(pcoin.first->GetHash(), coins))
+ if (!view.GetCoinsReadOnly(pcoin.first->GetHash(), coins))
continue;
}
bool fFatal = false;
bool fKernelFound = false;
- for (unsigned int n=0; n<min(nSearchInterval,(int64)nMaxStakeSearchInterval) && !fKernelFound && !fShutdown && pindexPrev == pindexBest && !fFatal; n++)
+ for (unsigned int n=0; n<min(nSearchInterval,(int64)nMaxStakeSearchInterval) && !fKernelFound && !fShutdown && pindexPrev == pindexBest; n++)
{
// Search backward in time from the given txNew timestamp
// Search nSearchInterval seconds back up to nMaxStakeSearchInterval
uint256 hashProofOfStake = 0, targetProofOfStake = 0;
COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second);
- if (CheckStakeKernelHash(nBits, block, nTxPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake, targetProofOfStake, fFatal))
+ if (CheckStakeKernelHash(nBits, block, nTxPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake, targetProofOfStake, fFatal, true))
{
// Found a kernel
if (fDebug && GetBoolArg("-printcoinstake"))
return ret;
}
-// ppcoin: check 'spent' consistency between wallet and txindex
-// ppcoin: fix wallet spent state according to txindex
+// 1. check 'spent' consistency between wallet and coins database
+// 2. fix wallet spent state according to coins database
+// 3. remove orphaned coinstakes and coinbases from wallet
void CWallet::FixSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion, bool fCheckOnly)
{
nMismatchFound = 0;
CCoinsViewCache &view = *pcoinsTip;
BOOST_FOREACH(CWalletTx* pcoin, vCoins)
{
- // Find the corresponding transaction index
- CCoins coins;
+ uint256 hash = pcoin->GetHash();
+ if(!view.HaveCoins(hash))
+ continue;
- bool fNotFound = view.GetCoins(pcoin->GetHash(), coins);
+ // Find the corresponding transaction index
+ CCoins &coins = view.GetCoins(hash);
for (unsigned int n=0; n < pcoin->vout.size(); n++)
{
- if (!fNotFound && IsMine(pcoin->vout[n]) && pcoin->IsSpent(n) && coins.IsAvailable(n))
+ bool fUpdated = false;
+ if (IsMine(pcoin->vout[n]))
{
- printf("FixSpentCoins found lost coin %sppc %s[%d], %s\n",
- FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
- nMismatchFound++;
- nBalanceInQuestion += pcoin->vout[n].nValue;
- if (!fCheckOnly)
+ if (pcoin->IsSpent(n) && coins.IsAvailable(n))
{
- pcoin->MarkUnspent(n);
- pcoin->WriteToDisk();
+ printf("FixSpentCoins found lost coin %snvc %s[%d], %s\n",
+ FormatMoney(pcoin->vout[n].nValue).c_str(), hash.ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
+ nMismatchFound++;
+ nBalanceInQuestion += pcoin->vout[n].nValue;
+ if (!fCheckOnly)
+ {
+ fUpdated = true;
+ pcoin->MarkUnspent(n);
+ pcoin->WriteToDisk();
+ }
}
- }
- else if (!fNotFound && IsMine(pcoin->vout[n]) && !pcoin->IsSpent(n) && coins.IsAvailable(n))
- {
- printf("FixSpentCoins found spent coin %sppc %s[%d], %s\n",
- FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
- nMismatchFound++;
- nBalanceInQuestion += pcoin->vout[n].nValue;
- if (!fCheckOnly)
+ else if (!pcoin->IsSpent(n) && !coins.IsAvailable(n))
{
- pcoin->MarkSpent(n);
- pcoin->WriteToDisk();
+ printf("FixSpentCoins found spent coin %snvc %s[%d], %s\n",
+ FormatMoney(pcoin->vout[n].nValue).c_str(), hash.ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
+ nMismatchFound++;
+ nBalanceInQuestion += pcoin->vout[n].nValue;
+ if (!fCheckOnly)
+ {
+ fUpdated = true;
+ pcoin->MarkSpent(n);
+ pcoin->WriteToDisk();
+ }
}
- }
+ if (fUpdated)
+ NotifyTransactionChanged(this, hash, CT_UPDATED);
+ }
}
- if(IsMine((CTransaction)*pcoin) && (pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetDepthInMainChain() == 0)
+ if((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetDepthInMainChain() == 0)
{
- printf("FixSpentCoins %s tx %s\n", fCheckOnly ? "found" : "removed", pcoin->GetHash().ToString().c_str());
if (!fCheckOnly)
{
- EraseFromWallet(pcoin->GetHash());
+ EraseFromWallet(hash);
+ NotifyTransactionChanged(this, hash, CT_DELETED);
}
+
+ printf("FixSpentCoins %s orphaned generation tx %s\n", fCheckOnly ? "found" : "removed", hash.ToString().c_str());
}
}
}