aboutsummaryrefslogtreecommitdiff
path: root/main.cpp
diff options
context:
space:
mode:
authors_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2010-02-03 22:58:40 +0000
committers_nakamoto <s_nakamoto@1a98c847-1fd6-4fd8-948a-caf3550aa51b>2010-02-03 22:58:40 +0000
commit53d508072b02d522371bde148dcc3e925f472be7 (patch)
tree3220aa303c10ebbcef8520e38a1010f6a7972586 /main.cpp
parent8be979d9aef606f2a196a2addcf80473d571185b (diff)
downloadbitcoin-53d508072b02d522371bde148dcc3e925f472be7.tar.xz
update fSpent flag on wallet transactions if they're seen spent in case copy of wallet.dat was used elsewhere or restored from backup,
better error dialog box if try to spend already spent coins, got rid of unused notebook with only one tab on main dialog, nicer looking About dialog, resize About dialog better on linux git-svn-id: https://bitcoin.svn.sourceforge.net/svnroot/bitcoin/trunk@55 1a98c847-1fd6-4fd8-948a-caf3550aa51b
Diffstat (limited to 'main.cpp')
-rw-r--r--main.cpp67
1 files changed, 60 insertions, 7 deletions
diff --git a/main.cpp b/main.cpp
index 416c616ad1..53acf8a753 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 Satoshi Nakamoto
+// Copyright (c) 2009-2010 Satoshi Nakamoto
// Distributed under the MIT/X11 software license, see the accompanying
// file license.txt or http://www.opensource.org/licenses/mit-license.php.
@@ -168,6 +168,27 @@ bool EraseFromWallet(uint256 hash)
return true;
}
+void WalletUpdateSpent(const COutPoint& prevout)
+{
+ // 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
+ // restored from backup or the user making copies of wallet.dat.
+ CRITICAL_BLOCK(cs_mapWallet)
+ {
+ map<uint256, CWalletTx>::iterator mi = mapWallet.find(prevout.hash);
+ if (mi != mapWallet.end())
+ {
+ CWalletTx& wtx = (*mi).second;
+ if (!wtx.fSpent && wtx.vout[prevout.n].IsMine())
+ {
+ printf("WalletUpdateSpent found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+ wtx.fSpent = true;
+ wtx.WriteToDisk();
+ vWalletUpdated.push_back(prevout.hash);
+ }
+ }
+ }
+}
@@ -622,15 +643,44 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
void ReacceptWalletTransactions()
{
- // Reaccept any txes of ours that aren't already in a block
CTxDB txdb("r");
CRITICAL_BLOCK(cs_mapWallet)
{
foreach(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
{
CWalletTx& wtx = item.second;
- if (!wtx.IsCoinBase() && !txdb.ContainsTx(wtx.GetHash()))
- wtx.AcceptWalletTransaction(txdb, false);
+ if (wtx.fSpent && wtx.IsCoinBase())
+ continue;
+
+ CTxIndex txindex;
+ if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
+ {
+ // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
+ if (!wtx.fSpent)
+ {
+ if (txindex.vSpent.size() != wtx.vout.size())
+ {
+ printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
+ continue;
+ }
+ for (int i = 0; i < txindex.vSpent.size(); i++)
+ {
+ if (!txindex.vSpent[i].IsNull() && wtx.vout[i].IsMine())
+ {
+ printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
+ wtx.fSpent = true;
+ wtx.WriteToDisk();
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Reaccept any txes of ours that aren't already in a block
+ if (!wtx.IsCoinBase())
+ wtx.AcceptWalletTransaction(txdb, false);
+ }
}
}
}
@@ -2843,9 +2893,13 @@ bool CommitTransactionSpent(const CWalletTx& wtxNew, const CKey& key)
CRITICAL_BLOCK(cs_main)
CRITICAL_BLOCK(cs_mapWallet)
{
- //// todo: eventually should make this transactional, never want to add a
+ //// old: eventually should make this transactional, never want to add a
//// transaction without marking spent transactions, although the risk of
//// interruption during this step is remote.
+ //// update: This matters even less now that fSpent can get corrected
+ //// when transactions are seen in VerifySignature. The remote chance of
+ //// unmarked fSpent will be handled by that. Don't need to make this
+ //// transactional.
// This is only to keep the database open to defeat the auto-flush for the
// duration of this scope. This is the only place where this optimization
@@ -2910,8 +2964,7 @@ bool SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew)
if (!wtxNew.AcceptTransaction())
{
// This must not fail. The transaction has already been signed and recorded.
- throw runtime_error("SendMoney() : wtxNew.AcceptTransaction() failed\n");
- wxMessageBox("Error: Transaction not valid ", "Sending...");
+ wxMessageBox("Error: The transaction was rejected. This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.", "Sending...");
return error("SendMoney() : Error: Transaction not valid");
}
wtxNew.RelayWalletTransaction();