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