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