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