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