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