PPCoin: RPC 'makekeypair' limits loop to avoid hang
[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->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0)
776                 nTotal += CWallet::GetCredit(*pcoin);
777         }
778     }
779     return nTotal;
780 }
781
782 int64 CWallet::GetNewMint() const
783 {
784     int64 nTotal = 0;
785     CRITICAL_BLOCK(cs_wallet)
786     {
787         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
788         {
789             const CWalletTx* pcoin = &(*it).second;
790             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0)
791                 nTotal += CWallet::GetCredit(*pcoin);
792         }
793     }
794     return nTotal;
795 }
796
797
798 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
799 {
800     setCoinsRet.clear();
801     nValueRet = 0;
802
803     // List of values less than target
804     pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
805     coinLowestLarger.first = INT64_MAX;
806     coinLowestLarger.second.first = NULL;
807     vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
808     int64 nTotalLower = 0;
809
810     CRITICAL_BLOCK(cs_wallet)
811     {
812        vector<const CWalletTx*> vCoins;
813        vCoins.reserve(mapWallet.size());
814        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
815            vCoins.push_back(&(*it).second);
816        random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
817
818        BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
819        {
820             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
821                 continue;
822
823             if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0)
824                 continue;
825
826             int nDepth = pcoin->GetDepthInMainChain();
827             if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
828                 continue;
829
830             for (int i = 0; i < pcoin->vout.size(); i++)
831             {
832                 if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
833                     continue;
834
835                 if (pcoin->nTime > nSpendTime)
836                     continue;  // ppcoin: timestamp must not exceed spend time
837
838                 int64 n = pcoin->vout[i].nValue;
839
840                 if (n <= 0)
841                     continue;
842
843                 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
844
845                 if (n == nTargetValue)
846                 {
847                     setCoinsRet.insert(coin.second);
848                     nValueRet += coin.first;
849                     return true;
850                 }
851                 else if (n < nTargetValue + CENT)
852                 {
853                     vValue.push_back(coin);
854                     nTotalLower += n;
855                 }
856                 else if (n < coinLowestLarger.first)
857                 {
858                     coinLowestLarger = coin;
859                 }
860             }
861         }
862     }
863
864     if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
865     {
866         for (int i = 0; i < vValue.size(); ++i)
867         {
868             setCoinsRet.insert(vValue[i].second);
869             nValueRet += vValue[i].first;
870         }
871         return true;
872     }
873
874     if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
875     {
876         if (coinLowestLarger.second.first == NULL)
877             return false;
878         setCoinsRet.insert(coinLowestLarger.second);
879         nValueRet += coinLowestLarger.first;
880         return true;
881     }
882
883     if (nTotalLower >= nTargetValue + CENT)
884         nTargetValue += CENT;
885
886     // Solve subset sum by stochastic approximation
887     sort(vValue.rbegin(), vValue.rend());
888     vector<char> vfIncluded;
889     vector<char> vfBest(vValue.size(), true);
890     int64 nBest = nTotalLower;
891
892     for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
893     {
894         vfIncluded.assign(vValue.size(), false);
895         int64 nTotal = 0;
896         bool fReachedTarget = false;
897         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
898         {
899             for (int i = 0; i < vValue.size(); i++)
900             {
901                 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
902                 {
903                     nTotal += vValue[i].first;
904                     vfIncluded[i] = true;
905                     if (nTotal >= nTargetValue)
906                     {
907                         fReachedTarget = true;
908                         if (nTotal < nBest)
909                         {
910                             nBest = nTotal;
911                             vfBest = vfIncluded;
912                         }
913                         nTotal -= vValue[i].first;
914                         vfIncluded[i] = false;
915                     }
916                 }
917             }
918         }
919     }
920
921     // If the next larger is still closer, return it
922     if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
923     {
924         setCoinsRet.insert(coinLowestLarger.second);
925         nValueRet += coinLowestLarger.first;
926     }
927     else {
928         for (int i = 0; i < vValue.size(); i++)
929             if (vfBest[i])
930             {
931                 setCoinsRet.insert(vValue[i].second);
932                 nValueRet += vValue[i].first;
933             }
934
935         //// debug print
936         printf("SelectCoins() best subset: ");
937         for (int i = 0; i < vValue.size(); i++)
938             if (vfBest[i])
939                 printf("%s ", FormatMoney(vValue[i].first).c_str());
940         printf("total %s\n", FormatMoney(nBest).c_str());
941     }
942
943     return true;
944 }
945
946 bool CWallet::SelectCoins(int64 nTargetValue, unsigned int nSpendTime, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
947 {
948     return (SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 6, setCoinsRet, nValueRet) ||
949             SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 1, setCoinsRet, nValueRet) ||
950             SelectCoinsMinConf(nTargetValue, nSpendTime, 0, 1, setCoinsRet, nValueRet));
951 }
952
953
954
955
956 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
957 {
958     int64 nValue = 0;
959     BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
960     {
961         if (nValue < 0)
962             return false;
963         nValue += s.second;
964     }
965     if (vecSend.empty() || nValue < 0)
966         return false;
967
968     wtxNew.pwallet = this;
969
970     CRITICAL_BLOCK(cs_main)
971     CRITICAL_BLOCK(cs_wallet)
972     {
973         // txdb must be opened before the mapWallet lock
974         CTxDB txdb("r");
975         {
976             nFeeRet = nTransactionFee;
977             loop
978             {
979                 wtxNew.vin.clear();
980                 wtxNew.vout.clear();
981                 wtxNew.fFromMe = true;
982
983                 int64 nTotalValue = nValue + nFeeRet;
984                 double dPriority = 0;
985                 // vouts to the payees
986                 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
987                     wtxNew.vout.push_back(CTxOut(s.second, s.first));
988
989                 // Choose coins to use
990                 set<pair<const CWalletTx*,unsigned int> > setCoins;
991                 int64 nValueIn = 0;
992                 if (!SelectCoins(nTotalValue, wtxNew.nTime, setCoins, nValueIn))
993                     return false;
994                 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
995                 {
996                     int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
997                     dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
998                 }
999
1000                 int64 nChange = nValueIn - nValue - nFeeRet;
1001                 // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
1002                 // or until nChange becomes zero
1003                 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
1004                 {
1005                     int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
1006                     nChange -= nMoveToFee;
1007                     nFeeRet += nMoveToFee;
1008                 }
1009
1010                 if (nChange > 0)
1011                 {
1012                     // Note: We use a new key here to keep it from being obvious which side is the change.
1013                     //  The drawback is that by not reusing a previous key, the change may be lost if a
1014                     //  backup is restored, if the backup doesn't have the new private key for the change.
1015                     //  If we reused the old key, it would be possible to add code to look for and
1016                     //  rediscover unknown transactions that were written with keys of ours to recover
1017                     //  post-backup change.
1018
1019                     // Reserve a new key pair from key pool
1020                     vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
1021                     // assert(mapKeys.count(vchPubKey));
1022
1023                     // Fill a vout to ourself, using same address type as the payment
1024                     CScript scriptChange;
1025                     if (vecSend[0].first.GetBitcoinAddress().IsValid())
1026                         scriptChange.SetBitcoinAddress(vchPubKey);
1027                     else
1028                         scriptChange << vchPubKey << OP_CHECKSIG;
1029
1030                     // Insert change txn at random position:
1031                     vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
1032                     wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
1033                 }
1034                 else
1035                     reservekey.ReturnKey();
1036
1037                 // Fill vin
1038                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1039                     wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
1040
1041                 // Sign
1042                 int nIn = 0;
1043                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1044                     if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
1045                         return false;
1046
1047                 // Limit size
1048                 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
1049                 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
1050                     return false;
1051                 dPriority /= nBytes;
1052
1053                 // Check that enough fee is included
1054                 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
1055                 int64 nMinFee = wtxNew.GetMinFee(1, false);
1056                 if (nFeeRet < max(nPayFee, nMinFee))
1057                 {
1058                     nFeeRet = max(nPayFee, nMinFee);
1059                     continue;
1060                 }
1061
1062                 // Fill vtxPrev by copying from previous transactions vtxPrev
1063                 wtxNew.AddSupportingTransactions(txdb);
1064                 wtxNew.fTimeReceivedIsTxTime = true;
1065
1066                 break;
1067             }
1068         }
1069     }
1070     return true;
1071 }
1072
1073 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
1074 {
1075     vector< pair<CScript, int64> > vecSend;
1076     vecSend.push_back(make_pair(scriptPubKey, nValue));
1077     return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
1078 }
1079
1080 // ppcoin: create coin stake transaction
1081 bool CWallet::CreateCoinStake(unsigned int nBits, CTransaction& txNew)
1082 {
1083     CBigNum bnTargetPerCoinDay;
1084     bnTargetPerCoinDay.SetCompact(nBits);
1085
1086     CRITICAL_BLOCK(cs_main)
1087     CRITICAL_BLOCK(cs_wallet)
1088     {
1089         txNew.vin.clear();
1090         txNew.vout.clear();
1091         // Mark coin stake transaction
1092         CScript scriptEmpty;
1093         scriptEmpty.clear();
1094         txNew.vout.push_back(CTxOut(0, scriptEmpty));
1095         // Choose coins to use
1096         int64 nBalance = GetBalance();
1097         if (nBalance <= nBalanceReserve)
1098             return false;
1099         set<pair<const CWalletTx*,unsigned int> > setCoins;
1100         vector<const CWalletTx*> vwtxPrev;
1101         int64 nValueIn = 0;
1102         if (!SelectCoins(nBalance - nBalanceReserve, txNew.nTime, setCoins, nValueIn))
1103             return false;
1104         if (setCoins.empty())
1105             return false;
1106         int64 nCredit = 0;
1107         BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1108         {
1109             CTxDB txdb("r");
1110             CTxIndex txindex;
1111             if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex))
1112                 continue;
1113
1114             // Read block header
1115             CBlock block;
1116             if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
1117                 continue;
1118             if (block.GetBlockTime() + STAKE_MIN_AGE > txNew.nTime)
1119                 continue; // only count coins meeting min age requirement
1120
1121             int64 nValueIn = pcoin.first->vout[pcoin.second].nValue;
1122             CBigNum bnCoinDay = CBigNum(nValueIn) * (txNew.nTime-pcoin.first->nTime) / COIN / (24 * 60 * 60);
1123             // Calculate hash
1124             CDataStream ss(SER_GETHASH, VERSION);
1125             ss << nBits << block.nTime << (txindex.pos.nTxPos - txindex.pos.nBlockPos) << pcoin.first->nTime << pcoin.second << txNew.nTime;
1126             if (CBigNum(Hash(ss.begin(), ss.end())) <= bnCoinDay * bnTargetPerCoinDay)
1127             {
1128                 txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
1129                 nCredit += pcoin.first->vout[pcoin.second].nValue;
1130                 vwtxPrev.push_back(pcoin.first);
1131                 // Set output scriptPubKey
1132                 txNew.vout.push_back(CTxOut(0, pcoin.first->vout[pcoin.second].scriptPubKey));
1133                 break;
1134             }
1135         }
1136         if (nCredit == 0 || nCredit > nBalance - nBalanceReserve)
1137             return false;
1138         BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1139         {
1140             if (pcoin.first->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey && pcoin.first->GetHash() != txNew.vin[0].prevout.hash)
1141             {
1142                 if (nCredit + pcoin.first->vout[pcoin.second].nValue > nBalance - nBalanceReserve)
1143                     break;
1144                 txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
1145                 nCredit += pcoin.first->vout[pcoin.second].nValue;
1146                 vwtxPrev.push_back(pcoin.first);
1147             }
1148         }
1149         // Calculate coin age reward
1150         {
1151             uint64 nCoinAge;
1152             CTxDB txdb("r");
1153             if (!txNew.GetCoinAge(txdb, nCoinAge))
1154                 return error("CreateCoinStake : failed to calculate coin age");
1155             nCredit += GetProofOfStakeReward(nCoinAge);
1156         }
1157         // Set output amount
1158         txNew.vout[1].nValue = nCredit;
1159
1160         // Sign
1161         int nIn = 0;
1162         BOOST_FOREACH(const CWalletTx* pcoin, vwtxPrev)
1163         {
1164             if (!SignSignature(*this, *pcoin, txNew, nIn++))
1165                 return error("CreateCoinStake : failed to sign coinstake");
1166         }
1167     }
1168     return true;
1169 }
1170
1171 // Call after CreateTransaction unless you want to abort
1172 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1173 {
1174     CRITICAL_BLOCK(cs_main)
1175     CRITICAL_BLOCK(cs_wallet)
1176     {
1177         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
1178         {
1179             // This is only to keep the database open to defeat the auto-flush for the
1180             // duration of this scope.  This is the only place where this optimization
1181             // maybe makes sense; please don't do it anywhere else.
1182             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1183
1184             // Take key pair from key pool so it won't be used again
1185             reservekey.KeepKey();
1186
1187             // Add tx to wallet, because if it has change it's also ours,
1188             // otherwise just for transaction history.
1189             AddToWallet(wtxNew);
1190
1191             // Mark old coins as spent
1192             set<CWalletTx*> setCoins;
1193             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1194             {
1195                 CWalletTx &coin = mapWallet[txin.prevout.hash];
1196                 coin.pwallet = this;
1197                 coin.MarkSpent(txin.prevout.n);
1198                 coin.WriteToDisk();
1199                 vWalletUpdated.push_back(coin.GetHash());
1200             }
1201
1202             if (fFileBacked)
1203                 delete pwalletdb;
1204         }
1205
1206         // Track how many getdata requests our transaction gets
1207         mapRequestCount[wtxNew.GetHash()] = 0;
1208
1209         // Broadcast
1210         if (!wtxNew.AcceptToMemoryPool())
1211         {
1212             // This must not fail. The transaction has already been signed and recorded.
1213             printf("CommitTransaction() : Error: Transaction not valid");
1214             return false;
1215         }
1216         wtxNew.RelayWalletTransaction();
1217     }
1218     MainFrameRepaint();
1219     return true;
1220 }
1221
1222
1223
1224
1225 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1226 {
1227     CReserveKey reservekey(this);
1228     int64 nFeeRequired;
1229
1230     if (IsLocked())
1231     {
1232         string strError = _("Error: Wallet locked, unable to create transaction  ");
1233         printf("SendMoney() : %s", strError.c_str());
1234         return strError;
1235     }
1236     if (fWalletUnlockStakeOnly)
1237     {
1238         string strError = _("Error: Wallet unlocked for coinstake only, unable to create transaction.");
1239         printf("SendMoney() : %s", strError.c_str());
1240         return strError;
1241     }
1242     if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
1243     {
1244         string strError;
1245         if (nValue + nFeeRequired > GetBalance())
1246             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());
1247         else
1248             strError = _("Error: Transaction creation failed  ");
1249         printf("SendMoney() : %s", strError.c_str());
1250         return strError;
1251     }
1252
1253     if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending..."), NULL))
1254         return "ABORTED";
1255
1256     if (!CommitTransaction(wtxNew, reservekey))
1257         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.");
1258
1259     MainFrameRepaint();
1260     return "";
1261 }
1262
1263
1264
1265 string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1266 {
1267     // Check amount
1268     if (nValue <= 0)
1269         return _("Invalid amount");
1270     if (nValue + nTransactionFee > GetBalance())
1271         return _("Insufficient funds");
1272
1273     // Parse bitcoin address
1274     CScript scriptPubKey;
1275     scriptPubKey.SetBitcoinAddress(address);
1276
1277     return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
1278 }
1279
1280
1281
1282
1283 int CWallet::LoadWallet(bool& fFirstRunRet)
1284 {
1285     if (!fFileBacked)
1286         return false;
1287     fFirstRunRet = false;
1288     int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1289     if (nLoadWalletRet == DB_NEED_REWRITE)
1290     {
1291         if (CDB::Rewrite(strWalletFile, "\x04pool"))
1292         {
1293             setKeyPool.clear();
1294             // Note: can't top-up keypool here, because wallet is locked.
1295             // User will be prompted to unlock wallet the next operation
1296             // the requires a new key.
1297         }
1298         nLoadWalletRet = DB_NEED_REWRITE;
1299     }
1300
1301     if (nLoadWalletRet != DB_LOAD_OK)
1302         return nLoadWalletRet;
1303     fFirstRunRet = vchDefaultKey.empty();
1304
1305     if (!HaveKey(Hash160(vchDefaultKey)))
1306     {
1307         // Create new keyUser and set as default key
1308         RandAddSeedPerfmon();
1309
1310         std::vector<unsigned char> newDefaultKey;
1311         if (!GetKeyFromPool(newDefaultKey, false))
1312             return DB_LOAD_FAIL;
1313         SetDefaultKey(newDefaultKey);
1314         if (!SetAddressBookName(CBitcoinAddress(vchDefaultKey), ""))
1315             return DB_LOAD_FAIL;
1316     }
1317
1318     CreateThread(ThreadFlushWalletDB, &strWalletFile);
1319     return DB_LOAD_OK;
1320 }
1321
1322
1323 bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
1324 {
1325     mapAddressBook[address] = strName;
1326     if (!fFileBacked)
1327         return false;
1328     return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
1329 }
1330
1331 bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
1332 {
1333     mapAddressBook.erase(address);
1334     if (!fFileBacked)
1335         return false;
1336     return CWalletDB(strWalletFile).EraseName(address.ToString());
1337 }
1338
1339
1340 void CWallet::PrintWallet(const CBlock& block)
1341 {
1342     CRITICAL_BLOCK(cs_wallet)
1343     {
1344         if (block.IsProofOfWork() && mapWallet.count(block.vtx[0].GetHash()))
1345         {
1346             CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1347             printf("    mine:  %d  %d  %s", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), FormatMoney(wtx.GetCredit()).c_str());
1348         }
1349         if (block.IsProofOfStake() && mapWallet.count(block.vtx[1].GetHash()))
1350         {
1351             CWalletTx& wtx = mapWallet[block.vtx[1].GetHash()];
1352             printf("    stake: %d  %d  %s", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), FormatMoney(wtx.GetCredit()).c_str());
1353         }
1354     }
1355     printf("\n");
1356 }
1357
1358 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
1359 {
1360     CRITICAL_BLOCK(cs_wallet)
1361     {
1362         map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
1363         if (mi != mapWallet.end())
1364         {
1365             wtx = (*mi).second;
1366             return true;
1367         }
1368     }
1369     return false;
1370 }
1371
1372 bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
1373 {
1374     if (fFileBacked)
1375     {
1376         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
1377             return false;
1378     }
1379     vchDefaultKey = vchPubKey;
1380     return true;
1381 }
1382
1383 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
1384 {
1385     if (!pwallet->fFileBacked)
1386         return false;
1387     strWalletFileOut = pwallet->strWalletFile;
1388     return true;
1389 }
1390
1391 //
1392 // Mark old keypool keys as used,
1393 // and generate all new keys
1394 //
1395 bool CWallet::NewKeyPool()
1396 {
1397     CRITICAL_BLOCK(cs_wallet)
1398     {
1399         CWalletDB walletdb(strWalletFile);
1400         BOOST_FOREACH(int64 nIndex, setKeyPool)
1401             walletdb.ErasePool(nIndex);
1402         setKeyPool.clear();
1403
1404         if (IsLocked())
1405             return false;
1406
1407         int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
1408         for (int i = 0; i < nKeys; i++)
1409         {
1410             int64 nIndex = i+1;
1411             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
1412             setKeyPool.insert(nIndex);
1413         }
1414         printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
1415     }
1416     return true;
1417 }
1418
1419 bool CWallet::TopUpKeyPool()
1420 {
1421     CRITICAL_BLOCK(cs_wallet)
1422     {
1423         if (IsLocked())
1424             return false;
1425
1426         CWalletDB walletdb(strWalletFile);
1427
1428         // Top up key pool
1429         int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
1430         while (setKeyPool.size() < nTargetSize+1)
1431         {
1432             int64 nEnd = 1;
1433             if (!setKeyPool.empty())
1434                 nEnd = *(--setKeyPool.end()) + 1;
1435             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
1436                 throw runtime_error("TopUpKeyPool() : writing generated key failed");
1437             setKeyPool.insert(nEnd);
1438             printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
1439         }
1440     }
1441     return true;
1442 }
1443
1444 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
1445 {
1446     nIndex = -1;
1447     keypool.vchPubKey.clear();
1448     CRITICAL_BLOCK(cs_wallet)
1449     {
1450         if (!IsLocked())
1451             TopUpKeyPool();
1452
1453         // Get the oldest key
1454         if(setKeyPool.empty())
1455             return;
1456
1457         CWalletDB walletdb(strWalletFile);
1458
1459         nIndex = *(setKeyPool.begin());
1460         setKeyPool.erase(setKeyPool.begin());
1461         if (!walletdb.ReadPool(nIndex, keypool))
1462             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1463         if (!HaveKey(Hash160(keypool.vchPubKey)))
1464             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1465         assert(!keypool.vchPubKey.empty());
1466         printf("keypool reserve %"PRI64d"\n", nIndex);
1467     }
1468 }
1469
1470 void CWallet::KeepKey(int64 nIndex)
1471 {
1472     // Remove from key pool
1473     if (fFileBacked)
1474     {
1475         CWalletDB walletdb(strWalletFile);
1476         walletdb.ErasePool(nIndex);
1477     }
1478     printf("keypool keep %"PRI64d"\n", nIndex);
1479 }
1480
1481 void CWallet::ReturnKey(int64 nIndex)
1482 {
1483     // Return to key pool
1484     CRITICAL_BLOCK(cs_wallet)
1485         setKeyPool.insert(nIndex);
1486     printf("keypool return %"PRI64d"\n", nIndex);
1487 }
1488
1489 bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
1490 {
1491     int64 nIndex = 0;
1492     CKeyPool keypool;
1493     CRITICAL_BLOCK(cs_wallet)
1494     {
1495         ReserveKeyFromKeyPool(nIndex, keypool);
1496         if (nIndex == -1)
1497         {
1498             if (fAllowReuse && !vchDefaultKey.empty())
1499             {
1500                 result = vchDefaultKey;
1501                 return true;
1502             }
1503             if (IsLocked()) return false;
1504             result = GenerateNewKey();
1505             return true;
1506         }
1507         KeepKey(nIndex);
1508         result = keypool.vchPubKey;
1509     }
1510     return true;
1511 }
1512
1513 int64 CWallet::GetOldestKeyPoolTime()
1514 {
1515     int64 nIndex = 0;
1516     CKeyPool keypool;
1517     ReserveKeyFromKeyPool(nIndex, keypool);
1518     if (nIndex == -1)
1519         return GetTime();
1520     ReturnKey(nIndex);
1521     return keypool.nTime;
1522 }
1523
1524 // ppcoin: check 'spent' consistency between wallet and txindex
1525 bool CWallet::CheckSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion)
1526 {
1527     nMismatchFound = 0;
1528     nBalanceInQuestion = 0;
1529     CRITICAL_BLOCK(cs_wallet)
1530     {
1531        vector<const CWalletTx*> vCoins;
1532        vCoins.reserve(mapWallet.size());
1533        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1534            vCoins.push_back(&(*it).second);
1535
1536        CTxDB txdb("r");
1537        BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
1538        {
1539            // Find the corresponding transaction index
1540            CTxIndex txindex;
1541            if (!txdb.ReadTxIndex(pcoin->GetHash(), txindex))
1542                continue;
1543            for (int n=0; n < pcoin->vout.size(); n++)
1544            {
1545                if (pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
1546                {
1547                    printf("CheckSpentCoins found lost coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
1548                    nMismatchFound++;
1549                    nBalanceInQuestion += pcoin->vout[n].nValue;
1550                }
1551                else if (!pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
1552                {
1553                    printf("CheckSpentCoins found spent coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
1554                    nMismatchFound++;
1555                    nBalanceInQuestion += pcoin->vout[n].nValue;
1556                }
1557            }
1558        }
1559     }
1560     return (nMismatchFound == 0);
1561 }
1562
1563 // ppcoin: fix wallet spent state according to txindex
1564 void CWallet::FixSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion)
1565 {
1566     nMismatchFound = 0;
1567     nBalanceInQuestion = 0;
1568     CRITICAL_BLOCK(cs_wallet)
1569     {
1570        vector<CWalletTx*> vCoins;
1571        vCoins.reserve(mapWallet.size());
1572        for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1573            vCoins.push_back(&(*it).second);
1574
1575        CTxDB txdb("r");
1576        BOOST_FOREACH(CWalletTx* pcoin, vCoins)
1577        {
1578            // Find the corresponding transaction index
1579            CTxIndex txindex;
1580            if (!txdb.ReadTxIndex(pcoin->GetHash(), txindex))
1581                continue;
1582            for (int n=0; n < pcoin->vout.size(); n++)
1583            {
1584                if (pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
1585                {
1586                    printf("FixSpentCoins found lost coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
1587                    nMismatchFound++;
1588                    nBalanceInQuestion += pcoin->vout[n].nValue;
1589                    pcoin->MarkUnspent(n);
1590                    pcoin->WriteToDisk();
1591                }
1592                else if (!pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
1593                {
1594                    printf("FixSpentCoins found spent coin %sppc %s[%d]\n", FormatMoney(pcoin->GetCredit()).c_str(), pcoin->GetHash().ToString().c_str(), n);
1595                    nMismatchFound++;
1596                    nBalanceInQuestion += pcoin->vout[n].nValue;
1597                    pcoin->MarkSpent(n);
1598                    pcoin->WriteToDisk();
1599                }
1600            }
1601        }
1602     }
1603 }
1604
1605 // ppcoin: disable transaction (only for coinstake)
1606 void CWallet::DisableTransaction(const CTransaction &tx)
1607 {
1608     if (!tx.IsCoinStake() || !IsFromMe(tx))
1609         return; // only disconnecting coinstake requires marking input unspent
1610     CRITICAL_BLOCK(cs_wallet)
1611     {
1612         BOOST_FOREACH(const CTxIn& txin, tx.vin)
1613         {
1614             map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
1615             if (mi != mapWallet.end())
1616             {
1617                 CWalletTx& prev = (*mi).second;
1618                 if (txin.prevout.n < prev.vout.size() && IsMine(prev.vout[txin.prevout.n]))
1619                 {
1620                     prev.MarkUnspent(txin.prevout.n);
1621                     prev.WriteToDisk();
1622                 }
1623             }
1624         }
1625     }
1626 }
1627
1628 vector<unsigned char> CReserveKey::GetReservedKey()
1629 {
1630     if (nIndex == -1)
1631     {
1632         CKeyPool keypool;
1633         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
1634         if (nIndex != -1)
1635             vchPubKey = keypool.vchPubKey;
1636         else
1637         {
1638             printf("CReserveKey::GetReservedKey(): Warning: using default key instead of a new key, top up your keypool.");
1639             vchPubKey = pwallet->vchDefaultKey;
1640         }
1641     }
1642     assert(!vchPubKey.empty());
1643     return vchPubKey;
1644 }
1645
1646 void CReserveKey::KeepKey()
1647 {
1648     if (nIndex != -1)
1649         pwallet->KeepKey(nIndex);
1650     nIndex = -1;
1651     vchPubKey.clear();
1652 }
1653
1654 void CReserveKey::ReturnKey()
1655 {
1656     if (nIndex != -1)
1657         pwallet->ReturnKey(nIndex);
1658     nIndex = -1;
1659     vchPubKey.clear();
1660 }
1661