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