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