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