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