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