Includes cleanup
[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 "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     CKeyPool(const CPubKey& vchPubKeyIn);
55
56     IMPLEMENT_SERIALIZE
57     (
58         if (!(nType & SER_GETHASH))
59             READWRITE(nVersion);
60         READWRITE(nTime);
61         READWRITE(vchPubKey);
62     )
63 };
64
65 /** A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
66  * and provides the ability to create new transactions.
67  */
68 class CWallet : public CCryptoKeyStore
69 {
70 private:
71     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;
72
73     CWalletDB *pwalletdbEncryption, *pwalletdbDecryption;
74
75     // the current wallet version: clients below this version are not able to load the wallet
76     int nWalletVersion;
77
78     // the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
79     int nWalletMaxVersion;
80
81     int64_t nNextResend;
82     int64_t nLastResend;
83
84     // stake mining statistics
85     uint64_t nKernelsTried;
86     uint64_t nCoinDaysTried;
87
88 public:
89     mutable CCriticalSection cs_wallet;
90
91     bool fFileBacked;
92     std::string strWalletFile;
93
94     std::set<int64_t> setKeyPool;
95     /*
96     std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
97     std::map<CMalleableKeyView, CKeyMetadata> mapMalleableKeyMetadata;
98     */
99
100     std::map<CBitcoinAddress, CKeyMetadata> mapKeyMetadata;
101
102     typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
103     MasterKeyMap mapMasterKeys;
104     unsigned int nMasterKeyMaxID;
105
106     CWallet();
107     CWallet(std::string strWalletFileIn);
108     void SetNull();
109
110     std::map<uint256, CWalletTx> mapWallet;
111     std::vector<uint256> vMintingWalletUpdated;
112     int64_t nOrderPosNext;
113     std::map<uint256, int> mapRequestCount;
114
115     std::map<CBitcoinAddress, std::string> mapAddressBook;
116
117     CPubKey vchDefaultKey;
118     int64_t nTimeFirstKey;
119
120     const CWalletTx* GetWalletTx(const uint256& hash) const;
121
122     // check whether we are allowed to upgrade (or already support) to the named feature
123     bool CanSupportFeature(enum WalletFeature wf) { return nWalletMaxVersion >= wf; }
124
125     void AvailableCoinsMinConf(std::vector<COutput>& vCoins, int nConf, int64_t nMinValue, int64_t nMaxValue) const;
126     void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl=NULL) const;
127     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;
128
129     // Simple select (without randomization)
130     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;
131
132     // keystore implementation
133     // Generate a new key
134     CPubKey GenerateNewKey();
135     CMalleableKeyView GenerateNewMalleableKey();
136     // Adds a key to the store, and saves it to disk.
137     bool AddKey(const CKey& key);
138     bool AddKey(const CMalleableKey& mKey);
139     // Adds a key to the store, without saving it to disk (used by LoadWallet)
140     bool LoadKey(const CKey& key) { return CCryptoKeyStore::AddKey(key); }
141     // Load metadata (used by LoadWallet)
142     bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
143     bool LoadKeyMetadata(const CMalleableKeyView &keyView, const CKeyMetadata &metadata);
144
145     // Load malleable key without saving it to disk (used by LoadWallet)
146     bool LoadKey(const CMalleableKeyView &keyView, const CSecret &vchSecretH) { return CCryptoKeyStore::AddMalleableKey(keyView, vchSecretH); }
147     bool LoadCryptedKey(const CMalleableKeyView &keyView, const std::vector<unsigned char> &vchCryptedSecretH) { return CCryptoKeyStore::AddCryptedMalleableKey(keyView, vchCryptedSecretH); }
148
149     bool LoadMinVersion(int nVersion) { nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
150
151     // Adds an encrypted key to the store, and saves it to disk.
152     bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
153     bool AddCryptedMalleableKey(const CMalleableKeyView& keyView, const std::vector<unsigned char> &vchCryptedSecretH);
154     // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
155     bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret) { SetMinVersion(FEATURE_WALLETCRYPT); return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); }
156     bool AddCScript(const CScript& redeemScript);
157     bool LoadCScript(const CScript& redeemScript);
158
159     // Adds a watch-only address to the store, and saves it to disk.
160     bool AddWatchOnly(const CScript &dest);
161     bool RemoveWatchOnly(const CScript &dest);
162     // Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
163     bool LoadWatchOnly(const CScript &dest);
164
165     bool Unlock(const SecureString& strWalletPassphrase);
166     bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
167     bool EncryptWallet(const SecureString& strWalletPassphrase);
168     bool DecryptWallet(const SecureString& strWalletPassphrase);
169
170     void GetAddresses(std::map<CBitcoinAddress, int64_t> &mapAddresses) const;
171
172
173     /** Increment the next transaction order id
174         @return next transaction order id
175      */
176     int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL);
177
178     typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
179     typedef std::multimap<int64_t, TxPair > TxItems;
180
181     /** Get the wallet's activity log
182         @return multimap of ordered transactions and accounting entries
183         @warning Returned pointers are *only* valid within the scope of passed acentries
184      */
185     TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = "");
186
187     void MarkDirty();
188     bool AddToWallet(const CWalletTx& wtxIn);
189     bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate = false);
190     bool EraseFromWallet(uint256 hash);
191     void ClearOrphans();
192     void WalletUpdateSpent(const CTransaction& prevout, bool fBlock = false);
193     int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
194     int ScanForWalletTransaction(const uint256& hashTx);
195     void ReacceptWalletTransactions();
196     void ResendWalletTransactions(int64_t nBestBlockTime);
197     std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime);
198     int64_t GetBalance() const;
199     int64_t GetWatchOnlyBalance() const;
200     int64_t GetUnconfirmedBalance() const;
201     int64_t GetUnconfirmedWatchOnlyBalance() const;
202     int64_t GetImmatureBalance() const;
203     int64_t GetImmatureWatchOnlyBalance() const;
204     int64_t GetStake() const;
205     int64_t GetNewMint() const;
206     int64_t GetWatchOnlyStake() const;
207     int64_t GetWatchOnlyNewMint() const;
208     bool CreateTransaction(const std::vector<std::pair<CScript, int64_t> >& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, const CCoinControl *coinControl=NULL);
209     bool CreateTransaction(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, const CCoinControl *coinControl=NULL);
210     bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
211
212     void GetStakeWeightFromValue(const int64_t& nTime, const int64_t& nValue, uint64_t& nWeight);
213     bool CreateCoinStake(uint256 &hashTx, uint32_t nOut, uint32_t nTime, uint32_t nBits, CTransaction &txNew, CKey& key);
214     bool MergeCoins(const int64_t& nAmount, const int64_t& nMinValue, const int64_t& nMaxValue, std::list<uint256>& listMerged);
215
216     std::string SendMoney(CScript scriptPubKey, int64_t nValue, CWalletTx& wtxNew, bool fAskFee=false);
217
218     bool NewKeyPool(unsigned int nSize = 0);
219     bool TopUpKeyPool(unsigned int nSize = 0);
220     int64_t AddReserveKey(const CKeyPool& keypool);
221     void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool);
222     void KeepKey(int64_t nIndex);
223     void ReturnKey(int64_t nIndex);
224     bool GetKeyFromPool(CPubKey &key, bool fAllowReuse=true);
225     int64_t GetOldestKeyPoolTime();
226     void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
227
228     std::set< std::set<CBitcoinAddress> > GetAddressGroupings();
229     std::map<CBitcoinAddress, int64_t> GetAddressBalances();
230
231     isminetype IsMine(const CTxIn& txin) const;
232     int64_t GetDebit(const CTxIn& txin, const isminefilter& filter) const;
233     isminetype IsMine(const CTxOut& txout) const;
234     int64_t GetCredit(const CTxOut& txout, const isminefilter& filter) const;
235     bool IsChange(const CTxOut& txout) const;
236     int64_t GetChange(const CTxOut& txout) const;
237     bool IsMine(const CTransaction& tx) const;
238     bool IsFromMe(const CTransaction& tx) const;
239     int64_t GetDebit(const CTransaction& tx, const isminefilter& filter) const;
240     int64_t GetCredit(const CTransaction& tx, const isminefilter& filter) const;
241     int64_t GetChange(const CTransaction& tx) const;
242     void SetBestChain(const CBlockLocator& loc);
243
244     DBErrors LoadWallet(bool& fFirstRunRet);
245     DBErrors ZapWalletTx();
246
247     bool SetAddressBookName(const CTxDestination& address, const std::string& strName);
248     bool SetAddressBookName(const CBitcoinAddress& address, const std::string& strName);
249     bool DelAddressBookName(const CBitcoinAddress& address);
250     void UpdatedTransaction(const uint256 &hashTx);
251     void PrintWallet(const CBlock& block);
252
253     void Inventory(const uint256 &hash);
254
255     unsigned int GetKeyPoolSize();
256
257     bool GetTransaction(const uint256 &hashTx, CWalletTx& wtx);
258     bool SetDefaultKey(const CPubKey &vchPubKey);
259
260     // signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
261     bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
262
263     // change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
264     bool SetMaxVersion(int nVersion);
265
266     // get the current wallet format (the oldest client version guaranteed to understand this wallet)
267     int GetVersion() { return nWalletVersion; }
268
269     void FixSpentCoins(int& nMismatchSpent, int64_t& nBalanceInQuestion, bool fCheckOnly = false);
270     void DisableTransaction(const CTransaction &tx);
271
272     /** Address book entry changed.
273      * @note called with lock cs_wallet held.
274      */
275     boost::signals2::signal<void (CWallet *wallet, const CBitcoinAddress &address, const std::string &label, bool isMine, ChangeType status)> NotifyAddressBookChanged;
276
277     /** Wallet transaction added, removed or updated.
278      * @note called with lock cs_wallet held.
279      */
280     boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged;
281
282     /** Watch-only address added */
283     boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
284 };
285
286 /** A key allocated from the key pool. */
287 class CReserveKey
288 {
289 protected:
290     CWallet* pwallet;
291     int64_t nIndex;
292     CPubKey vchPubKey;
293 public:
294     CReserveKey(CWallet* pwalletIn);
295
296     ~CReserveKey();
297
298     void ReturnKey();
299     CPubKey GetReservedKey();
300     void KeepKey();
301 };
302
303
304 typedef std::map<std::string, std::string> mapValue_t;
305
306
307 static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
308 {
309     if (!mapValue.count("n"))
310     {
311         nOrderPos = -1; // TODO: calculate elsewhere
312         return;
313     }
314     nOrderPos = atoi64(mapValue["n"].c_str());
315 }
316
317
318 static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
319 {
320     if (nOrderPos == -1)
321         return;
322     mapValue["n"] = i64tostr(nOrderPos);
323 }
324
325
326 /** A transaction with a bunch of additional info that only the owner cares about.
327  * It includes any unrecorded transactions needed to link it back to the block chain.
328  */
329 class CWalletTx : public CMerkleTx
330 {
331 private:
332     const CWallet* pwallet;
333
334 public:
335     std::vector<CMerkleTx> vtxPrev;
336     mapValue_t mapValue;
337     std::vector<std::pair<std::string, std::string> > vOrderForm;
338     unsigned int fTimeReceivedIsTxTime;
339     unsigned int nTimeReceived;  // time received by this node
340     unsigned int nTimeSmart;
341     char fFromMe;
342     std::string strFromAccount;
343     std::vector<char> vfSpent; // which outputs are already spent
344     int64_t nOrderPos;  // position in ordered transaction list
345
346     // memory only
347     mutable bool fDebitCached;
348     mutable bool fWatchDebitCached;
349     mutable bool fCreditCached;
350     mutable bool fWatchCreditCached;
351     mutable bool fAvailableCreditCached;
352     mutable bool fImmatureCreditCached;
353     mutable bool fImmatureWatchCreditCached;
354     mutable bool fAvailableWatchCreditCached;
355     mutable bool fChangeCached;
356     mutable int64_t nDebitCached;
357     mutable int64_t nWatchDebitCached;
358     mutable int64_t nCreditCached;
359     mutable int64_t nWatchCreditCached;
360     mutable int64_t nAvailableCreditCached;
361     mutable int64_t nImmatureCreditCached;
362     mutable int64_t nImmatureWatchCreditCached;
363     mutable int64_t nAvailableWatchCreditCached;
364     mutable int64_t nChangeCached;
365
366     CWalletTx()
367     {
368         Init(NULL);
369     }
370
371     CWalletTx(const CWallet* pwalletIn)
372     {
373         Init(pwalletIn);
374     }
375
376     CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
377     {
378         Init(pwalletIn);
379     }
380
381     CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
382     {
383         Init(pwalletIn);
384     }
385
386     void Init(const CWallet* pwalletIn);
387
388     IMPLEMENT_SERIALIZE
389     (
390         CWalletTx* pthis = const_cast<CWalletTx*>(this);
391         if (fRead)
392             pthis->Init(NULL);
393         char fSpent = false;
394
395         if (!fRead)
396         {
397             pthis->mapValue["fromaccount"] = pthis->strFromAccount;
398
399             std::string str;
400             for (char f : vfSpent)
401             {
402                 str += (f ? '1' : '0');
403                 if (f)
404                     fSpent = true;
405             }
406             pthis->mapValue["spent"] = str;
407
408             WriteOrderPos(pthis->nOrderPos, pthis->mapValue);
409
410             if (nTimeSmart)
411                 pthis->mapValue["timesmart"] = strprintf("%u", nTimeSmart);
412         }
413
414         nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
415         READWRITE(vtxPrev);
416         READWRITE(mapValue);
417         READWRITE(vOrderForm);
418         READWRITE(fTimeReceivedIsTxTime);
419         READWRITE(nTimeReceived);
420         READWRITE(fFromMe);
421         READWRITE(fSpent);
422
423         if (fRead)
424         {
425             pthis->strFromAccount = pthis->mapValue["fromaccount"];
426
427             if (mapValue.count("spent"))
428                 for (char c : pthis->mapValue["spent"])
429                     pthis->vfSpent.push_back(c != '0');
430             else
431                 pthis->vfSpent.assign(vout.size(), fSpent);
432
433             ReadOrderPos(pthis->nOrderPos, pthis->mapValue);
434
435             pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0;
436         }
437
438         pthis->mapValue.erase("fromaccount");
439         pthis->mapValue.erase("version");
440         pthis->mapValue.erase("spent");
441         pthis->mapValue.erase("n");
442         pthis->mapValue.erase("timesmart");
443     )
444
445     // marks certain txout's as spent
446     // returns true if any update took place
447     bool UpdateSpent(const std::vector<char>& vfNewSpent);
448
449     // make sure balances are recalculated
450     void MarkDirty();
451     void BindWallet(CWallet *pwalletIn);
452     void MarkSpent(unsigned int nOut);
453     void MarkUnspent(unsigned int nOut);
454     bool IsSpent(unsigned int nOut) const;
455
456     int64_t GetDebit(const isminefilter& filter) const;
457     int64_t GetCredit(const isminefilter& filter) const;
458     int64_t GetImmatureCredit(bool fUseCache=true) const;
459     int64_t GetImmatureWatchOnlyCredit(bool fUseCache=true) const;
460     int64_t GetAvailableCredit(bool fUseCache=true) const;
461     int64_t GetAvailableWatchCredit(bool fUseCache=true) const;
462     int64_t GetChange() const;
463
464     void GetAmounts(int64_t& nGeneratedImmature, int64_t& nGeneratedMature, std::list<std::pair<CBitcoinAddress, int64_t> >& listReceived,
465                     std::list<std::pair<CBitcoinAddress, int64_t> >& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter) const;
466
467     void GetAccountAmounts(const std::string& strAccount, int64_t& nGenerated, int64_t& nReceived,
468                            int64_t& nSent, int64_t& nFee, const isminefilter& filter) const;
469
470     bool IsFromMe(const isminefilter& filter) const
471     {
472         return (GetDebit(filter) > 0);
473     }
474
475     bool InMempool() const;
476     bool IsTrusted() const;
477
478     bool WriteToDisk();
479
480     int64_t GetTxTime() const;
481     int GetRequestCount() const;
482
483     void AddSupportingTransactions(CTxDB& txdb);
484
485     bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
486     bool AcceptWalletTransaction();
487
488     bool RelayWalletTransaction(CTxDB& txdb);
489     bool RelayWalletTransaction();
490 };
491
492
493
494
495 class COutput
496 {
497 public:
498     const CWalletTx *tx;
499     int i;
500     int nDepth;
501     bool fSpendable;
502
503     COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn);
504
505     std::string ToString() const;
506 };
507
508
509
510
511 /** Private key that includes an expiration date in case it never gets used. */
512 class CWalletKey
513 {
514 public:
515     CPrivKey vchPrivKey;
516     int64_t nTimeCreated;
517     int64_t nTimeExpires;
518     std::string strComment;
519     //// todo: add something to note what created it (user, getnewaddress, change)
520     ////   maybe should have a map<string, string> property map
521
522     CWalletKey(int64_t nExpires=0);
523
524     IMPLEMENT_SERIALIZE
525     (
526         if (!(nType & SER_GETHASH))
527             READWRITE(nVersion);
528         READWRITE(vchPrivKey);
529         READWRITE(nTimeCreated);
530         READWRITE(nTimeExpires);
531         READWRITE(strComment);
532     )
533 };
534
535
536
537
538
539
540 /** Account information.
541  * Stored in wallet with key "acc"+string account name.
542  */
543 class CAccount
544 {
545 public:
546     CPubKey vchPubKey;
547
548     CAccount();
549
550     void SetNull();
551
552     IMPLEMENT_SERIALIZE
553     (
554         if (!(nType & SER_GETHASH))
555             READWRITE(nVersion);
556         READWRITE(vchPubKey);
557     )
558 };
559
560
561
562 /** Internal transfers.
563  * Database key is acentry<account><counter>.
564  */
565 class CAccountingEntry
566 {
567 public:
568     std::string strAccount;
569     int64_t nCreditDebit;
570     int64_t nTime;
571     std::string strOtherAccount;
572     std::string strComment;
573     mapValue_t mapValue;
574     int64_t nOrderPos;  // position in ordered transaction list
575     uint64_t nEntryNo;
576
577     CAccountingEntry();
578
579     void SetNull();
580
581     IMPLEMENT_SERIALIZE
582     (
583         CAccountingEntry& me = *const_cast<CAccountingEntry*>(this);
584         if (!(nType & SER_GETHASH))
585             READWRITE(nVersion);
586         // Note: strAccount is serialized as part of the key, not here.
587         READWRITE(nCreditDebit);
588         READWRITE(nTime);
589         READWRITE(strOtherAccount);
590
591         if (!fRead)
592         {
593             WriteOrderPos(nOrderPos, me.mapValue);
594
595             if (!(mapValue.empty() && _ssExtra.empty()))
596             {
597                 CDataStream ss(nType, nVersion);
598                 ss.insert(ss.begin(), '\0');
599                 ss << mapValue;
600                 ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
601                 me.strComment.append(ss.str());
602             }
603         }
604
605         READWRITE(strComment);
606
607         size_t nSepPos = strComment.find("\0", 0, 1);
608         if (fRead)
609         {
610             me.mapValue.clear();
611             if (std::string::npos != nSepPos)
612             {
613                 CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion);
614                 ss >> me.mapValue;
615                 me._ssExtra = std::vector<char>(ss.begin(), ss.end());
616             }
617             ReadOrderPos(me.nOrderPos, me.mapValue);
618         }
619         if (std::string::npos != nSepPos)
620             me.strComment.erase(nSepPos);
621
622         me.mapValue.erase("n");
623     )
624
625 private:
626     std::vector<char> _ssExtra;
627 };
628
629 bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
630
631 #endif