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