Merge with Bitcoin v0.6.3
[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 // Distributed under the MIT/X11 software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 #ifndef BITCOIN_WALLET_H
7 #define BITCOIN_WALLET_H
8
9 #include "main.h"
10 #include "key.h"
11 #include "keystore.h"
12 #include "script.h"
13
14 extern bool fWalletUnlockStakeOnly;
15
16 class CWalletTx;
17 class CReserveKey;
18 class CWalletDB;
19
20 /** (client) version numbers for particular wallet features */
21 enum WalletFeature
22 {
23     FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output)
24
25     FEATURE_WALLETCRYPT = 40000, // wallet encryption
26     FEATURE_COMPRPUBKEY = 60000, // compressed public keys
27
28     FEATURE_LATEST = 60000
29 };
30
31
32 /** A key pool entry */
33 class CKeyPool
34 {
35 public:
36     int64 nTime;
37     std::vector<unsigned char> vchPubKey;
38
39     CKeyPool()
40     {
41         nTime = GetTime();
42     }
43
44     CKeyPool(const std::vector<unsigned char>& vchPubKeyIn)
45     {
46         nTime = GetTime();
47         vchPubKey = vchPubKeyIn;
48     }
49
50     IMPLEMENT_SERIALIZE
51     (
52         if (!(nType & SER_GETHASH))
53             READWRITE(nVersion);
54         READWRITE(nTime);
55         READWRITE(vchPubKey);
56     )
57 };
58
59 /** A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
60  * and provides the ability to create new transactions.
61  */
62 class CWallet : public CCryptoKeyStore
63 {
64 private:
65     bool SelectCoinsMinConf(int64 nTargetValue, unsigned int nSpendTime, int nConfMine, int nConfTheirs, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
66     bool SelectCoins(int64 nTargetValue, unsigned int nSpendTime, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const;
67
68     CWalletDB *pwalletdbEncryption;
69
70     // the current wallet version: clients below this version are not able to load the wallet
71     int nWalletVersion;
72
73     // the maxmimum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
74     int nWalletMaxVersion;
75
76 public:
77     mutable CCriticalSection cs_wallet;
78
79     bool fFileBacked;
80     std::string strWalletFile;
81
82     std::set<int64> setKeyPool;
83
84
85     typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
86     MasterKeyMap mapMasterKeys;
87     unsigned int nMasterKeyMaxID;
88
89     CWallet()
90     {
91         nWalletVersion = FEATURE_BASE;
92         nWalletMaxVersion = FEATURE_BASE;
93         fFileBacked = false;
94         nMasterKeyMaxID = 0;
95         pwalletdbEncryption = NULL;
96     }
97     CWallet(std::string strWalletFileIn)
98     {
99         nWalletVersion = FEATURE_BASE;
100         nWalletMaxVersion = FEATURE_BASE;
101         strWalletFile = strWalletFileIn;
102         fFileBacked = true;
103         nMasterKeyMaxID = 0;
104         pwalletdbEncryption = NULL;
105     }
106
107     std::map<uint256, CWalletTx> mapWallet;
108     std::vector<uint256> vWalletUpdated;
109
110     std::map<uint256, int> mapRequestCount;
111
112     std::map<CBitcoinAddress, std::string> mapAddressBook;
113
114     std::vector<unsigned char> vchDefaultKey;
115
116     // check whether we are allowed to upgrade (or already support) to the named feature
117     bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
118
119     // keystore implementation
120     // Generate a new key
121     std::vector<unsigned char> GenerateNewKey();
122     // Adds a key to the store, and saves it to disk.
123     bool AddKey(const CKey& key);
124     // Adds a key to the store, without saving it to disk (used by LoadWallet)
125     bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
126
127     bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
128
129     // Adds an encrypted key to the store, and saves it to disk.
130     bool AddCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
131     // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
132     bool LoadCryptedKey(const std::vector<unsigned char> &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
133     bool AddCScript(const CScript& redeemScript);
134     bool LoadCScript(const CScript& redeemScript) { return CCryptoKeyStore::AddCScript(redeemScript); }
135
136     bool Unlock(const SecureString& strWalletPassphrase);
137     bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
138     bool EncryptWallet(const SecureString& strWalletPassphrase);
139
140     void MarkDirty();
141     bool AddToWallet(const CWalletTx& wtxIn);
142     bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false, bool fFindBlock = false);
143     bool EraseFromWallet(uint256 hash);
144     void WalletUpdateSpent(const CTransaction& prevout);
145     int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
146     int ScanForWalletTransaction(const uint256& hashTx);
147     void ReacceptWalletTransactions();
148     void ResendWalletTransactions();
149     int64 GetBalance() const;
150     int64 GetUnconfirmedBalance() const;
151     int64 GetStake() const;
152     int64 GetNewMint() const;
153     bool CreateTransaction(const std::vector<std::pair<CScript, int64> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
154     bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64& nFeeRet);
155     bool CreateCoinStake(unsigned int nBits, CTransaction& txNew);
156     bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
157     std::string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
158     std::string SendMoneyToBitcoinAddress(const CBitcoinAddress& address, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);
159
160     bool NewKeyPool();
161     bool TopUpKeyPool();
162     int64 AddReserveKey(const CKeyPool& keypool);
163     void ReserveKeyFromKeyPool(int64& nIndex, CKeyPool& keypool);
164     void KeepKey(int64 nIndex);
165     void ReturnKey(int64 nIndex);
166     bool GetKeyFromPool(std::vector<unsigned char> &key, bool fAllowReuse=true);
167     int64 GetOldestKeyPoolTime();
168     void GetAllReserveAddresses(std::set<CBitcoinAddress>& setAddress);
169
170     bool IsMine(const CTxIn& txin) const;
171     int64 GetDebit(const CTxIn& txin) const;
172     bool IsMine(const CTxOut& txout) const
173     {
174         return ::IsMine(*this, txout.scriptPubKey);
175     }
176     int64 GetCredit(const CTxOut& txout) const
177     {
178         if (!MoneyRange(txout.nValue))
179             throw std::runtime_error("CWallet::GetCredit() : value out of range");
180         return (IsMine(txout) ? txout.nValue : 0);
181     }
182     bool IsChange(const CTxOut& txout) const;
183     int64 GetChange(const CTxOut& txout) const
184     {
185         if (!MoneyRange(txout.nValue))
186             throw std::runtime_error("CWallet::GetChange() : value out of range");
187         return (IsChange(txout) ? txout.nValue : 0);
188     }
189     bool IsMine(const CTransaction& tx) const
190     {
191         BOOST_FOREACH(const CTxOut& txout, tx.vout)
192             if (IsMine(txout))
193                 return true;
194         return false;
195     }
196     bool IsFromMe(const CTransaction& tx) const
197     {
198         return (GetDebit(tx) > 0);
199     }
200     int64 GetDebit(const CTransaction& tx) const
201     {
202         int64 nDebit = 0;
203         BOOST_FOREACH(const CTxIn& txin, tx.vin)
204         {
205             nDebit += GetDebit(txin);
206             if (!MoneyRange(nDebit))
207                 throw std::runtime_error("CWallet::GetDebit() : value out of range");
208         }
209         return nDebit;
210     }
211     int64 GetCredit(const CTransaction& tx) const
212     {
213         int64 nCredit = 0;
214         BOOST_FOREACH(const CTxOut& txout, tx.vout)
215         {
216             nCredit += GetCredit(txout);
217             if (!MoneyRange(nCredit))
218                 throw std::runtime_error("CWallet::GetCredit() : value out of range");
219         }
220         return nCredit;
221     }
222     int64 GetChange(const CTransaction& tx) const
223     {
224         int64 nChange = 0;
225         BOOST_FOREACH(const CTxOut& txout, tx.vout)
226         {
227             nChange += GetChange(txout);
228             if (!MoneyRange(nChange))
229                 throw std::runtime_error("CWallet::GetChange() : value out of range");
230         }
231         return nChange;
232     }
233     void SetBestChain(const CBlockLocator& loc);
234
235     int LoadWallet(bool& fFirstRunRet);
236
237     bool SetAddressBookName(const CBitcoinAddress& address, const std::string& strName);
238
239     bool DelAddressBookName(const CBitcoinAddress& address);
240
241     void UpdatedTransaction(const uint256 &hashTx)
242     {
243         {
244             LOCK(cs_wallet);
245             vWalletUpdated.push_back(hashTx);
246         }
247     }
248
249     void PrintWallet(const CBlock& block);
250
251     void Inventory(const uint256 &hash)
252     {
253         {
254             LOCK(cs_wallet);
255             std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
256             if (mi != mapRequestCount.end())
257                 (*mi).second++;
258         }
259     }
260
261     int GetKeyPoolSize()
262     {
263         return setKeyPool.size();
264     }
265
266     bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
267
268     bool SetDefaultKey(const std::vector<unsigned char> &vchPubKey);
269
270     // signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
271     bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
272
273     // change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
274     bool SetMaxVersion(int nVersion);
275
276     // get the current wallet format (the oldest client version guaranteed to understand this wallet)
277     int GetVersion() { return nWalletVersion; }
278
279     bool CheckSpentCoins(int& nMismatchSpent, int64& nBalanceInQuestion);
280     void FixSpentCoins(int& nMismatchSpent, int64& nBalanceInQuestion);
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