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