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