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