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