a531944dcd74f82c4857b26538d00b37ab3a0459
[novacoin.git] / src / wallet.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2012 The Bitcoin developers
3 // Copyright (c) 2011-2012 The PPCoin developers
4 // Copyright (c) 2012-2013 The NovaCoin developers
5 // Distributed under the MIT/X11 software license, see the accompanying
6 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 #ifndef BITCOIN_WALLET_H
8 #define BITCOIN_WALLET_H
9
10 #include "main.h"
11 #include "key.h"
12 #include "keystore.h"
13 #include "script.h"
14
15 extern bool fWalletUnlockMintOnly;
16
17 class CWalletTx;
18 class CReserveKey;
19 class CWalletDB;
20
21 /** (client) version numbers for particular wallet features */
22 enum WalletFeature
23 {
24     FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output)
25
26     FEATURE_WALLETCRYPT = 40000, // wallet encryption
27     FEATURE_COMPRPUBKEY = 60000, // compressed public keys
28
29     FEATURE_LATEST = 60000
30 };
31
32
33 /** A key pool entry */
34 class CKeyPool
35 {
36 public:
37     int64 nTime;
38     std::vector<unsigned char> vchPubKey;
39
40     CKeyPool()
41     {
42         nTime = GetTime();
43     }
44
45     CKeyPool(const std::vector<unsigned char>& vchPubKeyIn)
46     {
47         nTime = GetTime();
48         vchPubKey = vchPubKeyIn;
49     }
50
51     IMPLEMENT_SERIALIZE
52     (
53         if (!(nType & SER_GETHASH))
54             READWRITE(nVersion);
55         READWRITE(nTime);
56         READWRITE(vchPubKey);
57     )
58 };
59
60 /** A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
61  * and provides the ability to create new transactions.
62  */
63 class CWallet : public CCryptoKeyStore
64 {
65 private:
66     bool SelectCoinsMinConf(int64 nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
67     bool SelectCoins(int64 nTargetValue, unsigned int nSpendTime, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
68
69     CWalletDB *pwalletdbEncryption;
70
71     // the current wallet version: clients below this version are not able to load the wallet
72     int nWalletVersion;
73
74     // the maxmimum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
75     int nWalletMaxVersion;
76
77 public:
78     mutable CCriticalSection cs_wallet;
79
80     bool fFileBacked;
81     std::string strWalletFile;
82
83     std::set<int64> setKeyPool;
84
85
86     typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
87     MasterKeyMap mapMasterKeys;
88     unsigned int nMasterKeyMaxID;
89
90     CWallet()
91     {
92         nWalletVersion = FEATURE_BASE;
93         nWalletMaxVersion = FEATURE_BASE;
94         fFileBacked = false;
95         nMasterKeyMaxID = 0;
96         pwalletdbEncryption = NULL;
97     }
98     CWallet(std::string strWalletFileIn)
99     {
100         nWalletVersion = FEATURE_BASE;
101         nWalletMaxVersion = FEATURE_BASE;
102         strWalletFile = strWalletFileIn;
103         fFileBacked = true;
104         nMasterKeyMaxID = 0;
105         pwalletdbEncryption = NULL;
106     }
107
108     std::map<uint256, CWalletTx> mapWallet;
109     std::vector<uint256> vWalletUpdated;
110
111     std::map<uint256, int> mapRequestCount;
112
113     std::map<CBitcoinAddress, std::string> mapAddressBook;
114
115     std::vector<unsigned char> vchDefaultKey;
116
117     // check whether we are allowed to upgrade (or already support) to the named feature
118     bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
119
120     // keystore implementation
121     // Generate a new key
122     std::vector<unsigned char> GenerateNewKey(bool bCompressed);
123     // Adds a key to the store, and saves it to disk.
124     bool AddKey(const CKey& key);
125     // Adds a key to the store, without saving it to disk (used by LoadWallet)
126     bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
127
128     bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
129
130     // Adds an encrypted key to the store, and saves it to disk.
131     bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
132     // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
133     bool LoadCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
134     bool AddCScript(const CScript& redeemScript);
135     bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); }
136
137     bool Unlock(const SecureString& strWalletPassphrase);
138     bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
139     bool EncryptWallet(const SecureString& strWalletPassphrase);
140
141     void MarkDirty();
142     bool AddToWallet(const CWalletTx& wtxIn);
143     bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false);
144     bool EraseFromWallet(uint256 hash);
145     void WalletUpdateSpent(const CTransaction& prevout);
146     int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
147     int ScanForWalletTransaction(const uint256& hashTx);
148     void ReacceptWalletTransactions();
149     void ResendWalletTransactions();
150     int64 GetBalance() const;
151     int64 GetUnconfirmedBalance() const;
152     int64 GetStake() const;
153     int64 GetNewMint() const;
154     bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
155     bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
156     bool CreateCoinStake(const CKeyStore& keystore, unsigned int nBits, int64 nSearchInterval, CTransaction& txNew);
157     bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
158     std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
159     std::string SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
160
161     bool NewKeyPool();
162     bool TopUpKeyPool();
163     int64 AddReserveKey(const CKeyPool& keypool);
164     void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
165     void KeepKey(int64 nIndex);
166     void ReturnKey(int64 nIndex);
167     bool GetKeyFromPool(std::vector<unsigned char> &key, bool fAllowReuse=true);
168     int64 GetOldestKeyPoolTime();
169     void GetAllReserveAddresses(std::set<CBitcoinAddress>& setAddress);
170
171     bool IsMine(const CTxIn& txin) const;
172     int64 GetDebit(const CTxIn& txin) const;
173     bool IsMine(const CTxOut& txout) const
174     {
175         return ::IsMine(*this, txout.scriptPubKey);
176     }
177     int64 GetCredit(const CTxOut& txout) const
178     {
179         if (!MoneyRange(txout.nValue))
180             throw std::runtime_error("CWallet::GetCredit() : value out of range");
181         return (IsMine(txout) ? txout.nValue : 0);
182     }
183     bool IsChange(const CTxOut& txout) const;
184     int64 GetChange(const CTxOut& txout) const
185     {
186         if (!MoneyRange(txout.nValue))
187             throw std::runtime_error("CWallet::GetChange() : value out of range");
188         return (IsChange(txout) ? txout.nValue : 0);
189     }
190     bool IsMine(const CTransaction& tx) const
191     {
192         BOOST_FOREACH(const CTxOut& txout, tx.vout)
193             if (IsMine(txout))
194                 return true;
195         return false;
196     }
197     bool IsFromMe(const CTransaction& tx) const
198     {
199         return (GetDebit(tx) > 0);
200     }
201     int64 GetDebit(const CTransaction& tx) const
202     {
203         int64 nDebit = 0;
204         BOOST_FOREACH(const CTxIn& txin, tx.vin)
205         {
206             nDebit += GetDebit(txin);
207             if (!MoneyRange(nDebit))
208                 throw std::runtime_error("CWallet::GetDebit() : value out of range");
209         }
210         return nDebit;
211     }
212     int64 GetCredit(const CTransaction& tx) const
213     {
214         int64 nCredit = 0;
215         BOOST_FOREACH(const CTxOut& txout, tx.vout)
216         {
217             nCredit += GetCredit(txout);
218             if (!MoneyRange(nCredit))
219                 throw std::runtime_error("CWallet::GetCredit() : value out of range");
220         }
221         return nCredit;
222     }
223     int64 GetChange(const CTransaction& tx) const
224     {
225         int64 nChange = 0;
226         BOOST_FOREACH(const CTxOut& txout, tx.vout)
227         {
228             nChange += GetChange(txout);
229             if (!MoneyRange(nChange))
230                 throw std::runtime_error("CWallet::GetChange() : value out of range");
231         }
232         return nChange;
233     }
234     void SetBestChain(const CBlockLocator& loc);
235
236     int LoadWallet(bool& fFirstRunRet);
237
238     bool SetAddressBookName(const CBitcoinAddress& address, const std::string& strName);
239
240     bool DelAddressBookName(const CBitcoinAddress& address);
241
242     void UpdatedTransaction(const uint256 &hashTx)
243     {
244         {
245             LOCK(cs_wallet);
246             vWalletUpdated.push_back(hashTx);
247         }
248     }
249
250     void PrintWallet(const CBlock& block);
251
252     void Inventory(const uint256 &hash)
253     {
254         {
255             LOCK(cs_wallet);
256             std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
257             if (mi != mapRequestCount.end())
258                 (*mi).second++;
259         }
260     }
261
262     int GetKeyPoolSize()
263     {
264         return setKeyPool.size();
265     }
266
267     bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
268
269     bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
270
271     // signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
272     bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
273
274     // change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
275     bool SetMaxVersion(int nVersion);
276
277     // get the current wallet format (the oldest client version guaranteed to understand this wallet)
278     int GetVersion() { return nWalletVersion; }
279
280     void FixSpentCoins(int& nMismatchSpent, int64& nBalanceInQuestion, bool fCheckOnly = false);
281     void DisableTransaction(const CTransaction &tx);
282 };
283
284 /** A key allocated from the key pool. */
285 class CReserveKey
286 {
287 protected:
288     CWallet* pwallet;
289     int64 nIndex;
290     std::vector<unsigned char> vchPubKey;
291 public:
292     CReserveKey(CWallet* pwalletIn)
293     {
294         nIndex = -1;
295         pwallet = pwalletIn;
296     }
297
298     ~CReserveKey()
299     {
300         if (!fShutdown)
301             ReturnKey();
302     }
303
304     void ReturnKey();
305     std::vector<unsigned char> GetReservedKey();
306     void KeepKey();
307 };
308
309
310 /** A transaction with a bunch of additional info that only the owner cares about. 
311  * It includes any unrecorded transactions needed to link it back to the block chain.
312  */
313 class CWalletTx : public CMerkleTx
314 {
315 private:
316     const CWallet* pwallet;
317
318 public:
319     std::vector<CMerkleTx> vtxPrev;
320     std::map<std::string, std::string> mapValue;
321     std::vector<std::pair<std::string, std::string> > vOrderForm;
322     unsigned int fTimeReceivedIsTxTime;
323     unsigned int nTimeReceived;  // time received by this node
324     char fFromMe;
325     std::string strFromAccount;
326     std::vector<char> vfSpent; // which outputs are already spent
327
328     // memory only
329     mutable bool fDebitCached;
330     mutable bool fCreditCached;
331     mutable bool fAvailableCreditCached;
332     mutable bool fChangeCached;
333     mutable int64 nDebitCached;
334     mutable int64 nCreditCached;
335     mutable int64 nAvailableCreditCached;
336     mutable int64 nChangeCached;
337
338     CWalletTx()
339     {
340         Init(NULL);
341     }
342
343     CWalletTx(const CWallet* pwalletIn)
344     {
345         Init(pwalletIn);
346     }
347
348     CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
349     {
350         Init(pwalletIn);
351     }
352
353     CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
354     {
355         Init(pwalletIn);
356     }
357
358     void Init(const CWallet* pwalletIn)
359     {
360         pwallet = pwalletIn;
361         vtxPrev.clear();
362         mapValue.clear();
363         vOrderForm.clear();
364         fTimeReceivedIsTxTime = false;
365         nTimeReceived = 0;
366         fFromMe = false;
367         strFromAccount.clear();
368         vfSpent.clear();
369         fDebitCached = false;
370         fCreditCached = false;
371         fAvailableCreditCached = false;
372         fChangeCached = false;
373         nDebitCached = 0;
374         nCreditCached = 0;
375         nAvailableCreditCached = 0;
376         nChangeCached = 0;
377     }
378
379     IMPLEMENT_SERIALIZE
380     (
381         CWalletTx* pthis = const_cast<CWalletTx*>(this);
382         if (fRead)
383             pthis->Init(NULL);
384         char fSpent = false;
385
386         if (!fRead)
387         {
388             pthis->mapValue["fromaccount"] = pthis->strFromAccount;
389
390             std::string str;
391             BOOST_FOREACH(char f, vfSpent)
392             {
393                 str += (f ? '1' : '0');
394                 if (f)
395                     fSpent = true;
396             }
397             pthis->mapValue["spent"] = str;
398         }
399
400         nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
401         READWRITE(vtxPrev);
402         READWRITE(mapValue);
403         READWRITE(vOrderForm);
404         READWRITE(fTimeReceivedIsTxTime);
405         READWRITE(nTimeReceived);
406         READWRITE(fFromMe);
407         READWRITE(fSpent);
408
409         if (fRead)
410         {
411             pthis->strFromAccount = pthis->mapValue["fromaccount"];
412
413             if (mapValue.count("spent"))
414                 BOOST_FOREACH(char c, pthis->mapValue["spent"])
415                     pthis->vfSpent.push_back(c != '0');
416             else
417                 pthis->vfSpent.assign(vout.size(), fSpent);
418         }
419
420         pthis->mapValue.erase("fromaccount");
421         pthis->mapValue.erase("version");
422         pthis->mapValue.erase("spent");
423     )
424
425     // marks certain txout's as spent
426     // returns true if any update took place
427     bool UpdateSpent(const std::vector<char>& vfNewSpent)
428     {
429         bool fReturn = false;
430         for (unsigned int i = 0; i < vfNewSpent.size(); i++)
431         {
432             if (i == vfSpent.size())
433                 break;
434
435             if (vfNewSpent[i] && !vfSpent[i])
436             {
437                 vfSpent[i] = true;
438                 fReturn = true;
439                 fAvailableCreditCached = false;
440             }
441         }
442         return fReturn;
443     }
444
445     // make sure balances are recalculated
446     void MarkDirty()
447     {
448         fCreditCached = false;
449         fAvailableCreditCached = false;
450         fDebitCached = false;
451         fChangeCached = false;
452     }
453
454     void BindWallet(CWallet *pwalletIn)
455     {
456         pwallet = pwalletIn;
457         MarkDirty();
458     }
459
460     void MarkSpent(unsigned int nOut)
461     {
462         if (nOut >= vout.size())
463             throw std::runtime_error("CWalletTx::MarkSpent() : nOut out of range");
464         vfSpent.resize(vout.size());
465         if (!vfSpent[nOut])
466         {
467             vfSpent[nOut] = true;
468             fAvailableCreditCached = false;
469         }
470     }
471
472     void MarkUnspent(unsigned int nOut)
473     {
474         if (nOut >= vout.size())
475             throw std::runtime_error("CWalletTx::MarkUnspent() : nOut out of range");
476         vfSpent.resize(vout.size());
477         if (vfSpent[nOut])
478         {
479             vfSpent[nOut] = false;
480             fAvailableCreditCached = false;
481         }
482     }
483
484     bool IsSpent(unsigned int nOut) const
485     {
486         if (nOut >= vout.size())
487             throw std::runtime_error("CWalletTx::IsSpent() : nOut out of range");
488         if (nOut >= vfSpent.size())
489             return false;
490         return (!!vfSpent[nOut]);
491     }
492
493     int64 GetDebit() const
494     {
495         if (vin.empty())
496             return 0;
497         if (fDebitCached)
498             return nDebitCached;
499         nDebitCached = pwallet->GetDebit(*this);
500         fDebitCached = true;
501         return nDebitCached;
502     }
503
504     int64 GetCredit(bool fUseCache=true) const
505     {
506         // Must wait until coinbase is safely deep enough in the chain before valuing it
507         if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0)
508             return 0;
509
510         // GetBalance can assume transactions in mapWallet won't change
511         if (fUseCache && fCreditCached)
512             return nCreditCached;
513         nCreditCached = pwallet->GetCredit(*this);
514         fCreditCached = true;
515         return nCreditCached;
516     }
517
518     int64 GetAvailableCredit(bool fUseCache=true) const
519     {
520         // Must wait until coinbase is safely deep enough in the chain before valuing it
521         if ((IsCoinBase() || IsCoinStake()) && GetBlocksToMaturity() > 0)
522             return 0;
523
524         if (fUseCache && fAvailableCreditCached)
525             return nAvailableCreditCached;
526
527         int64 nCredit = 0;
528         for (unsigned int i = 0; i < vout.size(); i++)
529         {
530             if (!IsSpent(i))
531             {
532                 const CTxOut &txout = vout[i];
533                 nCredit += pwallet->GetCredit(txout);
534                 if (!MoneyRange(nCredit))
535                     throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
536             }
537         }
538
539         nAvailableCreditCached = nCredit;
540         fAvailableCreditCached = true;
541         return nCredit;
542     }
543
544
545     int64 GetChange() const
546     {
547         if (fChangeCached)
548             return nChangeCached;
549         nChangeCached = pwallet->GetChange(*this);
550         fChangeCached = true;
551         return nChangeCached;
552     }
553
554     void GetAmounts(int64& nGeneratedImmature, int64& nGeneratedMature, std::list<std::pair<CBitcoinAddress, int64> >& listReceived,
555                     std::list<std::pair<CBitcoinAddress, int64> >& listSent, int64& nFee, std::string& strSentAccount) const;
556
557     void GetAccountAmounts(const std::string& strAccount, int64& nGenerated, int64& nReceived, 
558                            int64& nSent, int64& nFee) const;
559
560     bool IsFromMe() const
561     {
562         return (GetDebit() > 0);
563     }
564
565     bool IsConfirmed() const
566     {
567         // Quick answer in most cases
568         if (!IsFinal())
569             return false;
570         if (GetDepthInMainChain() >= 1)
571             return true;
572         if (!IsFromMe()) // using wtx's cached debit
573             return false;
574
575         // If no confirmations but it's from us, we can still
576         // consider it confirmed if all dependencies are confirmed
577         std::map<uint256, const CMerkleTx*> mapPrev;
578         std::vector<const CMerkleTx*> vWorkQueue;
579         vWorkQueue.reserve(vtxPrev.size()+1);
580         vWorkQueue.push_back(this);
581         for (unsigned int i = 0; i < vWorkQueue.size(); i++)
582         {
583             const CMerkleTx* ptx = vWorkQueue[i];
584
585             if (!ptx->IsFinal())
586                 return false;
587             if (ptx->GetDepthInMainChain() >= 1)
588                 continue;
589             if (!pwallet->IsFromMe(*ptx))
590                 return false;
591
592             if (mapPrev.empty())
593             {
594                 BOOST_FOREACH(const CMerkleTx& tx, vtxPrev)
595                     mapPrev[tx.GetHash()] = &tx;
596             }
597
598             BOOST_FOREACH(const CTxIn& txin, ptx->vin)
599             {
600                 if (!mapPrev.count(txin.prevout.hash))
601                     return false;
602                 vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
603             }
604         }
605         return true;
606     }
607
608     bool WriteToDisk();
609
610     int64 GetTxTime() const;
611     int GetRequestCount() const;
612
613     void AddSupportingTransactions(CTxDB& txdb);
614
615     bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
616     bool AcceptWalletTransaction();
617
618     void RelayWalletTransaction(CTxDB& txdb);
619     void RelayWalletTransaction();
620 };
621
622
623 /** Private key that includes an expiration date in case it never gets used. */
624 class CWalletKey
625 {
626 public:
627     CPrivKey vchPrivKey;
628     int64 nTimeCreated;
629     int64 nTimeExpires;
630     std::string strComment;
631     //// todo: add something to note what created it (user, getnewaddress, change)
632     ////   maybe should have a map<string, string> property map
633
634     CWalletKey(int64 nExpires=0)
635     {
636         nTimeCreated = (nExpires ? GetTime() : 0);
637         nTimeExpires = nExpires;
638     }
639
640     IMPLEMENT_SERIALIZE
641     (
642         if (!(nType & SER_GETHASH))
643             READWRITE(nVersion);
644         READWRITE(vchPrivKey);
645         READWRITE(nTimeCreated);
646         READWRITE(nTimeExpires);
647         READWRITE(strComment);
648     )
649 };
650
651
652
653
654
655
656 /** Account information.
657  * Stored in wallet with key "acc"+string account name.
658  */
659 class CAccount
660 {
661 public:
662     std::vector<unsigned char> vchPubKey;
663
664     CAccount()
665     {
666         SetNull();
667     }
668
669     void SetNull()
670     {
671         vchPubKey.clear();
672     }
673
674     IMPLEMENT_SERIALIZE
675     (
676         if (!(nType & SER_GETHASH))
677             READWRITE(nVersion);
678         READWRITE(vchPubKey);
679     )
680 };
681
682
683
684 /** Internal transfers.
685  * Database key is acentry<account><counter>.
686  */
687 class CAccountingEntry
688 {
689 public:
690     std::string strAccount;
691     int64 nCreditDebit;
692     int64 nTime;
693     std::string strOtherAccount;
694     std::string strComment;
695
696     CAccountingEntry()
697     {
698         SetNull();
699     }
700
701     void SetNull()
702     {
703         nCreditDebit = 0;
704         nTime = 0;
705         strAccount.clear();
706         strOtherAccount.clear();
707         strComment.clear();
708     }
709
710     IMPLEMENT_SERIALIZE
711     (
712         if (!(nType & SER_GETHASH))
713             READWRITE(nVersion);
714         // Note: strAccount is serialized as part of the key, not here.
715         READWRITE(nCreditDebit);
716         READWRITE(nTime);
717         READWRITE(strOtherAccount);
718         READWRITE(strComment);
719     )
720 };
721
722 bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
723
724 #endif