Rename IsConfirmed() to IsTrusted()
[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 "txdb.h"
7 #include "wallet.h"
8 #include "walletdb.h"
9 #include "crypter.h"
10 #include "ui_interface.h"
11 #include "base58.h"
12 #include "kernel.h"
13 #include "coincontrol.h"
14 #include <boost/algorithm/string/replace.hpp>
15
16 using namespace std;
17 extern int nStakeMaxAge;
18
19 //////////////////////////////////////////////////////////////////////////////
20 //
21 // mapWallet
22 //
23
24 struct CompareValueOnly
25 {
26     bool operator()(const pair<int64, pair<const CWalletTx*, unsigned int> >& t1,
27                     const pair<int64, pair<const CWalletTx*, unsigned int> >& t2) const
28     {
29         return t1.first < t2.first;
30     }
31 };
32
33 CPubKey CWallet::GenerateNewKey()
34 {
35     bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
36
37     RandAddSeedPerfmon();
38     CKey key;
39     key.MakeNewKey(fCompressed);
40
41     // Compressed public keys were introduced in version 0.6.0
42     if (fCompressed)
43         SetMinVersion(FEATURE_COMPRPUBKEY);
44
45     CPubKey pubkey = key.GetPubKey();
46
47     // Create new metadata
48     int64 nCreationTime = GetTime();
49     mapKeyMetadata[pubkey.GetID()] = CKeyMetadata(nCreationTime);
50     if (!nTimeFirstKey || nCreationTime < nTimeFirstKey)
51         nTimeFirstKey = nCreationTime;
52
53     if (!AddKey(key))
54         throw std::runtime_error("CWallet::GenerateNewKey() : AddKey failed");
55     return key.GetPubKey();
56 }
57
58 bool CWallet::AddKey(const CKey& key)
59 {
60     CPubKey pubkey = key.GetPubKey();
61
62     if (!CCryptoKeyStore::AddKey(key))
63         return false;
64     if (!fFileBacked)
65         return true;
66     if (!IsCrypted())
67         return CWalletDB(strWalletFile).WriteKey(pubkey, key.GetPrivKey(), mapKeyMetadata[pubkey.GetID()]);
68     return true;
69 }
70
71 bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, const vector<unsigned char> &vchCryptedSecret)
72 {
73     if (!CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret))
74         return false;
75     if (!fFileBacked)
76         return true;
77     {
78         LOCK(cs_wallet);
79         if (pwalletdbEncryption)
80             return pwalletdbEncryption->WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]);
81         else
82             return CWalletDB(strWalletFile).WriteCryptedKey(vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]);
83     }
84     return false;
85 }
86
87 bool CWallet::LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &meta)
88 {
89     if (meta.nCreateTime && (!nTimeFirstKey || meta.nCreateTime < nTimeFirstKey))
90         nTimeFirstKey = meta.nCreateTime;
91
92     mapKeyMetadata[pubkey.GetID()] = meta;
93     return true;
94 }
95
96 bool CWallet::AddCScript(const CScript& redeemScript)
97 {
98     if (!CCryptoKeyStore::AddCScript(redeemScript))
99         return false;
100     if (!fFileBacked)
101         return true;
102     return CWalletDB(strWalletFile).WriteCScript(Hash160(redeemScript), redeemScript);
103 }
104
105 // ppcoin: optional setting to unlock wallet for block minting only;
106 //         serves to disable the trivial sendmoney when OS account compromised
107 bool fWalletUnlockMintOnly = false;
108
109 bool CWallet::Unlock(const SecureString& strWalletPassphrase)
110 {
111     if (!IsLocked())
112         return false;
113
114     CCrypter crypter;
115     CKeyingMaterial vMasterKey;
116
117     {
118         LOCK(cs_wallet);
119         BOOST_FOREACH(const MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
120         {
121             if(!crypter.SetKeyFromPassphrase(strWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
122                 return false;
123             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
124                 return false;
125             if (CCryptoKeyStore::Unlock(vMasterKey))
126                 return true;
127         }
128     }
129     return false;
130 }
131
132 bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase)
133 {
134     bool fWasLocked = IsLocked();
135
136     {
137         LOCK(cs_wallet);
138         Lock();
139
140         CCrypter crypter;
141         CKeyingMaterial vMasterKey;
142         BOOST_FOREACH(MasterKeyMap::value_type& pMasterKey, mapMasterKeys)
143         {
144             if(!crypter.SetKeyFromPassphrase(strOldWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
145                 return false;
146             if (!crypter.Decrypt(pMasterKey.second.vchCryptedKey, vMasterKey))
147                 return false;
148             if (CCryptoKeyStore::Unlock(vMasterKey))
149             {
150                 int64 nStartTime = GetTimeMillis();
151                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
152                 pMasterKey.second.nDeriveIterations = pMasterKey.second.nDeriveIterations * (100 / ((double)(GetTimeMillis() - nStartTime)));
153
154                 nStartTime = GetTimeMillis();
155                 crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod);
156                 pMasterKey.second.nDeriveIterations = (pMasterKey.second.nDeriveIterations + pMasterKey.second.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
157
158                 if (pMasterKey.second.nDeriveIterations < 25000)
159                     pMasterKey.second.nDeriveIterations = 25000;
160
161                 printf("Wallet passphrase changed to an nDeriveIterations of %i\n", pMasterKey.second.nDeriveIterations);
162
163                 if (!crypter.SetKeyFromPassphrase(strNewWalletPassphrase, pMasterKey.second.vchSalt, pMasterKey.second.nDeriveIterations, pMasterKey.second.nDerivationMethod))
164                     return false;
165                 if (!crypter.Encrypt(vMasterKey, pMasterKey.second.vchCryptedKey))
166                     return false;
167                 CWalletDB(strWalletFile).WriteMasterKey(pMasterKey.first, pMasterKey.second);
168                 if (fWasLocked)
169                     Lock();
170                 return true;
171             }
172         }
173     }
174
175     return false;
176 }
177
178 void CWallet::SetBestChain(const CBlockLocator& loc)
179 {
180     CWalletDB walletdb(strWalletFile);
181     walletdb.WriteBestBlock(loc);
182 }
183
184 // This class implements an addrIncoming entry that causes pre-0.4
185 // clients to crash on startup if reading a private-key-encrypted wallet.
186 class CCorruptAddress
187 {
188 public:
189     IMPLEMENT_SERIALIZE
190     (
191         if (nType & SER_DISK)
192             READWRITE(nVersion);
193     )
194 };
195
196 bool CWallet::SetMinVersion(enum WalletFeature nVersion, CWalletDB* pwalletdbIn, bool fExplicit)
197 {
198     if (nWalletVersion >= nVersion)
199         return true;
200
201     // when doing an explicit upgrade, if we pass the max version permitted, upgrade all the way
202     if (fExplicit && nVersion > nWalletMaxVersion)
203             nVersion = FEATURE_LATEST;
204
205     nWalletVersion = nVersion;
206
207     if (nVersion > nWalletMaxVersion)
208         nWalletMaxVersion = nVersion;
209
210     if (fFileBacked)
211     {
212         CWalletDB* pwalletdb = pwalletdbIn ? pwalletdbIn : new CWalletDB(strWalletFile);
213         if (nWalletVersion >= 40000)
214         {
215             // Versions prior to 0.4.0 did not support the "minversion" record.
216             // Use a CCorruptAddress to make them crash instead.
217             CCorruptAddress corruptAddress;
218             pwalletdb->WriteSetting("addrIncoming", corruptAddress);
219         }
220         if (nWalletVersion > 40000)
221             pwalletdb->WriteMinVersion(nWalletVersion);
222         if (!pwalletdbIn)
223             delete pwalletdb;
224     }
225
226     return true;
227 }
228
229 bool CWallet::SetMaxVersion(int nVersion)
230 {
231     // cannot downgrade below current version
232     if (nWalletVersion > nVersion)
233         return false;
234
235     nWalletMaxVersion = nVersion;
236
237     return true;
238 }
239
240 bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
241 {
242     if (IsCrypted())
243         return false;
244
245     CKeyingMaterial vMasterKey;
246     RandAddSeedPerfmon();
247
248     vMasterKey.resize(WALLET_CRYPTO_KEY_SIZE);
249     RAND_bytes(&vMasterKey[0], WALLET_CRYPTO_KEY_SIZE);
250
251     CMasterKey kMasterKey(nDerivationMethodIndex);
252
253     RandAddSeedPerfmon();
254     kMasterKey.vchSalt.resize(WALLET_CRYPTO_SALT_SIZE);
255     RAND_bytes(&kMasterKey.vchSalt[0], WALLET_CRYPTO_SALT_SIZE);
256
257     CCrypter crypter;
258     int64 nStartTime = GetTimeMillis();
259     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, 25000, kMasterKey.nDerivationMethod);
260     kMasterKey.nDeriveIterations = 2500000 / ((double)(GetTimeMillis() - nStartTime));
261
262     nStartTime = GetTimeMillis();
263     crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod);
264     kMasterKey.nDeriveIterations = (kMasterKey.nDeriveIterations + kMasterKey.nDeriveIterations * 100 / ((double)(GetTimeMillis() - nStartTime))) / 2;
265
266     if (kMasterKey.nDeriveIterations < 25000)
267         kMasterKey.nDeriveIterations = 25000;
268
269     printf("Encrypting Wallet with an nDeriveIterations of %i\n", kMasterKey.nDeriveIterations);
270
271     if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, kMasterKey.nDeriveIterations, kMasterKey.nDerivationMethod))
272         return false;
273     if (!crypter.Encrypt(vMasterKey, kMasterKey.vchCryptedKey))
274         return false;
275
276     {
277         LOCK(cs_wallet);
278         mapMasterKeys[++nMasterKeyMaxID] = kMasterKey;
279         if (fFileBacked)
280         {
281             pwalletdbEncryption = new CWalletDB(strWalletFile);
282             if (!pwalletdbEncryption->TxnBegin())
283                 return false;
284             pwalletdbEncryption->WriteMasterKey(nMasterKeyMaxID, kMasterKey);
285         }
286
287         if (!EncryptKeys(vMasterKey))
288         {
289             if (fFileBacked)
290                 pwalletdbEncryption->TxnAbort();
291             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.
292         }
293
294         // Encryption was introduced in version 0.4.0
295         SetMinVersion(FEATURE_WALLETCRYPT, pwalletdbEncryption, true);
296
297         if (fFileBacked)
298         {
299             if (!pwalletdbEncryption->TxnCommit())
300                 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.
301
302             delete pwalletdbEncryption;
303             pwalletdbEncryption = NULL;
304         }
305
306         Lock();
307         Unlock(strWalletPassphrase);
308         NewKeyPool();
309         Lock();
310
311         // Need to completely rewrite the wallet file; if we don't, bdb might keep
312         // bits of the unencrypted private key in slack space in the database file.
313         CDB::Rewrite(strWalletFile);
314
315     }
316     NotifyStatusChanged(this);
317
318     return true;
319 }
320
321 int64 CWallet::IncOrderPosNext(CWalletDB *pwalletdb)
322 {
323     int64 nRet = nOrderPosNext++;
324     if (pwalletdb) {
325         pwalletdb->WriteOrderPosNext(nOrderPosNext);
326     } else {
327         CWalletDB(strWalletFile).WriteOrderPosNext(nOrderPosNext);
328     }
329     return nRet;
330 }
331
332 CWallet::TxItems CWallet::OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount)
333 {
334     CWalletDB walletdb(strWalletFile);
335
336     // First: get all CWalletTx and CAccountingEntry into a sorted-by-order multimap.
337     TxItems txOrdered;
338
339     // Note: maintaining indices in the database of (account,time) --> txid and (account, time) --> acentry
340     // would make this much faster for applications that do this a lot.
341     for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
342     {
343         CWalletTx* wtx = &((*it).second);
344         txOrdered.insert(make_pair(wtx->nOrderPos, TxPair(wtx, (CAccountingEntry*)0)));
345     }
346     acentries.clear();
347     walletdb.ListAccountCreditDebit(strAccount, acentries);
348     BOOST_FOREACH(CAccountingEntry& entry, acentries)
349     {
350         txOrdered.insert(make_pair(entry.nOrderPos, TxPair((CWalletTx*)0, &entry)));
351     }
352
353     return txOrdered;
354 }
355
356 void CWallet::WalletUpdateSpent(const CTransaction &tx, bool fBlock)
357 {
358     // Anytime a signature is successfully verified, it's proof the outpoint is spent.
359     // Update the wallet spent flag if it doesn't know due to wallet.dat being
360     // restored from backup or the user making copies of wallet.dat.
361     {
362         LOCK(cs_wallet);
363         BOOST_FOREACH(const CTxIn& txin, tx.vin)
364         {
365             map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
366             if (mi != mapWallet.end())
367             {
368                 CWalletTx& wtx = (*mi).second;
369                 if (txin.prevout.n >= wtx.vout.size())
370                     printf("WalletUpdateSpent: bad wtx %s\n", wtx.GetHash().ToString().c_str());
371                 else if (!wtx.IsSpent(txin.prevout.n) && IsMine(wtx.vout[txin.prevout.n]))
372                 {
373                     printf("WalletUpdateSpent found spent coin %snvc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
374                     wtx.MarkSpent(txin.prevout.n);
375                     wtx.WriteToDisk();
376                     NotifyTransactionChanged(this, txin.prevout.hash, CT_UPDATED);
377                 }
378             }
379         }
380
381         if (fBlock)
382         {
383             uint256 hash = tx.GetHash();
384             map<uint256, CWalletTx>::iterator mi = mapWallet.find(hash);
385             CWalletTx& wtx = (*mi).second;
386
387             BOOST_FOREACH(const CTxOut& txout, tx.vout)
388             {
389                 if (IsMine(txout))
390                 {
391                     wtx.MarkUnspent(&txout - &tx.vout[0]);
392                     wtx.WriteToDisk();
393                     NotifyTransactionChanged(this, hash, CT_UPDATED);
394                 }
395             }
396         }
397
398     }
399 }
400
401 void CWallet::MarkDirty()
402 {
403     {
404         LOCK(cs_wallet);
405         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
406             item.second.MarkDirty();
407     }
408 }
409
410 bool CWallet::AddToWallet(const CWalletTx& wtxIn)
411 {
412     uint256 hash = wtxIn.GetHash();
413     {
414         LOCK(cs_wallet);
415         // Inserts only if not already there, returns tx inserted or tx found
416         pair<map<uint256, CWalletTx>::iterator, bool> ret = mapWallet.insert(make_pair(hash, wtxIn));
417         CWalletTx& wtx = (*ret.first).second;
418         wtx.BindWallet(this);
419         bool fInsertedNew = ret.second;
420         if (fInsertedNew)
421         {
422             wtx.nTimeReceived = GetAdjustedTime();
423             wtx.nOrderPos = IncOrderPosNext();
424
425             wtx.nTimeSmart = wtx.nTimeReceived;
426             if (wtxIn.hashBlock != 0)
427             {
428                 if (mapBlockIndex.count(wtxIn.hashBlock))
429                 {
430                     unsigned int latestNow = wtx.nTimeReceived;
431                     unsigned int latestEntry = 0;
432                     {
433                         // Tolerate times up to the last timestamp in the wallet not more than 5 minutes into the future
434                         int64 latestTolerated = latestNow + 300;
435                         std::list<CAccountingEntry> acentries;
436                         TxItems txOrdered = OrderedTxItems(acentries);
437                         for (TxItems::reverse_iterator it = txOrdered.rbegin(); it != txOrdered.rend(); ++it)
438                         {
439                             CWalletTx *const pwtx = (*it).second.first;
440                             if (pwtx == &wtx)
441                                 continue;
442                             CAccountingEntry *const pacentry = (*it).second.second;
443                             int64 nSmartTime;
444                             if (pwtx)
445                             {
446                                 nSmartTime = pwtx->nTimeSmart;
447                                 if (!nSmartTime)
448                                     nSmartTime = pwtx->nTimeReceived;
449                             }
450                             else
451                                 nSmartTime = pacentry->nTime;
452                             if (nSmartTime <= latestTolerated)
453                             {
454                                 latestEntry = nSmartTime;
455                                 if (nSmartTime > latestNow)
456                                     latestNow = nSmartTime;
457                                 break;
458                             }
459                         }
460                     }
461
462                     unsigned int& blocktime = mapBlockIndex[wtxIn.hashBlock]->nTime;
463                     wtx.nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow));
464                 }
465                 else
466                     printf("AddToWallet() : found %s in block %s not in index\n",
467                            wtxIn.GetHash().ToString().substr(0,10).c_str(),
468                            wtxIn.hashBlock.ToString().c_str());
469             }
470         }
471
472         bool fUpdated = false;
473         if (!fInsertedNew)
474         {
475             // Merge
476             if (wtxIn.hashBlock != 0 && wtxIn.hashBlock != wtx.hashBlock)
477             {
478                 wtx.hashBlock = wtxIn.hashBlock;
479                 fUpdated = true;
480             }
481             if (wtxIn.nIndex != -1 && (wtxIn.vMerkleBranch != wtx.vMerkleBranch || wtxIn.nIndex != wtx.nIndex))
482             {
483                 wtx.vMerkleBranch = wtxIn.vMerkleBranch;
484                 wtx.nIndex = wtxIn.nIndex;
485                 fUpdated = true;
486             }
487             if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe)
488             {
489                 wtx.fFromMe = wtxIn.fFromMe;
490                 fUpdated = true;
491             }
492             fUpdated |= wtx.UpdateSpent(wtxIn.vfSpent);
493         }
494
495         //// debug print
496         printf("AddToWallet %s  %s%s\n", wtxIn.GetHash().ToString().substr(0,10).c_str(), (fInsertedNew ? "new" : ""), (fUpdated ? "update" : ""));
497
498         // Write to disk
499         if (fInsertedNew || fUpdated)
500             if (!wtx.WriteToDisk())
501                 return false;
502 #ifndef QT_GUI
503         // If default receiving address gets used, replace it with a new one
504         CScript scriptDefaultKey;
505         scriptDefaultKey.SetDestination(vchDefaultKey.GetID());
506         BOOST_FOREACH(const CTxOut& txout, wtx.vout)
507         {
508             if (txout.scriptPubKey == scriptDefaultKey)
509             {
510                 CPubKey newDefaultKey;
511                 if (GetKeyFromPool(newDefaultKey, false))
512                 {
513                     SetDefaultKey(newDefaultKey);
514                     SetAddressBookName(vchDefaultKey.GetID(), "");
515                 }
516             }
517         }
518 #endif
519         // since AddToWallet is called directly for self-originating transactions, check for consumption of own coins
520         WalletUpdateSpent(wtx, (wtxIn.hashBlock != 0));
521
522         // Notify UI of new or updated transaction
523         NotifyTransactionChanged(this, hash, fInsertedNew ? CT_NEW : CT_UPDATED);
524
525         // notify an external script when a wallet transaction comes in or is updated
526         std::string strCmd = GetArg("-walletnotify", "");
527
528         if ( !strCmd.empty())
529         {
530             boost::replace_all(strCmd, "%s", wtxIn.GetHash().GetHex());
531             boost::thread t(runCommand, strCmd); // thread runs free
532         }
533
534     }
535     return true;
536 }
537
538 // Add a transaction to the wallet, or update it.
539 // pblock is optional, but should be provided if the transaction is known to be in a block.
540 // If fUpdate is true, existing transactions will be updated.
541 bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate, bool fFindBlock)
542 {
543     uint256 hash = tx.GetHash();
544     {
545         LOCK(cs_wallet);
546         bool fExisted = mapWallet.count(hash);
547         if (fExisted && !fUpdate) return false;
548         if (fExisted || IsMine(tx) || IsFromMe(tx))
549         {
550             CWalletTx wtx(this,tx);
551             // Get merkle branch if transaction was found in a block
552             if (pblock)
553                 wtx.SetMerkleBranch(pblock);
554             return AddToWallet(wtx);
555         }
556         else
557             WalletUpdateSpent(tx);
558     }
559     return false;
560 }
561
562 bool CWallet::EraseFromWallet(uint256 hash)
563 {
564     if (!fFileBacked)
565         return false;
566     {
567         LOCK(cs_wallet);
568         if (mapWallet.erase(hash))
569             CWalletDB(strWalletFile).EraseTx(hash);
570     }
571     return true;
572 }
573
574
575 bool CWallet::IsMine(const CTxIn &txin) const
576 {
577     {
578         LOCK(cs_wallet);
579         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
580         if (mi != mapWallet.end())
581         {
582             const CWalletTx& prev = (*mi).second;
583             if (txin.prevout.n < prev.vout.size())
584                 if (IsMine(prev.vout[txin.prevout.n]))
585                     return true;
586         }
587     }
588     return false;
589 }
590
591 int64 CWallet::GetDebit(const CTxIn &txin) const
592 {
593     {
594         LOCK(cs_wallet);
595         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(txin.prevout.hash);
596         if (mi != mapWallet.end())
597         {
598             const CWalletTx& prev = (*mi).second;
599             if (txin.prevout.n < prev.vout.size())
600                 if (IsMine(prev.vout[txin.prevout.n]))
601                     return prev.vout[txin.prevout.n].nValue;
602         }
603     }
604     return 0;
605 }
606
607 bool CWallet::IsChange(const CTxOut& txout) const
608 {
609     CTxDestination address;
610
611     // TODO: fix handling of 'change' outputs. The assumption is that any
612     // payment to a TX_PUBKEYHASH that is mine but isn't in the address book
613     // is change. That assumption is likely to break when we implement multisignature
614     // wallets that return change back into a multi-signature-protected address;
615     // a better way of identifying which outputs are 'the send' and which are
616     // 'the change' will need to be implemented (maybe extend CWalletTx to remember
617     // which output, if any, was change).
618     if (ExtractDestination(txout.scriptPubKey, address) && ::IsMine(*this, address))
619     {
620         LOCK(cs_wallet);
621         if (!mapAddressBook.count(address))
622             return true;
623     }
624     return false;
625 }
626
627 int64 CWalletTx::GetTxTime() const
628 {
629     int64 n = nTimeSmart;
630     return n ? n : nTimeReceived;
631 }
632
633 int CWalletTx::GetRequestCount() const
634 {
635     // Returns -1 if it wasn't being tracked
636     int nRequests = -1;
637     {
638         LOCK(pwallet->cs_wallet);
639         if (IsCoinBase() || IsCoinStake())
640         {
641             // Generated block
642             if (hashBlock != 0)
643             {
644                 map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
645                 if (mi != pwallet->mapRequestCount.end())
646                     nRequests = (*mi).second;
647             }
648         }
649         else
650         {
651             // Did anyone request this transaction?
652             map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(GetHash());
653             if (mi != pwallet->mapRequestCount.end())
654             {
655                 nRequests = (*mi).second;
656
657                 // How about the block it's in?
658                 if (nRequests == 0 && hashBlock != 0)
659                 {
660                     map<uint256, int>::const_iterator mi = pwallet->mapRequestCount.find(hashBlock);
661                     if (mi != pwallet->mapRequestCount.end())
662                         nRequests = (*mi).second;
663                     else
664                         nRequests = 1; // If it's in someone else's block it must have got out
665                 }
666             }
667         }
668     }
669     return nRequests;
670 }
671
672 void CWalletTx::GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, list<pair<CTxDestination, int64> >& listReceived,
673                            list<pair<CTxDestination, int64> >& listSent, int64& nFee, string& strSentAccount) const
674 {
675     nGeneratedImmature = nGeneratedMature = nFee = 0;
676     listReceived.clear();
677     listSent.clear();
678     strSentAccount = strFromAccount;
679
680     if (IsCoinBase() || IsCoinStake())
681     {
682         if (GetBlocksToMaturity() > 0)
683             nGeneratedImmature = pwallet->GetCredit(*this);
684         else
685             nGeneratedMature = GetCredit();
686         return;
687     }
688
689     // Compute fee:
690     int64 nDebit = GetDebit();
691     if (nDebit > 0) // debit>0 means we signed/sent this transaction
692     {
693         int64 nValueOut = GetValueOut();
694         nFee = nDebit - nValueOut;
695     }
696
697     // Sent/received.
698     BOOST_FOREACH(const CTxOut& txout, vout)
699     {
700         CTxDestination address;
701         vector<unsigned char> vchPubKey;
702         if (!ExtractDestination(txout.scriptPubKey, address))
703         {
704             printf("CWalletTx::GetAmounts: Unknown transaction type found, txid %s\n",
705                    this->GetHash().ToString().c_str());
706         }
707
708         // Don't report 'change' txouts
709         if (nDebit > 0 && pwallet->IsChange(txout))
710             continue;
711
712         if (nDebit > 0)
713             listSent.push_back(make_pair(address, txout.nValue));
714
715         if (pwallet->IsMine(txout))
716             listReceived.push_back(make_pair(address, txout.nValue));
717     }
718
719 }
720
721 void CWalletTx::GetAccountAmounts(const string& strAccount, int64& nGenerated, int64& nReceived,
722                                   int64& nSent, int64& nFee) const
723 {
724     nGenerated = nReceived = nSent = nFee = 0;
725
726     int64 allGeneratedImmature, allGeneratedMature, allFee;
727     allGeneratedImmature = allGeneratedMature = allFee = 0;
728     string strSentAccount;
729     list<pair<CTxDestination, int64> > listReceived;
730     list<pair<CTxDestination, int64> > listSent;
731     GetAmounts(allGeneratedImmature, allGeneratedMature, listReceived, listSent, allFee, strSentAccount);
732
733     if (strAccount == "")
734         nGenerated = allGeneratedMature;
735     if (strAccount == strSentAccount)
736     {
737         BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& s, listSent)
738             nSent += s.second;
739         nFee = allFee;
740     }
741     {
742         LOCK(pwallet->cs_wallet);
743         BOOST_FOREACH(const PAIRTYPE(CTxDestination,int64)& r, listReceived)
744         {
745             if (pwallet->mapAddressBook.count(r.first))
746             {
747                 map<CTxDestination, string>::const_iterator mi = pwallet->mapAddressBook.find(r.first);
748                 if (mi != pwallet->mapAddressBook.end() && (*mi).second == strAccount)
749                     nReceived += r.second;
750             }
751             else if (strAccount.empty())
752             {
753                 nReceived += r.second;
754             }
755         }
756     }
757 }
758
759 void CWalletTx::AddSupportingTransactions(CTxDB& txdb)
760 {
761     vtxPrev.clear();
762
763     const int COPY_DEPTH = 3;
764     if (SetMerkleBranch() < COPY_DEPTH)
765     {
766         vector<uint256> vWorkQueue;
767         BOOST_FOREACH(const CTxIn& txin, vin)
768             vWorkQueue.push_back(txin.prevout.hash);
769
770         // This critsect is OK because txdb is already open
771         {
772             LOCK(pwallet->cs_wallet);
773             map<uint256, const CMerkleTx*> mapWalletPrev;
774             set<uint256> setAlreadyDone;
775             for (unsigned int i = 0; i < vWorkQueue.size(); i++)
776             {
777                 uint256 hash = vWorkQueue[i];
778                 if (setAlreadyDone.count(hash))
779                     continue;
780                 setAlreadyDone.insert(hash);
781
782                 CMerkleTx tx;
783                 map<uint256, CWalletTx>::const_iterator mi = pwallet->mapWallet.find(hash);
784                 if (mi != pwallet->mapWallet.end())
785                 {
786                     tx = (*mi).second;
787                     BOOST_FOREACH(const CMerkleTx& txWalletPrev, (*mi).second.vtxPrev)
788                         mapWalletPrev[txWalletPrev.GetHash()] = &txWalletPrev;
789                 }
790                 else if (mapWalletPrev.count(hash))
791                 {
792                     tx = *mapWalletPrev[hash];
793                 }
794                 else if (!fClient && txdb.ReadDiskTx(hash, tx))
795                 {
796                     ;
797                 }
798                 else
799                 {
800                     printf("ERROR: AddSupportingTransactions() : unsupported transaction\n");
801                     continue;
802                 }
803
804                 int nDepth = tx.SetMerkleBranch();
805                 vtxPrev.push_back(tx);
806
807                 if (nDepth < COPY_DEPTH)
808                 {
809                     BOOST_FOREACH(const CTxIn& txin, tx.vin)
810                         vWorkQueue.push_back(txin.prevout.hash);
811                 }
812             }
813         }
814     }
815
816     reverse(vtxPrev.begin(), vtxPrev.end());
817 }
818
819 bool CWalletTx::WriteToDisk()
820 {
821     return CWalletDB(pwallet->strWalletFile).WriteTx(GetHash(), *this);
822 }
823
824 // Scan the block chain (starting in pindexStart) for transactions
825 // from or to us. If fUpdate is true, found transactions that already
826 // exist in the wallet will be updated.
827 int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
828 {
829     int ret = 0;
830
831     CBlockIndex* pindex = pindexStart;
832     {
833         LOCK(cs_wallet);
834         while (pindex)
835         {
836             CBlock block;
837             block.ReadFromDisk(pindex, true);
838             BOOST_FOREACH(CTransaction& tx, block.vtx)
839             {
840                 if (AddToWalletIfInvolvingMe(tx, &block, fUpdate))
841                     ret++;
842             }
843             pindex = pindex->pnext;
844         }
845     }
846     return ret;
847 }
848
849 int CWallet::ScanForWalletTransaction(const uint256& hashTx)
850 {
851     CTransaction tx;
852     tx.ReadFromDisk(COutPoint(hashTx, 0));
853     if (AddToWalletIfInvolvingMe(tx, NULL, true, true))
854         return 1;
855     return 0;
856 }
857
858 void CWallet::ReacceptWalletTransactions()
859 {
860     CTxDB txdb("r");
861     bool fRepeat = true;
862     while (fRepeat)
863     {
864         LOCK(cs_wallet);
865         fRepeat = false;
866         vector<CDiskTxPos> vMissingTx;
867         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
868         {
869             CWalletTx& wtx = item.second;
870             if ((wtx.IsCoinBase() && wtx.IsSpent(0)) || (wtx.IsCoinStake() && wtx.IsSpent(1)))
871                 continue;
872
873             CTxIndex txindex;
874             bool fUpdated = false;
875             if (txdb.ReadTxIndex(wtx.GetHash(), txindex))
876             {
877                 // Update fSpent if a tx got spent somewhere else by a copy of wallet.dat
878                 if (txindex.vSpent.size() != wtx.vout.size())
879                 {
880                     printf("ERROR: ReacceptWalletTransactions() : txindex.vSpent.size() %"PRIszu" != wtx.vout.size() %"PRIszu"\n", txindex.vSpent.size(), wtx.vout.size());
881                     continue;
882                 }
883                 for (unsigned int i = 0; i < txindex.vSpent.size(); i++)
884                 {
885                     if (wtx.IsSpent(i))
886                         continue;
887                     if (!txindex.vSpent[i].IsNull() && IsMine(wtx.vout[i]))
888                     {
889                         wtx.MarkSpent(i);
890                         fUpdated = true;
891                         vMissingTx.push_back(txindex.vSpent[i]);
892                     }
893                 }
894                 if (fUpdated)
895                 {
896                     printf("ReacceptWalletTransactions found spent coin %snvc %s\n", FormatMoney(wtx.GetCredit()).c_str(), wtx.GetHash().ToString().c_str());
897                     wtx.MarkDirty();
898                     wtx.WriteToDisk();
899                 }
900             }
901             else
902             {
903                 // Re-accept any txes of ours that aren't already in a block
904                 if (!(wtx.IsCoinBase() || wtx.IsCoinStake()))
905                     wtx.AcceptWalletTransaction(txdb, false);
906             }
907         }
908         if (!vMissingTx.empty())
909         {
910             // TODO: optimize this to scan just part of the block chain?
911             if (ScanForWalletTransactions(pindexGenesisBlock))
912                 fRepeat = true;  // Found missing transactions: re-do re-accept.
913         }
914     }
915 }
916
917 void CWalletTx::RelayWalletTransaction(CTxDB& txdb)
918 {
919     BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
920     {
921         if (!(tx.IsCoinBase() || tx.IsCoinStake()))
922         {
923             uint256 hash = tx.GetHash();
924             if (!txdb.ContainsTx(hash))
925                 RelayTransaction((CTransaction)tx, hash);
926         }
927     }
928     if (!(IsCoinBase() || IsCoinStake()))
929     {
930         uint256 hash = GetHash();
931         if (!txdb.ContainsTx(hash))
932         {
933             printf("Relaying wtx %s\n", hash.ToString().substr(0,10).c_str());
934             RelayTransaction((CTransaction)*this, hash);
935         }
936     }
937 }
938
939 void CWalletTx::RelayWalletTransaction()
940 {
941    CTxDB txdb("r");
942    RelayWalletTransaction(txdb);
943 }
944
945 void CWallet::ResendWalletTransactions()
946 {
947     // Do this infrequently and randomly to avoid giving away
948     // that these are our transactions.
949     static int64 nNextTime;
950     if (GetTime() < nNextTime)
951         return;
952     bool fFirst = (nNextTime == 0);
953     nNextTime = GetTime() + GetRand(30 * 60);
954     if (fFirst)
955         return;
956
957     // Only do it if there's been a new block since last time
958     static int64 nLastTime;
959     if (nTimeBestReceived < nLastTime)
960         return;
961     nLastTime = GetTime();
962
963     // Rebroadcast any of our txes that aren't in a block yet
964     printf("ResendWalletTransactions()\n");
965     CTxDB txdb("r");
966     {
967         LOCK(cs_wallet);
968         // Sort them in chronological order
969         multimap<unsigned int, CWalletTx*> mapSorted;
970         BOOST_FOREACH(PAIRTYPE(const uint256, CWalletTx)& item, mapWallet)
971         {
972             CWalletTx& wtx = item.second;
973             // Don't rebroadcast until it's had plenty of time that
974             // it should have gotten in already by now.
975             if (nTimeBestReceived - (int64)wtx.nTimeReceived > 5 * 60)
976                 mapSorted.insert(make_pair(wtx.nTimeReceived, &wtx));
977         }
978         BOOST_FOREACH(PAIRTYPE(const unsigned int, CWalletTx*)& item, mapSorted)
979         {
980             CWalletTx& wtx = *item.second;
981             if (wtx.CheckTransaction())
982                 wtx.RelayWalletTransaction(txdb);
983             else
984                 printf("ResendWalletTransactions() : CheckTransaction failed for transaction %s\n", wtx.GetHash().ToString().c_str());
985         }
986     }
987 }
988
989
990
991
992
993
994 //////////////////////////////////////////////////////////////////////////////
995 //
996 // Actions
997 //
998
999
1000 int64 CWallet::GetBalance() const
1001 {
1002     int64 nTotal = 0;
1003     {
1004         LOCK(cs_wallet);
1005         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1006         {
1007             const CWalletTx* pcoin = &(*it).second;
1008             if (pcoin->IsTrusted())
1009                 nTotal += pcoin->GetAvailableCredit();
1010         }
1011     }
1012
1013     return nTotal;
1014 }
1015
1016 int64 CWallet::GetUnconfirmedBalance() const
1017 {
1018     int64 nTotal = 0;
1019     {
1020         LOCK(cs_wallet);
1021         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1022         {
1023             const CWalletTx* pcoin = &(*it).second;
1024             if (!pcoin->IsFinal() || !pcoin->IsTrusted())
1025                 nTotal += pcoin->GetAvailableCredit();
1026         }
1027     }
1028     return nTotal;
1029 }
1030
1031 int64 CWallet::GetImmatureBalance() const
1032 {
1033     int64 nTotal = 0;
1034     {
1035         LOCK(cs_wallet);
1036         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1037         {
1038             const CWalletTx& pcoin = (*it).second;
1039             if (pcoin.IsCoinBase() && pcoin.GetBlocksToMaturity() > 0 && pcoin.IsInMainChain())
1040                 nTotal += GetCredit(pcoin);
1041         }
1042     }
1043     return nTotal;
1044 }
1045
1046 // populate vCoins with vector of spendable COutputs
1047 void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const CCoinControl *coinControl) const
1048 {
1049     vCoins.clear();
1050
1051     {
1052         LOCK(cs_wallet);
1053         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1054         {
1055             const CWalletTx* pcoin = &(*it).second;
1056
1057             if (!pcoin->IsFinal())
1058                 continue;
1059
1060             if (fOnlyConfirmed && !pcoin->IsTrusted())
1061                 continue;
1062
1063             if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0)
1064                 continue;
1065
1066             if(pcoin->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0)
1067                 continue;
1068
1069             for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1070                 if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && pcoin->vout[i].nValue >= nMinimumInputValue &&
1071                 (!coinControl || !coinControl->HasSelected() || coinControl->IsSelected((*it).first, i)))
1072                     vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain()));
1073
1074         }
1075     }
1076 }
1077
1078 void CWallet::AvailableCoinsMinConf(vector<COutput>& vCoins, int nConf) const
1079 {
1080     vCoins.clear();
1081
1082     {
1083         LOCK(cs_wallet);
1084         for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1085         {
1086             const CWalletTx* pcoin = &(*it).second;
1087
1088             if (!pcoin->IsFinal())
1089                 continue;
1090
1091             if(pcoin->GetDepthInMainChain() < nConf)
1092                 continue;
1093
1094             for (unsigned int i = 0; i < pcoin->vout.size(); i++)
1095                 if (!(pcoin->IsSpent(i)) && IsMine(pcoin->vout[i]) && pcoin->vout[i].nValue >= nMinimumInputValue)
1096                     vCoins.push_back(COutput(pcoin, i, pcoin->GetDepthInMainChain()));
1097         }
1098     }
1099 }
1100
1101 static void ApproximateBestSubset(vector<pair<int64, pair<const CWalletTx*,unsigned int> > >vValue, int64 nTotalLower, int64 nTargetValue,
1102                                   vector<char>& vfBest, int64& nBest, int iterations = 1000)
1103 {
1104     vector<char> vfIncluded;
1105
1106     vfBest.assign(vValue.size(), true);
1107     nBest = nTotalLower;
1108
1109     for (int nRep = 0; nRep < iterations && nBest != nTargetValue; nRep++)
1110     {
1111         vfIncluded.assign(vValue.size(), false);
1112         int64 nTotal = 0;
1113         bool fReachedTarget = false;
1114         for (int nPass = 0; nPass < 2 && !fReachedTarget; nPass++)
1115         {
1116             for (unsigned int i = 0; i < vValue.size(); i++)
1117             {
1118                 if (nPass == 0 ? rand() % 2 : !vfIncluded[i])
1119                 {
1120                     nTotal += vValue[i].first;
1121                     vfIncluded[i] = true;
1122                     if (nTotal >= nTargetValue)
1123                     {
1124                         fReachedTarget = true;
1125                         if (nTotal < nBest)
1126                         {
1127                             nBest = nTotal;
1128                             vfBest = vfIncluded;
1129                         }
1130                         nTotal -= vValue[i].first;
1131                         vfIncluded[i] = false;
1132                     }
1133                 }
1134             }
1135         }
1136     }
1137 }
1138
1139 // ppcoin: total coins staked (non-spendable until maturity)
1140 int64 CWallet::GetStake() const
1141 {
1142     int64 nTotal = 0;
1143     LOCK(cs_wallet);
1144     for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1145     {
1146         const CWalletTx* pcoin = &(*it).second;
1147         if (pcoin->IsCoinStake() && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0)
1148             nTotal += CWallet::GetCredit(*pcoin);
1149     }
1150     return nTotal;
1151 }
1152
1153 int64 CWallet::GetNewMint() const
1154 {
1155     int64 nTotal = 0;
1156     LOCK(cs_wallet);
1157     for (map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
1158     {
1159         const CWalletTx* pcoin = &(*it).second;
1160         if (pcoin->IsCoinBase() && pcoin->GetBlocksToMaturity() > 0 && pcoin->GetDepthInMainChain() > 0)
1161             nTotal += CWallet::GetCredit(*pcoin);
1162     }
1163     return nTotal;
1164 }
1165
1166 bool CWallet::SelectCoinsMinConf(int64 nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, vector<COutput> vCoins, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
1167 {
1168     setCoinsRet.clear();
1169     nValueRet = 0;
1170
1171     // List of values less than target
1172     pair<int64, pair<const CWalletTx*,unsigned int> > coinLowestLarger;
1173     coinLowestLarger.first = std::numeric_limits<int64>::max();
1174     coinLowestLarger.second.first = NULL;
1175     vector<pair<int64, pair<const CWalletTx*,unsigned int> > > vValue;
1176     int64 nTotalLower = 0;
1177
1178     random_shuffle(vCoins.begin(), vCoins.end(), GetRandInt);
1179
1180     BOOST_FOREACH(COutput output, vCoins)
1181     {
1182         const CWalletTx *pcoin = output.tx;
1183
1184         if (output.nDepth < (pcoin->IsFromMe() ? nConfMine : nConfTheirs))
1185             continue;
1186
1187         int i = output.i;
1188
1189         // Follow the timestamp rules
1190         if (pcoin->nTime > nSpendTime)
1191             continue;
1192
1193         int64 n = pcoin->vout[i].nValue;
1194
1195         pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
1196
1197         if (n == nTargetValue)
1198         {
1199             setCoinsRet.insert(coin.second);
1200             nValueRet += coin.first;
1201             return true;
1202         }
1203         else if (n < nTargetValue + CENT)
1204         {
1205             vValue.push_back(coin);
1206             nTotalLower += n;
1207         }
1208         else if (n < coinLowestLarger.first)
1209         {
1210             coinLowestLarger = coin;
1211         }
1212     }
1213
1214     if (nTotalLower == nTargetValue)
1215     {
1216         for (unsigned int i = 0; i < vValue.size(); ++i)
1217         {
1218             setCoinsRet.insert(vValue[i].second);
1219             nValueRet += vValue[i].first;
1220         }
1221         return true;
1222     }
1223
1224     if (nTotalLower < nTargetValue)
1225     {
1226         if (coinLowestLarger.second.first == NULL)
1227             return false;
1228         setCoinsRet.insert(coinLowestLarger.second);
1229         nValueRet += coinLowestLarger.first;
1230         return true;
1231     }
1232
1233     // Solve subset sum by stochastic approximation
1234     sort(vValue.rbegin(), vValue.rend(), CompareValueOnly());
1235     vector<char> vfBest;
1236     int64 nBest;
1237
1238     ApproximateBestSubset(vValue, nTotalLower, nTargetValue, vfBest, nBest, 1000);
1239     if (nBest != nTargetValue && nTotalLower >= nTargetValue + CENT)
1240         ApproximateBestSubset(vValue, nTotalLower, nTargetValue + CENT, vfBest, nBest, 1000);
1241
1242     // If we have a bigger coin and (either the stochastic approximation didn't find a good solution,
1243     //                                   or the next bigger coin is closer), return the bigger coin
1244     if (coinLowestLarger.second.first &&
1245         ((nBest != nTargetValue && nBest < nTargetValue + CENT) || coinLowestLarger.first <= nBest))
1246     {
1247         setCoinsRet.insert(coinLowestLarger.second);
1248         nValueRet += coinLowestLarger.first;
1249     }
1250     else {
1251         for (unsigned int i = 0; i < vValue.size(); i++)
1252             if (vfBest[i])
1253             {
1254                 setCoinsRet.insert(vValue[i].second);
1255                 nValueRet += vValue[i].first;
1256             }
1257
1258         if (fDebug && GetBoolArg("-printpriority"))
1259         {
1260             //// debug print
1261             printf("SelectCoins() best subset: ");
1262             for (unsigned int i = 0; i < vValue.size(); i++)
1263                 if (vfBest[i])
1264                     printf("%s ", FormatMoney(vValue[i].first).c_str());
1265             printf("total %s\n", FormatMoney(nBest).c_str());
1266         }
1267     }
1268
1269     return true;
1270 }
1271
1272 bool CWallet::SelectCoins(int64 nTargetValue, unsigned int nSpendTime, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet, const CCoinControl* coinControl) const
1273 {
1274     vector<COutput> vCoins;
1275     AvailableCoins(vCoins, true, coinControl);
1276
1277     // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
1278     if (coinControl && coinControl->HasSelected())
1279     {
1280         BOOST_FOREACH(const COutput& out, vCoins)
1281         {
1282             nValueRet += out.tx->vout[out.i].nValue;
1283             setCoinsRet.insert(make_pair(out.tx, out.i));
1284         }
1285         return (nValueRet >= nTargetValue);
1286     }
1287
1288     return (SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 6, vCoins, setCoinsRet, nValueRet) ||
1289             SelectCoinsMinConf(nTargetValue, nSpendTime, 1, 1, vCoins, setCoinsRet, nValueRet) ||
1290             SelectCoinsMinConf(nTargetValue, nSpendTime, 0, 1, vCoins, setCoinsRet, nValueRet));
1291 }
1292
1293 // Select some coins without random shuffle or best subset approximation
1294 bool CWallet::SelectCoinsSimple(int64 nTargetValue, unsigned int nSpendTime, int nMinConf, set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
1295 {
1296     vector<COutput> vCoins;
1297     AvailableCoinsMinConf(vCoins, nMinConf);
1298
1299     setCoinsRet.clear();
1300     nValueRet = 0;
1301
1302     BOOST_FOREACH(COutput output, vCoins)
1303     {
1304         const CWalletTx *pcoin = output.tx;
1305         int i = output.i;
1306
1307         // Stop if we've chosen enough inputs
1308         if (nValueRet >= nTargetValue)
1309             break;
1310
1311         // Follow the timestamp rules
1312         if (pcoin->nTime > nSpendTime)
1313             continue;
1314
1315         int64 n = pcoin->vout[i].nValue;
1316
1317         pair<int64,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
1318
1319         if (n >= nTargetValue)
1320         {
1321             // If input value is greater or equal to target then simply insert
1322             //    it into the current subset and exit
1323             setCoinsRet.insert(coin.second);
1324             nValueRet += coin.first;
1325             break;
1326         }
1327         else if (n < nTargetValue + CENT)
1328         {
1329             setCoinsRet.insert(coin.second);
1330             nValueRet += coin.first;
1331         }
1332     }
1333
1334     return true;
1335 }
1336
1337 bool CWallet::CreateTransaction(const vector<pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, const CCoinControl* coinControl)
1338 {
1339     int64 nValue = 0;
1340     BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
1341     {
1342         if (nValue < 0)
1343             return false;
1344         nValue += s.second;
1345     }
1346     if (vecSend.empty() || nValue < 0)
1347         return false;
1348
1349     wtxNew.BindWallet(this);
1350
1351     {
1352         LOCK2(cs_main, cs_wallet);
1353         // txdb must be opened before the mapWallet lock
1354         CTxDB txdb("r");
1355         {
1356             nFeeRet = nTransactionFee;
1357             while (true)
1358             {
1359                 wtxNew.vin.clear();
1360                 wtxNew.vout.clear();
1361                 wtxNew.fFromMe = true;
1362
1363                 int64 nTotalValue = nValue + nFeeRet;
1364                 double dPriority = 0;
1365                 // vouts to the payees
1366                 BOOST_FOREACH (const PAIRTYPE(CScript, int64)& s, vecSend)
1367                     wtxNew.vout.push_back(CTxOut(s.second, s.first));
1368
1369                 // Choose coins to use
1370                 set<pair<const CWalletTx*,unsigned int> > setCoins;
1371                 int64 nValueIn = 0;
1372                 if (!SelectCoins(nTotalValue, wtxNew.nTime, setCoins, nValueIn, coinControl))
1373                     return false;
1374                 BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1375                 {
1376                     int64 nCredit = pcoin.first->vout[pcoin.second].nValue;
1377                     dPriority += (double)nCredit * pcoin.first->GetDepthInMainChain();
1378                 }
1379
1380                 int64 nChange = nValueIn - nValue - nFeeRet;
1381                 // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE
1382                 // or until nChange becomes zero
1383                 // NOTE: this depends on the exact behaviour of GetMinFee
1384                 if (nFeeRet < MIN_TX_FEE && nChange > 0 && nChange < CENT)
1385                 {
1386                     int64 nMoveToFee = min(nChange, MIN_TX_FEE - nFeeRet);
1387                     nChange -= nMoveToFee;
1388                     nFeeRet += nMoveToFee;
1389                 }
1390
1391                 // ppcoin: sub-cent change is moved to fee
1392                 if (nChange > 0 && nChange < MIN_TXOUT_AMOUNT)
1393                 {
1394                     nFeeRet += nChange;
1395                     nChange = 0;
1396                 }
1397
1398                 if (nChange > 0)
1399                 {
1400                     // Fill a vout to ourself
1401                     // TODO: pass in scriptChange instead of reservekey so
1402                     // change transaction isn't always pay-to-bitcoin-address
1403                     CScript scriptChange;
1404
1405                     // coin control: send change to custom address
1406                     if (coinControl && !boost::get<CNoDestination>(&coinControl->destChange))
1407                         scriptChange.SetDestination(coinControl->destChange);
1408
1409                     // no coin control: send change to newly generated address
1410                     else
1411                     {
1412                         // Note: We use a new key here to keep it from being obvious which side is the change.
1413                         //  The drawback is that by not reusing a previous key, the change may be lost if a
1414                         //  backup is restored, if the backup doesn't have the new private key for the change.
1415                         //  If we reused the old key, it would be possible to add code to look for and
1416                         //  rediscover unknown transactions that were written with keys of ours to recover
1417                         //  post-backup change.
1418
1419                         // Reserve a new key pair from key pool
1420                         CPubKey vchPubKey = reservekey.GetReservedKey();
1421
1422                         scriptChange.SetDestination(vchPubKey.GetID());
1423                     }
1424
1425                     // Insert change txn at random position:
1426                     vector<CTxOut>::iterator position = wtxNew.vout.begin()+GetRandInt(wtxNew.vout.size());
1427                     wtxNew.vout.insert(position, CTxOut(nChange, scriptChange));
1428                 }
1429                 else
1430                     reservekey.ReturnKey();
1431
1432                 // Fill vin
1433                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1434                     wtxNew.vin.push_back(CTxIn(coin.first->GetHash(),coin.second));
1435
1436                 // Sign
1437                 int nIn = 0;
1438                 BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins)
1439                     if (!SignSignature(*this, *coin.first, wtxNew, nIn++))
1440                         return false;
1441
1442                 // Limit size
1443                 unsigned int nBytes = ::GetSerializeSize(*(CTransaction*)&wtxNew, SER_NETWORK, PROTOCOL_VERSION);
1444                 if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
1445                     return false;
1446                 dPriority /= nBytes;
1447
1448                 // Check that enough fee is included
1449                 int64 nPayFee = nTransactionFee * (1 + (int64)nBytes / 1000);
1450                 int64 nMinFee = wtxNew.GetMinFee(1, false, GMF_SEND, nBytes);
1451
1452                 if (nFeeRet < max(nPayFee, nMinFee))
1453                 {
1454                     nFeeRet = max(nPayFee, nMinFee);
1455                     continue;
1456                 }
1457
1458                 // Fill vtxPrev by copying from previous transactions vtxPrev
1459                 wtxNew.AddSupportingTransactions(txdb);
1460                 wtxNew.fTimeReceivedIsTxTime = true;
1461
1462                 break;
1463             }
1464         }
1465     }
1466     return true;
1467 }
1468
1469 bool CWallet::CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, const CCoinControl* coinControl)
1470 {
1471     vector< pair<CScript, int64> > vecSend;
1472     vecSend.push_back(make_pair(scriptPubKey, nValue));
1473     return CreateTransaction(vecSend, wtxNew, reservekey, nFeeRet, coinControl);
1474 }
1475
1476 // NovaCoin: get current stake weight
1477 bool CWallet::GetStakeWeight(const CKeyStore& keystore, uint64& nMinWeight, uint64& nMaxWeight, uint64& nWeight)
1478 {
1479     // Choose coins to use
1480     int64 nBalance = GetBalance();
1481     int64 nReserveBalance = 0;
1482
1483     if (mapArgs.count("-reservebalance") && !ParseMoney(mapArgs["-reservebalance"], nReserveBalance))
1484     {
1485         error("GetStakeWeight : invalid reserve balance amount");
1486         return false;
1487     }
1488
1489     if (nBalance <= nReserveBalance)
1490         return false;
1491
1492     vector<const CWalletTx*> vwtxPrev;
1493
1494 /*
1495  * TODO: performance comparison
1496
1497     static set<pair<const CWalletTx*,unsigned int> > setCoins;
1498     static uint256 hashPrevBlock;
1499     static int64 nValueIn = 0;
1500
1501     // Cache outputs unless best block changed
1502     if (hashPrevBlock != pindexBest->GetBlockHash())
1503     {
1504         if (!SelectCoinsSimple(nBalance - nReserveBalance, GetAdjustedTime(), nCoinbaseMaturity * 10, setCoins, nValueIn))
1505             return false;
1506
1507         if (setCoins.empty())
1508             return false;
1509
1510         hashPrevBlock == pindexBest->GetBlockHash();
1511     }
1512 */
1513
1514     set<pair<const CWalletTx*,unsigned int> > setCoins;
1515     int64 nValueIn = 0;
1516
1517     if (!SelectCoinsSimple(nBalance - nReserveBalance, GetTime(), nCoinbaseMaturity * 10, setCoins, nValueIn))
1518         return false;
1519
1520     if (setCoins.empty())
1521         return false;
1522
1523     CTxDB txdb("r");
1524     BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1525     {
1526         CTxIndex txindex;
1527         {
1528             LOCK2(cs_main, cs_wallet);
1529             if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex))
1530                 continue;
1531         }
1532
1533         int64 nTimeWeight = GetWeight((int64)pcoin.first->nTime, (int64)GetTime());
1534         CBigNum bnCoinDayWeight = CBigNum(pcoin.first->vout[pcoin.second].nValue) * nTimeWeight / COIN / (24 * 60 * 60);
1535
1536         // Weight is greater than zero
1537         if (nTimeWeight > 0)
1538         {
1539             nWeight += bnCoinDayWeight.getuint64();
1540         }
1541
1542         // Weight is greater than zero, but the maximum value isn't reached yet
1543         if (nTimeWeight > 0 && nTimeWeight < nStakeMaxAge)
1544         {
1545             nMinWeight += bnCoinDayWeight.getuint64();
1546         }
1547
1548         // Maximum weight was reached
1549         if (nTimeWeight == nStakeMaxAge)
1550         {
1551             nMaxWeight += bnCoinDayWeight.getuint64();
1552         }
1553     }
1554
1555     return true;
1556 }
1557
1558 bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64 nSearchInterval, CTransaction& txNew, CKey& key)
1559 {
1560     // The following combine threshold is important to security
1561     // Should not be adjusted if you don't understand the consequences
1562     int64 nCombineThreshold = GetProofOfWorkReward(GetLastBlockIndex(pindexBest, false)->nBits) / 3;
1563
1564     CBigNum bnTargetPerCoinDay;
1565     bnTargetPerCoinDay.SetCompact(nBits);
1566
1567     txNew.vin.clear();
1568     txNew.vout.clear();
1569
1570     // Mark coin stake transaction
1571     CScript scriptEmpty;
1572     scriptEmpty.clear();
1573     txNew.vout.push_back(CTxOut(0, scriptEmpty));
1574
1575     // Choose coins to use
1576     int64 nBalance = GetBalance();
1577     int64 nReserveBalance = 0;
1578
1579     if (mapArgs.count("-reservebalance") && !ParseMoney(mapArgs["-reservebalance"], nReserveBalance))
1580         return error("CreateCoinStake : invalid reserve balance amount");
1581
1582     if (nBalance <= nReserveBalance)
1583         return false;
1584
1585     vector<const CWalletTx*> vwtxPrev;
1586
1587 /*
1588  * TODO: performance comparison
1589
1590     static set<pair<const CWalletTx*,unsigned int> > setCoins;
1591     static uint256 hashPrevBlock;
1592     static int64 nValueIn = 0;
1593
1594     // Cache outputs unless best block changed
1595     if (hashPrevBlock != pindexBest->GetBlockHash())
1596     {
1597         if (!SelectCoinsSimple(nBalance - nReserveBalance, txNew.nTime, nCoinbaseMaturity * 10, setCoins, nValueIn))
1598             return false;
1599
1600         if (setCoins.empty())
1601             return false;
1602
1603         hashPrevBlock == pindexBest->GetBlockHash();
1604     }
1605 */
1606
1607     set<pair<const CWalletTx*,unsigned int> > setCoins;
1608     int64 nValueIn = 0;
1609
1610     // Select coins with suitable depth
1611     if (!SelectCoinsSimple(nBalance - nReserveBalance, txNew.nTime, nCoinbaseMaturity * 10, setCoins, nValueIn))
1612         return false;
1613
1614     if (setCoins.empty())
1615         return false;
1616
1617     int64 nCredit = 0;
1618     CScript scriptPubKeyKernel;
1619     CTxDB txdb("r");
1620     BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1621     {
1622         CTxIndex txindex;
1623         {
1624             LOCK2(cs_main, cs_wallet);
1625             if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex))
1626                 continue;
1627         }
1628
1629         // Read block header
1630         CBlock block;
1631         {
1632             LOCK2(cs_main, cs_wallet);
1633             if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
1634                 continue;
1635         }
1636
1637         static int nMaxStakeSearchInterval = 60;
1638         if (block.GetBlockTime() + nStakeMinAge > txNew.nTime - nMaxStakeSearchInterval)
1639             continue; // only count coins meeting min age requirement
1640
1641         bool fKernelFound = false;
1642         for (unsigned int n=0; n<min(nSearchInterval,(int64)nMaxStakeSearchInterval) && !fKernelFound && !fShutdown; n++)
1643         {
1644             // Search backward in time from the given txNew timestamp 
1645             // Search nSearchInterval seconds back up to nMaxStakeSearchInterval
1646             uint256 hashProofOfStake = 0, targetProofOfStake = 0;
1647             COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second);
1648             if (CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake, targetProofOfStake))
1649             {
1650                 // Found a kernel
1651                 if (fDebug && GetBoolArg("-printcoinstake"))
1652                     printf("CreateCoinStake : kernel found\n");
1653                 vector<valtype> vSolutions;
1654                 txnouttype whichType;
1655                 CScript scriptPubKeyOut;
1656                 scriptPubKeyKernel = pcoin.first->vout[pcoin.second].scriptPubKey;
1657                 if (!Solver(scriptPubKeyKernel, whichType, vSolutions))
1658                 {
1659                     if (fDebug && GetBoolArg("-printcoinstake"))
1660                         printf("CreateCoinStake : failed to parse kernel\n");
1661                     break;
1662                 }
1663                 if (fDebug && GetBoolArg("-printcoinstake"))
1664                     printf("CreateCoinStake : parsed kernel type=%d\n", whichType);
1665                 if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH)
1666                 {
1667                     if (fDebug && GetBoolArg("-printcoinstake"))
1668                         printf("CreateCoinStake : no support for kernel type=%d\n", whichType);
1669                     break;  // only support pay to public key and pay to address
1670                 }
1671                 if (whichType == TX_PUBKEYHASH) // pay to address type
1672                 {
1673                     // convert to pay to public key type
1674                     if (!keystore.GetKey(uint160(vSolutions[0]), key))
1675                     {
1676                         if (fDebug && GetBoolArg("-printcoinstake"))
1677                             printf("CreateCoinStake : failed to get key for kernel type=%d\n", whichType);
1678                         break;  // unable to find corresponding public key
1679                     }
1680                     scriptPubKeyOut << key.GetPubKey() << OP_CHECKSIG;
1681                 }
1682                 if (whichType == TX_PUBKEY)
1683                 {
1684                     valtype& vchPubKey = vSolutions[0];
1685                     if (!keystore.GetKey(Hash160(vchPubKey), key))
1686                     {
1687                         if (fDebug && GetBoolArg("-printcoinstake"))
1688                             printf("CreateCoinStake : failed to get key for kernel type=%d\n", whichType);
1689                         break;  // unable to find corresponding public key
1690                     }
1691
1692                 if (key.GetPubKey() != vchPubKey)
1693                 {
1694                     if (fDebug && GetBoolArg("-printcoinstake"))
1695                         printf("CreateCoinStake : invalid key for kernel type=%d\n", whichType);
1696                         break; // keys mismatch
1697                     }
1698
1699                     scriptPubKeyOut = scriptPubKeyKernel;
1700                 }
1701
1702                 txNew.nTime -= n;
1703                 txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
1704                 nCredit += pcoin.first->vout[pcoin.second].nValue;
1705                 vwtxPrev.push_back(pcoin.first);
1706                 txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
1707
1708                 if (GetWeight(block.GetBlockTime(), (int64)txNew.nTime) < nStakeMaxAge)
1709                     txNew.vout.push_back(CTxOut(0, scriptPubKeyOut)); //split stake
1710                 if (fDebug && GetBoolArg("-printcoinstake"))
1711                     printf("CreateCoinStake : added kernel type=%d\n", whichType);
1712                 fKernelFound = true;
1713                 break;
1714             }
1715         }
1716
1717         if (fKernelFound || fShutdown)
1718             break; // if kernel is found stop searching
1719     }
1720
1721     if (nCredit == 0 || nCredit > nBalance - nReserveBalance)
1722         return false;
1723
1724     BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1725     {
1726         // Attempt to add more inputs
1727         // Only add coins of the same key/address as kernel
1728         if (txNew.vout.size() == 2 && ((pcoin.first->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel || pcoin.first->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey))
1729             && pcoin.first->GetHash() != txNew.vin[0].prevout.hash)
1730         {
1731             int64 nTimeWeight = GetWeight((int64)pcoin.first->nTime, (int64)txNew.nTime);
1732
1733             // Stop adding more inputs if already too many inputs
1734             if (txNew.vin.size() >= 100)
1735                 break;
1736             // Stop adding more inputs if value is already pretty significant
1737             if (nCredit > nCombineThreshold)
1738                 break;
1739             // Stop adding inputs if reached reserve limit
1740             if (nCredit + pcoin.first->vout[pcoin.second].nValue > nBalance - nReserveBalance)
1741                 break;
1742             // Do not add additional significant input
1743             if (pcoin.first->vout[pcoin.second].nValue > nCombineThreshold)
1744                 continue;
1745             // Do not add input that is still too young
1746             if (nTimeWeight < nStakeMaxAge)
1747                 continue;
1748
1749             txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
1750             nCredit += pcoin.first->vout[pcoin.second].nValue;
1751             vwtxPrev.push_back(pcoin.first);
1752         }
1753     }
1754
1755     // Calculate coin age reward
1756     {
1757         uint64 nCoinAge;
1758         CTxDB txdb("r");
1759         if (!txNew.GetCoinAge(txdb, nCoinAge))
1760             return error("CreateCoinStake : failed to calculate coin age");
1761         nCredit += GetProofOfStakeReward(nCoinAge, nBits, txNew.nTime);
1762     }
1763
1764     int64 nMinFee = 0;
1765     while (true)
1766     {
1767         // Set output amount
1768         if (txNew.vout.size() == 3)
1769         {
1770             txNew.vout[1].nValue = ((nCredit - nMinFee) / 2 / CENT) * CENT;
1771             txNew.vout[2].nValue = nCredit - nMinFee - txNew.vout[1].nValue;
1772         }
1773         else
1774             txNew.vout[1].nValue = nCredit - nMinFee;
1775
1776         // Sign
1777         int nIn = 0;
1778         BOOST_FOREACH(const CWalletTx* pcoin, vwtxPrev)
1779         {
1780             if (!SignSignature(*this, *pcoin, txNew, nIn++))
1781                 return error("CreateCoinStake : failed to sign coinstake");
1782         }
1783
1784         // Limit size
1785         unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
1786         if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
1787             return error("CreateCoinStake : exceeded coinstake size limit");
1788
1789         // Check enough fee is paid
1790         if (nMinFee < txNew.GetMinFee() - MIN_TX_FEE)
1791         {
1792             nMinFee = txNew.GetMinFee() - MIN_TX_FEE;
1793             continue; // try signing again
1794         }
1795         else
1796         {
1797             if (fDebug && GetBoolArg("-printfee"))
1798                 printf("CreateCoinStake : fee for coinstake %s\n", FormatMoney(nMinFee).c_str());
1799             break;
1800         }
1801     }
1802
1803     // Successfully generated coinstake
1804     return true;
1805 }
1806
1807
1808 // Call after CreateTransaction unless you want to abort
1809 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1810 {
1811     {
1812         LOCK2(cs_main, cs_wallet);
1813         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
1814         {
1815             // This is only to keep the database open to defeat the auto-flush for the
1816             // duration of this scope.  This is the only place where this optimization
1817             // maybe makes sense; please don't do it anywhere else.
1818             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1819
1820             // Take key pair from key pool so it won't be used again
1821             reservekey.KeepKey();
1822
1823             // Add tx to wallet, because if it has change it's also ours,
1824             // otherwise just for transaction history.
1825             AddToWallet(wtxNew);
1826
1827             // Mark old coins as spent
1828             set<CWalletTx*> setCoins;
1829             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1830             {
1831                 CWalletTx &coin = mapWallet[txin.prevout.hash];
1832                 coin.BindWallet(this);
1833                 coin.MarkSpent(txin.prevout.n);
1834                 coin.WriteToDisk();
1835                 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
1836             }
1837
1838             if (fFileBacked)
1839                 delete pwalletdb;
1840         }
1841
1842         // Track how many getdata requests our transaction gets
1843         mapRequestCount[wtxNew.GetHash()] = 0;
1844
1845         // Broadcast
1846         if (!wtxNew.AcceptToMemoryPool())
1847         {
1848             // This must not fail. The transaction has already been signed and recorded.
1849             printf("CommitTransaction() : Error: Transaction not valid");
1850             return false;
1851         }
1852         wtxNew.RelayWalletTransaction();
1853     }
1854     return true;
1855 }
1856
1857
1858
1859
1860 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1861 {
1862     CReserveKey reservekey(this);
1863     int64 nFeeRequired;
1864
1865     if (IsLocked())
1866     {
1867         string strError = _("Error: Wallet locked, unable to create transaction  ");
1868         printf("SendMoney() : %s", strError.c_str());
1869         return strError;
1870     }
1871     if (fWalletUnlockMintOnly)
1872     {
1873         string strError = _("Error: Wallet unlocked for block minting only, unable to create transaction.");
1874         printf("SendMoney() : %s", strError.c_str());
1875         return strError;
1876     }
1877     if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
1878     {
1879         string strError;
1880         if (nValue + nFeeRequired > GetBalance())
1881             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());
1882         else
1883             strError = _("Error: Transaction creation failed  ");
1884         printf("SendMoney() : %s", strError.c_str());
1885         return strError;
1886     }
1887
1888     if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired, _("Sending...")))
1889         return "ABORTED";
1890
1891     if (!CommitTransaction(wtxNew, reservekey))
1892         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.");
1893
1894     return "";
1895 }
1896
1897
1898
1899 string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1900 {
1901     // Check amount
1902     if (nValue <= 0)
1903         return _("Invalid amount");
1904     if (nValue + nTransactionFee > GetBalance())
1905         return _("Insufficient funds");
1906
1907     // Parse Bitcoin address
1908     CScript scriptPubKey;
1909     scriptPubKey.SetDestination(address);
1910
1911     return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
1912 }
1913
1914
1915
1916
1917 DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
1918 {
1919     if (!fFileBacked)
1920         return DB_LOAD_OK;
1921     fFirstRunRet = false;
1922     DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1923     if (nLoadWalletRet == DB_NEED_REWRITE)
1924     {
1925         if (CDB::Rewrite(strWalletFile, "\x04pool"))
1926         {
1927             setKeyPool.clear();
1928             // Note: can't top-up keypool here, because wallet is locked.
1929             // User will be prompted to unlock wallet the next operation
1930             // the requires a new key.
1931         }
1932     }
1933
1934     if (nLoadWalletRet != DB_LOAD_OK)
1935         return nLoadWalletRet;
1936     fFirstRunRet = !vchDefaultKey.IsValid();
1937
1938     NewThread(ThreadFlushWalletDB, &strWalletFile);
1939     return DB_LOAD_OK;
1940 }
1941
1942
1943 bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName)
1944 {
1945     std::map<CTxDestination, std::string>::iterator mi = mapAddressBook.find(address);
1946     mapAddressBook[address] = strName;
1947     NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
1948     if (!fFileBacked)
1949         return false;
1950     return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
1951 }
1952
1953 bool CWallet::DelAddressBookName(const CTxDestination& address)
1954 {
1955     mapAddressBook.erase(address);
1956     NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
1957     if (!fFileBacked)
1958         return false;
1959     return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
1960 }
1961
1962
1963 void CWallet::PrintWallet(const CBlock& block)
1964 {
1965     {
1966         LOCK(cs_wallet);
1967         if (block.IsProofOfWork() && mapWallet.count(block.vtx[0].GetHash()))
1968         {
1969             CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1970             printf("    mine:  %d  %d  %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1971         }
1972         if (block.IsProofOfStake() && mapWallet.count(block.vtx[1].GetHash()))
1973         {
1974             CWalletTx& wtx = mapWallet[block.vtx[1].GetHash()];
1975             printf("    stake: %d  %d  %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1976          }
1977
1978     }
1979     printf("\n");
1980 }
1981
1982 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
1983 {
1984     {
1985         LOCK(cs_wallet);
1986         map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
1987         if (mi != mapWallet.end())
1988         {
1989             wtx = (*mi).second;
1990             return true;
1991         }
1992     }
1993     return false;
1994 }
1995
1996 bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
1997 {
1998     if (fFileBacked)
1999     {
2000         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
2001             return false;
2002     }
2003     vchDefaultKey = vchPubKey;
2004     return true;
2005 }
2006
2007 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
2008 {
2009     if (!pwallet->fFileBacked)
2010         return false;
2011     strWalletFileOut = pwallet->strWalletFile;
2012     return true;
2013 }
2014
2015 //
2016 // Mark old keypool keys as used,
2017 // and generate all new keys
2018 //
2019 bool CWallet::NewKeyPool()
2020 {
2021     {
2022         LOCK(cs_wallet);
2023         CWalletDB walletdb(strWalletFile);
2024         BOOST_FOREACH(int64 nIndex, setKeyPool)
2025             walletdb.ErasePool(nIndex);
2026         setKeyPool.clear();
2027
2028         if (IsLocked())
2029             return false;
2030
2031         int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
2032         for (int i = 0; i < nKeys; i++)
2033         {
2034             int64 nIndex = i+1;
2035             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
2036             setKeyPool.insert(nIndex);
2037         }
2038         printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
2039     }
2040     return true;
2041 }
2042
2043 bool CWallet::TopUpKeyPool(unsigned int nSize)
2044 {
2045     {
2046         LOCK(cs_wallet);
2047
2048         if (IsLocked())
2049             return false;
2050
2051         CWalletDB walletdb(strWalletFile);
2052
2053         // Top up key pool
2054         unsigned int nTargetSize;
2055         if (nSize > 0)
2056             nTargetSize = nSize;
2057         else
2058             nTargetSize = max(GetArg("-keypool", 100), 0LL);
2059
2060         while (setKeyPool.size() < (nTargetSize + 1))
2061         {
2062             int64 nEnd = 1;
2063             if (!setKeyPool.empty())
2064                 nEnd = *(--setKeyPool.end()) + 1;
2065             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
2066                 throw runtime_error("TopUpKeyPool() : writing generated key failed");
2067             setKeyPool.insert(nEnd);
2068             printf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
2069         }
2070     }
2071     return true;
2072 }
2073
2074 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
2075 {
2076     nIndex = -1;
2077     keypool.vchPubKey = CPubKey();
2078     {
2079         LOCK(cs_wallet);
2080
2081         if (!IsLocked())
2082             TopUpKeyPool();
2083
2084         // Get the oldest key
2085         if(setKeyPool.empty())
2086             return;
2087
2088         CWalletDB walletdb(strWalletFile);
2089
2090         nIndex = *(setKeyPool.begin());
2091         setKeyPool.erase(setKeyPool.begin());
2092         if (!walletdb.ReadPool(nIndex, keypool))
2093             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
2094         if (!HaveKey(keypool.vchPubKey.GetID()))
2095             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
2096         assert(keypool.vchPubKey.IsValid());
2097         if (fDebug && GetBoolArg("-printkeypool"))
2098             printf("keypool reserve %"PRI64d"\n", nIndex);
2099     }
2100 }
2101
2102 int64 CWallet::AddReserveKey(const CKeyPool& keypool)
2103 {
2104     {
2105         LOCK2(cs_main, cs_wallet);
2106         CWalletDB walletdb(strWalletFile);
2107
2108         int64 nIndex = 1 + *(--setKeyPool.end());
2109         if (!walletdb.WritePool(nIndex, keypool))
2110             throw runtime_error("AddReserveKey() : writing added key failed");
2111         setKeyPool.insert(nIndex);
2112         return nIndex;
2113     }
2114     return -1;
2115 }
2116
2117 void CWallet::KeepKey(int64 nIndex)
2118 {
2119     // Remove from key pool
2120     if (fFileBacked)
2121     {
2122         CWalletDB walletdb(strWalletFile);
2123         walletdb.ErasePool(nIndex);
2124     }
2125     if(fDebug)
2126         printf("keypool keep %"PRI64d"\n", nIndex);
2127 }
2128
2129 void CWallet::ReturnKey(int64 nIndex)
2130 {
2131     // Return to key pool
2132     {
2133         LOCK(cs_wallet);
2134         setKeyPool.insert(nIndex);
2135     }
2136     if(fDebug)
2137         printf("keypool return %"PRI64d"\n", nIndex);
2138 }
2139
2140 bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
2141 {
2142     int64 nIndex = 0;
2143     CKeyPool keypool;
2144     {
2145         LOCK(cs_wallet);
2146         ReserveKeyFromKeyPool(nIndex, keypool);
2147         if (nIndex == -1)
2148         {
2149             if (fAllowReuse && vchDefaultKey.IsValid())
2150             {
2151                 result = vchDefaultKey;
2152                 return true;
2153             }
2154             if (IsLocked()) return false;
2155             result = GenerateNewKey();
2156             return true;
2157         }
2158         KeepKey(nIndex);
2159         result = keypool.vchPubKey;
2160     }
2161     return true;
2162 }
2163
2164 int64 CWallet::GetOldestKeyPoolTime()
2165 {
2166     int64 nIndex = 0;
2167     CKeyPool keypool;
2168     ReserveKeyFromKeyPool(nIndex, keypool);
2169     if (nIndex == -1)
2170         return GetTime();
2171     ReturnKey(nIndex);
2172     return keypool.nTime;
2173 }
2174
2175 std::map<CTxDestination, int64> CWallet::GetAddressBalances()
2176 {
2177     map<CTxDestination, int64> balances;
2178
2179     {
2180         LOCK(cs_wallet);
2181         BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
2182         {
2183             CWalletTx *pcoin = &walletEntry.second;
2184
2185             if (!pcoin->IsFinal() || !pcoin->IsTrusted())
2186                 continue;
2187
2188             if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0)
2189                 continue;
2190
2191             int nDepth = pcoin->GetDepthInMainChain();
2192             if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
2193                 continue;
2194
2195             for (unsigned int i = 0; i < pcoin->vout.size(); i++)
2196             {
2197                 CTxDestination addr;
2198                 if (!IsMine(pcoin->vout[i]))
2199                     continue;
2200                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
2201                     continue;
2202
2203                 int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
2204
2205                 if (!balances.count(addr))
2206                     balances[addr] = 0;
2207                 balances[addr] += n;
2208             }
2209         }
2210     }
2211
2212     return balances;
2213 }
2214
2215 set< set<CTxDestination> > CWallet::GetAddressGroupings()
2216 {
2217     set< set<CTxDestination> > groupings;
2218     set<CTxDestination> grouping;
2219
2220     BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
2221     {
2222         CWalletTx *pcoin = &walletEntry.second;
2223
2224         if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0]))
2225         {
2226             // group all input addresses with each other
2227             BOOST_FOREACH(CTxIn txin, pcoin->vin)
2228             {
2229                 CTxDestination address;
2230                 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
2231                     continue;
2232                 grouping.insert(address);
2233             }
2234
2235             // group change with input addresses
2236             BOOST_FOREACH(CTxOut txout, pcoin->vout)
2237                 if (IsChange(txout))
2238                 {
2239                     CWalletTx tx = mapWallet[pcoin->vin[0].prevout.hash];
2240                     CTxDestination txoutAddr;
2241                     if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
2242                         continue;
2243                     grouping.insert(txoutAddr);
2244                 }
2245             groupings.insert(grouping);
2246             grouping.clear();
2247         }
2248
2249         // group lone addrs by themselves
2250         for (unsigned int i = 0; i < pcoin->vout.size(); i++)
2251             if (IsMine(pcoin->vout[i]))
2252             {
2253                 CTxDestination address;
2254                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
2255                     continue;
2256                 grouping.insert(address);
2257                 groupings.insert(grouping);
2258                 grouping.clear();
2259             }
2260     }
2261
2262     set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
2263     map< CTxDestination, set<CTxDestination>* > setmap;  // map addresses to the unique group containing it
2264     BOOST_FOREACH(set<CTxDestination> grouping, groupings)
2265     {
2266         // make a set of all the groups hit by this new group
2267         set< set<CTxDestination>* > hits;
2268         map< CTxDestination, set<CTxDestination>* >::iterator it;
2269         BOOST_FOREACH(CTxDestination address, grouping)
2270             if ((it = setmap.find(address)) != setmap.end())
2271                 hits.insert((*it).second);
2272
2273         // merge all hit groups into a new single group and delete old groups
2274         set<CTxDestination>* merged = new set<CTxDestination>(grouping);
2275         BOOST_FOREACH(set<CTxDestination>* hit, hits)
2276         {
2277             merged->insert(hit->begin(), hit->end());
2278             uniqueGroupings.erase(hit);
2279             delete hit;
2280         }
2281         uniqueGroupings.insert(merged);
2282
2283         // update setmap
2284         BOOST_FOREACH(CTxDestination element, *merged)
2285             setmap[element] = merged;
2286     }
2287
2288     set< set<CTxDestination> > ret;
2289     BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
2290     {
2291         ret.insert(*uniqueGrouping);
2292         delete uniqueGrouping;
2293     }
2294
2295     return ret;
2296 }
2297
2298 // ppcoin: check 'spent' consistency between wallet and txindex
2299 // ppcoin: fix wallet spent state according to txindex
2300 void CWallet::FixSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion, bool fCheckOnly)
2301 {
2302     nMismatchFound = 0;
2303     nBalanceInQuestion = 0;
2304
2305     LOCK(cs_wallet);
2306     vector<CWalletTx*> vCoins;
2307     vCoins.reserve(mapWallet.size());
2308     for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2309         vCoins.push_back(&(*it).second);
2310
2311     CTxDB txdb("r");
2312     BOOST_FOREACH(CWalletTx* pcoin, vCoins)
2313     {
2314         // Find the corresponding transaction index
2315         CTxIndex txindex;
2316         if (!txdb.ReadTxIndex(pcoin->GetHash(), txindex))
2317             continue;
2318         for (unsigned int n=0; n < pcoin->vout.size(); n++)
2319         {
2320             if (IsMine(pcoin->vout[n]) && pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
2321             {
2322                 printf("FixSpentCoins found lost coin %sppc %s[%d], %s\n",
2323                     FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
2324                 nMismatchFound++;
2325                 nBalanceInQuestion += pcoin->vout[n].nValue;
2326                 if (!fCheckOnly)
2327                 {
2328                     pcoin->MarkUnspent(n);
2329                     pcoin->WriteToDisk();
2330                 }
2331             }
2332             else if (IsMine(pcoin->vout[n]) && !pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
2333             {
2334                 printf("FixSpentCoins found spent coin %sppc %s[%d], %s\n",
2335                     FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
2336                 nMismatchFound++;
2337                 nBalanceInQuestion += pcoin->vout[n].nValue;
2338                 if (!fCheckOnly)
2339                 {
2340                     pcoin->MarkSpent(n);
2341                     pcoin->WriteToDisk();
2342                 }
2343             }
2344         }
2345     }
2346 }
2347
2348 // ppcoin: disable transaction (only for coinstake)
2349 void CWallet::DisableTransaction(const CTransaction &tx)
2350 {
2351     if (!tx.IsCoinStake() || !IsFromMe(tx))
2352         return; // only disconnecting coinstake requires marking input unspent
2353
2354     LOCK(cs_wallet);
2355     BOOST_FOREACH(const CTxIn& txin, tx.vin)
2356     {
2357         map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
2358         if (mi != mapWallet.end())
2359         {
2360             CWalletTx& prev = (*mi).second;
2361             if (txin.prevout.n < prev.vout.size() && IsMine(prev.vout[txin.prevout.n]))
2362             {
2363                 prev.MarkUnspent(txin.prevout.n);
2364                 prev.WriteToDisk();
2365             }
2366         }
2367     }
2368 }
2369
2370 CPubKey CReserveKey::GetReservedKey()
2371 {
2372     if (nIndex == -1)
2373     {
2374         CKeyPool keypool;
2375         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
2376         if (nIndex != -1)
2377             vchPubKey = keypool.vchPubKey;
2378         else
2379         {
2380             printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
2381             vchPubKey = pwallet->vchDefaultKey;
2382         }
2383     }
2384     assert(vchPubKey.IsValid());
2385     return vchPubKey;
2386 }
2387
2388 void CReserveKey::KeepKey()
2389 {
2390     if (nIndex != -1)
2391         pwallet->KeepKey(nIndex);
2392     nIndex = -1;
2393     vchPubKey = CPubKey();
2394 }
2395
2396 void CReserveKey::ReturnKey()
2397 {
2398     if (nIndex != -1)
2399         pwallet->ReturnKey(nIndex);
2400     nIndex = -1;
2401     vchPubKey = CPubKey();
2402 }
2403
2404 void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
2405 {
2406     setAddress.clear();
2407
2408     CWalletDB walletdb(strWalletFile);
2409
2410     LOCK2(cs_main, cs_wallet);
2411     BOOST_FOREACH(const int64& id, setKeyPool)
2412     {
2413         CKeyPool keypool;
2414         if (!walletdb.ReadPool(id, keypool))
2415             throw runtime_error("GetAllReserveKeyHashes() : read failed");
2416         assert(keypool.vchPubKey.IsValid());
2417         CKeyID keyID = keypool.vchPubKey.GetID();
2418         if (!HaveKey(keyID))
2419             throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
2420         setAddress.insert(keyID);
2421     }
2422 }
2423
2424 void CWallet::UpdatedTransaction(const uint256 &hashTx)
2425 {
2426     {
2427         LOCK(cs_wallet);
2428         // Only notify UI if this transaction is in this wallet
2429         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
2430         if (mi != mapWallet.end())
2431             NotifyTransactionChanged(this, hashTx, CT_UPDATED);
2432     }
2433 }
2434
2435 void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
2436     mapKeyBirth.clear();
2437
2438     // get birth times for keys with metadata
2439     for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
2440         if (it->second.nCreateTime)
2441             mapKeyBirth[it->first] = it->second.nCreateTime;
2442
2443     // map in which we'll infer heights of other keys
2444     CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
2445     std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
2446     std::set<CKeyID> setKeys;
2447     GetKeys(setKeys);
2448     BOOST_FOREACH(const CKeyID &keyid, setKeys) {
2449         if (mapKeyBirth.count(keyid) == 0)
2450             mapKeyFirstBlock[keyid] = pindexMax;
2451     }
2452     setKeys.clear();
2453
2454     // if there are no such keys, we're done
2455     if (mapKeyFirstBlock.empty())
2456         return;
2457
2458     // find first block that affects those keys, if there are any left
2459     std::vector<CKeyID> vAffected;
2460     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
2461         // iterate over all wallet transactions...
2462         const CWalletTx &wtx = (*it).second;
2463         std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
2464         if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
2465             // ... which are already in a block
2466             int nHeight = blit->second->nHeight;
2467             BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
2468                 // iterate over all their outputs
2469                 ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
2470                 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
2471                     // ... and all their affected keys
2472                     std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
2473                     if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
2474                         rit->second = blit->second;
2475                 }
2476                 vAffected.clear();
2477             }
2478         }
2479     }
2480
2481     // Extract block timestamps for those keys
2482     for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
2483         mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
2484 }