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