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