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