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