PPCoin: Fix CreateCoinStake() bug from 747f99fb
[novacoin.git] / src / wallet.cpp
1 // Copyright (c) 2009-2011 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Copyright (c) 2011-2012 The PPCoin developers
4 // Distributed under the MIT/X11 software license, see the accompanying
5 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
6
7 #include "headers.h"
8 #include "db.h"
9 #include "crypter.h"
10 #include "checkpoints.h"
11
12 using namespace std;
13
14
15 //////////////////////////////////////////////////////////////////////////////
16 //
17 // mapWallet
18 //
19
20 bool CWallet::AddKey(const CKey& key)
21 {
22     if (!CCryptoKeyStore::AddKey(key))
23         return false;
24     if (!fFileBacked)
25         return true;
26     if (!IsCrypted())
27         return CWalletDB(strWalletFile).WriteKey(key.GetPubKey(), key.GetPrivKey());
28     return true;
29 }
30
31 bool CWallet::AddCryptedKey(const vector<unsigned char> &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
32 {
33     if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
34         return false;
35     if (!fFileBacked)
36         return true;
37     CRITICAL_BLOCK(cs_wallet)
38     {
39         if (pwalletdbEncryption)
40             return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret);
41         else
42             return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret);
43     }
44     return false;
45 }
46
47 // ppcoin: optional setting to create coinstake only when unlocked;
48 //         serves to disable the trivial sendmoney when OS account compromised
49 bool fWalletUnlockStakeOnly = false;
50
51 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
52 {
53     if (!IsLocked())
54         return false;
55
56     CCrypter crypter;
57     CKeyingMaterial vMasterKey;
58
59     CRITICAL_BLOCK(cs_wallet)
60         BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
61         {
62             if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
63                 return false;
64             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
65                 return false;
66             if (CCryptoKeyStore::Unlock(vMasterKey))
67                 return true;
68         }
69     return false;
70 }
71
72 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
73 {
74     bool fWasLocked = IsLocked();
75
76     CRITICAL_BLOCK(cs_wallet)
77     {
78         Lock();
79
80         CCrypter crypter;
81         CKeyingMaterial vMasterKey;
82         BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
83         {
84             if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
85                 return false;
86             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
87                 return false;
88             if (CCryptoKeyStore::Unlock(vMasterKey))
89             {
90                 int64 nStartTime = GetTimeMillis();
91                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
92                 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
93
94                 nStartTime = GetTimeMillis();
95                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
96                 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
97
98                 if (pMasterKey.second.nDeriveIterations < 25000)
99                     pMasterKey.second.nDeriveIterations = 25000;
100
101                 printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
102
103                 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
104                     return false;
105                 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
106                     return false;
107                 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
108                 if (fWasLocked)
109                     Lock();
110                 return true;
111             }
112         }
113     }
114
115     return false;
116 }
117
118
119 // This class implements an addrIncoming entry that causes pre-0.4
120 // clients to crash on startup if reading a private-key-encrypted wallet.
121 class CCorruptAddress
122 {
123 public:
124     IMPLEMENT_SERIALIZE
125     (
126         if (nType & SER_DISK)
127             READWRITE(nVersion);
128     )
129 };
130
131 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
132 {
133     if (IsCrypted())
134         return false;
135
136     CKeyingMaterial vMasterKey;
137     RandAddSeedPerfmon();
138
139     vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
140     RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
141
142     CMasterKey kMasterKey;
143
144     RandAddSeedPerfmon();
145     kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
146     RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
147
148     CCrypter crypter;
149     int64 nStartTime = GetTimeMillis();
150     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
151     kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
152
153     nStartTime = GetTimeMillis();
154     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
155     kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
156
157     if (kMasterKey.nDeriveIterations < 25000)
158         kMasterKey.nDeriveIterations = 25000;
159
160     printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
161
162     if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
163         return false;
164     if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
165         return false;
166
167     CRITICAL_BLOCK(cs_wallet)
168     {
169         mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
170         if (fFileBacked)
171         {
172             pwalletdbEncryption = new CWalletDB(strWalletFile);
173             pwalletdbEncryption->TxnBegin();
174             pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
175         }
176
177         if (!EncryptKeys(vMasterKey))
178         {
179             if (fFileBacked)
180                 pwalletdbEncryption->TxnAbort();
181             exit(1); //We now probably have half of our keys encrypted in memory, and half not...die and let the user reload their unencrypted wallet.
182         }
183
184         if (fFileBacked)
185         {
186             CCorruptAddress corruptAddress;
187             pwalletdbEncryption->WriteSetting("addrIncoming", corruptAddress);
188             if (!pwalletdbEncryption->TxnCommit())
189                 exit(1); //We now have keys encrypted in memory, but no on disk...die to avoid confusion and let the user reload their unencrypted wallet.
190
191             pwalletdbEncryption->Close();
192             pwalletdbEncryption = NULL;
193         }
194
195         Lock();
196         Unlock(strWalletPassphrase);
197         NewKeyPool();
198         Lock();
199
200         // Need to completely rewrite the wallet file; if we don't, bdb might keep
201         // bits of the unencrypted private key in slack space in the database file.
202         CDB::Rewrite(strWalletFile);
203     }
204
205     return true;
206 }
207
208 void CWallet::WalletUpdateSpent(const CTransaction &tx)
209 {
210     // Anytime a signature is successfully verified, it's proof the outpoint is spent.
211     // Update the wallet spent flag if it doesn't know due to wallet.dat being
212     // restored from backup or the user making copies of wallet.dat.
213     CRITICAL_BLOCK(cs_wallet)
214     {
215         BOOST_FOREACH(const CTxIn& txin, tx.vin)
216         {
217             map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
218             if (mi != mapWallet.end())
219             {
220                 CWalletTx& wtx = (*mi).second;
221                 if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
222                 {
223                     printf("WalletUpdateSpent found spent coin %sppc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
224                     wtx.MarkSpent(txin.prevout.n);
225                     wtx.WriteToDisk();
226                     vWalletUpdated.push_back(txin.prevout.hash);
227                 }
228             }
229         }
230     }
231 }
232
233 bool CWallet::AddToWallet(const CWalletTx& wtxIn)
234 {
235     uint256 hash = wtxIn.GetHash();
236     CRITICAL_BLOCK(cs_wallet)
237     {
238         // Inserts only if not already there, returns tx inserted or tx found
239         pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
240         CWalletTx& wtx = (*ret.first).second;
241         wtx.pwallet = this;
242         bool fInsertedNew = ret.second;
243         if (fInsertedNew)
244             wtx.nTimeReceived = GetAdjustedTime();
245
246         bool fUpdated = false;
247         if (!fInsertedNew)
248         {
249             // Merge
250             if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
251             {
252                 wtx.hashBlock = wtxIn.hashBlock;
253                 fUpdated = true;
254             }
255             if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
256             {
257                 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
258                 wtx.nIndex = wtxIn.nIndex;
259                 fUpdated = true;
260             }
261             if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
262             {
263                 wtx.fFromMe = wtxIn.fFromMe;
264                 fUpdated = true;
265             }
266             fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
267         }
268
269         //// debug print
270         printf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
271
272         // Write to disk
273         if (fInsertedNew || fUpdated)
274             if (!wtx.WriteToDisk())
275                 return false;
276 #ifndef QT_GUI
277         // If default receiving address gets used, replace it with a new one
278         CScript scriptDefaultKey;
279         scriptDefaultKey.SetBitcoinAddress(vchDefaultKey);
280         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
281         {
282             if (txout.scriptPubKey == scriptDefaultKey)
283             {
284                 std::vector<unsigned char> newDefaultKey;
285                 if (GetKeyFromPool(newDefaultKey, false))
286                 {
287                     SetDefaultKey(newDefaultKey);
288                     SetAddressBookName(CBitcoinAddress(vchDefaultKey), "");
289                 }
290             }
291         }
292 #endif
293         // Notify UI
294         vWalletUpdated.push_back(hash);
295
296         // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
297         WalletUpdateSpent(wtx);
298     }
299
300     // Refresh UI
301     MainFrameRepaint();
302     return true;
303 }
304
305 // Add a transaction to the wallet, or update it.
306 // pblock is optional, but should be provided if the transaction is known to be in a block.
307 // If fUpdate is true, existing transactions will be updated.
308 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate)
309 {
310     uint256 hash = tx.GetHash();
311     CRITICAL_BLOCK(cs_wallet)
312     {
313         bool fExisted = mapWallet.count(hash);
314         if (fExisted && !fUpdate) return false;
315         if (fExisted || IsMine(tx) || IsFromMe(tx))
316         {
317             CWalletTx wtx(this,tx);
318             // Get merkle branch if transaction was found in a block
319             if (pblock)
320                 wtx.SetMerkleBranch(pblock);
321             return AddToWallet(wtx);
322         }
323         else
324             WalletUpdateSpent(tx);
325     }
326     return false;
327 }
328
329 bool CWallet::EraseFromWallet(uint256 hash)
330 {
331     if (!fFileBacked)
332         return false;
333     CRITICAL_BLOCK(cs_wallet)
334     {
335         if (mapWallet.erase(hash))
336             CWalletDB(strWalletFile).EraseTx(hash);
337     }
338     return true;
339 }
340
341
342 bool CWallet::IsMine(const CTxIn &txin) const
343 {
344     CRITICAL_BLOCK(cs_wallet)
345     {
346         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
347         if (mi != mapWallet.end())
348         {
349             const CWalletTx& prev = (*mi).second;
350             if (txin.prevout.n < prev.vout.size())
351                 if (IsMine(prev.vout[txin.prevout.n]))
352                     return true;
353         }
354     }
355     return false;
356 }
357
358 int64 CWallet::GetDebit(const CTxIn &txin) const
359 {
360     CRITICAL_BLOCK(cs_wallet)
361     {
362         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
363         if (mi != mapWallet.end())
364         {
365             const CWalletTx& prev = (*mi).second;
366             if (txin.prevout.n < prev.vout.size())
367                 if (IsMine(prev.vout[txin.prevout.n]))
368                     return prev.vout[txin.prevout.n].nValue;
369         }
370     }
371     return 0;
372 }
373
374 int64 CWalletTx::GetTxTime() const
375 {
376     return nTimeReceived;
377 }
378
379 int CWalletTx::GetRequestCount() const
380 {
381     // Returns -1 if it wasn't being tracked
382     int nRequests = -1;
383     CRITICAL_BLOCK(pwallet->cs_wallet)
384     {
385         if (IsCoinBase() || IsCoinStake())
386         {
387             // Generated block
388             if (hashBlock != 0)
389             {
390                 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
391                 if (mi != pwallet->mapRequestCount.end())
392                     nRequests = (*mi).second;
393             }
394         }
395         else
396         {
397             // Did anyone request this transaction?
398             map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
399             if (mi != pwallet->mapRequestCount.end())
400             {
401                 nRequests = (*mi).second;
402
403                 // How about the block it's in?
404                 if (nRequests == 0 && hashBlock != 0)
405                 {
406                     map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
407                     if (mi != pwallet->mapRequestCount.end())
408                         nRequests = (*mi).second;
409                     else
410                         nRequests = 1; // If it's in someone else's block it must have got out
411                 }
412             }
413         }
414     }
415     return nRequests;
416 }
417
418 void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<CBitcoinAddress, int64> >& listReceived,
419                            list<pair<CBitcoinAddress, int64> >& listSent, int64& nFee, string& strSentAccount) const
420 {
421     nGeneratedImmature = nGeneratedMature = nFee = 0;
422     listReceived.clear();
423     listSent.clear();
424     strSentAccount = strFromAccount;
425
426     if (IsCoinBase() || IsCoinStake())
427     {
428         if (GetBlocksToMaturity() > 0)
429             nGeneratedImmature = pwallet->GetCredit(*this);
430         else
431             nGeneratedMature = GetCredit();
432         return;
433     }
434
435     // Compute fee:
436     int64 nDebit = GetDebit();
437     if (nDebit > 0) // debit>0 means we signed/sent this transaction
438     {
439         int64 nValueOut = GetValueOut();
440         nFee = nDebit - nValueOut;
441     }
442
443     // Sent/received.  Standard client will never generate a send-to-multiple-recipients,
444     // but non-standard clients might (so return a list of address/amount pairs)
445     BOOST_FOREACH(const CTxOut& txout, vout)
446     {
447         CBitcoinAddress address;
448         vector<unsigned char> vchPubKey;
449         if (!ExtractAddress(txout.scriptPubKey, NULL, address))
450         {
451             printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
452                    this->GetHash().ToString().c_str());
453             address = " unknown ";
454         }
455
456         // Don't report 'change' txouts
457         if (nDebit > 0 && pwallet->IsChange(txout))
458             continue;
459
460         if (nDebit > 0)
461             listSent.push_back(make_pair(address, txout.nValue));
462
463         if (pwallet->IsMine(txout))
464             listReceived.push_back(make_pair(address, txout.nValue));
465     }
466
467 }
468
469 void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived, 
470                                   int64& nSent, int64& nFee) const
471 {
472     nGenerated = nReceived = nSent = nFee = 0;
473
474     int64 allGeneratedImmature, allGeneratedMature, allFee;
475     allGeneratedImmature = allGeneratedMature = allFee = 0;
476     string strSentAccount;
477     list<pair<CBitcoinAddress, int64> > listReceived;
478     list<pair<CBitcoinAddress, int64> > listSent;
479     GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
480
481     if (strAccount == "")
482         nGenerated = allGeneratedMature;
483     if (strAccount == strSentAccount)
484     {
485         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& s, listSent)
486             nSent += s.second;
487         nFee = allFee;
488     }
489     CRITICAL_BLOCK(pwallet->cs_wallet)
490     {
491         BOOST_FOREACH(const PAIRTYPE(CBitcoinAddress,int64)& r, listReceived)
492         {
493             if (pwallet->mapAddressBook.count(r.first))
494             {
495                 map<CBitcoinAddress, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
496                 if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
497                     nReceived += r.second;
498             }
499             else if (strAccount.empty())
500             {
501                 nReceived += r.second;
502             }
503         }
504     }
505 }
506
507 void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
508 {
509     vtxPrev.clear();
510
511     const int COPY_DEPTH = 3;
512     if (SetMerkleBranch() < COPY_DEPTH)
513     {
514         vector<uint256> vWorkQueue;
515         BOOST_FOREACH(const CTxIn& txin, vin)
516             vWorkQueue.push_back(txin.prevout.hash);
517
518         // This critsect is OK because txdb is already open
519         CRITICAL_BLOCK(pwallet->cs_wallet)
520         {
521             map<uint256, const CMerkleTx*> mapWalletPrev;
522             set<uint256> setAlreadyDone;
523             for (int i = 0; i < vWorkQueue.size(); i++)
524             {
525                 uint256 hash = vWorkQueue[i];
526                 if (setAlreadyDone.count(hash))
527                     continue;
528                 setAlreadyDone.insert(hash);
529
530                 CMerkleTx tx;
531                 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
532                 if (mi != pwallet->mapWallet.end())
533                 {
534                     tx = (*mi).second;
535                     BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
536                         mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
537                 }
538                 else if (mapWalletPrev.count(hash))
539                 {
540                     tx = *mapWalletPrev[hash];
541                 }
542                 else if (!fClient && txdb.ReadDiskTx(hash, tx))
543                 {
544                     ;
545                 }
546                 else
547                 {
548                     printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
549                     continue;
550                 }
551
552                 int nDepth = tx.SetMerkleBranch();
553                 vtxPrev.push_back(tx);
554
555                 if (nDepth < COPY_DEPTH)
556                     BOOST_FOREACH(const CTxIn& txin, tx.vin)
557                         vWorkQueue.push_back(txin.prevout.hash);
558             }
559         }
560     }
561
562     reverse(vtxPrev.begin(), vtxPrev.end());
563 }
564
565 bool CWalletTx::WriteToDisk()
566 {
567     return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
568 }
569
570 // Scan the block chain (starting in pindexStart) for transactions
571 // from or to us. If fUpdate is true, found transactions that already
572 // exist in the wallet will be updated.
573 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
574 {
575     int ret = 0;
576
577     CBlockIndex* pindex = pindexStart;
578     CRITICAL_BLOCK(cs_wallet)
579     {
580         while (pindex)
581         {
582             CBlock block;
583             block.ReadFromDisk(pindex, true);
584             BOOST_FOREACH(CTransaction& tx, block.vtx)
585             {
586                 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
587                     ret++;
588             }
589             pindex = pindex->pnext;
590         }
591     }
592     return ret;
593 }
594
595 void CWallet::ReacceptWalletTransactions()
596 {
597     CTxDB txdb("r");
598     bool fRepeat = true;
599     while (fRepeat) CRITICAL_BLOCK(cs_wallet)
600     {
601         fRepeat = false;
602         vector<CDiskTxPos> vMissingTx;
603         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
604         {
605             CWalletTx& wtx = item.second;
606             if ((wtx.IsCoinBase() && wtx.IsSpent(0)) || (wtx.IsCoinStake() && wtx.IsSpent(1)))
607                 continue;
608
609             CTxIndex txindex;
610             bool fUpdated = false;
611             if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
612             {
613                 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
614                 if (txindex.vSpent.size() != wtx.vout.size())
615                 {
616                     printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
617                     continue;
618                 }
619                 for (int i = 0; i < txindex.vSpent.size(); i++)
620                 {
621                     if (wtx.IsSpent(i))
622                         continue;
623                     if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
624                     {
625                         wtx.MarkSpent(i);
626                         fUpdated = true;
627                         vMissingTx.push_back(txindex.vSpent[i]);
628                     }
629                 }
630                 if (fUpdated)
631                 {
632                     printf("ReacceptWalletTransactions found spent coin %sppc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
633                     wtx.MarkDirty();
634                     wtx.WriteToDisk();
635                 }
636             }
637             else
638             {
639                 // Reaccept any txes of ours that aren't already in a block
640                 if (!(wtx.IsCoinBase() || wtx.IsCoinStake()))
641                     wtx.AcceptWalletTransaction(txdb, false);
642             }
643         }
644         if (!vMissingTx.empty())
645         {
646             // TODO: optimize this to scan just part of the block chain?
647             if (ScanForWalletTransactions(pindexGenesisBlock))
648                 fRepeat = true;  // Found missing transactions: re-do Reaccept.
649         }
650     }
651 }
652
653 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
654 {
655     BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
656     {
657         if (!(tx.IsCoinBase() || tx.IsCoinStake()))
658         {
659             uint256 hash = tx.GetHash();
660             if (!txdb.ContainsTx(hash))
661                 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
662         }
663     }
664     if (!(IsCoinBase() || IsCoinStake()))
665     {
666         uint256 hash = GetHash();
667         if (!txdb.ContainsTx(hash))
668         {
669             printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
670             RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
671         }
672     }
673 }
674
675 void CWalletTx::RelayWalletTransaction()
676 {
677    CTxDB txdb("r");
678    RelayWalletTransaction(txdb);
679 }
680
681 void CWallet::ResendWalletTransactions()
682 {
683     // Do this infrequently and randomly to avoid giving away
684     // that these are our transactions.
685     static int64 nNextTime;
686     if (GetTime() < nNextTime)
687         return;
688     bool fFirst = (nNextTime == 0);
689     nNextTime = GetTime() + GetRand(30 * 60);
690     if (fFirst)
691         return;
692
693     // Only do it if there's been a new block since last time
694     static int64 nLastTime;
695     if (nTimeBestReceived < nLastTime)
696         return;
697     nLastTime = GetTime();
698
699     // Rebroadcast any of our txes that aren't in a block yet
700     printf("ResendWalletTransactions()\n");
701     CTxDB txdb("r");
702     CRITICAL_BLOCK(cs_wallet)
703     {
704         // Sort them in chronological order
705         multimap<unsigned int, CWalletTx*> mapSorted;
706         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
707         {
708             CWalletTx& wtx = item.second;
709             // Don't rebroadcast until it's had plenty of time that
710             // it should have gotten in already by now.
711             if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
712                 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
713         }
714         BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
715         {
716             CWalletTx& wtx = *item.second;
717             wtx.RelayWalletTransaction(txdb);
718         }
719     }
720 }
721
722
723
724
725
726
727 //////////////////////////////////////////////////////////////////////////////
728 //
729 // Actions
730 //
731
732
733 int64 CWallet::GetBalance() const
734 {
735     int64 nTotal = 0;
736     CRITICAL_BLOCK(cs_wallet)
737     {
738         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
739         {
740             const CWalletTx* pcoin = &(*it).second;
741             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
742                 continue;
743             nTotal += pcoin->GetAvailableCredit();
744         }
745     }
746
747     return nTotal;
748 }
749
750 int64 CWallet::GetUnconfirmedBalance() const
751 {
752     int64 nTotal = 0;
753     CRITICAL_BLOCK(cs_wallet)
754     {
755         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
756         {
757             const CWalletTx* pcoin = &(*it).second;
758             if (pcoin->IsFinal() && pcoin->IsConfirmed())
759                 continue;
760             nTotal += pcoin->GetAvailableCredit();
761         }
762     }
763     return nTotal;
764 }
765
766 // ppcoin: total coins staked (non-spendable until maturity)
767 int64 CWallet::GetStake() const
768 {
769     int64 nTotal = 0;
770     CRITICAL_BLOCK(cs_wallet)
771     {
772         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
773         {
774             const CWalletTx* pcoin = &(*it).second;
775             if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0)
776                 nTotal += CWallet::GetCredit(*pcoin);
777         }
778     }
779     return nTotal;
780 }
781
782 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
783 {
784     setCoinsRet.clear();
785     nValueRet = 0;
786
787     // List of values less than target
788     pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
789     coinLowestLarger.first = INT64_MAX;
790     coinLowestLarger.second.first = NULL;
791     vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
792     int64 nTotalLower = 0;
793
794     CRITICAL_BLOCK(cs_wallet)
795     {
796        vector<const CWalletTx*> vCoins;
797        vCoins.reserve(mapWallet.size());
798        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
799            vCoins.push_back(&(*it).second);
800        random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
801
802        BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
803        {
804             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
805                 continue;
806
807             if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0)
808                 continue;
809
810             int nDepth = pcoin->GetDepthInMainChain();
811             if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
812                 continue;
813
814             for (int i = 0; i < pcoin->vout.size(); i++)
815             {
816                 if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
817                     continue;
818
819                 if (pcoin->nTime > nSpendTime)
820                     continue;  // ppcoin: timestamp must not exceed spend time
821
822                 int64 n = pcoin->vout[i].nValue;
823
824                 if (n <= 0)
825                     continue;
826
827                 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
828
829                 if (n == nTargetValue)
830                 {
831                     setCoinsRet.insert(coin.second);
832                     nValueRet += coin.first;
833                     return true;
834                 }
835                 else if (n < nTargetValue + CENT)
836                 {
837                     vValue.push_back(coin);
838                     nTotalLower += n;
839                 }
840                 else if (n < coinLowestLarger.first)
841                 {
842                     coinLowestLarger = coin;
843                 }
844             }
845         }
846     }
847
848     if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
849     {
850         for (int i = 0; i < vValue.size(); ++i)
851         {
852             setCoinsRet.insert(vValue[i].second);
853             nValueRet += vValue[i].first;
854         }
855         return true;
856     }
857
858     if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
859     {
860         if (coinLowestLarger.second.first == NULL)
861             return false;
862         setCoinsRet.insert(coinLowestLarger.second);
863         nValueRet += coinLowestLarger.first;
864         return true;
865     }
866
867     if (nTotalLower >= nTargetValue + CENT)
868         nTargetValue += CENT;
869
870     // Solve subset sum by stochastic approximation
871     sort(vValue.rbegin(), vValue.rend());
872     vector<char> vfIncluded;
873     vector<char> vfBest(vValue.size(), true);
874     int64 nBest = nTotalLower;
875
876     for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
877     {
878         vfIncluded.assign(vValue.size(), false);
879         int64 nTotal = 0;
880         bool fReachedTarget = false;
881         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
882         {
883             for (int i = 0; i < vValue.size(); i++)
884             {
885                 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
886                 {
887                     nTotal += vValue[i].first;
888                     vfIncluded[i] = true;
889                     if (nTotal >= nTargetValue)
890                     {
891                         fReachedTarget = true;
892                         if (nTotal < nBest)
893                         {
894                             nBest = nTotal;
895                             vfBest = vfIncluded;
896                         }
897                         nTotal -= vValue[i].first;
898                         vfIncluded[i] = false;
899                     }
900                 }
901             }
902         }
903     }
904
905     // If the next larger is still closer, return it
906     if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
907     {
908         setCoinsRet.insert(coinLowestLarger.second);
909         nValueRet += coinLowestLarger.first;
910     }
911     else {
912         for (int i = 0; i < vValue.size(); i++)
913             if (vfBest[i])
914             {
915                 setCoinsRet.insert(vValue[i].second);
916                 nValueRet += vValue[i].first;
917             }
918
919         //// debug print
920         printf("SelectCoins() best subset: ");
921         for (int i = 0; i < vValue.size(); i++)
922             if (vfBest[i])
923                 printf("%s ", FormatMoney(vValue[i].first).c_str());
924         printf("total %s\n", FormatMoney(nBest).c_str());
925     }
926
927     return true;
928 }
929
930 bool CWallet::SelectCoins(int64 nTargetValue, unsigned int nSpendTime, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
931 {
932     return (SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 6, setCoinsRet, nValueRet) ||
933             SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 1, setCoinsRet, nValueRet) ||
934             SelectCoinsMinConf(nTargetValue, nSpendTime, 0, 1, setCoinsRet, nValueRet));
935 }
936
937
938
939
940 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
941 {
942     int64 nValue = 0;
943     BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
944     {
945         if (nValue < 0)
946             return false;
947         nValue += s.second;
948     }
949     if (vecSend.empty() || nValue < 0)
950         return false;
951
952     wtxNew.pwallet = this;
953
954     CRITICAL_BLOCK(cs_main)
955     CRITICAL_BLOCK(cs_wallet)
956     {
957         // txdb must be opened before the mapWallet lock
958         CTxDB txdb("r");
959         {
960             nFeeRet = nTransactionFee;
961             loop
962             {
963                 wtxNew.vin.clear();
964                 wtxNew.vout.clear();
965                 wtxNew.fFromMe = true;
966
967                 int64 nTotalValue = nValue + nFeeRet;
968                 double dPriority = 0;
969                 // vouts to the payees
970                 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
971                     wtxNew.vout.push_back(CTxOut(s.second, s.first));
972
973                 // Choose coins to use
974                 set<pair<const CWalletTx*,unsigned int> > setCoins;
975                 int64 nValueIn = 0;
976                 if (!SelectCoins(nTotalValue, wtxNew.nTime, setCoins, nValueIn))
977                     return false;
978                 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
979                 {
980                     int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
981                     dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
982                 }
983
984                 int64 nChange = nValueIn - nValue - nFeeRet;
985                 // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
986                 // or until nChange becomes zero
987                 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
988                 {
989                     int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
990                     nChange -= nMoveToFee;
991                     nFeeRet += nMoveToFee;
992                 }
993
994                 if (nChange > 0)
995                 {
996                     // Note: We use a new key here to keep it from being obvious which side is the change.
997                     //  The drawback is that by not reusing a previous key, the change may be lost if a
998                     //  backup is restored, if the backup doesn't have the new private key for the change.
999                     //  If we reused the old key, it would be possible to add code to look for and
1000                     //  rediscover unknown transactions that were written with keys of ours to recover
1001                     //  post-backup change.
1002
1003                     // Reserve a new key pair from key pool
1004                     vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
1005                     // assert(mapKeys.count(vchPubKey));
1006
1007                     // Fill a vout to ourself, using same address type as the payment
1008                     CScript scriptChange;
1009                     if (vecSend[0].first.GetBitcoinAddress().IsValid())
1010                         scriptChange.SetBitcoinAddress(vchPubKey);
1011                     else
1012                         scriptChange << vchPubKey << OP_CHECKSIG;
1013
1014                     // Insert change txn at random position:
1015                     vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
1016                     wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
1017                 }
1018                 else
1019                     reservekey.ReturnKey();
1020
1021                 // Fill vin
1022                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1023                     wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
1024
1025                 // Sign
1026                 int nIn = 0;
1027                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1028                     if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
1029                         return false;
1030
1031                 // Limit size
1032                 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
1033                 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
1034                     return false;
1035                 dPriority /= nBytes;
1036
1037                 // Check that enough fee is included
1038                 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
1039                 int64 nMinFee = wtxNew.GetMinFee(1, false);
1040                 if (nFeeRet < max(nPayFee, nMinFee))
1041                 {
1042                     nFeeRet = max(nPayFee, nMinFee);
1043                     continue;
1044                 }
1045
1046                 // Fill vtxPrev by copying from previous transactions vtxPrev
1047                 wtxNew.AddSupportingTransactions(txdb);
1048                 wtxNew.fTimeReceivedIsTxTime = true;
1049
1050                 break;
1051             }
1052         }
1053     }
1054     return true;
1055 }
1056
1057 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
1058 {
1059     vector< pair<CScript, int64> > vecSend;
1060     vecSend.push_back(make_pair(scriptPubKey, nValue));
1061     return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
1062 }
1063
1064 // ppcoin: create coin stake transaction
1065 bool CWallet::CreateCoinStake(CScript scriptPubKey, unsigned int nBits, CTransaction& txNew)
1066 {
1067     CBigNum bnTargetPerCoinDay;
1068     bnTargetPerCoinDay.SetCompact(nBits);
1069
1070     CRITICAL_BLOCK(cs_main)
1071     CRITICAL_BLOCK(cs_wallet)
1072     {
1073         txNew.vin.clear();
1074         txNew.vout.clear();
1075         // Mark coin stake transaction
1076         CScript scriptEmpty;
1077         scriptEmpty.clear();
1078         txNew.vout.push_back(CTxOut(0, scriptEmpty));
1079         // Choose coins to use
1080         int64 nBalance = GetBalance();
1081         if (nBalance <= nBalanceReserve)
1082             return false;
1083         set<pair<const CWalletTx*,unsigned int> > setCoins;
1084         int64 nValueIn = 0;
1085         if (!SelectCoins(nBalance - nBalanceReserve, txNew.nTime, setCoins, nValueIn))
1086             return false;
1087         if (setCoins.empty())
1088             return false;
1089         int64 nCredit = 0;
1090         BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1091         {
1092             CTxDB txdb("r");
1093             CTxIndex txindex;
1094             if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex))
1095                 continue;
1096
1097             // Read block header
1098             CBlock block;
1099             if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
1100                 continue;
1101             if (block.GetBlockTime() + AUTO_CHECKPOINT_TRUST_SPAN > txNew.nTime)
1102                 continue; // only count coins from at least one week ago
1103
1104             int64 nValueIn = pcoin.first->vout[pcoin.second].nValue;
1105             CBigNum bnCoinDay = CBigNum(nValueIn) * (txNew.nTime-pcoin.first->nTime) / COIN / (24 * 60 * 60);
1106             // Calculate hash
1107             CDataStream ss(SER_GETHASH, VERSION);
1108             ss << nBits << block.nTime << pcoin.first->nTime << txNew.nTime;
1109             if (CBigNum(Hash(ss.begin(), ss.end())) <= bnCoinDay * bnTargetPerCoinDay)
1110             {
1111                 txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
1112                 nCredit += pcoin.first->vout[pcoin.second].nValue;
1113                 // Only spend one tx for now
1114                 break;
1115             }
1116         }
1117         if (nCredit == 0 || nCredit > nBalance - nBalanceReserve)
1118             return false;
1119         // Calculate coin age reward
1120         {
1121             uint64 nCoinAge;
1122             CTxDB txdb("r");
1123             if (!txNew.GetCoinAge(txdb, nCoinAge))
1124                 return false;
1125             nCredit += GetProofOfStakeReward(nCoinAge);
1126         }
1127         // Fill vout
1128         txNew.vout.push_back(CTxOut(nCredit, scriptPubKey));
1129
1130
1131         // Sign
1132         int nIn = 0;
1133         BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1134         {
1135             if (!SignSignature(*this, *coin.first, txNew, nIn++))
1136                 return false;
1137             // Only spend one tx for now
1138             break;
1139         }
1140     }
1141     return true;
1142 }
1143
1144 // Call after CreateTransaction unless you want to abort
1145 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1146 {
1147     CRITICAL_BLOCK(cs_main)
1148     CRITICAL_BLOCK(cs_wallet)
1149     {
1150         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
1151         {
1152             // This is only to keep the database open to defeat the auto-flush for the
1153             // duration of this scope.  This is the only place where this optimization
1154             // maybe makes sense; please don't do it anywhere else.
1155             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1156
1157             // Take key pair from key pool so it won't be used again
1158             reservekey.KeepKey();
1159
1160             // Add tx to wallet, because if it has change it's also ours,
1161             // otherwise just for transaction history.
1162             AddToWallet(wtxNew);
1163
1164             // Mark old coins as spent
1165             set<CWalletTx*> setCoins;
1166             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1167             {
1168                 CWalletTx &coin = mapWallet[txin.prevout.hash];
1169                 coin.pwallet = this;
1170                 coin.MarkSpent(txin.prevout.n);
1171                 coin.WriteToDisk();
1172                 vWalletUpdated.push_back(coin.GetHash());
1173             }
1174
1175             if (fFileBacked)
1176                 delete pwalletdb;
1177         }
1178
1179         // Track how many getdata requests our transaction gets
1180         mapRequestCount[wtxNew.GetHash()] = 0;
1181
1182         // Broadcast
1183         if (!wtxNew.AcceptToMemoryPool())
1184         {
1185             // This must not fail. The transaction has already been signed and recorded.
1186             printf("CommitTransaction() : Error: Transaction not valid");
1187             return false;
1188         }
1189         wtxNew.RelayWalletTransaction();
1190     }
1191     MainFrameRepaint();
1192     return true;
1193 }
1194
1195
1196
1197
1198 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1199 {
1200     CReserveKey reservekey(this);
1201     int64 nFeeRequired;
1202
1203     if (IsLocked())
1204     {
1205         string strError = _("Error: Wallet locked, unable to create transaction  ");
1206         printf("SendMoney() : %s", strError.c_str());
1207         return strError;
1208     }
1209     if (fWalletUnlockStakeOnly)
1210     {
1211         string strError = _("Error: Wallet unlocked for coinstake only, unable to create transaction.");
1212         printf("SendMoney() : %s", strError.c_str());
1213         return strError;
1214     }
1215     if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
1216     {
1217         string strError;
1218         if (nValue + nFeeRequired > GetBalance())
1219             strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds  "), FormatMoney(nFeeRequired).c_str());
1220         else
1221             strError = _("Error: Transaction creation failed  ");
1222         printf("SendMoney() : %s", strError.c_str());
1223         return strError;
1224     }
1225
1226     if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
1227         return "ABORTED";
1228
1229     if (!CommitTransaction(wtxNew, reservekey))
1230         return _("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.");
1231
1232     MainFrameRepaint();
1233     return "";
1234 }
1235
1236
1237
1238 string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1239 {
1240     // Check amount
1241     if (nValue <= 0)
1242         return _("Invalid amount");
1243     if (nValue + nTransactionFee > GetBalance())
1244         return _("Insufficient funds");
1245
1246     // Parse bitcoin address
1247     CScript scriptPubKey;
1248     scriptPubKey.SetBitcoinAddress(address);
1249
1250     return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
1251 }
1252
1253
1254
1255
1256 int CWallet::LoadWallet(bool& fFirstRunRet)
1257 {
1258     if (!fFileBacked)
1259         return false;
1260     fFirstRunRet = false;
1261     int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1262     if (nLoadWalletRet == DB_NEED_REWRITE)
1263     {
1264         if (CDB::Rewrite(strWalletFile, "\x04pool"))
1265         {
1266             setKeyPool.clear();
1267             // Note: can't top-up keypool here, because wallet is locked.
1268             // User will be prompted to unlock wallet the next operation
1269             // the requires a new key.
1270         }
1271         nLoadWalletRet = DB_NEED_REWRITE;
1272     }
1273
1274     if (nLoadWalletRet != DB_LOAD_OK)
1275         return nLoadWalletRet;
1276     fFirstRunRet = vchDefaultKey.empty();
1277
1278     if (!HaveKey(Hash160(vchDefaultKey)))
1279     {
1280         // Create new keyUser and set as default key
1281         RandAddSeedPerfmon();
1282
1283         std::vector<unsigned char> newDefaultKey;
1284         if (!GetKeyFromPool(newDefaultKey, false))
1285             return DB_LOAD_FAIL;
1286         SetDefaultKey(newDefaultKey);
1287         if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
1288             return DB_LOAD_FAIL;
1289     }
1290
1291     CreateThread(ThreadFlushWalletDB, &strWalletFile);
1292     return DB_LOAD_OK;
1293 }
1294
1295
1296 bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
1297 {
1298     mapAddressBook[address] = strName;
1299     if (!fFileBacked)
1300         return false;
1301     return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
1302 }
1303
1304 bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
1305 {
1306     mapAddressBook.erase(address);
1307     if (!fFileBacked)
1308         return false;
1309     return CWalletDB(strWalletFile).EraseName(address.ToString());
1310 }
1311
1312
1313 void CWallet::PrintWallet(const CBlock& block)
1314 {
1315     CRITICAL_BLOCK(cs_wallet)
1316     {
1317         if (mapWallet.count(block.vtx[0].GetHash()))
1318         {
1319             CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1320             printf("    mine:  %d  %d  %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1321         }
1322     }
1323     printf("\n");
1324 }
1325
1326 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
1327 {
1328     CRITICAL_BLOCK(cs_wallet)
1329     {
1330         map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
1331         if (mi != mapWallet.end())
1332         {
1333             wtx = (*mi).second;
1334             return true;
1335         }
1336     }
1337     return false;
1338 }
1339
1340 bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
1341 {
1342     if (fFileBacked)
1343     {
1344         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
1345             return false;
1346     }
1347     vchDefaultKey = vchPubKey;
1348     return true;
1349 }
1350
1351 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
1352 {
1353     if (!pwallet->fFileBacked)
1354         return false;
1355     strWalletFileOut = pwallet->strWalletFile;
1356     return true;
1357 }
1358
1359 //
1360 // Mark old keypool keys as used,
1361 // and generate all new keys
1362 //
1363 bool CWallet::NewKeyPool()
1364 {
1365     CRITICAL_BLOCK(cs_wallet)
1366     {
1367         CWalletDB walletdb(strWalletFile);
1368         BOOST_FOREACH(int64 nIndex, setKeyPool)
1369             walletdb.ErasePool(nIndex);
1370         setKeyPool.clear();
1371
1372         if (IsLocked())
1373             return false;
1374
1375         int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
1376         for (int i = 0; i < nKeys; i++)
1377         {
1378             int64 nIndex = i+1;
1379             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
1380             setKeyPool.insert(nIndex);
1381         }
1382         printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
1383     }
1384     return true;
1385 }
1386
1387 bool CWallet::TopUpKeyPool()
1388 {
1389     CRITICAL_BLOCK(cs_wallet)
1390     {
1391         if (IsLocked())
1392             return false;
1393
1394         CWalletDB walletdb(strWalletFile);
1395
1396         // Top up key pool
1397         int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
1398         while (setKeyPool.size() < nTargetSize+1)
1399         {
1400             int64 nEnd = 1;
1401             if (!setKeyPool.empty())
1402                 nEnd = *(--setKeyPool.end()) + 1;
1403             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
1404                 throw runtime_error("TopUpKeyPool() : writing generated key failed");
1405             setKeyPool.insert(nEnd);
1406             printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
1407         }
1408     }
1409     return true;
1410 }
1411
1412 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
1413 {
1414     nIndex = -1;
1415     keypool.vchPubKey.clear();
1416     CRITICAL_BLOCK(cs_wallet)
1417     {
1418         if (!IsLocked())
1419             TopUpKeyPool();
1420
1421         // Get the oldest key
1422         if(setKeyPool.empty())
1423             return;
1424
1425         CWalletDB walletdb(strWalletFile);
1426
1427         nIndex = *(setKeyPool.begin());
1428         setKeyPool.erase(setKeyPool.begin());
1429         if (!walletdb.ReadPool(nIndex, keypool))
1430             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1431         if (!HaveKey(Hash160(keypool.vchPubKey)))
1432             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1433         assert(!keypool.vchPubKey.empty());
1434         printf("keypool reserve %"PRI64d"\n", nIndex);
1435     }
1436 }
1437
1438 void CWallet::KeepKey(int64 nIndex)
1439 {
1440     // Remove from key pool
1441     if (fFileBacked)
1442     {
1443         CWalletDB walletdb(strWalletFile);
1444         walletdb.ErasePool(nIndex);
1445     }
1446     printf("keypool keep %"PRI64d"\n", nIndex);
1447 }
1448
1449 void CWallet::ReturnKey(int64 nIndex)
1450 {
1451     // Return to key pool
1452     CRITICAL_BLOCK(cs_wallet)
1453         setKeyPool.insert(nIndex);
1454     printf("keypool return %"PRI64d"\n", nIndex);
1455 }
1456
1457 bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
1458 {
1459     int64 nIndex = 0;
1460     CKeyPool keypool;
1461     CRITICAL_BLOCK(cs_wallet)
1462     {
1463         ReserveKeyFromKeyPool(nIndex, keypool);
1464         if (nIndex == -1)
1465         {
1466             if (fAllowReuse && !vchDefaultKey.empty())
1467             {
1468                 result = vchDefaultKey;
1469                 return true;
1470             }
1471             if (IsLocked()) return false;
1472             result = GenerateNewKey();
1473             return true;
1474         }
1475         KeepKey(nIndex);
1476         result = keypool.vchPubKey;
1477     }
1478     return true;
1479 }
1480
1481 int64 CWallet::GetOldestKeyPoolTime()
1482 {
1483     int64 nIndex = 0;
1484     CKeyPool keypool;
1485     ReserveKeyFromKeyPool(nIndex, keypool);
1486     if (nIndex == -1)
1487         return GetTime();
1488     ReturnKey(nIndex);
1489     return keypool.nTime;
1490 }
1491
1492 // ppcoin: check 'spent' consistency between wallet and txindex
1493 bool CWallet::CheckSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion)
1494 {
1495     nMismatchFound = 0;
1496     nBalanceInQuestion = 0;
1497     CRITICAL_BLOCK(cs_wallet)
1498     {
1499        vector<const CWalletTx*> vCoins;
1500        vCoins.reserve(mapWallet.size());
1501        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1502            vCoins.push_back(&(*it).second);
1503
1504        CTxDB txdb("r");
1505        BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
1506        {
1507            // Find the corresponding transaction index
1508            CTxIndex txindex;
1509            if (!txdb.ReadTxIndex(pcoin->GetHash(), txindex))
1510                continue;
1511            for (int n=0; n < pcoin->vout.size(); n++)
1512            {
1513                if (pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
1514                {
1515                    printf("CheckSpentCoins found lost coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
1516                    nMismatchFound++;
1517                    nBalanceInQuestion += pcoin->vout[n].nValue;
1518                }
1519                else if (!pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
1520                {
1521                    printf("CheckSpentCoins found spent coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
1522                    nMismatchFound++;
1523                    nBalanceInQuestion += pcoin->vout[n].nValue;
1524                }
1525            }
1526        }
1527     }
1528     return (nMismatchFound == 0);
1529 }
1530
1531 // ppcoin: fix wallet spent state according to txindex
1532 void CWallet::FixSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion)
1533 {
1534     nMismatchFound = 0;
1535     nBalanceInQuestion = 0;
1536     CRITICAL_BLOCK(cs_wallet)
1537     {
1538        vector<CWalletTx*> vCoins;
1539        vCoins.reserve(mapWallet.size());
1540        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1541            vCoins.push_back(&(*it).second);
1542
1543        CTxDB txdb("r");
1544        BOOST_FOREACH(CWalletTx* pcoin, vCoins)
1545        {
1546            // Find the corresponding transaction index
1547            CTxIndex txindex;
1548            if (!txdb.ReadTxIndex(pcoin->GetHash(), txindex))
1549                continue;
1550            for (int n=0; n < pcoin->vout.size(); n++)
1551            {
1552                if (pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
1553                {
1554                    printf("FixSpentCoins found lost coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
1555                    nMismatchFound++;
1556                    nBalanceInQuestion += pcoin->vout[n].nValue;
1557                    pcoin->MarkUnspent(n);
1558                    pcoin->WriteToDisk();
1559                }
1560                else if (!pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
1561                {
1562                    printf("FixSpentCoins found spent coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
1563                    nMismatchFound++;
1564                    nBalanceInQuestion += pcoin->vout[n].nValue;
1565                    pcoin->MarkSpent(n);
1566                    pcoin->WriteToDisk();
1567                }
1568            }
1569        }
1570     }
1571 }
1572
1573 // ppcoin: disable transaction (only for coinstake)
1574 void CWallet::DisableTransaction(const CTransaction &tx)
1575 {
1576     if (!tx.IsCoinStake() || !IsFromMe(tx))
1577         return; // only disconnecting coinstake requires marking input unspent
1578     CRITICAL_BLOCK(cs_wallet)
1579     {
1580         BOOST_FOREACH(const CTxIn& txin, tx.vin)
1581         {
1582             map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
1583             if (mi != mapWallet.end())
1584             {
1585                 CWalletTx& prev = (*mi).second;
1586                 if (txin.prevout.n < prev.vout.size() && IsMine(prev.vout[txin.prevout.n]))
1587                 {
1588                     prev.MarkUnspent(txin.prevout.n);
1589                     prev.WriteToDisk();
1590                 }
1591             }
1592         }
1593     }
1594 }
1595
1596 vector<unsigned char> CReserveKey::GetReservedKey()
1597 {
1598     if (nIndex == -1)
1599     {
1600         CKeyPool keypool;
1601         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
1602         if (nIndex != -1)
1603             vchPubKey = keypool.vchPubKey;
1604         else
1605         {
1606             printf("CReserveKey::GetReservedKey(): Warning: using default key instead of a new key, top up your keypool.");
1607             vchPubKey = pwallet->vchDefaultKey;
1608         }
1609     }
1610     assert(!vchPubKey.empty());
1611     return vchPubKey;
1612 }
1613
1614 void CReserveKey::KeepKey()
1615 {
1616     if (nIndex != -1)
1617         pwallet->KeepKey(nIndex);
1618     nIndex = -1;
1619     vchPubKey.clear();
1620 }
1621
1622 void CReserveKey::ReturnKey()
1623 {
1624     if (nIndex != -1)
1625         pwallet->ReturnKey(nIndex);
1626     nIndex = -1;
1627     vchPubKey.clear();
1628 }
1629