misc changes
[novacoin.git] / main.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto\r
2 // Distributed under the MIT/X11 software license, see the accompanying\r
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
4 \r
5 class COutPoint;\r
6 class CInPoint;\r
7 class CDiskTxPos;\r
8 class CCoinBase;\r
9 class CTxIn;\r
10 class CTxOut;\r
11 class CTransaction;\r
12 class CBlock;\r
13 class CBlockIndex;\r
14 class CWalletTx;\r
15 class CKeyItem;\r
16 \r
17 static const unsigned int MAX_SIZE = 0x02000000;\r
18 static const unsigned int MAX_BLOCK_SIZE = 1000000;\r
19 static const int64 COIN = 100000000;\r
20 static const int64 CENT = 1000000;\r
21 static const int COINBASE_MATURITY = 100;\r
22 \r
23 static const CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);\r
24 \r
25 \r
26 \r
27 \r
28 \r
29 \r
30 extern CCriticalSection cs_main;\r
31 extern map<uint256, CBlockIndex*> mapBlockIndex;\r
32 extern const uint256 hashGenesisBlock;\r
33 extern CBlockIndex* pindexGenesisBlock;\r
34 extern int nBestHeight;\r
35 extern CBigNum bnBestChainWork;\r
36 extern CBigNum bnBestInvalidWork;\r
37 extern uint256 hashBestChain;\r
38 extern CBlockIndex* pindexBest;\r
39 extern unsigned int nTransactionsUpdated;\r
40 extern map<uint256, int> mapRequestCount;\r
41 extern CCriticalSection cs_mapRequestCount;\r
42 extern map<string, string> mapAddressBook;\r
43 extern CCriticalSection cs_mapAddressBook;\r
44 extern vector<unsigned char> vchDefaultKey;\r
45 extern double dHashesPerSec;\r
46 extern int64 nHPSTimerStart;\r
47 \r
48 // Settings\r
49 extern int fGenerateBitcoins;\r
50 extern int64 nTransactionFee;\r
51 extern CAddress addrIncoming;\r
52 extern int fLimitProcessors;\r
53 extern int nLimitProcessors;\r
54 extern int fMinimizeToTray;\r
55 extern int fMinimizeOnClose;\r
56 \r
57 \r
58 \r
59 \r
60 \r
61 \r
62 \r
63 bool CheckDiskSpace(int64 nAdditionalBytes=0);\r
64 FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");\r
65 FILE* AppendBlockFile(unsigned int& nFileRet);\r
66 bool AddKey(const CKey& key);\r
67 vector<unsigned char> GenerateNewKey();\r
68 bool AddToWallet(const CWalletTx& wtxIn);\r
69 void WalletUpdateSpent(const COutPoint& prevout);\r
70 void ReacceptWalletTransactions();\r
71 bool LoadBlockIndex(bool fAllowNew=true);\r
72 void PrintBlockTree();\r
73 bool ProcessMessages(CNode* pfrom);\r
74 bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv);\r
75 bool SendMessages(CNode* pto, bool fSendTrickle);\r
76 int64 GetBalance();\r
77 bool CreateTransaction(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, CKey& keyRet, int64& nFeeRequiredRet);\r
78 bool CommitTransaction(CWalletTx& wtxNew, const CKey& key);\r
79 bool BroadcastTransaction(CWalletTx& wtxNew);\r
80 string SendMoney(CScript scriptPubKey, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);\r
81 string SendMoneyToBitcoinAddress(string strAddress, int64 nValue, CWalletTx& wtxNew, bool fAskFee=false);\r
82 void GenerateBitcoins(bool fGenerate);\r
83 void ThreadBitcoinMiner(void* parg);\r
84 void BitcoinMiner();\r
85 bool IsInitialBlockDownload();\r
86 bool IsLockdown();\r
87 \r
88 \r
89 \r
90 \r
91 \r
92 \r
93 \r
94 \r
95 \r
96 \r
97 \r
98 \r
99 class CDiskTxPos\r
100 {\r
101 public:\r
102     unsigned int nFile;\r
103     unsigned int nBlockPos;\r
104     unsigned int nTxPos;\r
105 \r
106     CDiskTxPos()\r
107     {\r
108         SetNull();\r
109     }\r
110 \r
111     CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn)\r
112     {\r
113         nFile = nFileIn;\r
114         nBlockPos = nBlockPosIn;\r
115         nTxPos = nTxPosIn;\r
116     }\r
117 \r
118     IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )\r
119     void SetNull() { nFile = -1; nBlockPos = 0; nTxPos = 0; }\r
120     bool IsNull() const { return (nFile == -1); }\r
121 \r
122     friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b)\r
123     {\r
124         return (a.nFile     == b.nFile &&\r
125                 a.nBlockPos == b.nBlockPos &&\r
126                 a.nTxPos    == b.nTxPos);\r
127     }\r
128 \r
129     friend bool operator!=(const CDiskTxPos& a, const CDiskTxPos& b)\r
130     {\r
131         return !(a == b);\r
132     }\r
133 \r
134     string ToString() const\r
135     {\r
136         if (IsNull())\r
137             return strprintf("null");\r
138         else\r
139             return strprintf("(nFile=%d, nBlockPos=%d, nTxPos=%d)", nFile, nBlockPos, nTxPos);\r
140     }\r
141 \r
142     void print() const\r
143     {\r
144         printf("%s", ToString().c_str());\r
145     }\r
146 };\r
147 \r
148 \r
149 \r
150 \r
151 class CInPoint\r
152 {\r
153 public:\r
154     CTransaction* ptx;\r
155     unsigned int n;\r
156 \r
157     CInPoint() { SetNull(); }\r
158     CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }\r
159     void SetNull() { ptx = NULL; n = -1; }\r
160     bool IsNull() const { return (ptx == NULL && n == -1); }\r
161 };\r
162 \r
163 \r
164 \r
165 \r
166 class COutPoint\r
167 {\r
168 public:\r
169     uint256 hash;\r
170     unsigned int n;\r
171 \r
172     COutPoint() { SetNull(); }\r
173     COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }\r
174     IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )\r
175     void SetNull() { hash = 0; n = -1; }\r
176     bool IsNull() const { return (hash == 0 && n == -1); }\r
177 \r
178     friend bool operator<(const COutPoint& a, const COutPoint& b)\r
179     {\r
180         return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));\r
181     }\r
182 \r
183     friend bool operator==(const COutPoint& a, const COutPoint& b)\r
184     {\r
185         return (a.hash == b.hash && a.n == b.n);\r
186     }\r
187 \r
188     friend bool operator!=(const COutPoint& a, const COutPoint& b)\r
189     {\r
190         return !(a == b);\r
191     }\r
192 \r
193     string ToString() const\r
194     {\r
195         return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,6).c_str(), n);\r
196     }\r
197 \r
198     void print() const\r
199     {\r
200         printf("%s\n", ToString().c_str());\r
201     }\r
202 };\r
203 \r
204 \r
205 \r
206 \r
207 //\r
208 // An input of a transaction.  It contains the location of the previous\r
209 // transaction's output that it claims and a signature that matches the\r
210 // output's public key.\r
211 //\r
212 class CTxIn\r
213 {\r
214 public:\r
215     COutPoint prevout;\r
216     CScript scriptSig;\r
217     unsigned int nSequence;\r
218 \r
219     CTxIn()\r
220     {\r
221         nSequence = UINT_MAX;\r
222     }\r
223 \r
224     explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)\r
225     {\r
226         prevout = prevoutIn;\r
227         scriptSig = scriptSigIn;\r
228         nSequence = nSequenceIn;\r
229     }\r
230 \r
231     CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)\r
232     {\r
233         prevout = COutPoint(hashPrevTx, nOut);\r
234         scriptSig = scriptSigIn;\r
235         nSequence = nSequenceIn;\r
236     }\r
237 \r
238     IMPLEMENT_SERIALIZE\r
239     (\r
240         READWRITE(prevout);\r
241         READWRITE(scriptSig);\r
242         READWRITE(nSequence);\r
243     )\r
244 \r
245     bool IsFinal() const\r
246     {\r
247         return (nSequence == UINT_MAX);\r
248     }\r
249 \r
250     friend bool operator==(const CTxIn& a, const CTxIn& b)\r
251     {\r
252         return (a.prevout   == b.prevout &&\r
253                 a.scriptSig == b.scriptSig &&\r
254                 a.nSequence == b.nSequence);\r
255     }\r
256 \r
257     friend bool operator!=(const CTxIn& a, const CTxIn& b)\r
258     {\r
259         return !(a == b);\r
260     }\r
261 \r
262     string ToString() const\r
263     {\r
264         string str;\r
265         str += strprintf("CTxIn(");\r
266         str += prevout.ToString();\r
267         if (prevout.IsNull())\r
268             str += strprintf(", coinbase %s", HexStr(scriptSig.begin(), scriptSig.end(), false).c_str());\r
269         else\r
270             str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());\r
271         if (nSequence != UINT_MAX)\r
272             str += strprintf(", nSequence=%u", nSequence);\r
273         str += ")";\r
274         return str;\r
275     }\r
276 \r
277     void print() const\r
278     {\r
279         printf("%s\n", ToString().c_str());\r
280     }\r
281 \r
282     bool IsMine() const;\r
283     int64 GetDebit() const;\r
284 };\r
285 \r
286 \r
287 \r
288 \r
289 //\r
290 // An output of a transaction.  It contains the public key that the next input\r
291 // must be able to sign with to claim it.\r
292 //\r
293 class CTxOut\r
294 {\r
295 public:\r
296     int64 nValue;\r
297     CScript scriptPubKey;\r
298 \r
299 public:\r
300     CTxOut()\r
301     {\r
302         SetNull();\r
303     }\r
304 \r
305     CTxOut(int64 nValueIn, CScript scriptPubKeyIn)\r
306     {\r
307         nValue = nValueIn;\r
308         scriptPubKey = scriptPubKeyIn;\r
309     }\r
310 \r
311     IMPLEMENT_SERIALIZE\r
312     (\r
313         READWRITE(nValue);\r
314         READWRITE(scriptPubKey);\r
315     )\r
316 \r
317     void SetNull()\r
318     {\r
319         nValue = -1;\r
320         scriptPubKey.clear();\r
321     }\r
322 \r
323     bool IsNull()\r
324     {\r
325         return (nValue == -1);\r
326     }\r
327 \r
328     uint256 GetHash() const\r
329     {\r
330         return SerializeHash(*this);\r
331     }\r
332 \r
333     bool IsMine() const\r
334     {\r
335         return ::IsMine(scriptPubKey);\r
336     }\r
337 \r
338     int64 GetCredit() const\r
339     {\r
340         if (IsMine())\r
341             return nValue;\r
342         return 0;\r
343     }\r
344 \r
345     friend bool operator==(const CTxOut& a, const CTxOut& b)\r
346     {\r
347         return (a.nValue       == b.nValue &&\r
348                 a.scriptPubKey == b.scriptPubKey);\r
349     }\r
350 \r
351     friend bool operator!=(const CTxOut& a, const CTxOut& b)\r
352     {\r
353         return !(a == b);\r
354     }\r
355 \r
356     string ToString() const\r
357     {\r
358         if (scriptPubKey.size() < 6)\r
359             return "CTxOut(error)";\r
360         return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,24).c_str());\r
361     }\r
362 \r
363     void print() const\r
364     {\r
365         printf("%s\n", ToString().c_str());\r
366     }\r
367 };\r
368 \r
369 \r
370 \r
371 \r
372 //\r
373 // The basic transaction that is broadcasted on the network and contained in\r
374 // blocks.  A transaction can contain multiple inputs and outputs.\r
375 //\r
376 class CTransaction\r
377 {\r
378 public:\r
379     int nVersion;\r
380     vector<CTxIn> vin;\r
381     vector<CTxOut> vout;\r
382     unsigned int nLockTime;\r
383 \r
384 \r
385     CTransaction()\r
386     {\r
387         SetNull();\r
388     }\r
389 \r
390     IMPLEMENT_SERIALIZE\r
391     (\r
392         READWRITE(this->nVersion);\r
393         nVersion = this->nVersion;\r
394         READWRITE(vin);\r
395         READWRITE(vout);\r
396         READWRITE(nLockTime);\r
397     )\r
398 \r
399     void SetNull()\r
400     {\r
401         nVersion = 1;\r
402         vin.clear();\r
403         vout.clear();\r
404         nLockTime = 0;\r
405     }\r
406 \r
407     bool IsNull() const\r
408     {\r
409         return (vin.empty() && vout.empty());\r
410     }\r
411 \r
412     uint256 GetHash() const\r
413     {\r
414         return SerializeHash(*this);\r
415     }\r
416 \r
417     bool IsFinal(int nBlockHeight=0, int64 nBlockTime=0) const\r
418     {\r
419         // Time based nLockTime implemented in 0.1.6\r
420         if (nLockTime == 0)\r
421             return true;\r
422         if (nBlockHeight == 0)\r
423             nBlockHeight = nBestHeight;\r
424         if (nBlockTime == 0)\r
425             nBlockTime = GetAdjustedTime();\r
426         if (nLockTime < (nLockTime < 500000000 ? nBlockHeight : nBlockTime))\r
427             return true;\r
428         foreach(const CTxIn& txin, vin)\r
429             if (!txin.IsFinal())\r
430                 return false;\r
431         return true;\r
432     }\r
433 \r
434     bool IsNewerThan(const CTransaction& old) const\r
435     {\r
436         if (vin.size() != old.vin.size())\r
437             return false;\r
438         for (int i = 0; i < vin.size(); i++)\r
439             if (vin[i].prevout != old.vin[i].prevout)\r
440                 return false;\r
441 \r
442         bool fNewer = false;\r
443         unsigned int nLowest = UINT_MAX;\r
444         for (int i = 0; i < vin.size(); i++)\r
445         {\r
446             if (vin[i].nSequence != old.vin[i].nSequence)\r
447             {\r
448                 if (vin[i].nSequence <= nLowest)\r
449                 {\r
450                     fNewer = false;\r
451                     nLowest = vin[i].nSequence;\r
452                 }\r
453                 if (old.vin[i].nSequence < nLowest)\r
454                 {\r
455                     fNewer = true;\r
456                     nLowest = old.vin[i].nSequence;\r
457                 }\r
458             }\r
459         }\r
460         return fNewer;\r
461     }\r
462 \r
463     bool IsCoinBase() const\r
464     {\r
465         return (vin.size() == 1 && vin[0].prevout.IsNull());\r
466     }\r
467 \r
468     bool CheckTransaction() const\r
469     {\r
470         // Basic checks that don't depend on any context\r
471         if (vin.empty() || vout.empty())\r
472             return error("CTransaction::CheckTransaction() : vin or vout empty");\r
473 \r
474         // Check for negative values\r
475         foreach(const CTxOut& txout, vout)\r
476             if (txout.nValue < 0)\r
477                 return error("CTransaction::CheckTransaction() : txout.nValue negative");\r
478 \r
479         if (IsCoinBase())\r
480         {\r
481             if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100)\r
482                 return error("CTransaction::CheckTransaction() : coinbase script size");\r
483         }\r
484         else\r
485         {\r
486             foreach(const CTxIn& txin, vin)\r
487                 if (txin.prevout.IsNull())\r
488                     return error("CTransaction::CheckTransaction() : prevout is null");\r
489         }\r
490 \r
491         return true;\r
492     }\r
493 \r
494     bool IsMine() const\r
495     {\r
496         foreach(const CTxOut& txout, vout)\r
497             if (txout.IsMine())\r
498                 return true;\r
499         return false;\r
500     }\r
501 \r
502     int64 GetDebit() const\r
503     {\r
504         int64 nDebit = 0;\r
505         foreach(const CTxIn& txin, vin)\r
506             nDebit += txin.GetDebit();\r
507         return nDebit;\r
508     }\r
509 \r
510     int64 GetCredit() const\r
511     {\r
512         int64 nCredit = 0;\r
513         foreach(const CTxOut& txout, vout)\r
514             nCredit += txout.GetCredit();\r
515         return nCredit;\r
516     }\r
517 \r
518     int64 GetValueOut() const\r
519     {\r
520         int64 nValueOut = 0;\r
521         foreach(const CTxOut& txout, vout)\r
522         {\r
523             if (txout.nValue < 0)\r
524                 throw runtime_error("CTransaction::GetValueOut() : negative value");\r
525             nValueOut += txout.nValue;\r
526         }\r
527         return nValueOut;\r
528     }\r
529 \r
530     int64 GetMinFee(unsigned int nBlockSize=1) const\r
531     {\r
532         // Base fee is 1 cent per kilobyte\r
533         unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);\r
534         int64 nMinFee = (1 + (int64)nBytes / 1000) * CENT;\r
535 \r
536         // Transactions under 60K are free as long as block size is under 80K\r
537         // (about 27,000bc if made of 50bc inputs)\r
538         if (nBytes < 60000 && nBlockSize < 80000)\r
539             nMinFee = 0;\r
540 \r
541         // Transactions under 3K are free as long as block size is under 200K\r
542         if (nBytes < 3000 && nBlockSize < 200000)\r
543             nMinFee = 0;\r
544 \r
545         // To limit dust spam, require a 0.01 fee if any output is less than 0.01\r
546         if (nMinFee < CENT)\r
547             foreach(const CTxOut& txout, vout)\r
548                 if (txout.nValue < CENT)\r
549                     nMinFee = CENT;\r
550 \r
551         return nMinFee;\r
552     }\r
553 \r
554 \r
555 \r
556     bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)\r
557     {\r
558         CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");\r
559         if (!filein)\r
560             return error("CTransaction::ReadFromDisk() : OpenBlockFile failed");\r
561 \r
562         // Read transaction\r
563         if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)\r
564             return error("CTransaction::ReadFromDisk() : fseek failed");\r
565         filein >> *this;\r
566 \r
567         // Return file pointer\r
568         if (pfileRet)\r
569         {\r
570             if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)\r
571                 return error("CTransaction::ReadFromDisk() : second fseek failed");\r
572             *pfileRet = filein.release();\r
573         }\r
574         return true;\r
575     }\r
576 \r
577 \r
578     friend bool operator==(const CTransaction& a, const CTransaction& b)\r
579     {\r
580         return (a.nVersion  == b.nVersion &&\r
581                 a.vin       == b.vin &&\r
582                 a.vout      == b.vout &&\r
583                 a.nLockTime == b.nLockTime);\r
584     }\r
585 \r
586     friend bool operator!=(const CTransaction& a, const CTransaction& b)\r
587     {\r
588         return !(a == b);\r
589     }\r
590 \r
591 \r
592     string ToString() const\r
593     {\r
594         string str;\r
595         str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",\r
596             GetHash().ToString().substr(0,6).c_str(),\r
597             nVersion,\r
598             vin.size(),\r
599             vout.size(),\r
600             nLockTime);\r
601         for (int i = 0; i < vin.size(); i++)\r
602             str += "    " + vin[i].ToString() + "\n";\r
603         for (int i = 0; i < vout.size(); i++)\r
604             str += "    " + vout[i].ToString() + "\n";\r
605         return str;\r
606     }\r
607 \r
608     void print() const\r
609     {\r
610         printf("%s", ToString().c_str());\r
611     }\r
612 \r
613 \r
614 \r
615     bool DisconnectInputs(CTxDB& txdb);\r
616     bool ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,\r
617                        CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);\r
618     bool ClientConnectInputs();\r
619 \r
620     bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);\r
621 \r
622     bool AcceptTransaction(bool fCheckInputs=true, bool* pfMissingInputs=NULL)\r
623     {\r
624         CTxDB txdb("r");\r
625         return AcceptTransaction(txdb, fCheckInputs, pfMissingInputs);\r
626     }\r
627 \r
628 protected:\r
629     bool AddToMemoryPool();\r
630 public:\r
631     bool RemoveFromMemoryPool();\r
632 };\r
633 \r
634 \r
635 \r
636 \r
637 \r
638 //\r
639 // A transaction with a merkle branch linking it to the block chain\r
640 //\r
641 class CMerkleTx : public CTransaction\r
642 {\r
643 public:\r
644     uint256 hashBlock;\r
645     vector<uint256> vMerkleBranch;\r
646     int nIndex;\r
647 \r
648     // memory only\r
649     mutable bool fMerkleVerified;\r
650     mutable bool fGetCreditCached;\r
651     mutable int64 nGetCreditCached;\r
652 \r
653 \r
654     CMerkleTx()\r
655     {\r
656         Init();\r
657     }\r
658 \r
659     CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)\r
660     {\r
661         Init();\r
662     }\r
663 \r
664     void Init()\r
665     {\r
666         hashBlock = 0;\r
667         nIndex = -1;\r
668         fMerkleVerified = false;\r
669         fGetCreditCached = false;\r
670         nGetCreditCached = 0;\r
671     }\r
672 \r
673     IMPLEMENT_SERIALIZE\r
674     (\r
675         nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);\r
676         nVersion = this->nVersion;\r
677         READWRITE(hashBlock);\r
678         READWRITE(vMerkleBranch);\r
679         READWRITE(nIndex);\r
680     )\r
681 \r
682     int64 GetCredit(bool fUseCache=false) const\r
683     {\r
684         // Must wait until coinbase is safely deep enough in the chain before valuing it\r
685         if (IsCoinBase() && GetBlocksToMaturity() > 0)\r
686             return 0;\r
687 \r
688         // GetBalance can assume transactions in mapWallet won't change\r
689         if (fUseCache && fGetCreditCached)\r
690             return nGetCreditCached;\r
691         nGetCreditCached = CTransaction::GetCredit();\r
692         fGetCreditCached = true;\r
693         return nGetCreditCached;\r
694     }\r
695 \r
696 \r
697     int SetMerkleBranch(const CBlock* pblock=NULL);\r
698     int GetDepthInMainChain(int& nHeightRet) const;\r
699     int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }\r
700     bool IsInMainChain() const { return GetDepthInMainChain() > 0; }\r
701     int GetBlocksToMaturity() const;\r
702     bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true);\r
703     bool AcceptTransaction() { CTxDB txdb("r"); return AcceptTransaction(txdb); }\r
704 };\r
705 \r
706 \r
707 \r
708 \r
709 //\r
710 // A transaction with a bunch of additional info that only the owner cares\r
711 // about.  It includes any unrecorded transactions needed to link it back\r
712 // to the block chain.\r
713 //\r
714 class CWalletTx : public CMerkleTx\r
715 {\r
716 public:\r
717     vector<CMerkleTx> vtxPrev;\r
718     map<string, string> mapValue;\r
719     vector<pair<string, string> > vOrderForm;\r
720     unsigned int fTimeReceivedIsTxTime;\r
721     unsigned int nTimeReceived;  // time received by this node\r
722     char fFromMe;\r
723     char fSpent;\r
724     //// probably need to sign the order info so know it came from payer\r
725 \r
726     // memory only UI hints\r
727     mutable unsigned int nTimeDisplayed;\r
728     mutable int nLinesDisplayed;\r
729 \r
730 \r
731     CWalletTx()\r
732     {\r
733         Init();\r
734     }\r
735 \r
736     CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)\r
737     {\r
738         Init();\r
739     }\r
740 \r
741     CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)\r
742     {\r
743         Init();\r
744     }\r
745 \r
746     void Init()\r
747     {\r
748         fTimeReceivedIsTxTime = false;\r
749         nTimeReceived = 0;\r
750         fFromMe = false;\r
751         fSpent = false;\r
752         nTimeDisplayed = 0;\r
753         nLinesDisplayed = 0;\r
754     }\r
755 \r
756     IMPLEMENT_SERIALIZE\r
757     (\r
758         nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action);\r
759         nVersion = this->nVersion;\r
760         READWRITE(vtxPrev);\r
761         READWRITE(mapValue);\r
762         READWRITE(vOrderForm);\r
763         READWRITE(fTimeReceivedIsTxTime);\r
764         READWRITE(nTimeReceived);\r
765         READWRITE(fFromMe);\r
766         READWRITE(fSpent);\r
767     )\r
768 \r
769     bool WriteToDisk()\r
770     {\r
771         return CWalletDB().WriteTx(GetHash(), *this);\r
772     }\r
773 \r
774 \r
775     int64 GetTxTime() const;\r
776     int GetRequestCount() const;\r
777 \r
778     void AddSupportingTransactions(CTxDB& txdb);\r
779 \r
780     bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);\r
781     bool AcceptWalletTransaction() { CTxDB txdb("r"); return AcceptWalletTransaction(txdb); }\r
782 \r
783     void RelayWalletTransaction(CTxDB& txdb);\r
784     void RelayWalletTransaction() { CTxDB txdb("r"); RelayWalletTransaction(txdb); }\r
785 };\r
786 \r
787 \r
788 \r
789 \r
790 //\r
791 // A txdb record that contains the disk location of a transaction and the\r
792 // locations of transactions that spend its outputs.  vSpent is really only\r
793 // used as a flag, but having the location is very helpful for debugging.\r
794 //\r
795 class CTxIndex\r
796 {\r
797 public:\r
798     CDiskTxPos pos;\r
799     vector<CDiskTxPos> vSpent;\r
800 \r
801     CTxIndex()\r
802     {\r
803         SetNull();\r
804     }\r
805 \r
806     CTxIndex(const CDiskTxPos& posIn, unsigned int nOutputs)\r
807     {\r
808         pos = posIn;\r
809         vSpent.resize(nOutputs);\r
810     }\r
811 \r
812     IMPLEMENT_SERIALIZE\r
813     (\r
814         if (!(nType & SER_GETHASH))\r
815             READWRITE(nVersion);\r
816         READWRITE(pos);\r
817         READWRITE(vSpent);\r
818     )\r
819 \r
820     void SetNull()\r
821     {\r
822         pos.SetNull();\r
823         vSpent.clear();\r
824     }\r
825 \r
826     bool IsNull()\r
827     {\r
828         return pos.IsNull();\r
829     }\r
830 \r
831     friend bool operator==(const CTxIndex& a, const CTxIndex& b)\r
832     {\r
833         if (a.pos != b.pos || a.vSpent.size() != b.vSpent.size())\r
834             return false;\r
835         for (int i = 0; i < a.vSpent.size(); i++)\r
836             if (a.vSpent[i] != b.vSpent[i])\r
837                 return false;\r
838         return true;\r
839     }\r
840 \r
841     friend bool operator!=(const CTxIndex& a, const CTxIndex& b)\r
842     {\r
843         return !(a == b);\r
844     }\r
845 };\r
846 \r
847 \r
848 \r
849 \r
850 \r
851 //\r
852 // Nodes collect new transactions into a block, hash them into a hash tree,\r
853 // and scan through nonce values to make the block's hash satisfy proof-of-work\r
854 // requirements.  When they solve the proof-of-work, they broadcast the block\r
855 // to everyone and the block is added to the block chain.  The first transaction\r
856 // in the block is a special one that creates a new coin owned by the creator\r
857 // of the block.\r
858 //\r
859 // Blocks are appended to blk0001.dat files on disk.  Their location on disk\r
860 // is indexed by CBlockIndex objects in memory.\r
861 //\r
862 class CBlock\r
863 {\r
864 public:\r
865     // header\r
866     int nVersion;\r
867     uint256 hashPrevBlock;\r
868     uint256 hashMerkleRoot;\r
869     unsigned int nTime;\r
870     unsigned int nBits;\r
871     unsigned int nNonce;\r
872 \r
873     // network and disk\r
874     vector<CTransaction> vtx;\r
875 \r
876     // memory only\r
877     mutable vector<uint256> vMerkleTree;\r
878 \r
879 \r
880     CBlock()\r
881     {\r
882         SetNull();\r
883     }\r
884 \r
885     IMPLEMENT_SERIALIZE\r
886     (\r
887         READWRITE(this->nVersion);\r
888         nVersion = this->nVersion;\r
889         READWRITE(hashPrevBlock);\r
890         READWRITE(hashMerkleRoot);\r
891         READWRITE(nTime);\r
892         READWRITE(nBits);\r
893         READWRITE(nNonce);\r
894 \r
895         // ConnectBlock depends on vtx being last so it can calculate offset\r
896         if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))\r
897             READWRITE(vtx);\r
898         else if (fRead)\r
899             const_cast<CBlock*>(this)->vtx.clear();\r
900     )\r
901 \r
902     void SetNull()\r
903     {\r
904         nVersion = 1;\r
905         hashPrevBlock = 0;\r
906         hashMerkleRoot = 0;\r
907         nTime = 0;\r
908         nBits = 0;\r
909         nNonce = 0;\r
910         vtx.clear();\r
911         vMerkleTree.clear();\r
912     }\r
913 \r
914     bool IsNull() const\r
915     {\r
916         return (nBits == 0);\r
917     }\r
918 \r
919     uint256 GetHash() const\r
920     {\r
921         return Hash(BEGIN(nVersion), END(nNonce));\r
922     }\r
923 \r
924 \r
925     uint256 BuildMerkleTree() const\r
926     {\r
927         vMerkleTree.clear();\r
928         foreach(const CTransaction& tx, vtx)\r
929             vMerkleTree.push_back(tx.GetHash());\r
930         int j = 0;\r
931         for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)\r
932         {\r
933             for (int i = 0; i < nSize; i += 2)\r
934             {\r
935                 int i2 = min(i+1, nSize-1);\r
936                 vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),\r
937                                            BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));\r
938             }\r
939             j += nSize;\r
940         }\r
941         return (vMerkleTree.empty() ? 0 : vMerkleTree.back());\r
942     }\r
943 \r
944     vector<uint256> GetMerkleBranch(int nIndex) const\r
945     {\r
946         if (vMerkleTree.empty())\r
947             BuildMerkleTree();\r
948         vector<uint256> vMerkleBranch;\r
949         int j = 0;\r
950         for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)\r
951         {\r
952             int i = min(nIndex^1, nSize-1);\r
953             vMerkleBranch.push_back(vMerkleTree[j+i]);\r
954             nIndex >>= 1;\r
955             j += nSize;\r
956         }\r
957         return vMerkleBranch;\r
958     }\r
959 \r
960     static uint256 CheckMerkleBranch(uint256 hash, const vector<uint256>& vMerkleBranch, int nIndex)\r
961     {\r
962         if (nIndex == -1)\r
963             return 0;\r
964         foreach(const uint256& otherside, vMerkleBranch)\r
965         {\r
966             if (nIndex & 1)\r
967                 hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));\r
968             else\r
969                 hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));\r
970             nIndex >>= 1;\r
971         }\r
972         return hash;\r
973     }\r
974 \r
975 \r
976     bool WriteToDisk(bool fWriteTransactions, unsigned int& nFileRet, unsigned int& nBlockPosRet)\r
977     {\r
978         // Open history file to append\r
979         CAutoFile fileout = AppendBlockFile(nFileRet);\r
980         if (!fileout)\r
981             return error("CBlock::WriteToDisk() : AppendBlockFile failed");\r
982         if (!fWriteTransactions)\r
983             fileout.nType |= SER_BLOCKHEADERONLY;\r
984 \r
985         // Write index header\r
986         unsigned int nSize = fileout.GetSerializeSize(*this);\r
987         fileout << FLATDATA(pchMessageStart) << nSize;\r
988 \r
989         // Write block\r
990         nBlockPosRet = ftell(fileout);\r
991         if (nBlockPosRet == -1)\r
992             return error("CBlock::WriteToDisk() : ftell failed");\r
993         fileout << *this;\r
994 \r
995         // Flush stdio buffers and commit to disk before returning\r
996         fflush(fileout);\r
997         if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0)\r
998         {\r
999 #ifdef __WXMSW__\r
1000             _commit(_fileno(fileout));\r
1001 #else\r
1002             fsync(fileno(fileout));\r
1003 #endif\r
1004         }\r
1005 \r
1006         return true;\r
1007     }\r
1008 \r
1009     bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true)\r
1010     {\r
1011         SetNull();\r
1012 \r
1013         // Open history file to read\r
1014         CAutoFile filein = OpenBlockFile(nFile, nBlockPos, "rb");\r
1015         if (!filein)\r
1016             return error("CBlock::ReadFromDisk() : OpenBlockFile failed");\r
1017         if (!fReadTransactions)\r
1018             filein.nType |= SER_BLOCKHEADERONLY;\r
1019 \r
1020         // Read block\r
1021         filein >> *this;\r
1022 \r
1023         // Check the header\r
1024         if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)\r
1025             return error("CBlock::ReadFromDisk() : nBits errors in block header");\r
1026         if (GetHash() > CBigNum().SetCompact(nBits).getuint256())\r
1027             return error("CBlock::ReadFromDisk() : GetHash() errors in block header");\r
1028 \r
1029         return true;\r
1030     }\r
1031 \r
1032 \r
1033 \r
1034     void print() const\r
1035     {\r
1036         printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",\r
1037             GetHash().ToString().substr(0,16).c_str(),\r
1038             nVersion,\r
1039             hashPrevBlock.ToString().substr(0,16).c_str(),\r
1040             hashMerkleRoot.ToString().substr(0,6).c_str(),\r
1041             nTime, nBits, nNonce,\r
1042             vtx.size());\r
1043         for (int i = 0; i < vtx.size(); i++)\r
1044         {\r
1045             printf("  ");\r
1046             vtx[i].print();\r
1047         }\r
1048         printf("  vMerkleTree: ");\r
1049         for (int i = 0; i < vMerkleTree.size(); i++)\r
1050             printf("%s ", vMerkleTree[i].ToString().substr(0,6).c_str());\r
1051         printf("\n");\r
1052     }\r
1053 \r
1054 \r
1055     int64 GetBlockValue(int nHeight, int64 nFees) const;\r
1056     bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);\r
1057     bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);\r
1058     bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions=true);\r
1059     bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);\r
1060     bool CheckBlock() const;\r
1061     bool AcceptBlock();\r
1062 };\r
1063 \r
1064 \r
1065 \r
1066 \r
1067 \r
1068 \r
1069 //\r
1070 // The block chain is a tree shaped structure starting with the\r
1071 // genesis block at the root, with each block potentially having multiple\r
1072 // candidates to be the next block.  pprev and pnext link a path through the\r
1073 // main/longest chain.  A blockindex may have multiple pprev pointing back\r
1074 // to it, but pnext will only point forward to the longest branch, or will\r
1075 // be null if the block is not part of the longest chain.\r
1076 //\r
1077 class CBlockIndex\r
1078 {\r
1079 public:\r
1080     const uint256* phashBlock;\r
1081     CBlockIndex* pprev;\r
1082     CBlockIndex* pnext;\r
1083     unsigned int nFile;\r
1084     unsigned int nBlockPos;\r
1085     int nHeight;\r
1086     CBigNum bnChainWork;\r
1087 \r
1088     // block header\r
1089     int nVersion;\r
1090     uint256 hashMerkleRoot;\r
1091     unsigned int nTime;\r
1092     unsigned int nBits;\r
1093     unsigned int nNonce;\r
1094 \r
1095 \r
1096     CBlockIndex()\r
1097     {\r
1098         phashBlock = NULL;\r
1099         pprev = NULL;\r
1100         pnext = NULL;\r
1101         nFile = 0;\r
1102         nBlockPos = 0;\r
1103         nHeight = 0;\r
1104         bnChainWork = 0;\r
1105 \r
1106         nVersion       = 0;\r
1107         hashMerkleRoot = 0;\r
1108         nTime          = 0;\r
1109         nBits          = 0;\r
1110         nNonce         = 0;\r
1111     }\r
1112 \r
1113     CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block)\r
1114     {\r
1115         phashBlock = NULL;\r
1116         pprev = NULL;\r
1117         pnext = NULL;\r
1118         nFile = nFileIn;\r
1119         nBlockPos = nBlockPosIn;\r
1120         nHeight = 0;\r
1121         bnChainWork = 0;\r
1122 \r
1123         nVersion       = block.nVersion;\r
1124         hashMerkleRoot = block.hashMerkleRoot;\r
1125         nTime          = block.nTime;\r
1126         nBits          = block.nBits;\r
1127         nNonce         = block.nNonce;\r
1128     }\r
1129 \r
1130     uint256 GetBlockHash() const\r
1131     {\r
1132         return *phashBlock;\r
1133     }\r
1134 \r
1135     CBigNum GetBlockWork() const\r
1136     {\r
1137         return (CBigNum(1)<<256) / (CBigNum().SetCompact(nBits)+1);\r
1138     }\r
1139 \r
1140     bool IsInMainChain() const\r
1141     {\r
1142         return (pnext || this == pindexBest);\r
1143     }\r
1144 \r
1145     bool EraseBlockFromDisk()\r
1146     {\r
1147         // Open history file\r
1148         CAutoFile fileout = OpenBlockFile(nFile, nBlockPos, "rb+");\r
1149         if (!fileout)\r
1150             return false;\r
1151 \r
1152         // Overwrite with empty null block\r
1153         CBlock block;\r
1154         block.SetNull();\r
1155         fileout << block;\r
1156 \r
1157         return true;\r
1158     }\r
1159 \r
1160     enum { nMedianTimeSpan=11 };\r
1161 \r
1162     int64 GetMedianTimePast() const\r
1163     {\r
1164         unsigned int pmedian[nMedianTimeSpan];\r
1165         unsigned int* pbegin = &pmedian[nMedianTimeSpan];\r
1166         unsigned int* pend = &pmedian[nMedianTimeSpan];\r
1167 \r
1168         const CBlockIndex* pindex = this;\r
1169         for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)\r
1170             *(--pbegin) = pindex->nTime;\r
1171 \r
1172         sort(pbegin, pend);\r
1173         return pbegin[(pend - pbegin)/2];\r
1174     }\r
1175 \r
1176     int64 GetMedianTime() const\r
1177     {\r
1178         const CBlockIndex* pindex = this;\r
1179         for (int i = 0; i < nMedianTimeSpan/2; i++)\r
1180         {\r
1181             if (!pindex->pnext)\r
1182                 return nTime;\r
1183             pindex = pindex->pnext;\r
1184         }\r
1185         return pindex->GetMedianTimePast();\r
1186     }\r
1187 \r
1188 \r
1189 \r
1190     string ToString() const\r
1191     {\r
1192         return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",\r
1193             pprev, pnext, nFile, nBlockPos, nHeight,\r
1194             hashMerkleRoot.ToString().substr(0,6).c_str(),\r
1195             GetBlockHash().ToString().substr(0,16).c_str());\r
1196     }\r
1197 \r
1198     void print() const\r
1199     {\r
1200         printf("%s\n", ToString().c_str());\r
1201     }\r
1202 };\r
1203 \r
1204 \r
1205 \r
1206 //\r
1207 // Used to marshal pointers into hashes for db storage.\r
1208 //\r
1209 class CDiskBlockIndex : public CBlockIndex\r
1210 {\r
1211 public:\r
1212     uint256 hashPrev;\r
1213     uint256 hashNext;\r
1214 \r
1215     CDiskBlockIndex()\r
1216     {\r
1217         hashPrev = 0;\r
1218         hashNext = 0;\r
1219     }\r
1220 \r
1221     explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex)\r
1222     {\r
1223         hashPrev = (pprev ? pprev->GetBlockHash() : 0);\r
1224         hashNext = (pnext ? pnext->GetBlockHash() : 0);\r
1225     }\r
1226 \r
1227     IMPLEMENT_SERIALIZE\r
1228     (\r
1229         if (!(nType & SER_GETHASH))\r
1230             READWRITE(nVersion);\r
1231 \r
1232         READWRITE(hashNext);\r
1233         READWRITE(nFile);\r
1234         READWRITE(nBlockPos);\r
1235         READWRITE(nHeight);\r
1236 \r
1237         // block header\r
1238         READWRITE(this->nVersion);\r
1239         READWRITE(hashPrev);\r
1240         READWRITE(hashMerkleRoot);\r
1241         READWRITE(nTime);\r
1242         READWRITE(nBits);\r
1243         READWRITE(nNonce);\r
1244     )\r
1245 \r
1246     uint256 GetBlockHash() const\r
1247     {\r
1248         CBlock block;\r
1249         block.nVersion        = nVersion;\r
1250         block.hashPrevBlock   = hashPrev;\r
1251         block.hashMerkleRoot  = hashMerkleRoot;\r
1252         block.nTime           = nTime;\r
1253         block.nBits           = nBits;\r
1254         block.nNonce          = nNonce;\r
1255         return block.GetHash();\r
1256     }\r
1257 \r
1258 \r
1259     string ToString() const\r
1260     {\r
1261         string str = "CDiskBlockIndex(";\r
1262         str += CBlockIndex::ToString();\r
1263         str += strprintf("\n                hashBlock=%s, hashPrev=%s, hashNext=%s)",\r
1264             GetBlockHash().ToString().c_str(),\r
1265             hashPrev.ToString().substr(0,16).c_str(),\r
1266             hashNext.ToString().substr(0,16).c_str());\r
1267         return str;\r
1268     }\r
1269 \r
1270     void print() const\r
1271     {\r
1272         printf("%s\n", ToString().c_str());\r
1273     }\r
1274 };\r
1275 \r
1276 \r
1277 \r
1278 \r
1279 \r
1280 \r
1281 \r
1282 \r
1283 //\r
1284 // Describes a place in the block chain to another node such that if the\r
1285 // other node doesn't have the same branch, it can find a recent common trunk.\r
1286 // The further back it is, the further before the fork it may be.\r
1287 //\r
1288 class CBlockLocator\r
1289 {\r
1290 protected:\r
1291     vector<uint256> vHave;\r
1292 public:\r
1293 \r
1294     CBlockLocator()\r
1295     {\r
1296     }\r
1297 \r
1298     explicit CBlockLocator(const CBlockIndex* pindex)\r
1299     {\r
1300         Set(pindex);\r
1301     }\r
1302 \r
1303     explicit CBlockLocator(uint256 hashBlock)\r
1304     {\r
1305         map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);\r
1306         if (mi != mapBlockIndex.end())\r
1307             Set((*mi).second);\r
1308     }\r
1309 \r
1310     IMPLEMENT_SERIALIZE\r
1311     (\r
1312         if (!(nType & SER_GETHASH))\r
1313             READWRITE(nVersion);\r
1314         READWRITE(vHave);\r
1315     )\r
1316 \r
1317     void Set(const CBlockIndex* pindex)\r
1318     {\r
1319         vHave.clear();\r
1320         int nStep = 1;\r
1321         while (pindex)\r
1322         {\r
1323             vHave.push_back(pindex->GetBlockHash());\r
1324 \r
1325             // Exponentially larger steps back\r
1326             for (int i = 0; pindex && i < nStep; i++)\r
1327                 pindex = pindex->pprev;\r
1328             if (vHave.size() > 10)\r
1329                 nStep *= 2;\r
1330         }\r
1331         vHave.push_back(hashGenesisBlock);\r
1332     }\r
1333 \r
1334     int GetDistanceBack()\r
1335     {\r
1336         // Retrace how far back it was in the sender's branch\r
1337         int nDistance = 0;\r
1338         int nStep = 1;\r
1339         foreach(const uint256& hash, vHave)\r
1340         {\r
1341             map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);\r
1342             if (mi != mapBlockIndex.end())\r
1343             {\r
1344                 CBlockIndex* pindex = (*mi).second;\r
1345                 if (pindex->IsInMainChain())\r
1346                     return nDistance;\r
1347             }\r
1348             nDistance += nStep;\r
1349             if (nDistance > 10)\r
1350                 nStep *= 2;\r
1351         }\r
1352         return nDistance;\r
1353     }\r
1354 \r
1355     CBlockIndex* GetBlockIndex()\r
1356     {\r
1357         // Find the first block the caller has in the main chain\r
1358         foreach(const uint256& hash, vHave)\r
1359         {\r
1360             map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);\r
1361             if (mi != mapBlockIndex.end())\r
1362             {\r
1363                 CBlockIndex* pindex = (*mi).second;\r
1364                 if (pindex->IsInMainChain())\r
1365                     return pindex;\r
1366             }\r
1367         }\r
1368         return pindexGenesisBlock;\r
1369     }\r
1370 \r
1371     uint256 GetBlockHash()\r
1372     {\r
1373         // Find the first block the caller has in the main chain\r
1374         foreach(const uint256& hash, vHave)\r
1375         {\r
1376             map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);\r
1377             if (mi != mapBlockIndex.end())\r
1378             {\r
1379                 CBlockIndex* pindex = (*mi).second;\r
1380                 if (pindex->IsInMainChain())\r
1381                     return hash;\r
1382             }\r
1383         }\r
1384         return hashGenesisBlock;\r
1385     }\r
1386 \r
1387     int GetHeight()\r
1388     {\r
1389         CBlockIndex* pindex = GetBlockIndex();\r
1390         if (!pindex)\r
1391             return 0;\r
1392         return pindex->nHeight;\r
1393     }\r
1394 };\r
1395 \r
1396 \r
1397 \r
1398 \r
1399 \r
1400 \r
1401 //\r
1402 // Private key that includes an expiration date in case it never gets used.\r
1403 //\r
1404 class CWalletKey\r
1405 {\r
1406 public:\r
1407     CPrivKey vchPrivKey;\r
1408     int64 nTimeCreated;\r
1409     int64 nTimeExpires;\r
1410     string strComment;\r
1411     //// todo: add something to note what created it (user, getnewaddress, change)\r
1412     ////   maybe should have a map<string, string> property map\r
1413 \r
1414     CWalletKey(int64 nTimeExpiresIn=0)\r
1415     {\r
1416         nTimeCreated = (nTimeExpiresIn ? GetTime() : 0);\r
1417         nTimeExpires = nTimeExpiresIn;\r
1418     }\r
1419 \r
1420     IMPLEMENT_SERIALIZE\r
1421     (\r
1422         if (!(nType & SER_GETHASH))\r
1423             READWRITE(nVersion);\r
1424         READWRITE(vchPrivKey);\r
1425         READWRITE(nTimeCreated);\r
1426         READWRITE(nTimeExpires);\r
1427         READWRITE(strComment);\r
1428     )\r
1429 };\r
1430 \r
1431 \r
1432 \r
1433 \r
1434 \r
1435 \r
1436 extern map<uint256, CTransaction> mapTransactions;\r
1437 extern map<uint256, CWalletTx> mapWallet;\r
1438 extern vector<uint256> vWalletUpdated;\r
1439 extern CCriticalSection cs_mapWallet;\r
1440 extern map<vector<unsigned char>, CPrivKey> mapKeys;\r
1441 extern map<uint160, vector<unsigned char> > mapPubKeys;\r
1442 extern CCriticalSection cs_mapKeys;\r
1443 extern CKey keyUser;\r