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