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