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