Calculate actual kernel and coin*day rates on the fly.
[novacoin.git] / src / wallet.h
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 #ifndef BITCOIN_WALLET_H
6 #define BITCOIN_WALLET_H
7
8 #include <string>
9 #include <vector>
10
11 #include <stdlib.h>
12
13 #include "main.h"
14 #include "key.h"
15 #include "keystore.h"
16 #include "script.h"
17 #include "ui_interface.h"
18 #include "util.h"
19 #include "walletdb.h"
20
21 extern unsigned int nStakeMaxAge;
22 extern bool fWalletUnlockMintOnly;
23 extern bool fConfChange;
24 class CAccountingEntry;
25 class CWalletTx;
26 class CReserveKey;
27 class COutput;
28 class CCoinControl;
29
30 /** (client) version numbers for particular wallet features */
31 enum WalletFeature
32 {
33     FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output)
34
35     FEATURE_WALLETCRYPT = 40000, // wallet encryption
36     FEATURE_COMPRPUBKEY = 60000, // compressed public keys
37     FEATURE_LATEST = 60000
38 };
39
40 /** A key pool entry */
41 class CKeyPool
42 {
43 public:
44     int64 nTime;
45     CPubKey vchPubKey;
46
47     CKeyPool()
48     {
49         nTime = GetTime();
50     }
51
52     CKeyPool(const CPubKey& vchPubKeyIn)
53     {
54         nTime = GetTime();
55         vchPubKey = vchPubKeyIn;
56     }
57
58     IMPLEMENT_SERIALIZE
59     (
60         if (!(nType & SER_GETHASH))
61             READWRITE(nVersion);
62         READWRITE(nTime);
63         READWRITE(vchPubKey);
64     )
65 };
66
67 /** A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
68  * and provides the ability to create new transactions.
69  */
70 class CWallet : public CCryptoKeyStore
71 {
72 private:
73     bool SelectCoinsSimple(int64 nTargetValue, int64 nMinValue, int64 nMaxValue, unsigned int nSpendTime, int nMinConf, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
74     bool SelectCoins(int64 nTargetValue, unsigned int nSpendTime, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet, const CCoinControl *coinControl=NULL) const;
75
76     CWalletDB *pwalletdbEncryption;
77
78     // the current wallet version: clients below this version are not able to load the wallet
79     int nWalletVersion;
80
81     // the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
82     int nWalletMaxVersion;
83
84     // selected coins metadata
85     std::map<std::pair<uint256, unsigned int>, std::pair<std::pair<CTxIndex, std::pair<const CWalletTx*,unsigned int> >, std::pair<CBlock, uint64> > > mapMeta;
86
87     // stake mining statistics
88     uint64 nKernelsTried;
89     uint64 nCoinDaysTried;
90
91 public:
92     mutable CCriticalSection cs_wallet;
93
94     bool fFileBacked;
95     std::string strWalletFile;
96
97     std::set<int64> setKeyPool;
98     std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
99
100
101     typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
102     MasterKeyMap mapMasterKeys;
103     unsigned int nMasterKeyMaxID;
104
105     CWallet()
106     {
107         nWalletVersion = FEATURE_BASE;
108         nWalletMaxVersion = FEATURE_BASE;
109         fFileBacked = false;
110         nMasterKeyMaxID = 0;
111         pwalletdbEncryption = NULL;
112         nOrderPosNext = 0;
113         nKernelsTried = 0;
114         nCoinDaysTried = 0;
115     }
116     CWallet(std::string strWalletFileIn)
117     {
118         nWalletVersion = FEATURE_BASE;
119         nWalletMaxVersion = FEATURE_BASE;
120         strWalletFile = strWalletFileIn;
121         fFileBacked = true;
122         nMasterKeyMaxID = 0;
123         pwalletdbEncryption = NULL;
124         nOrderPosNext = 0;
125         nKernelsTried = 0;
126         nCoinDaysTried = 0;
127     }
128
129     std::map<uint256, CWalletTx> mapWallet;
130     std::vector<uint256> vMintingWalletUpdated;
131     int64 nOrderPosNext;
132     std::map<uint256, int> mapRequestCount;
133
134     std::map<CTxDestination, std::string> mapAddressBook;
135
136     CPubKey vchDefaultKey;
137     int64 nTimeFirstKey;
138
139     // check whether we are allowed to upgrade (or already support) to the named feature
140     bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
141
142     void AvailableCoinsMinConf(std::vector<COutput>& vCoins, int nConf, int64 nMinValue, int64 nMaxValue) const;
143     void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl=NULL) const;
144     bool SelectCoinsMinConf(int64 nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
145     // keystore implementation
146     // Generate a new key
147     CPubKey GenerateNewKey();
148     // Adds a key to the store, and saves it to disk.
149     bool AddKey(const CKey& key);
150     // Adds a key to the store, without saving it to disk (used by LoadWallet)
151     bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
152     // Load metadata (used by LoadWallet)
153     bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
154
155     bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
156
157     // Adds an encrypted key to the store, and saves it to disk.
158     bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
159     // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
160     bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
161     bool AddCScript(const CScript& redeemScript);
162     bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); }
163
164     // Adds a watch-only address to the store, and saves it to disk.
165     bool AddWatchOnly(const CScript &dest);
166     // Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
167     bool LoadWatchOnly(const CScript &dest);
168
169     bool Unlock(const SecureString& strWalletPassphrase);
170     bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
171     bool EncryptWallet(const SecureString& strWalletPassphrase);
172
173     void GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const;
174
175
176     /** Increment the next transaction order id
177         @return next transaction order id
178      */
179     int64 IncOrderPosNext(CWalletDB *pwalletdb = NULL);
180
181     typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
182     typedef std::multimap<int64, TxPair > TxItems;
183
184     /** Get the wallet's activity log
185         @return multimap of ordered transactions and accounting entries
186         @warning Returned pointers are *only* valid within the scope of passed acentries
187      */
188     TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = "");
189
190     void MarkDirty();
191     bool AddToWallet(const CWalletTx& wtxIn);
192     bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false);
193     bool EraseFromWallet(uint256 hash);
194     void ClearOrphans();
195     void WalletUpdateSpent(const CTransaction& prevout, bool fBlock = false);
196     int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
197     int ScanForWalletTransaction(const uint256& hashTx);
198     void ReacceptWalletTransactions();
199     void ResendWalletTransactions();
200     int64 GetBalance() const;
201     int64 GetWatchOnlyBalance() const;
202     int64 GetUnconfirmedBalance() const;
203     int64 GetUnconfirmedWatchOnlyBalance() const;
204     int64 GetImmatureBalance() const;
205     int64 GetImmatureWatchOnlyBalance() const;
206     int64 GetStake() const;
207     int64 GetNewMint() const;
208     int64 GetWatchOnlyStake() const;
209     int64 GetWatchOnlyNewMint() const;
210     bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, const CCoinControl *coinControl=NULL);
211     bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet, const CCoinControl *coinControl=NULL);
212     bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
213
214     void GetStakeStats(float &nKernelsRate, float &nCoinDaysRate);
215     void GetStakeWeightFromValue(const int64& nTime, const int64& nValue, uint64& nWeight);
216     bool CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64 nSearchInterval, CTransaction& txNew, CKey& key);
217     bool MergeCoins(const int64& nAmount, const int64& nMinValue, const int64& nMaxValue, std::list<uint256>& listMerged);
218
219     std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
220     std::string SendMoneyToDestination(const CTxDestination &address, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
221
222     bool NewKeyPool();
223     bool TopUpKeyPool(unsigned int nSize = 0);
224     int64 AddReserveKey(const CKeyPool& keypool);
225     void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
226     void KeepKey(int64 nIndex);
227     void ReturnKey(int64 nIndex);
228     bool GetKeyFromPool(CPubKey &key, bool fAllowReuse=true);
229     int64 GetOldestKeyPoolTime();
230     void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
231
232     std::set< std::set<CTxDestination> > GetAddressGroupings();
233     std::map<CTxDestination, int64> GetAddressBalances();
234
235     isminetype IsMine(const CTxIn& txin) const;
236     int64 GetDebit(const CTxIn& txin, const isminefilter& filter) const;
237     isminetype IsMine(const CTxOut& txout) const
238     {
239         return ::IsMine(*this, txout.scriptPubKey);
240     }
241     int64 GetCredit(const CTxOut& txout, const isminefilter& filter) const
242     {
243         if (!MoneyRange(txout.nValue))
244             throw std::runtime_error("CWallet::GetCredit() : value out of range");
245         return (IsMine(txout) & filter ? txout.nValue : 0);
246     }
247     bool IsChange(const CTxOut& txout) const;
248     int64 GetChange(const CTxOut& txout) const
249     {
250         if (!MoneyRange(txout.nValue))
251             throw std::runtime_error("CWallet::GetChange() : value out of range");
252         return (IsChange(txout) ? txout.nValue : 0);
253     }
254     bool IsMine(const CTransaction& tx) const
255     {
256         BOOST_FOREACH(const CTxOut& txout, tx.vout)
257             if (IsMine(txout) && txout.nValue >= nMinimumInputValue)
258                 return true;
259         return false;
260     }
261     bool IsFromMe(const CTransaction& tx) const
262     {
263         return (GetDebit(tx, MINE_ALL) > 0);
264     }
265     int64 GetDebit(const CTransaction& tx, const isminefilter& filter) const
266     {
267         int64 nDebit = 0;
268         BOOST_FOREACH(const CTxIn& txin, tx.vin)
269         {
270             nDebit += GetDebit(txin, filter);
271             if (!MoneyRange(nDebit))
272                 throw std::runtime_error("CWallet::GetDebit() : value out of range");
273         }
274         return nDebit;
275     }
276     int64 GetCredit(const CTransaction& tx, const isminefilter& filter) const
277     {
278         int64 nCredit = 0;
279         BOOST_FOREACH(const CTxOut& txout, tx.vout)
280         {
281             nCredit += GetCredit(txout, filter);
282             if (!MoneyRange(nCredit))
283                 throw std::runtime_error("CWallet::GetCredit() : value out of range");
284         }
285         return nCredit;
286     }
287     int64 GetChange(const CTransaction& tx) const
288     {
289         int64 nChange = 0;
290         BOOST_FOREACH(const CTxOut& txout, tx.vout)
291         {
292             nChange += GetChange(txout);
293             if (!MoneyRange(nChange))
294                 throw std::runtime_error("CWallet::GetChange() : value out of range");
295         }
296         return nChange;
297     }
298     void SetBestChain(const CBlockLocator& loc);
299
300     DBErrors LoadWallet(bool& fFirstRunRet);
301
302     bool SetAddressBookName(const CTxDestination& address, const std::string& strName);
303
304     bool DelAddressBookName(const CTxDestination& address);
305
306     void UpdatedTransaction(const uint256 &hashTx);
307
308     void PrintWallet(const CBlock& block);
309
310     void Inventory(const uint256 &hash)
311     {
312         {
313             LOCK(cs_wallet);
314             std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
315             if (mi != mapRequestCount.end())
316                 (*mi).second++;
317         }
318     }
319
320     unsigned int GetKeyPoolSize()
321     {
322         return setKeyPool.size();
323     }
324
325     bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
326
327     bool SetDefaultKey(const CPubKey &vchPubKey);
328
329     // signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
330     bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
331
332     // change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
333     bool SetMaxVersion(int nVersion);
334
335     // get the current wallet format (the oldest client version guaranteed to understand this wallet)
336     int GetVersion() { return nWalletVersion; }
337
338     void FixSpentCoins(int& nMismatchSpent, int64& nBalanceInQuestion, bool fCheckOnly = false);
339     void DisableTransaction(const CTransaction &tx);
340
341     /** Address book entry changed.
342      * @note called with lock cs_wallet held.
343      */
344     boost::signals2::signal<void (CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, ChangeType status)> NotifyAddressBookChanged;
345
346     /** Wallet transaction added, removed or updated.
347      * @note called with lock cs_wallet held.
348      */
349     boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged;
350 };
351
352 /** A key allocated from the key pool. */
353 class CReserveKey
354 {
355 protected:
356     CWallet* pwallet;
357     int64 nIndex;
358     CPubKey vchPubKey;
359 public:
360     CReserveKey(CWallet* pwalletIn)
361     {
362         nIndex = -1;
363         pwallet = pwalletIn;
364     }
365
366     ~CReserveKey()
367     {
368         if (!fShutdown)
369             ReturnKey();
370     }
371
372     void ReturnKey();
373     CPubKey GetReservedKey();
374     void KeepKey();
375 };
376
377
378 typedef std::map<std::string, std::string> mapValue_t;
379
380
381 static void ReadOrderPos(int64& nOrderPos, mapValue_t& mapValue)
382 {
383     if (!mapValue.count("n"))
384     {
385         nOrderPos = -1; // TODO: calculate elsewhere
386         return;
387     }
388     nOrderPos = atoi64(mapValue["n"].c_str());
389 }
390
391
392 static void WriteOrderPos(const int64& nOrderPos, mapValue_t& mapValue)
393 {
394     if (nOrderPos == -1)
395         return;
396     mapValue["n"] = i64tostr(nOrderPos);
397 }
398
399
400 /** A transaction with a bunch of additional info that only the owner cares about.
401  * It includes any unrecorded transactions needed to link it back to the block chain.
402  */
403 class CWalletTx : public CMerkleTx
404 {
405 private:
406     const CWallet* pwallet;
407
408 public:
409     std::vector<CMerkleTx> vtxPrev;
410     mapValue_t mapValue;
411     std::vector<std::pair<std::string, std::string> > vOrderForm;
412     unsigned int fTimeReceivedIsTxTime;
413     unsigned int nTimeReceived;  // time received by this node
414     unsigned int nTimeSmart;
415     char fFromMe;
416     std::string strFromAccount;
417     std::vector<char> vfSpent; // which outputs are already spent
418     int64 nOrderPos;  // position in ordered transaction list
419
420     // memory only
421     mutable bool fDebitCached;
422     mutable bool fWatchDebitCached;
423     mutable bool fCreditCached;
424     mutable bool fWatchCreditCached;
425     mutable bool fAvailableCreditCached;
426     mutable bool fImmatureCreditCached;
427     mutable bool fImmatureWatchCreditCached;
428     mutable bool fAvailableWatchCreditCached;
429     mutable bool fChangeCached;
430     mutable int64 nDebitCached;
431     mutable int64 nWatchDebitCached;
432     mutable int64 nCreditCached;
433     mutable int64 nWatchCreditCached;
434     mutable int64 nAvailableCreditCached;
435     mutable int64 nImmatureCreditCached;
436     mutable int64 nImmatureWatchCreditCached;
437     mutable int64 nAvailableWatchCreditCached;
438     mutable int64 nChangeCached;
439
440     CWalletTx()
441     {
442         Init(NULL);
443     }
444
445     CWalletTx(const CWallet* pwalletIn)
446     {
447         Init(pwalletIn);
448     }
449
450     CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
451     {
452         Init(pwalletIn);
453     }
454
455     CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
456     {
457         Init(pwalletIn);
458     }
459
460     void Init(const CWallet* pwalletIn)
461     {
462         pwallet = pwalletIn;
463         vtxPrev.clear();
464         mapValue.clear();
465         vOrderForm.clear();
466         fTimeReceivedIsTxTime = false;
467         nTimeReceived = 0;
468         nTimeSmart = 0;
469         fFromMe = false;
470         strFromAccount.clear();
471         vfSpent.clear();
472         fDebitCached = false;
473         fWatchDebitCached = false;
474         fCreditCached = false;
475         fWatchCreditCached = false;
476         fAvailableCreditCached = false;
477         fAvailableWatchCreditCached = false;
478         fImmatureCreditCached = false;
479         fImmatureWatchCreditCached = false;
480         fChangeCached = false;
481         nDebitCached = 0;
482         nWatchDebitCached = 0;
483         nCreditCached = 0;
484         nWatchCreditCached = 0;
485         nAvailableCreditCached = 0;
486         nAvailableWatchCreditCached = 0;
487         nImmatureCreditCached = 0;
488         nImmatureWatchCreditCached = 0;
489         nChangeCached = 0;
490         nOrderPos = -1;
491     }
492
493     IMPLEMENT_SERIALIZE
494     (
495         CWalletTx* pthis = const_cast<CWalletTx*>(this);
496         if (fRead)
497             pthis->Init(NULL);
498         char fSpent = false;
499
500         if (!fRead)
501         {
502             pthis->mapValue["fromaccount"] = pthis->strFromAccount;
503
504             std::string str;
505             BOOST_FOREACH(char f, vfSpent)
506             {
507                 str += (f ? '1' : '0');
508                 if (f)
509                     fSpent = true;
510             }
511             pthis->mapValue["spent"] = str;
512
513             WriteOrderPos(pthis->nOrderPos, pthis->mapValue);
514
515             if (nTimeSmart)
516                 pthis->mapValue["timesmart"] = strprintf("%u", nTimeSmart);
517         }
518
519         nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
520         READWRITE(vtxPrev);
521         READWRITE(mapValue);
522         READWRITE(vOrderForm);
523         READWRITE(fTimeReceivedIsTxTime);
524         READWRITE(nTimeReceived);
525         READWRITE(fFromMe);
526         READWRITE(fSpent);
527
528         if (fRead)
529         {
530             pthis->strFromAccount = pthis->mapValue["fromaccount"];
531
532             if (mapValue.count("spent"))
533                 BOOST_FOREACH(char c, pthis->mapValue["spent"])
534                     pthis->vfSpent.push_back(c != '0');
535             else
536                 pthis->vfSpent.assign(vout.size(), fSpent);
537
538             ReadOrderPos(pthis->nOrderPos, pthis->mapValue);
539
540             pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0;
541         }
542
543         pthis->mapValue.erase("fromaccount");
544         pthis->mapValue.erase("version");
545         pthis->mapValue.erase("spent");
546         pthis->mapValue.erase("n");
547         pthis->mapValue.erase("timesmart");
548     )
549
550     // marks certain txout's as spent
551     // returns true if any update took place
552     bool UpdateSpent(const std::vector<char>& vfNewSpent)
553     {
554         bool fReturn = false;
555         for (unsigned int i = 0; i < vfNewSpent.size(); i++)
556         {
557             if (i == vfSpent.size())
558                 break;
559
560             if (vfNewSpent[i] && !vfSpent[i])
561             {
562                 vfSpent[i] = true;
563                 fReturn = true;
564                 fAvailableCreditCached = fAvailableWatchCreditCached = false;
565             }
566         }
567         return fReturn;
568     }
569
570     // make sure balances are recalculated
571     void MarkDirty()
572     {
573         fCreditCached = false;
574         fAvailableCreditCached = fAvailableWatchCreditCached = false;
575         fDebitCached = fWatchDebitCached = false;
576         fChangeCached = false;
577     }
578
579     void BindWallet(CWallet *pwalletIn)
580     {
581         pwallet = pwalletIn;
582         MarkDirty();
583     }
584
585     void MarkSpent(unsigned int nOut)
586     {
587         if (nOut >= vout.size())
588             throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range");
589         vfSpent.resize(vout.size());
590         if (!vfSpent[nOut])
591         {
592             vfSpent[nOut] = true;
593             fAvailableCreditCached = fAvailableWatchCreditCached = false;
594         }
595     }
596
597     void MarkUnspent(unsigned int nOut)
598     {
599         if (nOut >= vout.size())
600             throw std::runtime_error("CWalletTx::MarkUnspent() : nOut out of range");
601         vfSpent.resize(vout.size());
602         if (vfSpent[nOut])
603         {
604             vfSpent[nOut] = false;
605             fAvailableCreditCached = fAvailableWatchCreditCached = false;
606         }
607     }
608
609     bool IsSpent(unsigned int nOut) const
610     {
611         if (nOut >= vout.size())
612             throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range");
613         if (nOut >= vfSpent.size())
614             return false;
615         return (!!vfSpent[nOut]);
616     }
617
618     int64 GetDebit(const isminefilter& filter) const
619     {
620         if (vin.empty())
621             return 0;
622
623         int64 nDebit = 0;
624         if (filter & MINE_SPENDABLE)
625         {
626             if (fDebitCached)
627                 nDebit += nDebitCached;
628             else
629             {
630                 nDebitCached = pwallet->GetDebit(*this, MINE_SPENDABLE);
631                 fDebitCached = true;
632                 nDebit += nDebitCached;
633             }
634         }
635         if (filter & MINE_WATCH_ONLY)
636         {
637             if (fWatchDebitCached)
638                 nDebit += nWatchDebitCached;
639             else
640             {
641                 nWatchDebitCached = pwallet->GetDebit(*this, MINE_WATCH_ONLY);
642                 fWatchDebitCached = true;
643                 nDebit += nWatchDebitCached;
644             }
645         }
646
647         return nDebit;
648     }
649
650     int64 GetCredit(bool fUseCache=true) const
651     {
652         // Must wait until coinbase is safely deep enough in the chain before valuing it
653         if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0)
654             return 0;
655
656         // GetBalance can assume transactions in mapWallet won't change
657         if (fUseCache) {
658             if (fCreditCached)
659                 return nCreditCached;
660         }
661
662         nCreditCached = pwallet->GetCredit(*this, MINE_ALL);
663         fCreditCached = true;
664
665         return nCreditCached;
666     }
667
668     int64 GetImmatureCredit(bool fUseCache=true) const
669     {
670         if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
671         {
672             if (fUseCache && fImmatureCreditCached)
673                 return nImmatureCreditCached;
674             nImmatureCreditCached = pwallet->GetCredit(*this, MINE_SPENDABLE);
675             fImmatureCreditCached = true;
676             return nImmatureCreditCached;
677         }
678
679         return 0;
680     }
681
682     int64 GetImmatureWatchOnlyCredit(bool fUseCache=true) const
683     {
684         if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
685         {
686             if (fUseCache && fImmatureWatchCreditCached)
687                 return nImmatureWatchCreditCached;
688             nImmatureWatchCreditCached = pwallet->GetCredit(*this, MINE_WATCH_ONLY);
689             fImmatureWatchCreditCached = true;
690             return nImmatureWatchCreditCached;
691         }
692
693         return 0;
694     }
695
696
697     int64 GetAvailableCredit(bool fUseCache=true) const
698     {
699         // Must wait until coinbase is safely deep enough in the chain before valuing it
700         if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0)
701             return 0;
702
703         if (fUseCache) {
704             if (fAvailableCreditCached)
705                 return nAvailableCreditCached;
706         }
707
708         int64 nCredit = 0;
709         for (unsigned int i = 0; i < vout.size(); i++)
710         {
711             if (!IsSpent(i))
712             {
713                 const CTxOut &txout = vout[i];
714                 nCredit += pwallet->GetCredit(txout, MINE_SPENDABLE);
715                 if (!MoneyRange(nCredit))
716                     throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
717             }
718         }
719
720         nAvailableCreditCached = nCredit;
721         fAvailableCreditCached = true;
722
723         return nCredit;
724     }
725
726     int64 GetAvailableWatchCredit(bool fUseCache=true) const
727     {
728         // Must wait until coinbase is safely deep enough in the chain before valuing it
729         if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0)
730             return 0;
731
732         if (fUseCache) {
733             if (fAvailableWatchCreditCached)
734                 return nAvailableWatchCreditCached;
735         }
736
737         int64 nCredit = 0;
738         for (unsigned int i = 0; i < vout.size(); i++)
739         {
740             if (!IsSpent(i))
741             {
742                 const CTxOut &txout = vout[i];
743                 nCredit += pwallet->GetCredit(txout, MINE_WATCH_ONLY);
744                 if (!MoneyRange(nCredit))
745                     throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
746             }
747         }
748
749         nAvailableWatchCreditCached = nCredit;
750         fAvailableWatchCreditCached = true;
751
752         return nCredit;
753     }
754
755     int64 GetChange() const
756     {
757         if (fChangeCached)
758             return nChangeCached;
759         nChangeCached = pwallet->GetChange(*this);
760         fChangeCached = true;
761         return nChangeCached;
762     }
763
764     void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list<std::pair<CTxDestination, int64> >& listReceived,
765                     std::list<std::pair<CTxDestination, int64> >& listSent, int64& nFee, std::string& strSentAccount, const isminefilter& filter) const;
766
767     void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived,
768                            int64& nSent, int64& nFee, const isminefilter& filter) const;
769
770     bool IsFromMe(const isminefilter& filter) const
771     {
772         return (GetDebit(filter) > 0);
773     }
774
775     bool IsTrusted() const
776     {
777         // Quick answer in most cases
778         if (!IsFinal())
779             return false;
780         if (GetDepthInMainChain() >= 1)
781             return true;
782         if (fConfChange || !IsFromMe(MINE_ALL)) // using wtx's cached debit
783             return false;
784
785         // If no confirmations but it's from us, we can still
786         // consider it confirmed if all dependencies are confirmed
787         std::map<uint256, const CMerkleTx*> mapPrev;
788         std::vector<const CMerkleTx*> vWorkQueue;
789         vWorkQueue.reserve(vtxPrev.size()+1);
790         vWorkQueue.push_back(this);
791         for (unsigned int i = 0; i < vWorkQueue.size(); i++)
792         {
793             const CMerkleTx* ptx = vWorkQueue[i];
794
795             if (!ptx->IsFinal())
796                 return false;
797             if (ptx->GetDepthInMainChain() >= 1)
798                 continue;
799             if (!pwallet->IsFromMe(*ptx))
800                 return false;
801
802             if (mapPrev.empty())
803             {
804                 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
805                     mapPrev[tx.GetHash()] = &tx;
806             }
807
808             BOOST_FOREACH(const CTxIn& txin, ptx->vin)
809             {
810                 if (!mapPrev.count(txin.prevout.hash))
811                     return false;
812                 vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
813             }
814         }
815
816         return true;
817     }
818
819     bool WriteToDisk();
820
821     int64 GetTxTime() const;
822     int GetRequestCount() const;
823
824     void AddSupportingTransactions(CTxDB& txdb);
825
826     bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
827     bool AcceptWalletTransaction();
828
829     void RelayWalletTransaction(CTxDB& txdb);
830     void RelayWalletTransaction();
831 };
832
833
834
835
836 class COutput
837 {
838 public:
839     const CWalletTx *tx;
840     int i;
841     int nDepth;
842     bool fSpendable;
843
844     COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn)
845     {
846         tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn;
847     }
848
849     std::string ToString() const
850     {
851         return strprintf("COutput(%s, %d, %d, %d) [%s]", tx->GetHash().ToString().substr(0,10).c_str(), i, fSpendable, nDepth, FormatMoney(tx->vout[i].nValue).c_str());
852     }
853
854     void print() const
855     {
856         printf("%s\n", ToString().c_str());
857     }
858 };
859
860
861
862
863 /** Private key that includes an expiration date in case it never gets used. */
864 class CWalletKey
865 {
866 public:
867     CPrivKey vchPrivKey;
868     int64 nTimeCreated;
869     int64 nTimeExpires;
870     std::string strComment;
871     //// todo: add something to note what created it (user, getnewaddress, change)
872     ////   maybe should have a map<string, string> property map
873
874     CWalletKey(int64 nExpires=0)
875     {
876         nTimeCreated = (nExpires ? GetTime() : 0);
877         nTimeExpires = nExpires;
878     }
879
880     IMPLEMENT_SERIALIZE
881     (
882         if (!(nType & SER_GETHASH))
883             READWRITE(nVersion);
884         READWRITE(vchPrivKey);
885         READWRITE(nTimeCreated);
886         READWRITE(nTimeExpires);
887         READWRITE(strComment);
888     )
889 };
890
891
892
893
894
895
896 /** Account information.
897  * Stored in wallet with key "acc"+string account name.
898  */
899 class CAccount
900 {
901 public:
902     CPubKey vchPubKey;
903
904     CAccount()
905     {
906         SetNull();
907     }
908
909     void SetNull()
910     {
911         vchPubKey = CPubKey();
912     }
913
914     IMPLEMENT_SERIALIZE
915     (
916         if (!(nType & SER_GETHASH))
917             READWRITE(nVersion);
918         READWRITE(vchPubKey);
919     )
920 };
921
922
923
924 /** Internal transfers.
925  * Database key is acentry<account><counter>.
926  */
927 class CAccountingEntry
928 {
929 public:
930     std::string strAccount;
931     int64 nCreditDebit;
932     int64 nTime;
933     std::string strOtherAccount;
934     std::string strComment;
935     mapValue_t mapValue;
936     int64 nOrderPos;  // position in ordered transaction list
937     uint64 nEntryNo;
938
939     CAccountingEntry()
940     {
941         SetNull();
942     }
943
944     void SetNull()
945     {
946         nCreditDebit = 0;
947         nTime = 0;
948         strAccount.clear();
949         strOtherAccount.clear();
950         strComment.clear();
951         nOrderPos = -1;
952     }
953
954     IMPLEMENT_SERIALIZE
955     (
956         CAccountingEntry& me = *const_cast<CAccountingEntry*>(this);
957         if (!(nType & SER_GETHASH))
958             READWRITE(nVersion);
959         // Note: strAccount is serialized as part of the key, not here.
960         READWRITE(nCreditDebit);
961         READWRITE(nTime);
962         READWRITE(strOtherAccount);
963
964         if (!fRead)
965         {
966             WriteOrderPos(nOrderPos, me.mapValue);
967
968             if (!(mapValue.empty() && _ssExtra.empty()))
969             {
970                 CDataStream ss(nType, nVersion);
971                 ss.insert(ss.begin(), '\0');
972                 ss << mapValue;
973                 ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
974                 me.strComment.append(ss.str());
975             }
976         }
977
978         READWRITE(strComment);
979
980         size_t nSepPos = strComment.find("\0", 0, 1);
981         if (fRead)
982         {
983             me.mapValue.clear();
984             if (std::string::npos != nSepPos)
985             {
986                 CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion);
987                 ss >> me.mapValue;
988                 me._ssExtra = std::vector<char>(ss.begin(), ss.end());
989             }
990             ReadOrderPos(me.nOrderPos, me.mapValue);
991         }
992         if (std::string::npos != nSepPos)
993             me.strComment.erase(nSepPos);
994
995         me.mapValue.erase("n");
996     )
997
998 private:
999     std::vector<char> _ssExtra;
1000 };
1001
1002 bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
1003
1004 #endif