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