upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp
index dbb2c41..85f89d9 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -693,6 +693,71 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
693 return true; 693 return true;
694} 694}
695 695
696int RescanSpentFlags()
697{
698 // Believe the chain, not the wallet, about what has already been spent.
699 //
700 // fSpent lives in wallet.dat and is written when this node spends
701 // something. A wallet.dat that was restored from backup, or copied and
702 // used on another machine, carries whatever that flag was at the moment
703 // the copy was taken -- so it can say "unspent" about coins the chain
704 // shows as gone. The balance then reads high, and the error only surfaces
705 // when a send is attempted against coins that no longer exist.
706 //
707 // Issue #47 is about this shape of problem and #40 reports living through
708 // it. Bitcoin fixed the same thing in 53d508072.
709 //
710 // One direction only. Marking spent when the chain says spent is safe;
711 // clearing the flag because the chain has not caught up yet would offer
712 // up coins that are already on their way out.
713 CTxDB txdb("r");
714 int nCorrected = 0;
715 int nExamined = 0;
716 int nAlreadySpent = 0, nNotIndexed = 0;
717 CRITICAL_BLOCK(cs_mapWallet)
718 {
719 foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
720 {
721 CWalletTx& wtx = item.second;
722 nExamined++;
723 if (wtx.fSpent)
724 { nAlreadySpent++; continue; }
725
726 CTxIndex txindex;
727 if (!txdb.ReadTxIndex(wtx.GetHash(), txindex))
728 { nNotIndexed++; continue; }
729
730 // fSpent is one flag for the whole transaction, not one per
731 // output -- CommitTransactionSpent already marks the entire
732 // previous transaction when it spends any part of it, so matching
733 // that here keeps the two consistent.
734 bool fSeenSpent = false;
735 for (int i = 0; i < (int)txindex.vSpent.size() && i < (int)wtx.vout.size(); i++)
736 if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
737 fSeenSpent = true;
738
739 if (fSeenSpent)
740 {
741 wtx.fSpent = true;
742 wtx.WriteToDisk();
743 nCorrected++;
744 printf("RescanSpentFlags() : %s was spent on chain but the wallet did not know\n",
745 wtx.GetHash().ToString().substr(0,10).c_str());
746 }
747 }
748 }
749 // Always say it ran. A check that reports only when it finds something is
750 // indistinguishable from a check that never executed, and this codebase has
751 // paid for that confusion more than once.
752 printf("RescanSpentFlags() : examined %d, already-spent %d, not-indexed %d, corrected %d\n",
753 nExamined, nAlreadySpent, nNotIndexed, nCorrected);
754 if (nCorrected)
755 printf("RescanSpentFlags() : this wallet was behind the chain about what it had already spent, "
756 "which is what a restored backup looks like\n");
757 return nCorrected;
758}
759
760
696void ReacceptWalletTransactions() 761void ReacceptWalletTransactions()
697{ 762{
698 // Reaccept any txes of ours that aren't already in a block 763 // Reaccept any txes of ours that aren't already in a block