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