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