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