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