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