]> Git Repo - VerusCoin.git/blob - src/wallet/wallet.h
Rename GetNoteNullifier to GetSproutNoteNullifier.
[VerusCoin.git] / src / wallet / wallet.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #ifndef BITCOIN_WALLET_WALLET_H
7 #define BITCOIN_WALLET_WALLET_H
8
9 #include "amount.h"
10 #include "coins.h"
11 #include "key.h"
12 #include "keystore.h"
13 #include "main.h"
14 #include "primitives/block.h"
15 #include "primitives/transaction.h"
16 #include "tinyformat.h"
17 #include "ui_interface.h"
18 #include "util.h"
19 #include "utilstrencodings.h"
20 #include "validationinterface.h"
21 #include "wallet/crypter.h"
22 #include "wallet/wallet_ismine.h"
23 #include "wallet/walletdb.h"
24 #include "wallet/rpcwallet.h"
25 #include "zcash/Address.hpp"
26 #include "base58.h"
27
28 #include <algorithm>
29 #include <map>
30 #include <set>
31 #include <stdexcept>
32 #include <stdint.h>
33 #include <string>
34 #include <utility>
35 #include <vector>
36
37 /**
38  * Settings
39  */
40 extern CFeeRate payTxFee;
41 extern CAmount maxTxFee;
42 extern unsigned int nTxConfirmTarget;
43 extern bool bSpendZeroConfChange;
44 extern bool fSendFreeTransactions;
45 extern bool fPayAtLeastCustomFee;
46
47 //! -paytxfee default
48 static const CAmount DEFAULT_TRANSACTION_FEE = 0;
49 //! -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB
50 static const CAmount nHighTransactionFeeWarning = 0.01 * COIN;
51 //! -maxtxfee default
52 static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.1 * COIN;
53 //! -txconfirmtarget default
54 static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2;
55 //! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
56 static const CAmount nHighTransactionMaxFeeWarning = 100 * nHighTransactionFeeWarning;
57 //! Largest (in bytes) free transaction we're willing to create
58 static const unsigned int MAX_FREE_TRANSACTION_CREATE_SIZE = 1000;
59 //! Size of witness cache
60 //  Should be large enough that we can expect not to reorg beyond our cache
61 //  unless there is some exceptional network disruption.
62 static const unsigned int WITNESS_CACHE_SIZE = MAX_REORG_LENGTH + 1;
63
64 class CBlockIndex;
65 class CCoinControl;
66 class COutput;
67 class CReserveKey;
68 class CScript;
69 class CTxMemPool;
70 class CWalletTx;
71
72 /** (client) version numbers for particular wallet features */
73 enum WalletFeature
74 {
75     FEATURE_BASE = 10500, // the earliest version new wallets supports (only useful for getinfo's clientversion output)
76
77     FEATURE_WALLETCRYPT = 40000, // wallet encryption
78     FEATURE_COMPRPUBKEY = 60000, // compressed public keys
79
80     FEATURE_LATEST = 60000
81 };
82
83
84 /** A key pool entry */
85 class CKeyPool
86 {
87 public:
88     int64_t nTime;
89     CPubKey vchPubKey;
90
91     CKeyPool();
92     CKeyPool(const CPubKey& vchPubKeyIn);
93
94     ADD_SERIALIZE_METHODS;
95
96     template <typename Stream, typename Operation>
97     inline void SerializationOp(Stream& s, Operation ser_action) {
98         int nVersion = s.GetVersion();
99         if (!(s.GetType() & SER_GETHASH))
100             READWRITE(nVersion);
101         READWRITE(nTime);
102         READWRITE(vchPubKey);
103     }
104 };
105
106 /** Address book data */
107 class CAddressBookData
108 {
109 public:
110     std::string name;
111     std::string purpose;
112
113     CAddressBookData()
114     {
115         purpose = "unknown";
116     }
117
118     typedef std::map<std::string, std::string> StringMap;
119     StringMap destdata;
120 };
121
122 struct CRecipient
123 {
124     CScript scriptPubKey;
125     CAmount nAmount;
126     bool fSubtractFeeFromAmount;
127 };
128
129 typedef std::map<std::string, std::string> mapValue_t;
130
131
132 static void ReadOrderPos(int64_t& nOrderPos, mapValue_t& mapValue)
133 {
134     if (!mapValue.count("n"))
135     {
136         nOrderPos = -1; // TODO: calculate elsewhere
137         return;
138     }
139     nOrderPos = atoi64(mapValue["n"].c_str());
140 }
141
142
143 static void WriteOrderPos(const int64_t& nOrderPos, mapValue_t& mapValue)
144 {
145     if (nOrderPos == -1)
146         return;
147     mapValue["n"] = i64tostr(nOrderPos);
148 }
149
150 struct COutputEntry
151 {
152     CTxDestination destination;
153     CAmount amount;
154     int vout;
155 };
156
157 /** A note outpoint */
158 class JSOutPoint
159 {
160 public:
161     // Transaction hash
162     uint256 hash;
163     // Index into CTransaction.vjoinsplit
164     uint64_t js;
165     // Index into JSDescription fields of length ZC_NUM_JS_OUTPUTS
166     uint8_t n;
167
168     JSOutPoint() { SetNull(); }
169     JSOutPoint(uint256 h, uint64_t js, uint8_t n) : hash {h}, js {js}, n {n} { }
170
171     ADD_SERIALIZE_METHODS;
172
173     template <typename Stream, typename Operation>
174     inline void SerializationOp(Stream& s, Operation ser_action) {
175         READWRITE(hash);
176         READWRITE(js);
177         READWRITE(n);
178     }
179
180     void SetNull() { hash.SetNull(); }
181     bool IsNull() const { return hash.IsNull(); }
182
183     friend bool operator<(const JSOutPoint& a, const JSOutPoint& b) {
184         return (a.hash < b.hash ||
185                 (a.hash == b.hash && a.js < b.js) ||
186                 (a.hash == b.hash && a.js == b.js && a.n < b.n));
187     }
188
189     friend bool operator==(const JSOutPoint& a, const JSOutPoint& b) {
190         return (a.hash == b.hash && a.js == b.js && a.n == b.n);
191     }
192
193     friend bool operator!=(const JSOutPoint& a, const JSOutPoint& b) {
194         return !(a == b);
195     }
196
197     std::string ToString() const;
198 };
199
200 class SproutNoteData
201 {
202 public:
203     libzcash::SproutPaymentAddress address;
204
205     /**
206      * Cached note nullifier. May not be set if the wallet was not unlocked when
207      * this was SproutNoteData was created. If not set, we always assume that the
208      * note has not been spent.
209      *
210      * It's okay to cache the nullifier in the wallet, because we are storing
211      * the spending key there too, which could be used to derive this.
212      * If the wallet is encrypted, this means that someone with access to the
213      * locked wallet cannot spend notes, but can connect received notes to the
214      * transactions they are spent in. This is the same security semantics as
215      * for transparent addresses.
216      */
217     boost::optional<uint256> nullifier;
218
219     /**
220      * Cached incremental witnesses for spendable Notes.
221      * Beginning of the list is the most recent witness.
222      */
223     std::list<SproutWitness> witnesses;
224
225     /**
226      * Block height corresponding to the most current witness.
227      *
228      * When we first create a SproutNoteData in CWallet::FindMySproutNotes, this is set to
229      * -1 as a placeholder. The next time CWallet::ChainTip is called, we can
230      * determine what height the witness cache for this note is valid for (even
231      * if no witnesses were cached), and so can set the correct value in
232      * CWallet::IncrementNoteWitnesses and CWallet::DecrementNoteWitnesses.
233      */
234     int witnessHeight;
235
236     SproutNoteData() : address(), nullifier(), witnessHeight {-1} { }
237     SproutNoteData(libzcash::SproutPaymentAddress a) :
238             address {a}, nullifier(), witnessHeight {-1} { }
239     SproutNoteData(libzcash::SproutPaymentAddress a, uint256 n) :
240             address {a}, nullifier {n}, witnessHeight {-1} { }
241
242     ADD_SERIALIZE_METHODS;
243
244     template <typename Stream, typename Operation>
245     inline void SerializationOp(Stream& s, Operation ser_action) {
246         READWRITE(address);
247         READWRITE(nullifier);
248         READWRITE(witnesses);
249         READWRITE(witnessHeight);
250     }
251
252     friend bool operator<(const SproutNoteData& a, const SproutNoteData& b) {
253         return (a.address < b.address ||
254                 (a.address == b.address && a.nullifier < b.nullifier));
255     }
256
257     friend bool operator==(const SproutNoteData& a, const SproutNoteData& b) {
258         return (a.address == b.address && a.nullifier == b.nullifier);
259     }
260
261     friend bool operator!=(const SproutNoteData& a, const SproutNoteData& b) {
262         return !(a == b);
263     }
264 };
265
266 class SaplingNoteData
267 {
268 public:
269     /**
270      * We initialize the hight to -1 for the same reason as we do in SproutNoteData.
271      * See the comment in that class for a full description.
272      */
273     SaplingNoteData() : witnessHeight {-1} { }
274
275     std::list<SaplingWitness> witnesses;
276     int witnessHeight;
277 };
278
279 typedef std::map<JSOutPoint, SproutNoteData> mapSproutNoteData_t;
280 typedef std::map<SaplingOutPoint, SaplingNoteData> mapSaplingNoteData_t;
281
282 /** Decrypted note and its location in a transaction. */
283 struct CSproutNotePlaintextEntry
284 {
285     JSOutPoint jsop;
286     libzcash::SproutPaymentAddress address;
287     libzcash::SproutNotePlaintext plaintext;
288 };
289
290 /** Decrypted note, location in a transaction, and confirmation height. */
291 struct CUnspentSproutNotePlaintextEntry {
292     JSOutPoint jsop;
293     libzcash::SproutPaymentAddress address;
294     libzcash::SproutNotePlaintext plaintext;
295     int nHeight;
296 };
297
298 /** A transaction with a merkle branch linking it to the block chain. */
299 class CMerkleTx : public CTransaction
300 {
301 private:
302     int GetDepthInMainChainINTERNAL(const CBlockIndex* &pindexRet) const;
303
304 public:
305     uint256 hashBlock;
306     std::vector<uint256> vMerkleBranch;
307     int nIndex;
308
309     // memory only
310     mutable bool fMerkleVerified;
311
312
313     CMerkleTx()
314     {
315         Init();
316     }
317
318     CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
319     {
320         Init();
321     }
322
323     void Init()
324     {
325         hashBlock = uint256();
326         nIndex = -1;
327         fMerkleVerified = false;
328     }
329
330     ADD_SERIALIZE_METHODS;
331
332     template <typename Stream, typename Operation>
333     inline void SerializationOp(Stream& s, Operation ser_action) {
334         READWRITE(*(CTransaction*)this);
335         READWRITE(hashBlock);
336         READWRITE(vMerkleBranch);
337         READWRITE(nIndex);
338     }
339
340     int SetMerkleBranch(const CBlock& block);
341
342
343     /**
344      * Return depth of transaction in blockchain:
345      * -1  : not in blockchain, and not in memory pool (conflicted transaction)
346      *  0  : in memory pool, waiting to be included in a block
347      * >=1 : this many blocks deep in the main chain
348      */
349     int GetDepthInMainChain(const CBlockIndex* &pindexRet) const;
350     int GetDepthInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChain(pindexRet); }
351     bool IsInMainChain() const { const CBlockIndex *pindexRet; return GetDepthInMainChainINTERNAL(pindexRet) > 0; }
352     int GetBlocksToMaturity() const;
353     bool AcceptToMemoryPool(bool fLimitFree=true, bool fRejectAbsurdFee=true);
354 };
355
356 /** 
357  * A transaction with a bunch of additional info that only the owner cares about.
358  * It includes any unrecorded transactions needed to link it back to the block chain.
359  */
360 class CWalletTx : public CMerkleTx
361 {
362 private:
363     const CWallet* pwallet;
364
365 public:
366     mapValue_t mapValue;
367     mapSproutNoteData_t mapSproutNoteData;
368     mapSaplingNoteData_t mapSaplingNoteData;
369     std::vector<std::pair<std::string, std::string> > vOrderForm;
370     unsigned int fTimeReceivedIsTxTime;
371     unsigned int nTimeReceived; //! time received by this node
372     unsigned int nTimeSmart;
373     char fFromMe;
374     std::string strFromAccount;
375     int64_t nOrderPos; //! position in ordered transaction list
376
377     // memory only
378     mutable bool fDebitCached;
379     mutable bool fCreditCached;
380     mutable bool fImmatureCreditCached;
381     mutable bool fAvailableCreditCached;
382     mutable bool fWatchDebitCached;
383     mutable bool fWatchCreditCached;
384     mutable bool fImmatureWatchCreditCached;
385     mutable bool fAvailableWatchCreditCached;
386     mutable bool fChangeCached;
387     mutable CAmount nDebitCached;
388     mutable CAmount nCreditCached;
389     mutable CAmount nImmatureCreditCached;
390     mutable CAmount nAvailableCreditCached;
391     mutable CAmount nWatchDebitCached;
392     mutable CAmount nWatchCreditCached;
393     mutable CAmount nImmatureWatchCreditCached;
394     mutable CAmount nAvailableWatchCreditCached;
395     mutable CAmount nChangeCached;
396
397     CWalletTx()
398     {
399         Init(NULL);
400     }
401
402     CWalletTx(const CWallet* pwalletIn)
403     {
404         Init(pwalletIn);
405     }
406
407     CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
408     {
409         Init(pwalletIn);
410     }
411
412     CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
413     {
414         Init(pwalletIn);
415     }
416
417     void Init(const CWallet* pwalletIn)
418     {
419         pwallet = pwalletIn;
420         mapValue.clear();
421         mapSproutNoteData.clear();
422         mapSaplingNoteData.clear();
423         vOrderForm.clear();
424         fTimeReceivedIsTxTime = false;
425         nTimeReceived = 0;
426         nTimeSmart = 0;
427         fFromMe = false;
428         strFromAccount.clear();
429         fDebitCached = false;
430         fCreditCached = false;
431         fImmatureCreditCached = false;
432         fAvailableCreditCached = false;
433         fWatchDebitCached = false;
434         fWatchCreditCached = false;
435         fImmatureWatchCreditCached = false;
436         fAvailableWatchCreditCached = false;
437         fChangeCached = false;
438         nDebitCached = 0;
439         nCreditCached = 0;
440         nImmatureCreditCached = 0;
441         nAvailableCreditCached = 0;
442         nWatchDebitCached = 0;
443         nWatchCreditCached = 0;
444         nAvailableWatchCreditCached = 0;
445         nImmatureWatchCreditCached = 0;
446         nChangeCached = 0;
447         nOrderPos = -1;
448     }
449
450     ADD_SERIALIZE_METHODS;
451
452     template <typename Stream, typename Operation>
453     inline void SerializationOp(Stream& s, Operation ser_action) {
454         if (ser_action.ForRead())
455             Init(NULL);
456         char fSpent = false;
457
458         if (!ser_action.ForRead())
459         {
460             mapValue["fromaccount"] = strFromAccount;
461
462             WriteOrderPos(nOrderPos, mapValue);
463
464             if (nTimeSmart)
465                 mapValue["timesmart"] = strprintf("%u", nTimeSmart);
466         }
467
468         READWRITE(*(CMerkleTx*)this);
469         std::vector<CMerkleTx> vUnused; //! Used to be vtxPrev
470         READWRITE(vUnused);
471         READWRITE(mapValue);
472         READWRITE(mapSproutNoteData);
473         READWRITE(vOrderForm);
474         READWRITE(fTimeReceivedIsTxTime);
475         READWRITE(nTimeReceived);
476         READWRITE(fFromMe);
477         READWRITE(fSpent);
478         // TODO:
479         //READWRITE(mapSaplingNoteData);
480
481         if (ser_action.ForRead())
482         {
483             strFromAccount = mapValue["fromaccount"];
484
485             ReadOrderPos(nOrderPos, mapValue);
486
487             nTimeSmart = mapValue.count("timesmart") ? (unsigned int)atoi64(mapValue["timesmart"]) : 0;
488         }
489
490         mapValue.erase("fromaccount");
491         mapValue.erase("version");
492         mapValue.erase("spent");
493         mapValue.erase("n");
494         mapValue.erase("timesmart");
495     }
496
497     //! make sure balances are recalculated
498     void MarkDirty()
499     {
500         fCreditCached = false;
501         fAvailableCreditCached = false;
502         fWatchDebitCached = false;
503         fWatchCreditCached = false;
504         fAvailableWatchCreditCached = false;
505         fImmatureWatchCreditCached = false;
506         fDebitCached = false;
507         fChangeCached = false;
508     }
509
510     void BindWallet(CWallet *pwalletIn)
511     {
512         pwallet = pwalletIn;
513         MarkDirty();
514     }
515
516     void SetSproutNoteData(mapSproutNoteData_t &noteData);
517     void SetSaplingNoteData(mapSaplingNoteData_t &noteData);
518
519     //! filter decides which addresses will count towards the debit
520     CAmount GetDebit(const isminefilter& filter) const;
521     CAmount GetCredit(const isminefilter& filter) const;
522     CAmount GetImmatureCredit(bool fUseCache=true) const;
523     CAmount GetAvailableCredit(bool fUseCache=true) const;
524     CAmount GetImmatureWatchOnlyCredit(const bool& fUseCache=true) const;
525     CAmount GetAvailableWatchOnlyCredit(const bool& fUseCache=true) const;
526     CAmount GetChange() const;
527
528     void GetAmounts(std::list<COutputEntry>& listReceived,
529                     std::list<COutputEntry>& listSent, CAmount& nFee, std::string& strSentAccount, const isminefilter& filter) const;
530
531     void GetAccountAmounts(const std::string& strAccount, CAmount& nReceived,
532                            CAmount& nSent, CAmount& nFee, const isminefilter& filter) const;
533
534     bool IsFromMe(const isminefilter& filter) const
535     {
536         return (GetDebit(filter) > 0);
537     }
538
539     bool IsTrusted() const;
540
541     bool WriteToDisk(CWalletDB *pwalletdb);
542
543     int64_t GetTxTime() const;
544     int GetRequestCount() const;
545
546     bool RelayWalletTransaction();
547
548     std::set<uint256> GetConflicts() const;
549 };
550
551
552
553
554 class COutput
555 {
556 public:
557     const CWalletTx *tx;
558     int i;
559     int nDepth;
560     bool fSpendable;
561
562     COutput(const CWalletTx *txIn, int iIn, int nDepthIn, bool fSpendableIn)
563     {
564         tx = txIn; i = iIn; nDepth = nDepthIn; fSpendable = fSpendableIn;
565     }
566
567     std::string ToString() const;
568 };
569
570
571
572
573 /** Private key that includes an expiration date in case it never gets used. */
574 class CWalletKey
575 {
576 public:
577     CPrivKey vchPrivKey;
578     int64_t nTimeCreated;
579     int64_t nTimeExpires;
580     std::string strComment;
581     //! todo: add something to note what created it (user, getnewaddress, change)
582     //!   maybe should have a map<string, string> property map
583
584     CWalletKey(int64_t nExpires=0);
585
586     ADD_SERIALIZE_METHODS;
587
588     template <typename Stream, typename Operation>
589     inline void SerializationOp(Stream& s, Operation ser_action) {
590         int nVersion = s.GetVersion();
591         if (!(s.GetType() & SER_GETHASH))
592             READWRITE(nVersion);
593         READWRITE(vchPrivKey);
594         READWRITE(nTimeCreated);
595         READWRITE(nTimeExpires);
596         READWRITE(LIMITED_STRING(strComment, 65536));
597     }
598 };
599
600 /**
601  * Internal transfers.
602  * Database key is acentry<account><counter>.
603  */
604 class CAccountingEntry
605 {
606 public:
607     std::string strAccount;
608     CAmount nCreditDebit;
609     int64_t nTime;
610     std::string strOtherAccount;
611     std::string strComment;
612     mapValue_t mapValue;
613     int64_t nOrderPos;  //! position in ordered transaction list
614     uint64_t nEntryNo;
615
616     CAccountingEntry()
617     {
618         SetNull();
619     }
620
621     void SetNull()
622     {
623         nCreditDebit = 0;
624         nTime = 0;
625         strAccount.clear();
626         strOtherAccount.clear();
627         strComment.clear();
628         nOrderPos = -1;
629         nEntryNo = 0;
630     }
631
632     ADD_SERIALIZE_METHODS;
633
634     template <typename Stream, typename Operation>
635     inline void SerializationOp(Stream& s, Operation ser_action) {
636         int nVersion = s.GetVersion();
637         if (!(s.GetType() & SER_GETHASH))
638             READWRITE(nVersion);
639         //! Note: strAccount is serialized as part of the key, not here.
640         READWRITE(nCreditDebit);
641         READWRITE(nTime);
642         READWRITE(LIMITED_STRING(strOtherAccount, 65536));
643
644         if (!ser_action.ForRead())
645         {
646             WriteOrderPos(nOrderPos, mapValue);
647
648             if (!(mapValue.empty() && _ssExtra.empty()))
649             {
650                 CDataStream ss(s.GetType(), s.GetVersion());
651                 ss.insert(ss.begin(), '\0');
652                 ss << mapValue;
653                 ss.insert(ss.end(), _ssExtra.begin(), _ssExtra.end());
654                 strComment.append(ss.str());
655             }
656         }
657
658         READWRITE(LIMITED_STRING(strComment, 65536));
659
660         size_t nSepPos = strComment.find("\0", 0, 1);
661         if (ser_action.ForRead())
662         {
663             mapValue.clear();
664             if (std::string::npos != nSepPos)
665             {
666                 CDataStream ss(std::vector<char>(strComment.begin() + nSepPos + 1, strComment.end()), s.GetType(), s.GetVersion());
667                 ss >> mapValue;
668                 _ssExtra = std::vector<char>(ss.begin(), ss.end());
669             }
670             ReadOrderPos(nOrderPos, mapValue);
671         }
672         if (std::string::npos != nSepPos)
673             strComment.erase(nSepPos);
674
675         mapValue.erase("n");
676     }
677
678 private:
679     std::vector<char> _ssExtra;
680 };
681
682
683 /** 
684  * A CWallet is an extension of a keystore, which also maintains a set of transactions and balances,
685  * and provides the ability to create new transactions.
686  */
687 class CWallet : public CCryptoKeyStore, public CValidationInterface
688 {
689 private:
690     bool SelectCoins(const CAmount& nTargetValue, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet, bool& fOnlyCoinbaseCoinsRet, bool& fNeedCoinbaseCoinsRet, const CCoinControl *coinControl = NULL) const;
691
692     CWalletDB *pwalletdbEncryption;
693
694     //! the current wallet version: clients below this version are not able to load the wallet
695     int nWalletVersion;
696
697     //! the maximum wallet format version: memory-only variable that specifies to what version this wallet may be upgraded
698     int nWalletMaxVersion;
699
700     int64_t nNextResend;
701     int64_t nLastResend;
702     bool fBroadcastTransactions;
703
704     template <class T>
705     using TxSpendMap = std::multimap<T, uint256>;
706     /**
707      * Used to keep track of spent outpoints, and
708      * detect and report conflicts (double-spends or
709      * mutated transactions where the mutant gets mined).
710      */
711     typedef TxSpendMap<COutPoint> TxSpends;
712     TxSpends mapTxSpends;
713     /**
714      * Used to keep track of spent Notes, and
715      * detect and report conflicts (double-spends).
716      */
717     typedef TxSpendMap<uint256> TxNullifiers;
718     TxNullifiers mapTxNullifiers;
719
720     void AddToSpends(const COutPoint& outpoint, const uint256& wtxid);
721     void AddToSpends(const uint256& nullifier, const uint256& wtxid);
722     void AddToSpends(const uint256& wtxid);
723
724 public:
725     /*
726      * Size of the incremental witness cache for the notes in our wallet.
727      * This will always be greater than or equal to the size of the largest
728      * incremental witness cache in any transaction in mapWallet.
729      */
730     int64_t nWitnessCacheSize;
731
732     void ClearNoteWitnessCache();
733
734 protected:
735     /**
736      * pindex is the new tip being connected.
737      */
738     void IncrementNoteWitnesses(const CBlockIndex* pindex,
739                                 const CBlock* pblock,
740                                 SproutMerkleTree& sproutTree,
741                                 SaplingMerkleTree& saplingTree);
742     /**
743      * pindex is the old tip being disconnected.
744      */
745     void DecrementNoteWitnesses(const CBlockIndex* pindex);
746
747     template <typename WalletDB>
748     void SetBestChainINTERNAL(WalletDB& walletdb, const CBlockLocator& loc) {
749         if (!walletdb.TxnBegin()) {
750             // This needs to be done atomically, so don't do it at all
751             LogPrintf("SetBestChain(): Couldn't start atomic write\n");
752             return;
753         }
754         try {
755             for (std::pair<const uint256, CWalletTx>& wtxItem : mapWallet) {
756                 if (!walletdb.WriteTx(wtxItem.first, wtxItem.second)) {
757                     LogPrintf("SetBestChain(): Failed to write CWalletTx, aborting atomic write\n");
758                     walletdb.TxnAbort();
759                     return;
760                 }
761             }
762             if (!walletdb.WriteWitnessCacheSize(nWitnessCacheSize)) {
763                 LogPrintf("SetBestChain(): Failed to write nWitnessCacheSize, aborting atomic write\n");
764                 walletdb.TxnAbort();
765                 return;
766             }
767             if (!walletdb.WriteBestBlock(loc)) {
768                 LogPrintf("SetBestChain(): Failed to write best block, aborting atomic write\n");
769                 walletdb.TxnAbort();
770                 return;
771             }
772         } catch (const std::exception &exc) {
773             // Unexpected failure
774             LogPrintf("SetBestChain(): Unexpected error during atomic write:\n");
775             LogPrintf("%s\n", exc.what());
776             walletdb.TxnAbort();
777             return;
778         }
779         if (!walletdb.TxnCommit()) {
780             // Couldn't commit all to db, but in-memory state is fine
781             LogPrintf("SetBestChain(): Couldn't commit atomic write\n");
782             return;
783         }
784     }
785
786 private:
787     template <class T>
788     void SyncMetaData(std::pair<typename TxSpendMap<T>::iterator, typename TxSpendMap<T>::iterator>);
789
790 protected:
791     bool UpdatedNoteData(const CWalletTx& wtxIn, CWalletTx& wtx);
792     void MarkAffectedTransactionsDirty(const CTransaction& tx);
793
794 public:
795     /*
796      * Main wallet lock.
797      * This lock protects all the fields added by CWallet
798      *   except for:
799      *      fFileBacked (immutable after instantiation)
800      *      strWalletFile (immutable after instantiation)
801      */
802     mutable CCriticalSection cs_wallet;
803
804     bool fFileBacked;
805     std::string strWalletFile;
806
807     std::set<int64_t> setKeyPool;
808     std::map<CKeyID, CKeyMetadata> mapKeyMetadata;
809     std::map<libzcash::SproutPaymentAddress, CKeyMetadata> mapZKeyMetadata;
810     std::map<libzcash::SaplingPaymentAddress, CKeyMetadata> mapSaplingZKeyMetadata;
811
812     typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
813     MasterKeyMap mapMasterKeys;
814     unsigned int nMasterKeyMaxID;
815
816     CWallet()
817     {
818         SetNull();
819     }
820
821     CWallet(const std::string& strWalletFileIn)
822     {
823         SetNull();
824
825         strWalletFile = strWalletFileIn;
826         fFileBacked = true;
827     }
828
829     ~CWallet()
830     {
831         delete pwalletdbEncryption;
832         pwalletdbEncryption = NULL;
833     }
834
835     void SetNull()
836     {
837         nWalletVersion = FEATURE_BASE;
838         nWalletMaxVersion = FEATURE_BASE;
839         fFileBacked = false;
840         nMasterKeyMaxID = 0;
841         pwalletdbEncryption = NULL;
842         nOrderPosNext = 0;
843         nNextResend = 0;
844         nLastResend = 0;
845         nTimeFirstKey = 0;
846         fBroadcastTransactions = false;
847         nWitnessCacheSize = 0;
848     }
849
850     /**
851      * The reverse mapping of nullifiers to notes.
852      *
853      * The mapping cannot be updated while an encrypted wallet is locked,
854      * because we need the SpendingKey to create the nullifier (#1502). This has
855      * several implications for transactions added to the wallet while locked:
856      *
857      * - Parent transactions can't be marked dirty when a child transaction that
858      *   spends their output notes is updated.
859      *
860      *   - We currently don't cache any note values, so this is not a problem,
861      *     yet.
862      *
863      * - GetFilteredNotes can't filter out spent notes.
864      *
865      *   - Per the comment in SproutNoteData, we assume that if we don't have a
866      *     cached nullifier, the note is not spent.
867      *
868      * Another more problematic implication is that the wallet can fail to
869      * detect transactions on the blockchain that spend our notes. There are two
870      * possible cases in which this could happen:
871      *
872      * - We receive a note when the wallet is locked, and then spend it using a
873      *   different wallet client.
874      *
875      * - We spend from a PaymentAddress we control, then we export the
876      *   SpendingKey and import it into a new wallet, and reindex/rescan to find
877      *   the old transactions.
878      *
879      * The wallet will only miss "pure" spends - transactions that are only
880      * linked to us by the fact that they contain notes we spent. If it also
881      * sends notes to us, or interacts with our transparent addresses, we will
882      * detect the transaction and add it to the wallet (again without caching
883      * nullifiers for new notes). As by default JoinSplits send change back to
884      * the origin PaymentAddress, the wallet should rarely miss transactions.
885      *
886      * To work around these issues, whenever the wallet is unlocked, we scan all
887      * cached notes, and cache any missing nullifiers. Since the wallet must be
888      * unlocked in order to spend notes, this means that GetFilteredNotes will
889      * always behave correctly within that context (and any other uses will give
890      * correct responses afterwards), for the transactions that the wallet was
891      * able to detect. Any missing transactions can be rediscovered by:
892      *
893      * - Unlocking the wallet (to fill all nullifier caches).
894      *
895      * - Restarting the node with -reindex (which operates on a locked wallet
896      *   but with the now-cached nullifiers).
897      */
898     std::map<uint256, JSOutPoint> mapNullifiersToNotes;
899
900     std::map<uint256, CWalletTx> mapWallet;
901
902     int64_t nOrderPosNext;
903     std::map<uint256, int> mapRequestCount;
904
905     std::map<CTxDestination, CAddressBookData> mapAddressBook;
906
907     CPubKey vchDefaultKey;
908
909     std::set<COutPoint> setLockedCoins;
910     std::set<JSOutPoint> setLockedNotes;
911
912     int64_t nTimeFirstKey;
913
914     const CWalletTx* GetWalletTx(const uint256& hash) const;
915
916     //! check whether we are allowed to upgrade (or already support) to the named feature
917     bool CanSupportFeature(enum WalletFeature wf) { AssertLockHeld(cs_wallet); return nWalletMaxVersion >= wf; }
918
919     void AvailableCoins(std::vector<COutput>& vCoins, bool fOnlyConfirmed=true, const CCoinControl *coinControl = NULL, bool fIncludeZeroValue=false, bool fIncludeCoinBase=true) const;
920     bool SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int nConfTheirs, std::vector<COutput> vCoins, std::set<std::pair<const CWalletTx*,unsigned int> >& setCoinsRet, CAmount& nValueRet) const;
921
922     bool IsSpent(const uint256& hash, unsigned int n) const;
923     bool IsSpent(const uint256& nullifier) const;
924
925     bool IsLockedCoin(uint256 hash, unsigned int n) const;
926     void LockCoin(COutPoint& output);
927     void UnlockCoin(COutPoint& output);
928     void UnlockAllCoins();
929     void ListLockedCoins(std::vector<COutPoint>& vOutpts);
930
931
932     bool IsLockedNote(const JSOutPoint& outpt) const;
933     void LockNote(const JSOutPoint& output);
934     void UnlockNote(const JSOutPoint& output);
935     void UnlockAllNotes();
936     std::vector<JSOutPoint> ListLockedNotes();
937
938
939     /**
940      * keystore implementation
941      * Generate a new key
942      */
943     CPubKey GenerateNewKey();
944     //! Adds a key to the store, and saves it to disk.
945     bool AddKeyPubKey(const CKey& key, const CPubKey &pubkey);
946     //! Adds a key to the store, without saving it to disk (used by LoadWallet)
947     bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); }
948     //! Load metadata (used by LoadWallet)
949     bool LoadKeyMetadata(const CPubKey &pubkey, const CKeyMetadata &metadata);
950
951     bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; }
952
953     //! Adds an encrypted key to the store, and saves it to disk.
954     bool AddCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
955     //! Adds an encrypted key to the store, without saving it to disk (used by LoadWallet)
956     bool LoadCryptedKey(const CPubKey &vchPubKey, const std::vector<unsigned char> &vchCryptedSecret);
957     bool AddCScript(const CScript& redeemScript);
958     bool LoadCScript(const CScript& redeemScript);
959
960     //! Adds a destination data tuple to the store, and saves it to disk
961     bool AddDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
962     //! Erases a destination data tuple in the store and on disk
963     bool EraseDestData(const CTxDestination &dest, const std::string &key);
964     //! Adds a destination data tuple to the store, without saving it to disk
965     bool LoadDestData(const CTxDestination &dest, const std::string &key, const std::string &value);
966     //! Look up a destination data tuple in the store, return true if found false otherwise
967     bool GetDestData(const CTxDestination &dest, const std::string &key, std::string *value) const;
968
969     //! Adds a watch-only address to the store, and saves it to disk.
970     bool AddWatchOnly(const CScript &dest);
971     bool RemoveWatchOnly(const CScript &dest);
972     //! Adds a watch-only address to the store, without saving it to disk (used by LoadWallet)
973     bool LoadWatchOnly(const CScript &dest);
974
975     bool Unlock(const SecureString& strWalletPassphrase);
976     bool ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase, const SecureString& strNewWalletPassphrase);
977     bool EncryptWallet(const SecureString& strWalletPassphrase);
978
979     void GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const;
980
981     /**
982       * ZKeys
983       */
984     //! Generates a new zaddr
985     libzcash::PaymentAddress GenerateNewZKey();
986     //! Adds spending key to the store, and saves it to disk
987     bool AddZKey(const libzcash::SproutSpendingKey &key);
988     //! Adds spending key to the store, without saving it to disk (used by LoadWallet)
989     bool LoadZKey(const libzcash::SproutSpendingKey &key);
990     //! Load spending key metadata (used by LoadWallet)
991     bool LoadZKeyMetadata(const libzcash::SproutPaymentAddress &addr, const CKeyMetadata &meta);
992     //! Adds an encrypted spending key to the store, without saving it to disk (used by LoadWallet)
993     bool LoadCryptedZKey(const libzcash::SproutPaymentAddress &addr, const libzcash::ReceivingKey &rk, const std::vector<unsigned char> &vchCryptedSecret);
994     //! Adds an encrypted spending key to the store, and saves it to disk (virtual method, declared in crypter.h)
995     bool AddCryptedSproutSpendingKey(
996         const libzcash::SproutPaymentAddress &address,
997         const libzcash::ReceivingKey &rk,
998         const std::vector<unsigned char> &vchCryptedSecret);
999
1000     //! Adds a Sprout viewing key to the store, and saves it to disk.
1001     bool AddSproutViewingKey(const libzcash::SproutViewingKey &vk);
1002     bool RemoveSproutViewingKey(const libzcash::SproutViewingKey &vk);
1003     //! Adds a Sprout viewing key to the store, without saving it to disk (used by LoadWallet)
1004     bool LoadSproutViewingKey(const libzcash::SproutViewingKey &dest);
1005
1006     /**
1007       * Sapling ZKeys
1008       */
1009     //! Generates new Sapling key
1010     libzcash::SaplingPaymentAddress GenerateNewSaplingZKey();
1011     //! Adds Sapling spending key to the store, and saves it to disk
1012     bool AddSaplingZKey(
1013         const libzcash::SaplingSpendingKey &key,
1014         const boost::optional<libzcash::SaplingPaymentAddress> &defaultAddr = boost::none);
1015     bool AddCryptedSaplingSpendingKey(
1016         const libzcash::SaplingFullViewingKey &fvk,
1017         const std::vector<unsigned char> &vchCryptedSecret,
1018         const boost::optional<libzcash::SaplingPaymentAddress> &defaultAddr = boost::none);
1019
1020     /** 
1021      * Increment the next transaction order id
1022      * @return next transaction order id
1023      */
1024     int64_t IncOrderPosNext(CWalletDB *pwalletdb = NULL);
1025
1026     typedef std::pair<CWalletTx*, CAccountingEntry*> TxPair;
1027     typedef std::multimap<int64_t, TxPair > TxItems;
1028
1029     /**
1030      * Get the wallet's activity log
1031      * @return multimap of ordered transactions and accounting entries
1032      * @warning Returned pointers are *only* valid within the scope of passed acentries
1033      */
1034     TxItems OrderedTxItems(std::list<CAccountingEntry>& acentries, std::string strAccount = "");
1035
1036     void MarkDirty();
1037     bool UpdateNullifierNoteMap();
1038     void UpdateNullifierNoteMapWithTx(const CWalletTx& wtx);
1039     bool AddToWallet(const CWalletTx& wtxIn, bool fFromLoadWallet, CWalletDB* pwalletdb);
1040     void SyncTransaction(const CTransaction& tx, const CBlock* pblock);
1041     bool AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlock* pblock, bool fUpdate);
1042     void EraseFromWallet(const uint256 &hash);
1043     void WitnessNoteCommitment(
1044          std::vector<uint256> commitments,
1045          std::vector<boost::optional<SproutWitness>>& witnesses,
1046          uint256 &final_anchor);
1047     int ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate = false);
1048     void ReacceptWalletTransactions();
1049     void ResendWalletTransactions(int64_t nBestBlockTime);
1050     std::vector<uint256> ResendWalletTransactionsBefore(int64_t nTime);
1051     CAmount GetBalance() const;
1052     CAmount GetUnconfirmedBalance() const;
1053     CAmount GetImmatureBalance() const;
1054     CAmount GetWatchOnlyBalance() const;
1055     CAmount GetUnconfirmedWatchOnlyBalance() const;
1056     CAmount GetImmatureWatchOnlyBalance() const;
1057     bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosRet, std::string& strFailReason);
1058     bool CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet, int& nChangePosRet,
1059                            std::string& strFailReason, const CCoinControl *coinControl = NULL, bool sign = true);
1060     bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
1061
1062     static CFeeRate minTxFee;
1063     static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool);
1064
1065     bool NewKeyPool();
1066     bool TopUpKeyPool(unsigned int kpSize = 0);
1067     void ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool);
1068     void KeepKey(int64_t nIndex);
1069     void ReturnKey(int64_t nIndex);
1070     bool GetKeyFromPool(CPubKey &key);
1071     int64_t GetOldestKeyPoolTime();
1072     void GetAllReserveKeys(std::set<CKeyID>& setAddress) const;
1073
1074     std::set< std::set<CTxDestination> > GetAddressGroupings();
1075     std::map<CTxDestination, CAmount> GetAddressBalances();
1076
1077     std::set<CTxDestination> GetAccountAddresses(const std::string& strAccount) const;
1078
1079     boost::optional<uint256> GetSproutNoteNullifier(
1080         const JSDescription& jsdesc,
1081         const libzcash::SproutPaymentAddress& address,
1082         const ZCNoteDecryption& dec,
1083         const uint256& hSig,
1084         uint8_t n) const;
1085     mapSproutNoteData_t FindMySproutNotes(const CTransaction& tx) const;
1086     bool IsFromMe(const uint256& nullifier) const;
1087     void GetSproutNoteWitnesses(
1088          std::vector<JSOutPoint> notes,
1089          std::vector<boost::optional<SproutWitness>>& witnesses,
1090          uint256 &final_anchor);
1091     void GetSaplingNoteWitnesses(
1092          std::vector<SaplingOutPoint> notes,
1093          std::vector<boost::optional<SaplingWitness>>& witnesses,
1094          uint256 &final_anchor);
1095
1096     isminetype IsMine(const CTxIn& txin) const;
1097     CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;
1098     isminetype IsMine(const CTxOut& txout) const;
1099     CAmount GetCredit(const CTxOut& txout, const isminefilter& filter) const;
1100     bool IsChange(const CTxOut& txout) const;
1101     CAmount GetChange(const CTxOut& txout) const;
1102     bool IsMine(const CTransaction& tx) const;
1103     /** should probably be renamed to IsRelevantToMe */
1104     bool IsFromMe(const CTransaction& tx) const;
1105     CAmount GetDebit(const CTransaction& tx, const isminefilter& filter) const;
1106     CAmount GetCredit(const CTransaction& tx, const isminefilter& filter) const;
1107     CAmount GetChange(const CTransaction& tx) const;
1108     void ChainTip(const CBlockIndex *pindex, const CBlock *pblock, SproutMerkleTree sproutTree, SaplingMerkleTree saplingTree, bool added);
1109     /** Saves witness caches and best block locator to disk. */
1110     void SetBestChain(const CBlockLocator& loc);
1111     std::set<std::pair<libzcash::PaymentAddress, uint256>> GetNullifiersForAddresses(const std::set<libzcash::PaymentAddress> & addresses);
1112     bool IsNoteChange(const std::set<std::pair<libzcash::PaymentAddress, uint256>> & nullifierSet, const libzcash::PaymentAddress & address, const JSOutPoint & entry);
1113
1114     DBErrors LoadWallet(bool& fFirstRunRet);
1115     DBErrors ZapWalletTx(std::vector<CWalletTx>& vWtx);
1116
1117     bool SetAddressBook(const CTxDestination& address, const std::string& strName, const std::string& purpose);
1118
1119     bool DelAddressBook(const CTxDestination& address);
1120
1121     void UpdatedTransaction(const uint256 &hashTx);
1122
1123     void Inventory(const uint256 &hash)
1124     {
1125         {
1126             LOCK(cs_wallet);
1127             std::map<uint256, int>::iterator mi = mapRequestCount.find(hash);
1128             if (mi != mapRequestCount.end())
1129                 (*mi).second++;
1130         }
1131     }
1132
1133     unsigned int GetKeyPoolSize()
1134     {
1135         AssertLockHeld(cs_wallet); // setKeyPool
1136         return setKeyPool.size();
1137     }
1138
1139     bool SetDefaultKey(const CPubKey &vchPubKey);
1140
1141     //! signify that a particular wallet feature is now used. this may change nWalletVersion and nWalletMaxVersion if those are lower
1142     bool SetMinVersion(enum WalletFeature, CWalletDB* pwalletdbIn = NULL, bool fExplicit = false);
1143
1144     //! change which version we're allowed to upgrade to (note that this does not immediately imply upgrading to that format)
1145     bool SetMaxVersion(int nVersion);
1146
1147     //! get the current wallet format (the oldest client version guaranteed to understand this wallet)
1148     int GetVersion() { LOCK(cs_wallet); return nWalletVersion; }
1149
1150     //! Get wallet transactions that conflict with given transaction (spend same outputs)
1151     std::set<uint256> GetConflicts(const uint256& txid) const;
1152
1153     //! Flush wallet (bitdb flush)
1154     void Flush(bool shutdown=false);
1155
1156     //! Verify the wallet database and perform salvage if required
1157     static bool Verify(const std::string& walletFile, std::string& warningString, std::string& errorString);
1158     
1159     /** 
1160      * Address book entry changed.
1161      * @note called with lock cs_wallet held.
1162      */
1163     boost::signals2::signal<void (CWallet *wallet, const CTxDestination
1164             &address, const std::string &label, bool isMine,
1165             const std::string &purpose,
1166             ChangeType status)> NotifyAddressBookChanged;
1167
1168     /** 
1169      * Wallet transaction added, removed or updated.
1170      * @note called with lock cs_wallet held.
1171      */
1172     boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
1173             ChangeType status)> NotifyTransactionChanged;
1174
1175     /** Show progress e.g. for rescan */
1176     boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
1177
1178     /** Watch-only address added */
1179     boost::signals2::signal<void (bool fHaveWatchOnly)> NotifyWatchonlyChanged;
1180
1181     /** Inquire whether this wallet broadcasts transactions. */
1182     bool GetBroadcastTransactions() const { return fBroadcastTransactions; }
1183     /** Set whether this wallet broadcasts transactions. */
1184     void SetBroadcastTransactions(bool broadcast) { fBroadcastTransactions = broadcast; }
1185     
1186     /* Find notes filtered by payment address, min depth, ability to spend */
1187     void GetFilteredNotes(std::vector<CSproutNotePlaintextEntry> & outEntries,
1188                           std::string address,
1189                           int minDepth=1,
1190                           bool ignoreSpent=true,
1191                           bool ignoreUnspendable=true);
1192
1193     /* Find notes filtered by payment addresses, min depth, ability to spend */
1194     void GetFilteredNotes(std::vector<CSproutNotePlaintextEntry>& outEntries,
1195                           std::set<libzcash::PaymentAddress>& filterAddresses,
1196                           int minDepth=1,
1197                           bool ignoreSpent=true,
1198                           bool ignoreUnspendable=true);
1199     
1200     /* Find unspent notes filtered by payment address, min depth and max depth */
1201     void GetUnspentFilteredNotes(std::vector<CUnspentSproutNotePlaintextEntry>& outEntries,
1202                                  std::set<libzcash::PaymentAddress>& filterAddresses,
1203                                  int minDepth=1,
1204                                  int maxDepth=INT_MAX,
1205                                  bool requireSpendingKey=true);
1206 };
1207
1208 /** A key allocated from the key pool. */
1209 class CReserveKey
1210 {
1211 protected:
1212     CWallet* pwallet;
1213     int64_t nIndex;
1214     CPubKey vchPubKey;
1215 public:
1216     CReserveKey(CWallet* pwalletIn)
1217     {
1218         nIndex = -1;
1219         pwallet = pwalletIn;
1220     }
1221
1222     ~CReserveKey()
1223     {
1224         ReturnKey();
1225     }
1226
1227     void ReturnKey();
1228     virtual bool GetReservedKey(CPubKey &pubkey);
1229     void KeepKey();
1230 };
1231
1232
1233 /** 
1234  * Account information.
1235  * Stored in wallet with key "acc"+string account name.
1236  */
1237 class CAccount
1238 {
1239 public:
1240     CPubKey vchPubKey;
1241
1242     CAccount()
1243     {
1244         SetNull();
1245     }
1246
1247     void SetNull()
1248     {
1249         vchPubKey = CPubKey();
1250     }
1251
1252     ADD_SERIALIZE_METHODS;
1253
1254     template <typename Stream, typename Operation>
1255     inline void SerializationOp(Stream& s, Operation ser_action) {
1256         int nVersion = s.GetVersion();
1257         if (!(s.GetType() & SER_GETHASH))
1258             READWRITE(nVersion);
1259         READWRITE(vchPubKey);
1260     }
1261 };
1262
1263 #endif // BITCOIN_WALLET_WALLET_H
This page took 0.094984 seconds and 4 git commands to generate.