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