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