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