Remove loop macro from util.h
[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(nDerivationMethodIndex);
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             while (true)
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, targetProofOfStake = 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, targetProofOfStake))
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     while (true)
1606     {
1607         // Set output amount
1608         if (txNew.vout.size() == 3)
1609         {
1610             // Should we use keys from pool for the last coinstake output?
1611             if (fStakeUsePooledKeys)
1612             {
1613                 CReserveKey reservekey((CWallet*) &keystore);
1614
1615                 // Replace current key with the new one
1616                 txNew.vout[2].SetNull();
1617                 txNew.vout[2].scriptPubKey << reservekey.GetReservedKey() << OP_CHECKSIG;
1618
1619                 // Remove key from pool
1620                 reservekey.KeepKey();
1621             }
1622
1623             txNew.vout[1].nValue = ((nCredit - nMinFee) / 2 / CENT) * CENT;
1624             txNew.vout[2].nValue = nCredit - nMinFee - txNew.vout[1].nValue;
1625         }
1626         else
1627             txNew.vout[1].nValue = nCredit - nMinFee;
1628
1629         // Sign
1630         int nIn = 0;
1631         BOOST_FOREACH(const CWalletTx* pcoin, vwtxPrev)
1632         {
1633             if (!SignSignature(*this, *pcoin, txNew, nIn++))
1634                 return error("CreateCoinStake : failed to sign coinstake");
1635         }
1636
1637         // Limit size
1638         unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
1639         if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
1640             return error("CreateCoinStake : exceeded coinstake size limit");
1641
1642         // Check enough fee is paid
1643         if (nMinFee < txNew.GetMinFee() - MIN_TX_FEE)
1644         {
1645             nMinFee = txNew.GetMinFee() - MIN_TX_FEE;
1646             continue; // try signing again
1647         }
1648         else
1649         {
1650             if (fDebug && GetBoolArg("-printfee"))
1651                 printf("CreateCoinStake : fee for coinstake %s\n", FormatMoney(nMinFee).c_str());
1652             break;
1653         }
1654     }
1655
1656     // Successfully generated coinstake
1657     return true;
1658 }
1659
1660
1661 // Call after CreateTransaction unless you want to abort
1662 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1663 {
1664     {
1665         LOCK2(cs_main, cs_wallet);
1666         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
1667         {
1668             // This is only to keep the database open to defeat the auto-flush for the
1669             // duration of this scope.  This is the only place where this optimization
1670             // maybe makes sense; please don't do it anywhere else.
1671             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1672
1673             // Take key pair from key pool so it won't be used again
1674             reservekey.KeepKey();
1675
1676             // Add tx to wallet, because if it has change it's also ours,
1677             // otherwise just for transaction history.
1678             AddToWallet(wtxNew);
1679
1680             // Mark old coins as spent
1681             set<CWalletTx*> setCoins;
1682             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1683             {
1684                 CWalletTx &coin = mapWallet[txin.prevout.hash];
1685                 coin.BindWallet(this);
1686                 coin.MarkSpent(txin.prevout.n);
1687                 coin.WriteToDisk();
1688                 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
1689             }
1690
1691             if (fFileBacked)
1692                 delete pwalletdb;
1693         }
1694
1695         // Track how many getdata requests our transaction gets
1696         mapRequestCount[wtxNew.GetHash()] = 0;
1697
1698         // Broadcast
1699         if (!wtxNew.AcceptToMemoryPool())
1700         {
1701             // This must not fail. The transaction has already been signed and recorded.
1702             printf("CommitTransaction() : Error: Transaction not valid");
1703             return false;
1704         }
1705         wtxNew.RelayWalletTransaction();
1706     }
1707     return true;
1708 }
1709
1710
1711
1712
1713 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1714 {
1715     CReserveKey reservekey(this);
1716     int64 nFeeRequired;
1717
1718     if (IsLocked())
1719     {
1720         string strError = _("Error: Wallet locked, unable to create transaction  ");
1721         printf("SendMoney() : %s", strError.c_str());
1722         return strError;
1723     }
1724     if (fWalletUnlockMintOnly)
1725     {
1726         string strError = _("Error: Wallet unlocked for block minting only, unable to create transaction.");
1727         printf("SendMoney() : %s", strError.c_str());
1728         return strError;
1729     }
1730     if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
1731     {
1732         string strError;
1733         if (nValue + nFeeRequired > GetBalance())
1734             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());
1735         else
1736             strError = _("Error: Transaction creation failed  ");
1737         printf("SendMoney() : %s", strError.c_str());
1738         return strError;
1739     }
1740
1741     if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired, _("Sending...")))
1742         return "ABORTED";
1743
1744     if (!CommitTransaction(wtxNew, reservekey))
1745         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.");
1746
1747     return "";
1748 }
1749
1750
1751
1752 string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1753 {
1754     // Check amount
1755     if (nValue <= 0)
1756         return _("Invalid amount");
1757     if (nValue + nTransactionFee > GetBalance())
1758         return _("Insufficient funds");
1759
1760     // Parse Bitcoin address
1761     CScript scriptPubKey;
1762     scriptPubKey.SetDestination(address);
1763
1764     return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
1765 }
1766
1767
1768
1769
1770 DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
1771 {
1772     if (!fFileBacked)
1773         return DB_LOAD_OK;
1774     fFirstRunRet = false;
1775     DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1776     if (nLoadWalletRet == DB_NEED_REWRITE)
1777     {
1778         if (CDB::Rewrite(strWalletFile, "\x04pool"))
1779         {
1780             setKeyPool.clear();
1781             // Note: can't top-up keypool here, because wallet is locked.
1782             // User will be prompted to unlock wallet the next operation
1783             // the requires a new key.
1784         }
1785     }
1786
1787     if (nLoadWalletRet != DB_LOAD_OK)
1788         return nLoadWalletRet;
1789     fFirstRunRet = !vchDefaultKey.IsValid();
1790
1791     NewThread(ThreadFlushWalletDB, &strWalletFile);
1792     return DB_LOAD_OK;
1793 }
1794
1795
1796 bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName)
1797 {
1798     std::map<CTxDestination, std::string>::iterator mi = mapAddressBook.find(address);
1799     mapAddressBook[address] = strName;
1800     NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
1801     if (!fFileBacked)
1802         return false;
1803     return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
1804 }
1805
1806 bool CWallet::DelAddressBookName(const CTxDestination& address)
1807 {
1808     mapAddressBook.erase(address);
1809     NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
1810     if (!fFileBacked)
1811         return false;
1812     return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
1813 }
1814
1815
1816 void CWallet::PrintWallet(const CBlock& block)
1817 {
1818     {
1819         LOCK(cs_wallet);
1820         if (block.IsProofOfWork() && mapWallet.count(block.vtx[0].GetHash()))
1821         {
1822             CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1823             printf("    mine:  %d  %d  %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1824         }
1825         if (block.IsProofOfStake() && mapWallet.count(block.vtx[1].GetHash()))
1826         {
1827             CWalletTx& wtx = mapWallet[block.vtx[1].GetHash()];
1828             printf("    stake: %d  %d  %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1829          }
1830
1831     }
1832     printf("\n");
1833 }
1834
1835 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
1836 {
1837     {
1838         LOCK(cs_wallet);
1839         map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
1840         if (mi != mapWallet.end())
1841         {
1842             wtx = (*mi).second;
1843             return true;
1844         }
1845     }
1846     return false;
1847 }
1848
1849 bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
1850 {
1851     if (fFileBacked)
1852     {
1853         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
1854             return false;
1855     }
1856     vchDefaultKey = vchPubKey;
1857     return true;
1858 }
1859
1860 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
1861 {
1862     if (!pwallet->fFileBacked)
1863         return false;
1864     strWalletFileOut = pwallet->strWalletFile;
1865     return true;
1866 }
1867
1868 //
1869 // Mark old keypool keys as used,
1870 // and generate all new keys
1871 //
1872 bool CWallet::NewKeyPool()
1873 {
1874     {
1875         LOCK(cs_wallet);
1876         CWalletDB walletdb(strWalletFile);
1877         BOOST_FOREACH(int64 nIndex, setKeyPool)
1878             walletdb.ErasePool(nIndex);
1879         setKeyPool.clear();
1880
1881         if (IsLocked())
1882             return false;
1883
1884         int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
1885         for (int i = 0; i < nKeys; i++)
1886         {
1887             int64 nIndex = i+1;
1888             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
1889             setKeyPool.insert(nIndex);
1890         }
1891         printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
1892     }
1893     return true;
1894 }
1895
1896 bool CWallet::TopUpKeyPool(unsigned int nSize)
1897 {
1898     {
1899         LOCK(cs_wallet);
1900
1901         if (IsLocked())
1902             return false;
1903
1904         CWalletDB walletdb(strWalletFile);
1905
1906         // Top up key pool
1907         unsigned int nTargetSize;
1908         if (nSize > 0)
1909             nTargetSize = nSize;
1910         else
1911             nTargetSize = max(GetArg("-keypool", 100), 0LL);
1912
1913         while (setKeyPool.size() < (nTargetSize + 1))
1914         {
1915             int64 nEnd = 1;
1916             if (!setKeyPool.empty())
1917                 nEnd = *(--setKeyPool.end()) + 1;
1918             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
1919                 throw runtime_error("TopUpKeyPool() : writing generated key failed");
1920             setKeyPool.insert(nEnd);
1921             printf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
1922         }
1923     }
1924     return true;
1925 }
1926
1927 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
1928 {
1929     nIndex = -1;
1930     keypool.vchPubKey = CPubKey();
1931     {
1932         LOCK(cs_wallet);
1933
1934         if (!IsLocked())
1935             TopUpKeyPool();
1936
1937         // Get the oldest key
1938         if(setKeyPool.empty())
1939             return;
1940
1941         CWalletDB walletdb(strWalletFile);
1942
1943         nIndex = *(setKeyPool.begin());
1944         setKeyPool.erase(setKeyPool.begin());
1945         if (!walletdb.ReadPool(nIndex, keypool))
1946             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1947         if (!HaveKey(keypool.vchPubKey.GetID()))
1948             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1949         assert(keypool.vchPubKey.IsValid());
1950         if (fDebug && GetBoolArg("-printkeypool"))
1951             printf("keypool reserve %"PRI64d"\n", nIndex);
1952     }
1953 }
1954
1955 int64 CWallet::AddReserveKey(const CKeyPool& keypool)
1956 {
1957     {
1958         LOCK2(cs_main, cs_wallet);
1959         CWalletDB walletdb(strWalletFile);
1960
1961         int64 nIndex = 1 + *(--setKeyPool.end());
1962         if (!walletdb.WritePool(nIndex, keypool))
1963             throw runtime_error("AddReserveKey() : writing added key failed");
1964         setKeyPool.insert(nIndex);
1965         return nIndex;
1966     }
1967     return -1;
1968 }
1969
1970 void CWallet::KeepKey(int64 nIndex)
1971 {
1972     // Remove from key pool
1973     if (fFileBacked)
1974     {
1975         CWalletDB walletdb(strWalletFile);
1976         walletdb.ErasePool(nIndex);
1977     }
1978     if(fDebug)
1979         printf("keypool keep %"PRI64d"\n", nIndex);
1980 }
1981
1982 void CWallet::ReturnKey(int64 nIndex)
1983 {
1984     // Return to key pool
1985     {
1986         LOCK(cs_wallet);
1987         setKeyPool.insert(nIndex);
1988     }
1989     if(fDebug)
1990         printf("keypool return %"PRI64d"\n", nIndex);
1991 }
1992
1993 bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
1994 {
1995     int64 nIndex = 0;
1996     CKeyPool keypool;
1997     {
1998         LOCK(cs_wallet);
1999         ReserveKeyFromKeyPool(nIndex, keypool);
2000         if (nIndex == -1)
2001         {
2002             if (fAllowReuse && vchDefaultKey.IsValid())
2003             {
2004                 result = vchDefaultKey;
2005                 return true;
2006             }
2007             if (IsLocked()) return false;
2008             result = GenerateNewKey();
2009             return true;
2010         }
2011         KeepKey(nIndex);
2012         result = keypool.vchPubKey;
2013     }
2014     return true;
2015 }
2016
2017 int64 CWallet::GetOldestKeyPoolTime()
2018 {
2019     int64 nIndex = 0;
2020     CKeyPool keypool;
2021     ReserveKeyFromKeyPool(nIndex, keypool);
2022     if (nIndex == -1)
2023         return GetTime();
2024     ReturnKey(nIndex);
2025     return keypool.nTime;
2026 }
2027
2028 std::map<CTxDestination, int64> CWallet::GetAddressBalances()
2029 {
2030     map<CTxDestination, int64> balances;
2031
2032     {
2033         LOCK(cs_wallet);
2034         BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
2035         {
2036             CWalletTx *pcoin = &walletEntry.second;
2037
2038             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
2039                 continue;
2040
2041             if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0)
2042                 continue;
2043
2044             int nDepth = pcoin->GetDepthInMainChain();
2045             if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
2046                 continue;
2047
2048             for (unsigned int i = 0; i < pcoin->vout.size(); i++)
2049             {
2050                 CTxDestination addr;
2051                 if (!IsMine(pcoin->vout[i]))
2052                     continue;
2053                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
2054                     continue;
2055
2056                 int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
2057
2058                 if (!balances.count(addr))
2059                     balances[addr] = 0;
2060                 balances[addr] += n;
2061             }
2062         }
2063     }
2064
2065     return balances;
2066 }
2067
2068 set< set<CTxDestination> > CWallet::GetAddressGroupings()
2069 {
2070     set< set<CTxDestination> > groupings;
2071     set<CTxDestination> grouping;
2072
2073     BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
2074     {
2075         CWalletTx *pcoin = &walletEntry.second;
2076
2077         if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0]))
2078         {
2079             // group all input addresses with each other
2080             BOOST_FOREACH(CTxIn txin, pcoin->vin)
2081             {
2082                 CTxDestination address;
2083                 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
2084                     continue;
2085                 grouping.insert(address);
2086             }
2087
2088             // group change with input addresses
2089             BOOST_FOREACH(CTxOut txout, pcoin->vout)
2090                 if (IsChange(txout))
2091                 {
2092                     CWalletTx tx = mapWallet[pcoin->vin[0].prevout.hash];
2093                     CTxDestination txoutAddr;
2094                     if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
2095                         continue;
2096                     grouping.insert(txoutAddr);
2097                 }
2098             groupings.insert(grouping);
2099             grouping.clear();
2100         }
2101
2102         // group lone addrs by themselves
2103         for (unsigned int i = 0; i < pcoin->vout.size(); i++)
2104             if (IsMine(pcoin->vout[i]))
2105             {
2106                 CTxDestination address;
2107                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
2108                     continue;
2109                 grouping.insert(address);
2110                 groupings.insert(grouping);
2111                 grouping.clear();
2112             }
2113     }
2114
2115     set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
2116     map< CTxDestination, set<CTxDestination>* > setmap;  // map addresses to the unique group containing it
2117     BOOST_FOREACH(set<CTxDestination> grouping, groupings)
2118     {
2119         // make a set of all the groups hit by this new group
2120         set< set<CTxDestination>* > hits;
2121         map< CTxDestination, set<CTxDestination>* >::iterator it;
2122         BOOST_FOREACH(CTxDestination address, grouping)
2123             if ((it = setmap.find(address)) != setmap.end())
2124                 hits.insert((*it).second);
2125
2126         // merge all hit groups into a new single group and delete old groups
2127         set<CTxDestination>* merged = new set<CTxDestination>(grouping);
2128         BOOST_FOREACH(set<CTxDestination>* hit, hits)
2129         {
2130             merged->insert(hit->begin(), hit->end());
2131             uniqueGroupings.erase(hit);
2132             delete hit;
2133         }
2134         uniqueGroupings.insert(merged);
2135
2136         // update setmap
2137         BOOST_FOREACH(CTxDestination element, *merged)
2138             setmap[element] = merged;
2139     }
2140
2141     set< set<CTxDestination> > ret;
2142     BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
2143     {
2144         ret.insert(*uniqueGrouping);
2145         delete uniqueGrouping;
2146     }
2147
2148     return ret;
2149 }
2150
2151 // ppcoin: check 'spent' consistency between wallet and txindex
2152 // ppcoin: fix wallet spent state according to txindex
2153 void CWallet::FixSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion, bool fCheckOnly)
2154 {
2155     nMismatchFound = 0;
2156     nBalanceInQuestion = 0;
2157
2158     LOCK(cs_wallet);
2159     vector<CWalletTx*> vCoins;
2160     vCoins.reserve(mapWallet.size());
2161     for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2162         vCoins.push_back(&(*it).second);
2163
2164     CTxDB txdb("r");
2165     BOOST_FOREACH(CWalletTx* pcoin, vCoins)
2166     {
2167         // Find the corresponding transaction index
2168         CTxIndex txindex;
2169         if (!txdb.ReadTxIndex(pcoin->GetHash(), txindex))
2170             continue;
2171         for (unsigned int n=0; n < pcoin->vout.size(); n++)
2172         {
2173             if (IsMine(pcoin->vout[n]) && pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
2174             {
2175                 printf("FixSpentCoins found lost coin %sppc %s[%d], %s\n",
2176                     FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
2177                 nMismatchFound++;
2178                 nBalanceInQuestion += pcoin->vout[n].nValue;
2179                 if (!fCheckOnly)
2180                 {
2181                     pcoin->MarkUnspent(n);
2182                     pcoin->WriteToDisk();
2183                 }
2184             }
2185             else if (IsMine(pcoin->vout[n]) && !pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
2186             {
2187                 printf("FixSpentCoins found spent coin %sppc %s[%d], %s\n",
2188                     FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
2189                 nMismatchFound++;
2190                 nBalanceInQuestion += pcoin->vout[n].nValue;
2191                 if (!fCheckOnly)
2192                 {
2193                     pcoin->MarkSpent(n);
2194                     pcoin->WriteToDisk();
2195                 }
2196             }
2197         }
2198     }
2199 }
2200
2201 // ppcoin: disable transaction (only for coinstake)
2202 void CWallet::DisableTransaction(const CTransaction &tx)
2203 {
2204     if (!tx.IsCoinStake() || !IsFromMe(tx))
2205         return; // only disconnecting coinstake requires marking input unspent
2206
2207     LOCK(cs_wallet);
2208     BOOST_FOREACH(const CTxIn& txin, tx.vin)
2209     {
2210         map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
2211         if (mi != mapWallet.end())
2212         {
2213             CWalletTx& prev = (*mi).second;
2214             if (txin.prevout.n < prev.vout.size() && IsMine(prev.vout[txin.prevout.n]))
2215             {
2216                 prev.MarkUnspent(txin.prevout.n);
2217                 prev.WriteToDisk();
2218             }
2219         }
2220     }
2221 }
2222
2223 CPubKey CReserveKey::GetReservedKey()
2224 {
2225     if (nIndex == -1)
2226     {
2227         CKeyPool keypool;
2228         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
2229         if (nIndex != -1)
2230             vchPubKey = keypool.vchPubKey;
2231         else
2232         {
2233             printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
2234             vchPubKey = pwallet->vchDefaultKey;
2235         }
2236     }
2237     assert(vchPubKey.IsValid());
2238     return vchPubKey;
2239 }
2240
2241 void CReserveKey::KeepKey()
2242 {
2243     if (nIndex != -1)
2244         pwallet->KeepKey(nIndex);
2245     nIndex = -1;
2246     vchPubKey = CPubKey();
2247 }
2248
2249 void CReserveKey::ReturnKey()
2250 {
2251     if (nIndex != -1)
2252         pwallet->ReturnKey(nIndex);
2253     nIndex = -1;
2254     vchPubKey = CPubKey();
2255 }
2256
2257 void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
2258 {
2259     setAddress.clear();
2260
2261     CWalletDB walletdb(strWalletFile);
2262
2263     LOCK2(cs_main, cs_wallet);
2264     BOOST_FOREACH(const int64& id, setKeyPool)
2265     {
2266         CKeyPool keypool;
2267         if (!walletdb.ReadPool(id, keypool))
2268             throw runtime_error("GetAllReserveKeyHashes() : read failed");
2269         assert(keypool.vchPubKey.IsValid());
2270         CKeyID keyID = keypool.vchPubKey.GetID();
2271         if (!HaveKey(keyID))
2272             throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
2273         setAddress.insert(keyID);
2274     }
2275 }
2276
2277 void CWallet::UpdatedTransaction(const uint256 &hashTx)
2278 {
2279     {
2280         LOCK(cs_wallet);
2281         // Only notify UI if this transaction is in this wallet
2282         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
2283         if (mi != mapWallet.end())
2284             NotifyTransactionChanged(this, hashTx, CT_UPDATED);
2285     }
2286 }
2287
2288 void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
2289     mapKeyBirth.clear();
2290
2291     // get birth times for keys with metadata
2292     for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
2293         if (it->second.nCreateTime)
2294             mapKeyBirth[it->first] = it->second.nCreateTime;
2295
2296     // map in which we'll infer heights of other keys
2297     CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
2298     std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
2299     std::set<CKeyID> setKeys;
2300     GetKeys(setKeys);
2301     BOOST_FOREACH(const CKeyID &keyid, setKeys) {
2302         if (mapKeyBirth.count(keyid) == 0)
2303             mapKeyFirstBlock[keyid] = pindexMax;
2304     }
2305     setKeys.clear();
2306
2307     // if there are no such keys, we're done
2308     if (mapKeyFirstBlock.empty())
2309         return;
2310
2311     // find first block that affects those keys, if there are any left
2312     std::vector<CKeyID> vAffected;
2313     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
2314         // iterate over all wallet transactions...
2315         const CWalletTx &wtx = (*it).second;
2316         std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
2317         if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
2318             // ... which are already in a block
2319             int nHeight = blit->second->nHeight;
2320             BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
2321                 // iterate over all their outputs
2322                 ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
2323                 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
2324                     // ... and all their affected keys
2325                     std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
2326                     if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
2327                         rit->second = blit->second;
2328                 }
2329                 vAffected.clear();
2330             }
2331         }
2332     }
2333
2334     // Extract block timestamps for those keys
2335     for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
2336         mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
2337 }