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