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