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