35d24b52a38611787fed5768964080b246dc6a8d
[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 generation power
1372 uint64 CWallet::GetStakeMintPower(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("GetStakeMintPower : 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         switch(mode)
1406         {
1407             case STAKE_NORMAL:
1408                 // Do not count input that is still less than 30 days old
1409                 if (pcoin.first->nTime + nStakeMinAge > GetTime())
1410                     continue;
1411             break;
1412             case STAKE_MAXWEIGHT:
1413                 // Do not count input that is still less than 90 days old
1414                 if (pcoin.first->nTime + nStakeMaxAge > GetTime())
1415                     continue;
1416             break;
1417             case STAKE_MINWEIGHT:
1418                 // Count only inputs with suitable age (from 30 to 90 days old)
1419                 if (pcoin.first->nTime + nStakeMaxAge < GetTime())
1420                     continue;
1421                 if (pcoin.first->nTime + nStakeMinAge > GetTime())
1422                     continue;
1423             break;
1424             case STAKE_BELOWMIN:
1425                 // Count only inputs with suitable age (less than 30 days old)
1426                 if (pcoin.first->nTime + nStakeMinAge < GetTime())
1427                     continue;
1428             break;
1429         }
1430
1431         CBigNum bnCentSecond = CBigNum(pcoin.first->vout[pcoin.second].nValue) * (GetTime()-pcoin.first->nTime) / CENT;
1432         CBigNum bnCoinDay = bnCentSecond * CENT / COIN / (24 * 60 * 60);
1433
1434
1435         nCoinAge += bnCoinDay.getuint64();
1436     }
1437
1438     if (fDebug && GetBoolArg("-printcoinage"))
1439         printf("StakePower bnCoinDay=%"PRI64d"\n", nCoinAge);
1440
1441     return nCoinAge;
1442 }
1443
1444 // ppcoin: create coin stake transaction
1445 bool CWallet::CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64 nSearchInterval, CTransaction& txNew)
1446 {
1447     // The following split & combine thresholds are important to security
1448     // Should not be adjusted if you don't understand the consequences
1449     static unsigned int nStakeSplitAge = (60 * 60 * 24 * 90);
1450     int64 nCombineThreshold = GetProofOfWorkReward(GetLastBlockIndex(pindexBest, false)->nBits) / 3;
1451
1452     CBigNum bnTargetPerCoinDay;
1453     bnTargetPerCoinDay.SetCompact(nBits);
1454
1455     LOCK2(cs_main, cs_wallet);
1456     txNew.vin.clear();
1457     txNew.vout.clear();
1458     // Mark coin stake transaction
1459     CScript scriptEmpty;
1460     scriptEmpty.clear();
1461     txNew.vout.push_back(CTxOut(0, scriptEmpty));
1462     // Choose coins to use
1463     int64 nBalance = GetBalance();
1464     int64 nReserveBalance = 0;
1465     if (mapArgs.count("-reservebalance") && !ParseMoney(mapArgs["-reservebalance"], nReserveBalance))
1466         return error("CreateCoinStake : invalid reserve balance amount");
1467     if (nBalance <= nReserveBalance)
1468         return false;
1469     set<pair<const CWalletTx*,unsigned int> > setCoins;
1470     vector<const CWalletTx*> vwtxPrev;
1471     int64 nValueIn = 0;
1472     if (!SelectCoins(nBalance - nReserveBalance, txNew.nTime, setCoins, nValueIn))
1473         return false;
1474     if (setCoins.empty())
1475         return false;
1476     int64 nCredit = 0;
1477     CScript scriptPubKeyKernel;
1478     BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1479     {
1480         CTxDB txdb("r");
1481         CTxIndex txindex;
1482         if (!txdb.ReadTxIndex(pcoin.first->GetHash(), txindex))
1483             continue;
1484
1485         // Read block header
1486         CBlock block;
1487         if (!block.ReadFromDisk(txindex.pos.nFile, txindex.pos.nBlockPos, false))
1488             continue;
1489         static int nMaxStakeSearchInterval = 60;
1490         if (block.GetBlockTime() + nStakeMinAge > txNew.nTime - nMaxStakeSearchInterval)
1491             continue; // only count coins meeting min age requirement
1492
1493         bool fKernelFound = false;
1494         for (unsigned int n=0; n<min(nSearchInterval,(int64)nMaxStakeSearchInterval) && !fKernelFound && !fShutdown; n++)
1495         {
1496             // Search backward in time from the given txNew timestamp 
1497             // Search nSearchInterval seconds back up to nMaxStakeSearchInterval
1498             uint256 hashProofOfStake = 0;
1499             COutPoint prevoutStake = COutPoint(pcoin.first->GetHash(), pcoin.second);
1500             if (CheckStakeKernelHash(nBits, block, txindex.pos.nTxPos - txindex.pos.nBlockPos, *pcoin.first, prevoutStake, txNew.nTime - n, hashProofOfStake))
1501             {
1502                 // Found a kernel
1503                 if (fDebug && GetBoolArg("-printcoinstake"))
1504                     printf("CreateCoinStake : kernel found\n");
1505                 vector<valtype> vSolutions;
1506                 txnouttype whichType;
1507                 CScript scriptPubKeyOut;
1508                 scriptPubKeyKernel = pcoin.first->vout[pcoin.second].scriptPubKey;
1509                 if (!Solver(scriptPubKeyKernel, whichType, vSolutions))
1510                 {
1511                     if (fDebug && GetBoolArg("-printcoinstake"))
1512                         printf("CreateCoinStake : failed to parse kernel\n");
1513                     break;
1514                 }
1515                 if (fDebug && GetBoolArg("-printcoinstake"))
1516                     printf("CreateCoinStake : parsed kernel type=%d\n", whichType);
1517                 if (whichType != TX_PUBKEY && whichType != TX_PUBKEYHASH)
1518                 {
1519                     if (fDebug && GetBoolArg("-printcoinstake"))
1520                         printf("CreateCoinStake : no support for kernel type=%d\n", whichType);
1521                     break;  // only support pay to public key and pay to address
1522                 }
1523                 if (whichType == TX_PUBKEYHASH) // pay to address type
1524                 {
1525                     // convert to pay to public key type
1526                     CKey key;
1527                     if (!keystore.GetKey(uint160(vSolutions[0]), key))
1528                     {
1529                         if (fDebug && GetBoolArg("-printcoinstake"))
1530                             printf("CreateCoinStake : failed to get key for kernel type=%d\n", whichType);
1531                         break;  // unable to find corresponding public key
1532                     }
1533                     scriptPubKeyOut << key.GetPubKey() << OP_CHECKSIG;
1534                 }
1535                 else
1536                     scriptPubKeyOut = scriptPubKeyKernel;
1537
1538                 txNew.nTime -= n; 
1539                 txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
1540                 nCredit += pcoin.first->vout[pcoin.second].nValue;
1541                 vwtxPrev.push_back(pcoin.first);
1542                 txNew.vout.push_back(CTxOut(0, scriptPubKeyOut));
1543                 if (block.GetBlockTime() + nStakeSplitAge > txNew.nTime)
1544                     txNew.vout.push_back(CTxOut(0, scriptPubKeyOut)); //split stake
1545                 if (fDebug && GetBoolArg("-printcoinstake"))
1546                     printf("CreateCoinStake : added kernel type=%d\n", whichType);
1547                 fKernelFound = true;
1548                 break;
1549             }
1550         }
1551         if (fKernelFound || fShutdown)
1552             break; // if kernel is found stop searching
1553     }
1554     if (nCredit == 0 || nCredit > nBalance - nReserveBalance)
1555         return false;
1556     BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
1557     {
1558         // Attempt to add more inputs
1559         // Only add coins of the same key/address as kernel
1560         if (txNew.vout.size() == 2 && ((pcoin.first->vout[pcoin.second].scriptPubKey == scriptPubKeyKernel || pcoin.first->vout[pcoin.second].scriptPubKey == txNew.vout[1].scriptPubKey))
1561             && pcoin.first->GetHash() != txNew.vin[0].prevout.hash)
1562         {
1563             // Stop adding more inputs if already too many inputs
1564             if (txNew.vin.size() >= 100)
1565                 break;
1566             // Stop adding more inputs if value is already pretty significant
1567             if (nCredit > nCombineThreshold)
1568                 break;
1569             // Stop adding inputs if reached reserve limit
1570             if (nCredit + pcoin.first->vout[pcoin.second].nValue > nBalance - nReserveBalance)
1571                 break;
1572             // Do not add additional significant input
1573             if (pcoin.first->vout[pcoin.second].nValue > nCombineThreshold)
1574                 continue;
1575             // Do not add input that is still too young
1576             if (pcoin.first->nTime + nStakeMaxAge > txNew.nTime)
1577                 continue;
1578             txNew.vin.push_back(CTxIn(pcoin.first->GetHash(), pcoin.second));
1579             nCredit += pcoin.first->vout[pcoin.second].nValue;
1580             vwtxPrev.push_back(pcoin.first);
1581         }
1582     }
1583     // Calculate coin age reward
1584     {
1585         uint64 nCoinAge;
1586         CTxDB txdb("r");
1587         if (!txNew.GetCoinAge(txdb, nCoinAge))
1588             return error("CreateCoinStake : failed to calculate coin age");
1589         nCredit += GetProofOfStakeReward(nCoinAge, nBits, txNew.nTime);
1590     }
1591
1592     int64 nMinFee = 0;
1593     loop
1594     {
1595         // Set output amount
1596         if (txNew.vout.size() == 3)
1597         {
1598             txNew.vout[1].nValue = ((nCredit - nMinFee) / 2 / CENT) * CENT;
1599             txNew.vout[2].nValue = nCredit - nMinFee - txNew.vout[1].nValue;
1600         }
1601         else
1602             txNew.vout[1].nValue = nCredit - nMinFee;
1603
1604         // Sign
1605         int nIn = 0;
1606         BOOST_FOREACH(const CWalletTx* pcoin, vwtxPrev)
1607         {
1608             if (!SignSignature(*this, *pcoin, txNew, nIn++))
1609                 return error("CreateCoinStake : failed to sign coinstake");
1610         }
1611
1612         // Limit size
1613         unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
1614         if (nBytes >= MAX_BLOCK_SIZE_GEN/5)
1615             return error("CreateCoinStake : exceeded coinstake size limit");
1616
1617         // Check enough fee is paid
1618         if (nMinFee < txNew.GetMinFee() - MIN_TX_FEE)
1619         {
1620             nMinFee = txNew.GetMinFee() - MIN_TX_FEE;
1621             continue; // try signing again
1622         }
1623         else
1624         {
1625             if (fDebug && GetBoolArg("-printfee"))
1626                 printf("CreateCoinStake : fee for coinstake %s\n", FormatMoney(nMinFee).c_str());
1627             break;
1628         }
1629     }
1630
1631     // Successfully generated coinstake
1632     return true;
1633 }
1634
1635
1636 // Call after CreateTransaction unless you want to abort
1637 bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
1638 {
1639     {
1640         LOCK2(cs_main, cs_wallet);
1641         printf("CommitTransaction:\n%s", wtxNew.ToString().c_str());
1642         {
1643             // This is only to keep the database open to defeat the auto-flush for the
1644             // duration of this scope.  This is the only place where this optimization
1645             // maybe makes sense; please don't do it anywhere else.
1646             CWalletDB* pwalletdb = fFileBacked ? new CWalletDB(strWalletFile,"r") : NULL;
1647
1648             // Take key pair from key pool so it won't be used again
1649             reservekey.KeepKey();
1650
1651             // Add tx to wallet, because if it has change it's also ours,
1652             // otherwise just for transaction history.
1653             AddToWallet(wtxNew);
1654
1655             // Mark old coins as spent
1656             set<CWalletTx*> setCoins;
1657             BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
1658             {
1659                 CWalletTx &coin = mapWallet[txin.prevout.hash];
1660                 coin.BindWallet(this);
1661                 coin.MarkSpent(txin.prevout.n);
1662                 coin.WriteToDisk();
1663                 NotifyTransactionChanged(this, coin.GetHash(), CT_UPDATED);
1664             }
1665
1666             if (fFileBacked)
1667                 delete pwalletdb;
1668         }
1669
1670         // Track how many getdata requests our transaction gets
1671         mapRequestCount[wtxNew.GetHash()] = 0;
1672
1673         // Broadcast
1674         if (!wtxNew.AcceptToMemoryPool())
1675         {
1676             // This must not fail. The transaction has already been signed and recorded.
1677             printf("CommitTransaction() : Error: Transaction not valid");
1678             return false;
1679         }
1680         wtxNew.RelayWalletTransaction();
1681     }
1682     return true;
1683 }
1684
1685
1686
1687
1688 string CWallet::SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1689 {
1690     CReserveKey reservekey(this);
1691     int64 nFeeRequired;
1692
1693     if (IsLocked())
1694     {
1695         string strError = _("Error: Wallet locked, unable to create transaction  ");
1696         printf("SendMoney() : %s", strError.c_str());
1697         return strError;
1698     }
1699     if (fWalletUnlockMintOnly)
1700     {
1701         string strError = _("Error: Wallet unlocked for block minting only, unable to create transaction.");
1702         printf("SendMoney() : %s", strError.c_str());
1703         return strError;
1704     }
1705     if (!CreateTransaction(scriptPubKey, nValue, wtxNew, reservekey, nFeeRequired))
1706     {
1707         string strError;
1708         if (nValue + nFeeRequired > GetBalance())
1709             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());
1710         else
1711             strError = _("Error: Transaction creation failed  ");
1712         printf("SendMoney() : %s", strError.c_str());
1713         return strError;
1714     }
1715
1716     if (fAskFee && !uiInterface.ThreadSafeAskFee(nFeeRequired, _("Sending...")))
1717         return "ABORTED";
1718
1719     if (!CommitTransaction(wtxNew, reservekey))
1720         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.");
1721
1722     return "";
1723 }
1724
1725
1726
1727 string CWallet::SendMoneyToDestination(const CTxDestination& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee)
1728 {
1729     // Check amount
1730     if (nValue <= 0)
1731         return _("Invalid amount");
1732     if (nValue + nTransactionFee > GetBalance())
1733         return _("Insufficient funds");
1734
1735     // Parse Bitcoin address
1736     CScript scriptPubKey;
1737     scriptPubKey.SetDestination(address);
1738
1739     return SendMoney(scriptPubKey, nValue, wtxNew, fAskFee);
1740 }
1741
1742
1743
1744
1745 DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
1746 {
1747     if (!fFileBacked)
1748         return DB_LOAD_OK;
1749     fFirstRunRet = false;
1750     DBErrors nLoadWalletRet = CWalletDB(strWalletFile,"cr+").LoadWallet(this);
1751     if (nLoadWalletRet == DB_NEED_REWRITE)
1752     {
1753         if (CDB::Rewrite(strWalletFile, "\x04pool"))
1754         {
1755             setKeyPool.clear();
1756             // Note: can't top-up keypool here, because wallet is locked.
1757             // User will be prompted to unlock wallet the next operation
1758             // the requires a new key.
1759         }
1760     }
1761
1762     if (nLoadWalletRet != DB_LOAD_OK)
1763         return nLoadWalletRet;
1764     fFirstRunRet = !vchDefaultKey.IsValid();
1765
1766     NewThread(ThreadFlushWalletDB, &strWalletFile);
1767     return DB_LOAD_OK;
1768 }
1769
1770
1771 bool CWallet::SetAddressBookName(const CTxDestination& address, const string& strName)
1772 {
1773     std::map<CTxDestination, std::string>::iterator mi = mapAddressBook.find(address);
1774     mapAddressBook[address] = strName;
1775     NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
1776     if (!fFileBacked)
1777         return false;
1778     return CWalletDB(strWalletFile).WriteName(CBitcoinAddress(address).ToString(), strName);
1779 }
1780
1781 bool CWallet::DelAddressBookName(const CTxDestination& address)
1782 {
1783     mapAddressBook.erase(address);
1784     NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
1785     if (!fFileBacked)
1786         return false;
1787     return CWalletDB(strWalletFile).EraseName(CBitcoinAddress(address).ToString());
1788 }
1789
1790
1791 void CWallet::PrintWallet(const CBlock& block)
1792 {
1793     {
1794         LOCK(cs_wallet);
1795         if (block.IsProofOfWork() && mapWallet.count(block.vtx[0].GetHash()))
1796         {
1797             CWalletTx& wtx = mapWallet[block.vtx[0].GetHash()];
1798             printf("    mine:  %d  %d  %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1799         }
1800         if (block.IsProofOfStake() && mapWallet.count(block.vtx[1].GetHash()))
1801         {
1802             CWalletTx& wtx = mapWallet[block.vtx[1].GetHash()];
1803             printf("    stake: %d  %d  %"PRI64d"", wtx.GetDepthInMainChain(), wtx.GetBlocksToMaturity(), wtx.GetCredit());
1804          }
1805
1806     }
1807     printf("\n");
1808 }
1809
1810 bool CWallet::GetTransaction(const uint256 &hashTx, CWalletTx& wtx)
1811 {
1812     {
1813         LOCK(cs_wallet);
1814         map<uint256, CWalletTx>::iterator mi = mapWallet.find(hashTx);
1815         if (mi != mapWallet.end())
1816         {
1817             wtx = (*mi).second;
1818             return true;
1819         }
1820     }
1821     return false;
1822 }
1823
1824 bool CWallet::SetDefaultKey(const CPubKey &vchPubKey)
1825 {
1826     if (fFileBacked)
1827     {
1828         if (!CWalletDB(strWalletFile).WriteDefaultKey(vchPubKey))
1829             return false;
1830     }
1831     vchDefaultKey = vchPubKey;
1832     return true;
1833 }
1834
1835 bool GetWalletFile(CWallet* pwallet, string &strWalletFileOut)
1836 {
1837     if (!pwallet->fFileBacked)
1838         return false;
1839     strWalletFileOut = pwallet->strWalletFile;
1840     return true;
1841 }
1842
1843 //
1844 // Mark old keypool keys as used,
1845 // and generate all new keys
1846 //
1847 bool CWallet::NewKeyPool()
1848 {
1849     {
1850         LOCK(cs_wallet);
1851         CWalletDB walletdb(strWalletFile);
1852         BOOST_FOREACH(int64 nIndex, setKeyPool)
1853             walletdb.ErasePool(nIndex);
1854         setKeyPool.clear();
1855
1856         if (IsLocked())
1857             return false;
1858
1859         int64 nKeys = max(GetArg("-keypool", 100), (int64)0);
1860         for (int i = 0; i < nKeys; i++)
1861         {
1862             int64 nIndex = i+1;
1863             walletdb.WritePool(nIndex, CKeyPool(GenerateNewKey()));
1864             setKeyPool.insert(nIndex);
1865         }
1866         printf("CWallet::NewKeyPool wrote %"PRI64d" new keys\n", nKeys);
1867     }
1868     return true;
1869 }
1870
1871 bool CWallet::TopUpKeyPool()
1872 {
1873     {
1874         LOCK(cs_wallet);
1875
1876         if (IsLocked())
1877             return false;
1878
1879         CWalletDB walletdb(strWalletFile);
1880
1881         // Top up key pool
1882         unsigned int nTargetSize = max(GetArg("-keypool", 100), 0LL);
1883         while (setKeyPool.size() < (nTargetSize + 1))
1884         {
1885             int64 nEnd = 1;
1886             if (!setKeyPool.empty())
1887                 nEnd = *(--setKeyPool.end()) + 1;
1888             if (!walletdb.WritePool(nEnd, CKeyPool(GenerateNewKey())))
1889                 throw runtime_error("TopUpKeyPool() : writing generated key failed");
1890             setKeyPool.insert(nEnd);
1891             printf("keypool added key %"PRI64d", size=%"PRIszu"\n", nEnd, setKeyPool.size());
1892         }
1893     }
1894     return true;
1895 }
1896
1897 void CWallet::ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool)
1898 {
1899     nIndex = -1;
1900     keypool.vchPubKey = CPubKey();
1901     {
1902         LOCK(cs_wallet);
1903
1904         if (!IsLocked())
1905             TopUpKeyPool();
1906
1907         // Get the oldest key
1908         if(setKeyPool.empty())
1909             return;
1910
1911         CWalletDB walletdb(strWalletFile);
1912
1913         nIndex = *(setKeyPool.begin());
1914         setKeyPool.erase(setKeyPool.begin());
1915         if (!walletdb.ReadPool(nIndex, keypool))
1916             throw runtime_error("ReserveKeyFromKeyPool() : read failed");
1917         if (!HaveKey(keypool.vchPubKey.GetID()))
1918             throw runtime_error("ReserveKeyFromKeyPool() : unknown key in key pool");
1919         assert(keypool.vchPubKey.IsValid());
1920         if (fDebug && GetBoolArg("-printkeypool"))
1921             printf("keypool reserve %"PRI64d"\n", nIndex);
1922     }
1923 }
1924
1925 int64 CWallet::AddReserveKey(const CKeyPool& keypool)
1926 {
1927     {
1928         LOCK2(cs_main, cs_wallet);
1929         CWalletDB walletdb(strWalletFile);
1930
1931         int64 nIndex = 1 + *(--setKeyPool.end());
1932         if (!walletdb.WritePool(nIndex, keypool))
1933             throw runtime_error("AddReserveKey() : writing added key failed");
1934         setKeyPool.insert(nIndex);
1935         return nIndex;
1936     }
1937     return -1;
1938 }
1939
1940 void CWallet::KeepKey(int64 nIndex)
1941 {
1942     // Remove from key pool
1943     if (fFileBacked)
1944     {
1945         CWalletDB walletdb(strWalletFile);
1946         walletdb.ErasePool(nIndex);
1947     }
1948     if(fDebug)
1949         printf("keypool keep %"PRI64d"\n", nIndex);
1950 }
1951
1952 void CWallet::ReturnKey(int64 nIndex)
1953 {
1954     // Return to key pool
1955     {
1956         LOCK(cs_wallet);
1957         setKeyPool.insert(nIndex);
1958     }
1959     if(fDebug)
1960         printf("keypool return %"PRI64d"\n", nIndex);
1961 }
1962
1963 bool CWallet::GetKeyFromPool(CPubKey& result, bool fAllowReuse)
1964 {
1965     int64 nIndex = 0;
1966     CKeyPool keypool;
1967     {
1968         LOCK(cs_wallet);
1969         ReserveKeyFromKeyPool(nIndex, keypool);
1970         if (nIndex == -1)
1971         {
1972             if (fAllowReuse && vchDefaultKey.IsValid())
1973             {
1974                 result = vchDefaultKey;
1975                 return true;
1976             }
1977             if (IsLocked()) return false;
1978             result = GenerateNewKey();
1979             return true;
1980         }
1981         KeepKey(nIndex);
1982         result = keypool.vchPubKey;
1983     }
1984     return true;
1985 }
1986
1987 int64 CWallet::GetOldestKeyPoolTime()
1988 {
1989     int64 nIndex = 0;
1990     CKeyPool keypool;
1991     ReserveKeyFromKeyPool(nIndex, keypool);
1992     if (nIndex == -1)
1993         return GetTime();
1994     ReturnKey(nIndex);
1995     return keypool.nTime;
1996 }
1997
1998 std::map<CTxDestination, int64> CWallet::GetAddressBalances()
1999 {
2000     map<CTxDestination, int64> balances;
2001
2002     {
2003         LOCK(cs_wallet);
2004         BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
2005         {
2006             CWalletTx *pcoin = &walletEntry.second;
2007
2008             if (!pcoin->IsFinal() || !pcoin->IsConfirmed())
2009                 continue;
2010
2011             if ((pcoin->IsCoinBase() || pcoin->IsCoinStake()) && pcoin->GetBlocksToMaturity() > 0)
2012                 continue;
2013
2014             int nDepth = pcoin->GetDepthInMainChain();
2015             if (nDepth < (pcoin->IsFromMe() ? 0 : 1))
2016                 continue;
2017
2018             for (unsigned int i = 0; i < pcoin->vout.size(); i++)
2019             {
2020                 CTxDestination addr;
2021                 if (!IsMine(pcoin->vout[i]))
2022                     continue;
2023                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
2024                     continue;
2025
2026                 int64 n = pcoin->IsSpent(i) ? 0 : pcoin->vout[i].nValue;
2027
2028                 if (!balances.count(addr))
2029                     balances[addr] = 0;
2030                 balances[addr] += n;
2031             }
2032         }
2033     }
2034
2035     return balances;
2036 }
2037
2038 set< set<CTxDestination> > CWallet::GetAddressGroupings()
2039 {
2040     set< set<CTxDestination> > groupings;
2041     set<CTxDestination> grouping;
2042
2043     BOOST_FOREACH(PAIRTYPE(uint256, CWalletTx) walletEntry, mapWallet)
2044     {
2045         CWalletTx *pcoin = &walletEntry.second;
2046
2047         if (pcoin->vin.size() > 0 && IsMine(pcoin->vin[0]))
2048         {
2049             // group all input addresses with each other
2050             BOOST_FOREACH(CTxIn txin, pcoin->vin)
2051             {
2052                 CTxDestination address;
2053                 if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
2054                     continue;
2055                 grouping.insert(address);
2056             }
2057
2058             // group change with input addresses
2059             BOOST_FOREACH(CTxOut txout, pcoin->vout)
2060                 if (IsChange(txout))
2061                 {
2062                     CWalletTx tx = mapWallet[pcoin->vin[0].prevout.hash];
2063                     CTxDestination txoutAddr;
2064                     if(!ExtractDestination(txout.scriptPubKey, txoutAddr))
2065                         continue;
2066                     grouping.insert(txoutAddr);
2067                 }
2068             groupings.insert(grouping);
2069             grouping.clear();
2070         }
2071
2072         // group lone addrs by themselves
2073         for (unsigned int i = 0; i < pcoin->vout.size(); i++)
2074             if (IsMine(pcoin->vout[i]))
2075             {
2076                 CTxDestination address;
2077                 if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
2078                     continue;
2079                 grouping.insert(address);
2080                 groupings.insert(grouping);
2081                 grouping.clear();
2082             }
2083     }
2084
2085     set< set<CTxDestination>* > uniqueGroupings; // a set of pointers to groups of addresses
2086     map< CTxDestination, set<CTxDestination>* > setmap;  // map addresses to the unique group containing it
2087     BOOST_FOREACH(set<CTxDestination> grouping, groupings)
2088     {
2089         // make a set of all the groups hit by this new group
2090         set< set<CTxDestination>* > hits;
2091         map< CTxDestination, set<CTxDestination>* >::iterator it;
2092         BOOST_FOREACH(CTxDestination address, grouping)
2093             if ((it = setmap.find(address)) != setmap.end())
2094                 hits.insert((*it).second);
2095
2096         // merge all hit groups into a new single group and delete old groups
2097         set<CTxDestination>* merged = new set<CTxDestination>(grouping);
2098         BOOST_FOREACH(set<CTxDestination>* hit, hits)
2099         {
2100             merged->insert(hit->begin(), hit->end());
2101             uniqueGroupings.erase(hit);
2102             delete hit;
2103         }
2104         uniqueGroupings.insert(merged);
2105
2106         // update setmap
2107         BOOST_FOREACH(CTxDestination element, *merged)
2108             setmap[element] = merged;
2109     }
2110
2111     set< set<CTxDestination> > ret;
2112     BOOST_FOREACH(set<CTxDestination>* uniqueGrouping, uniqueGroupings)
2113     {
2114         ret.insert(*uniqueGrouping);
2115         delete uniqueGrouping;
2116     }
2117
2118     return ret;
2119 }
2120
2121 // ppcoin: check 'spent' consistency between wallet and txindex
2122 // ppcoin: fix wallet spent state according to txindex
2123 void CWallet::FixSpentCoins(int& nMismatchFound, int64& nBalanceInQuestion, bool fCheckOnly)
2124 {
2125     nMismatchFound = 0;
2126     nBalanceInQuestion = 0;
2127
2128     LOCK(cs_wallet);
2129     vector<CWalletTx*> vCoins;
2130     vCoins.reserve(mapWallet.size());
2131     for (map<uint256, CWalletTx>::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it)
2132         vCoins.push_back(&(*it).second);
2133
2134     CTxDB txdb("r");
2135     BOOST_FOREACH(CWalletTx* pcoin, vCoins)
2136     {
2137         // Find the corresponding transaction index
2138         CTxIndex txindex;
2139         if (!txdb.ReadTxIndex(pcoin->GetHash(), txindex))
2140             continue;
2141         for (unsigned int n=0; n < pcoin->vout.size(); n++)
2142         {
2143             if (IsMine(pcoin->vout[n]) && pcoin->IsSpent(n) && (txindex.vSpent.size() <= n || txindex.vSpent[n].IsNull()))
2144             {
2145                 printf("FixSpentCoins found lost coin %sppc %s[%d], %s\n",
2146                     FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
2147                 nMismatchFound++;
2148                 nBalanceInQuestion += pcoin->vout[n].nValue;
2149                 if (!fCheckOnly)
2150                 {
2151                     pcoin->MarkUnspent(n);
2152                     pcoin->WriteToDisk();
2153                 }
2154             }
2155             else if (IsMine(pcoin->vout[n]) && !pcoin->IsSpent(n) && (txindex.vSpent.size() > n && !txindex.vSpent[n].IsNull()))
2156             {
2157                 printf("FixSpentCoins found spent coin %sppc %s[%d], %s\n",
2158                     FormatMoney(pcoin->vout[n].nValue).c_str(), pcoin->GetHash().ToString().c_str(), n, fCheckOnly? "repair not attempted" : "repairing");
2159                 nMismatchFound++;
2160                 nBalanceInQuestion += pcoin->vout[n].nValue;
2161                 if (!fCheckOnly)
2162                 {
2163                     pcoin->MarkSpent(n);
2164                     pcoin->WriteToDisk();
2165                 }
2166             }
2167         }
2168     }
2169 }
2170
2171 // ppcoin: disable transaction (only for coinstake)
2172 void CWallet::DisableTransaction(const CTransaction &tx)
2173 {
2174     if (!tx.IsCoinStake() || !IsFromMe(tx))
2175         return; // only disconnecting coinstake requires marking input unspent
2176
2177     LOCK(cs_wallet);
2178     BOOST_FOREACH(const CTxIn& txin, tx.vin)
2179     {
2180         map<uint256, CWalletTx>::iterator mi = mapWallet.find(txin.prevout.hash);
2181         if (mi != mapWallet.end())
2182         {
2183             CWalletTx& prev = (*mi).second;
2184             if (txin.prevout.n < prev.vout.size() && IsMine(prev.vout[txin.prevout.n]))
2185             {
2186                 prev.MarkUnspent(txin.prevout.n);
2187                 prev.WriteToDisk();
2188             }
2189         }
2190     }
2191 }
2192
2193 CPubKey CReserveKey::GetReservedKey()
2194 {
2195     if (nIndex == -1)
2196     {
2197         CKeyPool keypool;
2198         pwallet->ReserveKeyFromKeyPool(nIndex, keypool);
2199         if (nIndex != -1)
2200             vchPubKey = keypool.vchPubKey;
2201         else
2202         {
2203             printf("CReserveKey::GetReservedKey(): Warning: Using default key instead of a new key, top up your keypool!");
2204             vchPubKey = pwallet->vchDefaultKey;
2205         }
2206     }
2207     assert(vchPubKey.IsValid());
2208     return vchPubKey;
2209 }
2210
2211 void CReserveKey::KeepKey()
2212 {
2213     if (nIndex != -1)
2214         pwallet->KeepKey(nIndex);
2215     nIndex = -1;
2216     vchPubKey = CPubKey();
2217 }
2218
2219 void CReserveKey::ReturnKey()
2220 {
2221     if (nIndex != -1)
2222         pwallet->ReturnKey(nIndex);
2223     nIndex = -1;
2224     vchPubKey = CPubKey();
2225 }
2226
2227 void CWallet::GetAllReserveKeys(set<CKeyID>& setAddress) const
2228 {
2229     setAddress.clear();
2230
2231     CWalletDB walletdb(strWalletFile);
2232
2233     LOCK2(cs_main, cs_wallet);
2234     BOOST_FOREACH(const int64& id, setKeyPool)
2235     {
2236         CKeyPool keypool;
2237         if (!walletdb.ReadPool(id, keypool))
2238             throw runtime_error("GetAllReserveKeyHashes() : read failed");
2239         assert(keypool.vchPubKey.IsValid());
2240         CKeyID keyID = keypool.vchPubKey.GetID();
2241         if (!HaveKey(keyID))
2242             throw runtime_error("GetAllReserveKeyHashes() : unknown key in key pool");
2243         setAddress.insert(keyID);
2244     }
2245 }
2246
2247 void CWallet::UpdatedTransaction(const uint256 &hashTx)
2248 {
2249     {
2250         LOCK(cs_wallet);
2251         // Only notify UI if this transaction is in this wallet
2252         map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(hashTx);
2253         if (mi != mapWallet.end())
2254             NotifyTransactionChanged(this, hashTx, CT_UPDATED);
2255     }
2256 }
2257
2258 void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
2259     mapKeyBirth.clear();
2260
2261     // get birth times for keys with metadata
2262     for (std::map<CKeyID, CKeyMetadata>::const_iterator it = mapKeyMetadata.begin(); it != mapKeyMetadata.end(); it++)
2263         if (it->second.nCreateTime)
2264             mapKeyBirth[it->first] = it->second.nCreateTime;
2265
2266     // map in which we'll infer heights of other keys
2267     CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
2268     std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
2269     std::set<CKeyID> setKeys;
2270     GetKeys(setKeys);
2271     BOOST_FOREACH(const CKeyID &keyid, setKeys) {
2272         if (mapKeyBirth.count(keyid) == 0)
2273             mapKeyFirstBlock[keyid] = pindexMax;
2274     }
2275     setKeys.clear();
2276
2277     // if there are no such keys, we're done
2278     if (mapKeyFirstBlock.empty())
2279         return;
2280
2281     // find first block that affects those keys, if there are any left
2282     std::vector<CKeyID> vAffected;
2283     for (std::map<uint256, CWalletTx>::const_iterator it = mapWallet.begin(); it != mapWallet.end(); it++) {
2284         // iterate over all wallet transactions...
2285         const CWalletTx &wtx = (*it).second;
2286         std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
2287         if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
2288             // ... which are already in a block
2289             int nHeight = blit->second->nHeight;
2290             BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
2291                 // iterate over all their outputs
2292                 ::ExtractAffectedKeys(*this, txout.scriptPubKey, vAffected);
2293                 BOOST_FOREACH(const CKeyID &keyid, vAffected) {
2294                     // ... and all their affected keys
2295                     std::map<CKeyID, CBlockIndex*>::iterator rit = mapKeyFirstBlock.find(keyid);
2296                     if (rit != mapKeyFirstBlock.end() && nHeight < rit->second->nHeight)
2297                         rit->second = blit->second;
2298                 }
2299                 vAffected.clear();
2300             }
2301         }
2302     }
2303
2304     // Extract block timestamps for those keys
2305     for (std::map<CKeyID, CBlockIndex*>::const_iterator it = mapKeyFirstBlock.begin(); it != mapKeyFirstBlock.end(); it++)
2306         mapKeyBirth[it->first] = it->second->nTime - 7200; // block times can be 2h off
2307 }