Use scoped locks instead of CRITICAL_BLOCK
[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 (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                     BOOST_FOREACH(const CTxIn& txin, tx.vin)
652                         vWorkQueue.push_back(txin.prevout.hash);
653             }
654         }
655     }
656
657     reverse(vtxPrev.begin(), vtxPrev.end());
658 }
659
660 bool CWalletTx::WriteToDisk()
661 {
662     return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
663 }
664
665 // Scan the block chain (starting in pindexStart) for transactions
666 // from or to us. If fUpdate is true, found transactions that already
667 // exist in the wallet will be updated.
668 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
669 {
670     int ret = 0;
671
672     CBlockIndex* pindex = pindexStart;
673     {
674         LOCK(cs_wallet);
675         while (pindex)
676         {
677             CBlock block;
678             block.ReadFromDisk(pindex, true);
679             BOOST_FOREACH(CTransaction& tx, block.vtx)
680             {
681                 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
682                     ret++;
683             }
684             pindex = pindex->pnext;
685         }
686     }
687     return ret;
688 }
689
690 int CWallet::ScanForWalletTransaction(const uint256& hashTx)
691 {
692     CTransaction tx;
693     tx.ReadFromDisk(COutPoint(hashTx, 0));
694     if (AddToWalletIfInvolvingMe(tx, NULL, true, true))
695         return 1;
696     return 0;
697 }
698
699 void CWallet::ReacceptWalletTransactions()
700 {
701     CTxDB txdb("r");
702     bool fRepeat = true;
703     while (fRepeat)
704     {
705         LOCK(cs_wallet);
706         fRepeat = false;
707         vector<CDiskTxPos> vMissingTx;
708         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
709         {
710             CWalletTx& wtx = item.second;
711             if (wtx.IsCoinBase() && wtx.IsSpent(0))
712                 continue;
713
714             CTxIndex txindex;
715             bool fUpdated = false;
716             if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
717             {
718                 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
719                 if (txindex.vSpent.size() != wtx.vout.size())
720                 {
721                     printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %d != wtx.vout.size() %d\n", txindex.vSpent.size(), wtx.vout.size());
722                     continue;
723                 }
724                 for (int i = 0; i < txindex.vSpent.size(); i++)
725                 {
726                     if (wtx.IsSpent(i))
727                         continue;
728                     if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
729                     {
730                         wtx.MarkSpent(i);
731                         fUpdated = true;
732                         vMissingTx.push_back(txindex.vSpent[i]);
733                     }
734                 }
735                 if (fUpdated)
736                 {
737                     printf("ReacceptWalletTransactions found spent coin %sbc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
738                     wtx.MarkDirty();
739                     wtx.WriteToDisk();
740                 }
741             }
742             else
743             {
744                 // Reaccept any txes of ours that aren't already in a block
745                 if (!wtx.IsCoinBase())
746                     wtx.AcceptWalletTransaction(txdb, false);
747             }
748         }
749         if (!vMissingTx.empty())
750         {
751             // TODO: optimize this to scan just part of the block chain?
752             if (ScanForWalletTransactions(pindexGenesisBlock))
753                 fRepeat = true;  // Found missing transactions: re-do Reaccept.
754         }
755     }
756 }
757
758 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
759 {
760     BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
761     {
762         if (!tx.IsCoinBase())
763         {
764             uint256 hash = tx.GetHash();
765             if (!txdb.ContainsTx(hash))
766                 RelayMessage(CInv(MSG_TX, hash), (CTransaction)tx);
767         }
768     }
769     if (!IsCoinBase())
770     {
771         uint256 hash = GetHash();
772         if (!txdb.ContainsTx(hash))
773         {
774             printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
775             RelayMessage(CInv(MSG_TX, hash), (CTransaction)*this);
776         }
777     }
778 }
779
780 void CWalletTx::RelayWalletTransaction()
781 {
782    CTxDB txdb("r");
783    RelayWalletTransaction(txdb);
784 }
785
786 void CWallet::ResendWalletTransactions()
787 {
788     // Do this infrequently and randomly to avoid giving away
789     // that these are our transactions.
790     static int64 nNextTime;
791     if (GetTime() < nNextTime)
792         return;
793     bool fFirst = (nNextTime == 0);
794     nNextTime = GetTime() + GetRand(30 * 60);
795     if (fFirst)
796         return;
797
798     // Only do it if there's been a new block since last time
799     static int64 nLastTime;
800     if (nTimeBestReceived < nLastTime)
801         return;
802     nLastTime = GetTime();
803
804     // Rebroadcast any of our txes that aren't in a block yet
805     printf("ResendWalletTransactions()\n");
806     CTxDB txdb("r");
807     {
808         LOCK(cs_wallet);
809         // Sort them in chronological order
810         multimap<unsigned int, CWalletTx*> mapSorted;
811         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
812         {
813             CWalletTx& wtx = item.second;
814             // Don't rebroadcast until it's had plenty of time that
815             // it should have gotten in already by now.
816             if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
817                 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
818         }
819         BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
820         {
821             CWalletTx& wtx = *item.second;
822             wtx.RelayWalletTransaction(txdb);
823         }
824     }
825 }
826
827
828
829
830
831
832 //////////////////////////////////////////////////////////////////////////////
833 //
834 // Actions
835 //
836
837
838 int64 CWallet::GetBalance() const
839 {
840     int64 nTotal = 0;
841     {
842         LOCK(cs_wallet);
843         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
844         {
845             const CWalletTx* pcoin = &(*it).second;
846             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
847                 continue;
848             nTotal += pcoin->GetAvailableCredit();
849         }
850     }
851
852     return nTotal;
853 }
854
855 int64 CWallet::GetUnconfirmedBalance() const
856 {
857     int64 nTotal = 0;
858     {
859         LOCK(cs_wallet);
860         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
861         {
862             const CWalletTx* pcoin = &(*it).second;
863             if (pcoin->IsFinal() && pcoin->IsConfirmed())
864                 continue;
865             nTotal += pcoin->GetAvailableCredit();
866         }
867     }
868     return nTotal;
869 }
870
871 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
872 {
873     setCoinsRet.clear();
874     nValueRet = 0;
875
876     // List of values less than target
877     pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
878     coinLowestLarger.first = std::numeric_limits<int64>::max();
879     coinLowestLarger.second.first = NULL;
880     vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
881     int64 nTotalLower = 0;
882
883     {
884        LOCK(cs_wallet);
885        vector<const CWalletTx*> vCoins;
886        vCoins.reserve(mapWallet.size());
887        for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
888            vCoins.push_back(&(*it).second);
889        random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
890
891        BOOST_FOREACH(const CWalletTx* pcoin, vCoins)
892        {
893             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
894                 continue;
895
896             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
897                 continue;
898
899             int nDepth = pcoin->GetDepthInMainChain();
900             if (nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
901                 continue;
902
903             for (int i = 0; i < pcoin->vout.size(); i++)
904             {
905                 if (pcoin->IsSpent(i) || !IsMine(pcoin->vout[i]))
906                     continue;
907
908                 int64 n = pcoin->vout[i].nValue;
909
910                 if (n <= 0)
911                     continue;
912
913                 pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin,i));
914
915                 if (n == nTargetValue)
916                 {
917                     setCoinsRet.insert(coin.second);
918                     nValueRet += coin.first;
919                     return true;
920                 }
921                 else if (n < nTargetValue + CENT)
922                 {
923                     vValue.push_back(coin);
924                     nTotalLower += n;
925                 }
926                 else if (n < coinLowestLarger.first)
927                 {
928                     coinLowestLarger = coin;
929                 }
930             }
931         }
932     }
933
934     if (nTotalLower == nTargetValue || nTotalLower == nTargetValue + CENT)
935     {
936         for (int i = 0; i < vValue.size(); ++i)
937         {
938             setCoinsRet.insert(vValue[i].second);
939             nValueRet += vValue[i].first;
940         }
941         return true;
942     }
943
944     if (nTotalLower < nTargetValue + (coinLowestLarger.second.first ? CENT : 0))
945     {
946         if (coinLowestLarger.second.first == NULL)
947             return false;
948         setCoinsRet.insert(coinLowestLarger.second);
949         nValueRet += coinLowestLarger.first;
950         return true;
951     }
952
953     if (nTotalLower >= nTargetValue + CENT)
954         nTargetValue += CENT;
955
956     // Solve subset sum by stochastic approximation
957     sort(vValue.rbegin(), vValue.rend());
958     vector<char> vfIncluded;
959     vector<char> vfBest(vValue.size(), true);
960     int64 nBest = nTotalLower;
961
962     for (int nRep = 0; nRep < 1000 && nBest != nTargetValue; nRep++)
963     {
964         vfIncluded.assign(vValue.size(), false);
965         int64 nTotal = 0;
966         bool fReachedTarget = false;
967         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
968         {
969             for (int i = 0; i < vValue.size(); i++)
970             {
971                 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
972                 {
973                     nTotal += vValue[i].first;
974                     vfIncluded[i] = true;
975                     if (nTotal >= nTargetValue)
976                     {
977                         fReachedTarget = true;
978                         if (nTotal < nBest)
979                         {
980                             nBest = nTotal;
981                             vfBest = vfIncluded;
982                         }
983                         nTotal -= vValue[i].first;
984                         vfIncluded[i] = false;
985                     }
986                 }
987             }
988         }
989     }
990
991     // If the next larger is still closer, return it
992     if (coinLowestLarger.second.first && coinLowestLarger.first - nTargetValue <= nBest - nTargetValue)
993     {
994         setCoinsRet.insert(coinLowestLarger.second);
995         nValueRet += coinLowestLarger.first;
996     }
997     else {
998         for (int i = 0; i < vValue.size(); i++)
999             if (vfBest[i])
1000             {
1001                 setCoinsRet.insert(vValue[i].second);
1002                 nValueRet += vValue[i].first;
1003             }
1004
1005         //// debug print
1006         printf("SelectCoins() best subset: ");
1007         for (int i = 0; i < vValue.size(); i++)
1008             if (vfBest[i])
1009                 printf("%s ", FormatMoney(vValue[i].first).c_str());
1010         printf("total %s\n", FormatMoney(nBest).c_str());
1011     }
1012
1013     return true;
1014 }
1015
1016 bool CWallet::SelectCoins(int64 nTargetValue, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
1017 {
1018     return (SelectCoinsMinConf(nTargetValue, 1, 6, setCoinsRet, nValueRet) ||
1019             SelectCoinsMinConf(nTargetValue, 1, 1, setCoinsRet, nValueRet) ||
1020             SelectCoinsMinConf(nTargetValue, 0, 1, setCoinsRet, nValueRet));
1021 }
1022
1023
1024
1025
1026 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
1027 {
1028     int64 nValue = 0;
1029     BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
1030     {
1031         if (nValue < 0)
1032             return false;
1033         nValue += s.second;
1034     }
1035     if (vecSend.empty() || nValue < 0)
1036         return false;
1037
1038     wtxNew.BindWallet(this);
1039
1040     {
1041         LOCK2(cs_main, cs_wallet);
1042         // txdb must be opened before the mapWallet lock
1043         CTxDB txdb("r");
1044         {
1045             nFeeRet = nTransactionFee;
1046             loop
1047             {
1048                 wtxNew.vin.clear();
1049                 wtxNew.vout.clear();
1050                 wtxNew.fFromMe = true;
1051
1052                 int64 nTotalValue = nValue + nFeeRet;
1053                 double dPriority = 0;
1054                 // vouts to the payees
1055                 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
1056                     wtxNew.vout.push_back(CTxOut(s.second, s.first));
1057
1058                 // Choose coins to use
1059                 set<pair<const CWalletTx*,unsigned int> > setCoins;
1060                 int64 nValueIn = 0;
1061                 if (!SelectCoins(nTotalValue, setCoins, nValueIn))
1062                     return false;
1063                 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1064                 {
1065                     int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
1066                     dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
1067                 }
1068
1069                 int64 nChange = nValueIn - nValue - nFeeRet;
1070                 // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
1071                 // or until nChange becomes zero
1072                 // NOTE: this depends on the exact behaviour of GetMinFee
1073                 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
1074                 {
1075                     int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
1076                     nChange -= nMoveToFee;
1077                     nFeeRet += nMoveToFee;
1078                 }
1079
1080                 if (nChange > 0)
1081                 {
1082                     // Note: We use a new key here to keep it from being obvious which side is the change.
1083                     //  The drawback is that by not reusing a previous key, the change may be lost if a
1084                     //  backup is restored, if the backup doesn't have the new private key for the change.
1085                     //  If we reused the old key, it would be possible to add code to look for and
1086                     //  rediscover unknown transactions that were written with keys of ours to recover
1087                     //  post-backup change.
1088
1089                     // Reserve a new key pair from key pool
1090                     vector<unsigned char> vchPubKey = reservekey.GetReservedKey();
1091                     // assert(mapKeys.count(vchPubKey));
1092
1093                     // Fill a vout to ourself
1094                     // TODO: pass in scriptChange instead of reservekey so
1095                     // change transaction isn't always pay-to-bitcoin-address
1096                     CScript scriptChange;
1097                     scriptChange.SetBitcoinAddress(vchPubKey);
1098
1099                     // Insert change txn at random position:
1100                     vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
1101                     wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
1102                 }
1103                 else
1104                     reservekey.ReturnKey();
1105
1106                 // Fill vin
1107                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1108                     wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
1109
1110                 // Sign
1111                 int nIn = 0;
1112                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1113                     if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
1114                         return false;
1115
1116                 // Limit size
1117                 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK);
1118                 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
1119                     return false;
1120                 dPriority /= nBytes;
1121
1122                 // Check that enough fee is included
1123                 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
1124                 bool fAllowFree = CTransaction::AllowFree(dPriority);
1125                 int64 nMinFee = wtxNew.GetMinFee(1, fAllowFree, GMF_SEND);
1126                 if (nFeeRet < max(nPayFee, nMinFee))
1127                 {
1128                     nFeeRet = max(nPayFee, nMinFee);
1129                     continue;
1130                 }
1131
1132                 // Fill vtxPrev by copying from previous transactions vtxPrev
1133                 wtxNew.AddSupportingTransactions(txdb);
1134                 wtxNew.fTimeReceivedIsTxTime = true;
1135
1136                 break;
1137             }
1138         }
1139     }
1140     return true;
1141 }
1142
1143 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet)
1144 {
1145     vector< pair<CScript, int64> > vecSend;
1146     vecSend.push_back(make_pair(scriptPubKey, nValue));
1147     return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet);
1148 }
1149
1150 // Call after CreateTransaction unless you want to abort
1151 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1152 {
1153     {
1154         LOCK2(cs_main, cs_wallet);
1155         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
1156         {
1157             // This is only to keep the database open to defeat the auto-flush for the
1158             // duration of this scope.  This is the only place where this optimization
1159             // maybe makes sense; please don't do it anywhere else.
1160             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1161
1162             // Take key pair from key pool so it won't be used again
1163             reservekey.KeepKey();
1164
1165             // Add tx to wallet, because if it has change it's also ours,
1166             // otherwise just for transaction history.
1167             AddToWallet(wtxNew);
1168
1169             // Mark old coins as spent
1170             set<CWalletTx*> setCoins;
1171             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1172             {
1173                 CWalletTx &coin = mapWallet[txin.prevout.hash];
1174                 coin.BindWallet(this);
1175                 coin.MarkSpent(txin.prevout.n);
1176                 coin.WriteToDisk();
1177                 vWalletUpdated.push_back(coin.GetHash());
1178             }
1179
1180             if (fFileBacked)
1181                 delete pwalletdb;
1182         }
1183
1184         // Track how many getdata requests our transaction gets
1185         mapRequestCount[wtxNew.GetHash()] = 0;
1186
1187         // Broadcast
1188         if (!wtxNew.AcceptToMemoryPool())
1189         {
1190             // This must not fail. The transaction has already been signed and recorded.
1191             printf("CommitTransaction() : Error: Transaction not valid");
1192             return false;
1193         }
1194         wtxNew.RelayWalletTransaction();
1195     }
1196     MainFrameRepaint();
1197     return true;
1198 }
1199
1200
1201
1202
1203 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1204 {
1205     CReserveKey reservekey(this);
1206     int64 nFeeRequired;
1207
1208     if (IsLocked())
1209     {
1210         string strError = _("Error: Wallet locked, unable to create transaction  ");
1211         printf("SendMoney() : %s", strError.c_str());
1212         return strError;
1213     }
1214     if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
1215     {
1216         string strError;
1217         if (nValue + nFeeRequired > GetBalance())
1218             strError = strprintf(_("Error: This transaction requires a transaction fee of at least %s because of its amount, complexity, or use of recently received funds  "), FormatMoney(nFeeRequired).c_str());
1219         else
1220             strError = _("Error: Transaction creation failed  ");
1221         printf("SendMoney() : %s", strError.c_str());
1222         return strError;
1223     }
1224
1225     if (fAskFee && !ThreadSafeAskFee(nFeeRequired, _("Sending...")))
1226         return "ABORTED";
1227
1228     if (!CommitTransaction(wtxNew, reservekey))
1229         return _("Error: The transaction was rejected.  This might happen if some of the coins in your wallet were already spent, such as if you used a copy of wallet.dat and coins were spent in the copy but not marked as spent here.");
1230
1231     MainFrameRepaint();
1232     return "";
1233 }
1234
1235
1236
1237 string CWallet::SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1238 {
1239     // Check amount
1240     if (nValue <= 0)
1241         return _("Invalid amount");
1242     if (nValue + nTransactionFee > GetBalance())
1243         return _("Insufficient funds");
1244
1245     // Parse bitcoin address
1246     CScript scriptPubKey;
1247     scriptPubKey.SetBitcoinAddress(address);
1248
1249     return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
1250 }
1251
1252
1253
1254
1255 int CWallet::LoadWallet(bool& fFirstRunRet)
1256 {
1257     if (!fFileBacked)
1258         return false;
1259     fFirstRunRet = false;
1260     int nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1261     if (nLoadWalletRet == DB_NEED_REWRITE)
1262     {
1263         if (CDB::Rewrite(strWalletFile, "\x04pool"))
1264         {
1265             setKeyPool.clear();
1266             // Note: can't top-up keypool here, because wallet is locked.
1267             // User will be prompted to unlock wallet the next operation
1268             // the requires a new key.
1269         }
1270         nLoadWalletRet = DB_NEED_REWRITE;
1271     }
1272
1273     if (nLoadWalletRet != DB_LOAD_OK)
1274         return nLoadWalletRet;
1275     fFirstRunRet = vchDefaultKey.empty();
1276
1277     CreateThread(ThreadFlushWalletDB, &strWalletFile);
1278     return DB_LOAD_OK;
1279 }
1280
1281
1282 bool CWallet::SetAddressBookName(const CBitcoinAddress& address, const string& strName)
1283 {
1284     mapAddressBook[address] = strName;
1285     AddressBookRepaint();
1286     if (!fFileBacked)
1287         return false;
1288     return CWalletDB(strWalletFile).WriteName(address.ToString(), strName);
1289 }
1290
1291 bool CWallet::DelAddressBookName(const CBitcoinAddress& address)
1292 {
1293     mapAddressBook.erase(address);
1294     AddressBookRepaint();
1295     if (!fFileBacked)
1296         return false;
1297     return CWalletDB(strWalletFile).EraseName(address.ToString());
1298 }
1299
1300
1301 void CWallet::PrintWallet(const CBlock& block)
1302 {
1303     {
1304         LOCK(cs_wallet);
1305         if (mapWallet.count(block.vtx[0].GetHash()))
1306         {
1307             CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1308             printf("    mine:  %d  %d  %d", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1309         }
1310     }
1311     printf("\n");
1312 }
1313
1314 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
1315 {
1316     {
1317         LOCK(cs_wallet);
1318         map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
1319         if (mi != mapWallet.end())
1320         {
1321             wtx = (*mi).second;
1322             return true;
1323         }
1324     }
1325     return false;
1326 }
1327
1328 bool CWallet::SetDefaultKey(const std::vector<unsigned char> &vchPubKey)
1329 {
1330     if (fFileBacked)
1331     {
1332         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
1333             return false;
1334     }
1335     vchDefaultKey = vchPubKey;
1336     return true;
1337 }
1338
1339 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
1340 {
1341     if (!pwallet->fFileBacked)
1342         return false;
1343     strWalletFileOut = pwallet->strWalletFile;
1344     return true;
1345 }
1346
1347 //
1348 // Mark old keypool keys as used,
1349 // and generate all new keys
1350 //
1351 bool CWallet::NewKeyPool()
1352 {
1353     {
1354         LOCK(cs_wallet);
1355         CWalletDB walletdb(strWalletFile);
1356         BOOST_FOREACH(int64 nIndex, setKeyPool)
1357             walletdb.ErasePool(nIndex);
1358         setKeyPool.clear();
1359
1360         if (IsLocked())
1361             return false;
1362
1363         int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
1364         for (int i = 0; i < nKeys; i++)
1365         {
1366             int64 nIndex = i+1;
1367             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
1368             setKeyPool.insert(nIndex);
1369         }
1370         printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
1371     }
1372     return true;
1373 }
1374
1375 bool CWallet::TopUpKeyPool()
1376 {
1377     {
1378         LOCK(cs_wallet);
1379
1380         if (IsLocked())
1381             return false;
1382
1383         CWalletDB walletdb(strWalletFile);
1384
1385         // Top up key pool
1386         int64 nTargetSize = max(GetArg("-keypool", 100), (int64)0);
1387         while (setKeyPool.size() < nTargetSize+1)
1388         {
1389             int64 nEnd = 1;
1390             if (!setKeyPool.empty())
1391                 nEnd = *(--setKeyPool.end()) + 1;
1392             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
1393                 throw runtime_error("TopUpKeyPool() : writing generated key failed");
1394             setKeyPool.insert(nEnd);
1395             printf("keypool added key %"PRI64d", size=%d\n", nEnd, setKeyPool.size());
1396         }
1397     }
1398     return true;
1399 }
1400
1401 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
1402 {
1403     nIndex = -1;
1404     keypool.vchPubKey.clear();
1405     {
1406         LOCK(cs_wallet);
1407
1408         if (!IsLocked())
1409             TopUpKeyPool();
1410
1411         // Get the oldest key
1412         if(setKeyPool.empty())
1413             return;
1414
1415         CWalletDB walletdb(strWalletFile);
1416
1417         nIndex = *(setKeyPool.begin());
1418         setKeyPool.erase(setKeyPool.begin());
1419         if (!walletdb.ReadPool(nIndex, keypool))
1420             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1421         if (!HaveKey(Hash160(keypool.vchPubKey)))
1422             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1423         assert(!keypool.vchPubKey.empty());
1424         printf("keypool reserve %"PRI64d"\n", nIndex);
1425     }
1426 }
1427
1428 int64 CWallet::AddReserveKey(const CKeyPool& keypool)
1429 {
1430     {
1431         LOCK2(cs_main, cs_wallet);
1432         CWalletDB walletdb(strWalletFile);
1433
1434         int64 nIndex = 1 + *(--setKeyPool.end());
1435         if (!walletdb.WritePool(nIndex, keypool))
1436             throw runtime_error("AddReserveKey() : writing added key failed");
1437         setKeyPool.insert(nIndex);
1438         return nIndex;
1439     }
1440     return -1;
1441 }
1442
1443 void CWallet::KeepKey(int64 nIndex)
1444 {
1445     // Remove from key pool
1446     if (fFileBacked)
1447     {
1448         CWalletDB walletdb(strWalletFile);
1449         walletdb.ErasePool(nIndex);
1450     }
1451     printf("keypool keep %"PRI64d"\n", nIndex);
1452 }
1453
1454 void CWallet::ReturnKey(int64 nIndex)
1455 {
1456     // Return to key pool
1457     {
1458         LOCK(cs_wallet);
1459         setKeyPool.insert(nIndex);
1460     }
1461     printf("keypool return %"PRI64d"\n", nIndex);
1462 }
1463
1464 bool CWallet::GetKeyFromPool(vector<unsigned char>& result, bool fAllowReuse)
1465 {
1466     int64 nIndex = 0;
1467     CKeyPool keypool;
1468     {
1469         LOCK(cs_wallet);
1470         ReserveKeyFromKeyPool(nIndex, keypool);
1471         if (nIndex == -1)
1472         {
1473             if (fAllowReuse && !vchDefaultKey.empty())
1474             {
1475                 result = vchDefaultKey;
1476                 return true;
1477             }
1478             if (IsLocked()) return false;
1479             result = GenerateNewKey();
1480             return true;
1481         }
1482         KeepKey(nIndex);
1483         result = keypool.vchPubKey;
1484     }
1485     return true;
1486 }
1487
1488 int64 CWallet::GetOldestKeyPoolTime()
1489 {
1490     int64 nIndex = 0;
1491     CKeyPool keypool;
1492     ReserveKeyFromKeyPool(nIndex, keypool);
1493     if (nIndex == -1)
1494         return GetTime();
1495     ReturnKey(nIndex);
1496     return keypool.nTime;
1497 }
1498
1499 vector<unsigned char> CReserveKey::GetReservedKey()
1500 {
1501     if (nIndex == -1)
1502     {
1503         CKeyPool keypool;
1504         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
1505         if (nIndex != -1)
1506             vchPubKey = keypool.vchPubKey;
1507         else
1508         {
1509             printf("CReserveKey::GetReservedKey(): Warning: using default key instead of a new key, top up your keypool.");
1510             vchPubKey = pwallet->vchDefaultKey;
1511         }
1512     }
1513     assert(!vchPubKey.empty());
1514     return vchPubKey;
1515 }
1516
1517 void CReserveKey::KeepKey()
1518 {
1519     if (nIndex != -1)
1520         pwallet->KeepKey(nIndex);
1521     nIndex = -1;
1522     vchPubKey.clear();
1523 }
1524
1525 void CReserveKey::ReturnKey()
1526 {
1527     if (nIndex != -1)
1528         pwallet->ReturnKey(nIndex);
1529     nIndex = -1;
1530     vchPubKey.clear();
1531 }
1532
1533 void CWallet::GetAllReserveAddresses(set<CBitcoinAddress>& setAddress)
1534 {
1535     setAddress.clear();
1536
1537     CWalletDB walletdb(strWalletFile);
1538
1539     LOCK2(cs_main, cs_wallet);
1540     BOOST_FOREACH(const int64& id, setKeyPool)
1541     {
1542         CKeyPool keypool;
1543         if (!walletdb.ReadPool(id, keypool))
1544             throw runtime_error("GetAllReserveKeyHashes() : read failed");
1545         CBitcoinAddress address(keypool.vchPubKey);
1546         assert(!keypool.vchPubKey.empty());
1547         if (!HaveKey(address))
1548             throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
1549         setAddress.insert(address);
1550     }
1551 }