1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2013 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
13 #include "ui_interface.h"
27 extern CFeeRate payTxFee;
28 extern unsigned int nTxConfirmTarget;
29 extern bool bSpendZeroConfChange;
32 static const int64_t DEFAULT_TRANSACTION_FEE = 0;
33 // -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB
34 static const int nHighTransactionFeeWarning = 0.01 * COIN;
35 // Largest (in bytes) free transaction we're willing to create
36 static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
38 class CAccountingEntry;
45 /** (client) version numbers for particular wallet features */
48 FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output)
50 FEATURE_WALLETCRYPT = 40000, // wallet encryption
51 FEATURE_COMPRPUBKEY = 60000, // compressed public keys
53 FEATURE_LATEST = 60000
57 /** A key pool entry */
69 CKeyPool(const CPubKey& vchPubKeyIn)
72 vchPubKey = vchPubKeyIn;
77 if (!(nType & SER_GETHASH))
84 /** Address book data */
85 class CAddressBookData
96 typedef std::map<std::string, std::string> StringMap;
100 /** A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
101 * and provides the ability to create new transactions.
103 class CWallet : public CCryptoKeyStore, public CWalletInterface
106 bool SelectCoins(int64_t nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet, const CCoinControl *coinControl = NULL) const;
108 CWalletDB *pwalletdbEncryption;
110 // the current wallet version: clients below this version are not able to load the wallet
113 // the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
114 int nWalletMaxVersion;
119 // Used to keep track of spent outpoints, and
120 // detect and report conflicts (double-spends or
121 // mutated transactions where the mutant gets mined).
122 typedef std::multimap<COutPoint, uint256> TxSpends;
123 TxSpends mapTxSpends;
124 void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);
125 void AddToSpends(const uint256& wtxid);
127 void SyncMetaData(std::pair<TxSpends::iterator, TxSpends::iterator>);
130 /// Main wallet lock.
131 /// This lock protects all the fields added by CWallet
133 /// fFileBacked (immutable after instantiation)
134 /// strWalletFile (immutable after instantiation)
135 mutable CCriticalSection cs_wallet;
138 std::string strWalletFile;
140 std::set<int64_t> setKeyPool;
141 std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
143 typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
144 MasterKeyMap mapMasterKeys;
145 unsigned int nMasterKeyMaxID;
151 CWallet(std::string strWalletFileIn)
155 strWalletFile = strWalletFileIn;
160 nWalletVersion = FEATURE_BASE;
161 nWalletMaxVersion = FEATURE_BASE;
164 pwalletdbEncryption = NULL;
171 std::map<uint256, CWalletTx> mapWallet;
173 int64_t nOrderPosNext;
174 std::map<uint256, int> mapRequestCount;
176 std::map<CTxDestination, CAddressBookData> mapAddressBook;
178 CPubKey vchDefaultKey;
180 std::set<COutPoint> setLockedCoins;
182 int64_t nTimeFirstKey;
184 const CWalletTx* GetWalletTx(const uint256& hash) const;
186 // check whether we are allowed to upgrade (or already support) to the named feature
187 bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
189 void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL) const;
190 bool SelectCoinsMinConf(int64_t nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64_t& nValueRet) const;
192 bool IsSpent(const uint256& hash, unsigned int n) const;
194 bool IsLockedCoin(uint256 hash, unsigned int n) const;
195 void LockCoin(COutPoint& output);
196 void UnlockCoin(COutPoint& output);
197 void UnlockAllCoins();
198 void ListLockedCoins(std::vector<COutPoint>& vOutpts);
200 // keystore implementation
201 // Generate a new key
202 CPubKey GenerateNewKey();
203 // Adds a key to the store, and saves it to disk.
204 bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
205 // Adds a key to the store, without saving it to disk (used by LoadWallet)
206 bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
207 // Load metadata (used by LoadWallet)
208 bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
210 bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
212 // Adds an encrypted key to the store, and saves it to disk.
213 bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
214 // Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
215 bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
216 bool AddCScript(const CScript& redeemScript);
217 bool LoadCScript(const CScript& redeemScript);
219 /// Adds a destination data tuple to the store, and saves it to disk
220 bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
221 /// Erases a destination data tuple in the store and on disk
222 bool EraseDestData(const CTxDestination &dest, const std::string &key);
223 /// Adds a destination data tuple to the store, without saving it to disk
224 bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
225 /// Look up a destination data tuple in the store, return true if found false otherwise
226 bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const;
228 // Adds a watch-only address to the store, and saves it to disk.
229 bool AddWatchOnly(const CScript &dest);
230 // Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
231 bool LoadWatchOnly(const CScript &dest);
233 bool Unlock(const SecureString& strWalletPassphrase);
234 bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
235 bool EncryptWallet(const SecureString& strWalletPassphrase);
237 void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const;
239 /** Increment the next transaction order id
240 @return next transaction order id
242 int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL);
244 typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
245 typedef std::multimap<int64_t, TxPair > TxItems;
247 /** Get the wallet's activity log
248 @return multimap of ordered transactions and accounting entries
249 @warning Returned pointers are *only* valid within the scope of passed acentries
251 TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = "");
254 bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet=false);
255 void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
256 bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
257 void EraseFromWallet(const uint256 &hash);
258 int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
259 void ReacceptWalletTransactions();
260 void ResendWalletTransactions();
261 int64_t GetBalance() const;
262 int64_t GetUnconfirmedBalance() const;
263 int64_t GetImmatureBalance() const;
264 int64_t GetWatchOnlyBalance() const;
265 int64_t GetUnconfirmedWatchOnlyBalance() const;
266 int64_t GetImmatureWatchOnlyBalance() const;
267 bool CreateTransaction(const std::vector<std::pair<CScript, int64_t> >& vecSend,
268 CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
269 bool CreateTransaction(CScript scriptPubKey, int64_t nValue,
270 CWalletTx& wtxNew, CReserveKey& reservekey, int64_t& nFeeRet, std::string& strFailReason, const CCoinControl *coinControl = NULL);
271 bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
272 std::string SendMoney(const CTxDestination &address, int64_t nValue, CWalletTx& wtxNew);
274 static CFeeRate minTxFee;
275 static int64_t GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool);
278 bool TopUpKeyPool(unsigned int kpSize = 0);
279 void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool);
280 void KeepKey(int64_t nIndex);
281 void ReturnKey(int64_t nIndex);
282 bool GetKeyFromPool(CPubKey &key);
283 int64_t GetOldestKeyPoolTime();
284 void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
286 std::set< std::set<CTxDestination> > GetAddressGroupings();
287 std::map<CTxDestination, int64_t> GetAddressBalances();
289 std::set<CTxDestination> GetAccountAddresses(std::string strAccount) const;
291 isminetype IsMine(const CTxIn& txin) const;
292 int64_t GetDebit(const CTxIn& txin, const isminefilter& filter) const;
293 isminetype IsMine(const CTxOut& txout) const
295 return ::IsMine(*this, txout.scriptPubKey);
297 int64_t GetCredit(const CTxOut& txout, const isminefilter& filter) const
299 if (!MoneyRange(txout.nValue))
300 throw std::runtime_error("CWallet::GetCredit() : value out of range");
301 return ((IsMine(txout) & filter) ? txout.nValue : 0);
303 bool IsChange(const CTxOut& txout) const;
304 int64_t GetChange(const CTxOut& txout) const
306 if (!MoneyRange(txout.nValue))
307 throw std::runtime_error("CWallet::GetChange() : value out of range");
308 return (IsChange(txout) ? txout.nValue : 0);
310 bool IsMine(const CTransaction& tx) const
312 BOOST_FOREACH(const CTxOut& txout, tx.vout)
317 bool IsFromMe(const CTransaction& tx) const // should probably be renamed to IsRelevantToMe
319 return (GetDebit(tx, ISMINE_ALL) > 0);
321 int64_t GetDebit(const CTransaction& tx, const isminefilter& filter) const
324 BOOST_FOREACH(const CTxIn& txin, tx.vin)
326 nDebit += GetDebit(txin, filter);
327 if (!MoneyRange(nDebit))
328 throw std::runtime_error("CWallet::GetDebit() : value out of range");
332 int64_t GetCredit(const CTransaction& tx, const isminefilter& filter) const
335 BOOST_FOREACH(const CTxOut& txout, tx.vout)
337 nCredit += GetCredit(txout, filter);
338 if (!MoneyRange(nCredit))
339 throw std::runtime_error("CWallet::GetCredit() : value out of range");
343 int64_t GetChange(const CTransaction& tx) const
346 BOOST_FOREACH(const CTxOut& txout, tx.vout)
348 nChange += GetChange(txout);
349 if (!MoneyRange(nChange))
350 throw std::runtime_error("CWallet::GetChange() : value out of range");
354 void SetBestChain(const CBlockLocator& loc);
356 DBErrors LoadWallet(bool& fFirstRunRet);
357 DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
359 bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
361 bool DelAddressBook(const CTxDestination& address);
363 void UpdatedTransaction(const uint256 &hashTx);
365 void Inventory(const uint256 &hash)
369 std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
370 if (mi != mapRequestCount.end())
375 unsigned int GetKeyPoolSize()
377 AssertLockHeld(cs_wallet); // setKeyPool
378 return setKeyPool.size();
381 bool SetDefaultKey(const CPubKey &vchPubKey);
383 // signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
384 bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
386 // change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
387 bool SetMaxVersion(int nVersion);
389 // get the current wallet format (the oldest client version guaranteed to understand this wallet)
390 int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
392 // Get wallet transactions that conflict with given transaction (spend same outputs)
393 std::set<uint256> GetConflicts(const uint256& txid) const;
395 /** Address book entry changed.
396 * @note called with lock cs_wallet held.
398 boost::signals2::signal<void (CWallet *wallet, const CTxDestination
399 &address, const std::string &label, bool isMine,
400 const std::string &purpose,
401 ChangeType status)> NotifyAddressBookChanged;
403 /** Wallet transaction added, removed or updated.
404 * @note called with lock cs_wallet held.
406 boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
407 ChangeType status)> NotifyTransactionChanged;
409 /** Show progress e.g. for rescan */
410 boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
413 /** A key allocated from the key pool. */
421 CReserveKey(CWallet* pwalletIn)
433 bool GetReservedKey(CPubKey &pubkey);
438 typedef std::map<std::string, std::string> mapValue_t;
441 static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
443 if (!mapValue.count("n"))
445 nOrderPos = -1; // TODO: calculate elsewhere
448 nOrderPos = atoi64(mapValue["n"].c_str());
452 static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
456 mapValue["n"] = i64tostr(nOrderPos);
461 CTxDestination destination;
466 /** A transaction with a bunch of additional info that only the owner cares about.
467 * It includes any unrecorded transactions needed to link it back to the block chain.
469 class CWalletTx : public CMerkleTx
472 const CWallet* pwallet;
476 std::vector<std::pair<std::string, std::string> > vOrderForm;
477 unsigned int fTimeReceivedIsTxTime;
478 unsigned int nTimeReceived; // time received by this node
479 unsigned int nTimeSmart;
481 std::string strFromAccount;
482 int64_t nOrderPos; // position in ordered transaction list
485 mutable bool fDebitCached;
486 mutable bool fCreditCached;
487 mutable bool fImmatureCreditCached;
488 mutable bool fAvailableCreditCached;
489 mutable bool fWatchDebitCached;
490 mutable bool fWatchCreditCached;
491 mutable bool fImmatureWatchCreditCached;
492 mutable bool fAvailableWatchCreditCached;
493 mutable bool fChangeCached;
494 mutable int64_t nDebitCached;
495 mutable int64_t nCreditCached;
496 mutable int64_t nImmatureCreditCached;
497 mutable int64_t nAvailableCreditCached;
498 mutable int64_t nWatchDebitCached;
499 mutable int64_t nWatchCreditCached;
500 mutable int64_t nImmatureWatchCreditCached;
501 mutable int64_t nAvailableWatchCreditCached;
502 mutable int64_t nChangeCached;
509 CWalletTx(const CWallet* pwalletIn)
514 CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
519 CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
524 void Init(const CWallet* pwalletIn)
529 fTimeReceivedIsTxTime = false;
533 strFromAccount.clear();
534 fDebitCached = false;
535 fCreditCached = false;
536 fImmatureCreditCached = false;
537 fAvailableCreditCached = false;
538 fWatchDebitCached = false;
539 fWatchCreditCached = false;
540 fImmatureWatchCreditCached = false;
541 fAvailableWatchCreditCached = false;
542 fChangeCached = false;
545 nImmatureCreditCached = 0;
546 nAvailableCreditCached = 0;
547 nWatchDebitCached = 0;
548 nWatchCreditCached = 0;
549 nAvailableWatchCreditCached = 0;
550 nImmatureWatchCreditCached = 0;
557 CWalletTx* pthis = const_cast<CWalletTx*>(this);
564 pthis->mapValue["fromaccount"] = pthis->strFromAccount;
566 WriteOrderPos(pthis->nOrderPos, pthis->mapValue);
569 pthis->mapValue["timesmart"] = strprintf("%u", nTimeSmart);
572 nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion,ser_action);
573 std::vector<CMerkleTx> vUnused; // Used to be vtxPrev
576 READWRITE(vOrderForm);
577 READWRITE(fTimeReceivedIsTxTime);
578 READWRITE(nTimeReceived);
584 pthis->strFromAccount = pthis->mapValue["fromaccount"];
586 ReadOrderPos(pthis->nOrderPos, pthis->mapValue);
588 pthis->nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(pthis->mapValue["timesmart"]) : 0;
591 pthis->mapValue.erase("fromaccount");
592 pthis->mapValue.erase("version");
593 pthis->mapValue.erase("spent");
594 pthis->mapValue.erase("n");
595 pthis->mapValue.erase("timesmart");
598 // make sure balances are recalculated
601 fCreditCached = false;
602 fAvailableCreditCached = false;
603 fWatchDebitCached = false;
604 fWatchCreditCached = false;
605 fAvailableWatchCreditCached = false;
606 fImmatureWatchCreditCached = false;
607 fDebitCached = false;
608 fChangeCached = false;
611 void BindWallet(CWallet *pwalletIn)
617 // filter decides which addresses will count towards the debit
618 int64_t GetDebit(const isminefilter& filter) const
624 if(filter & ISMINE_SPENDABLE)
627 debit += nDebitCached;
630 nDebitCached = pwallet->GetDebit(*this, ISMINE_SPENDABLE);
632 debit += nDebitCached;
635 if(filter & ISMINE_WATCH_ONLY)
637 if(fWatchDebitCached)
638 debit += nWatchDebitCached;
641 nWatchDebitCached = pwallet->GetDebit(*this, ISMINE_WATCH_ONLY);
642 fWatchDebitCached = true;
643 debit += nWatchDebitCached;
649 int64_t GetCredit(bool fUseCache=true) const
651 // Must wait until coinbase is safely deep enough in the chain before valuing it
652 if (IsCoinBase() && GetBlocksToMaturity() > 0)
655 // GetBalance can assume transactions in mapWallet won't change
656 if (fUseCache && fCreditCached)
657 return nCreditCached;
658 nCreditCached = pwallet->GetCredit(*this, ISMINE_ALL);
659 fCreditCached = true;
660 return nCreditCached;
663 int64_t GetImmatureCredit(bool fUseCache=true) const
665 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
667 if (fUseCache && fImmatureCreditCached)
668 return nImmatureCreditCached;
669 nImmatureCreditCached = pwallet->GetCredit(*this, ISMINE_SPENDABLE);
670 fImmatureCreditCached = true;
671 return nImmatureCreditCached;
677 int64_t GetAvailableCredit(bool fUseCache=true) const
682 // Must wait until coinbase is safely deep enough in the chain before valuing it
683 if (IsCoinBase() && GetBlocksToMaturity() > 0)
686 if (fUseCache && fAvailableCreditCached)
687 return nAvailableCreditCached;
690 uint256 hashTx = GetHash();
691 for (unsigned int i = 0; i < vout.size(); i++)
693 if (!pwallet->IsSpent(hashTx, i))
695 const CTxOut &txout = vout[i];
696 nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
697 if (!MoneyRange(nCredit))
698 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
702 nAvailableCreditCached = nCredit;
703 fAvailableCreditCached = true;
707 int64_t GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const
709 if (IsCoinBase() && GetBlocksToMaturity() > 0 && IsInMainChain())
711 if (fUseCache && fImmatureWatchCreditCached)
712 return nImmatureWatchCreditCached;
713 nImmatureWatchCreditCached = pwallet->GetCredit(*this, ISMINE_WATCH_ONLY);
714 fImmatureWatchCreditCached = true;
715 return nImmatureWatchCreditCached;
721 int64_t GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const
726 // Must wait until coinbase is safely deep enough in the chain before valuing it
727 if (IsCoinBase() && GetBlocksToMaturity() > 0)
730 if (fUseCache && fAvailableWatchCreditCached)
731 return nAvailableWatchCreditCached;
734 for (unsigned int i = 0; i < vout.size(); i++)
736 if (!pwallet->IsSpent(GetHash(), i))
738 const CTxOut &txout = vout[i];
739 nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY);
740 if (!MoneyRange(nCredit))
741 throw std::runtime_error("CWalletTx::GetAvailableCredit() : value out of range");
745 nAvailableWatchCreditCached = nCredit;
746 fAvailableWatchCreditCached = true;
750 int64_t GetChange() const
753 return nChangeCached;
754 nChangeCached = pwallet->GetChange(*this);
755 fChangeCached = true;
756 return nChangeCached;
759 void GetAmounts(std::list<COutputEntry>& listReceived,
760 std::list<COutputEntry>& listSent, int64_t& nFee, std::string& strSentAccount, const isminefilter& filter) const;
762 void GetAccountAmounts(const std::string& strAccount, int64_t& nReceived,
763 int64_t& nSent, int64_t& nFee, const isminefilter& filter) const;
765 bool IsFromMe(const isminefilter& filter) const
767 return (GetDebit(filter) > 0);
770 bool IsTrusted() const
772 // Quick answer in most cases
773 if (!IsFinalTx(*this))
775 int nDepth = GetDepthInMainChain();
780 if (!bSpendZeroConfChange || !IsFromMe(ISMINE_ALL)) // using wtx's cached debit
783 // Trusted if all inputs are from us and are in the mempool:
784 BOOST_FOREACH(const CTxIn& txin, vin)
786 // Transactions not sent by us: not trusted
787 const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
790 const CTxOut& parentOut = parent->vout[txin.prevout.n];
791 if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
799 int64_t GetTxTime() const;
800 int GetRequestCount() const;
802 void RelayWalletTransaction();
804 std::set<uint256> GetConflicts() const;
818 COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn)
820 tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn;
823 std::string ToString() const
825 return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue).c_str());
830 LogPrintf("%s\n", ToString());
837 /** Private key that includes an expiration date in case it never gets used. */
842 int64_t nTimeCreated;
843 int64_t nTimeExpires;
844 std::string strComment;
845 //// todo: add something to note what created it (user, getnewaddress, change)
846 //// maybe should have a map<string, string> property map
848 CWalletKey(int64_t nExpires=0)
850 nTimeCreated = (nExpires ? GetTime() : 0);
851 nTimeExpires = nExpires;
856 if (!(nType & SER_GETHASH))
858 READWRITE(vchPrivKey);
859 READWRITE(nTimeCreated);
860 READWRITE(nTimeExpires);
861 READWRITE(LIMITED_STRING(strComment, 65536));
870 /** Account information.
871 * Stored in wallet with key "acc"+string account name.
885 vchPubKey = CPubKey();
890 if (!(nType & SER_GETHASH))
892 READWRITE(vchPubKey);
898 /** Internal transfers.
899 * Database key is acentry<account><counter>.
901 class CAccountingEntry
904 std::string strAccount;
905 int64_t nCreditDebit;
907 std::string strOtherAccount;
908 std::string strComment;
910 int64_t nOrderPos; // position in ordered transaction list
923 strOtherAccount.clear();
930 CAccountingEntry& me = *const_cast<CAccountingEntry*>(this);
931 if (!(nType & SER_GETHASH))
933 // Note: strAccount is serialized as part of the key, not here.
934 READWRITE(nCreditDebit);
936 READWRITE(LIMITED_STRING(strOtherAccount, 65536));
940 WriteOrderPos(nOrderPos, me.mapValue);
942 if (!(mapValue.empty() && _ssExtra.empty()))
944 CDataStream ss(nType, nVersion);
945 ss.insert(ss.begin(), '\0');
947 ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
948 me.strComment.append(ss.str());
952 READWRITE(LIMITED_STRING(strComment, 65536));
954 size_t nSepPos = strComment.find("\0", 0, 1);
958 if (std::string::npos != nSepPos)
960 CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), nType, nVersion);
962 me._ssExtra = std::vector<char>(ss.begin(), ss.end());
964 ReadOrderPos(me.nOrderPos, me.mapValue);
966 if (std::string::npos != nSepPos)
967 me.strComment.erase(nSepPos);
969 me.mapValue.erase("n");
973 std::vector<char> _ssExtra;