addr relaying fixes, proxy option and privacy patches, detect connect to self, non...
[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     unsigned 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(int64 nBlockTime=0) const\r
405     {\r
406         // Time based nLockTime implemented in 0.1.6,\r
407         // do not use time based until most 0.1.5 nodes have upgraded.\r
408         if (nBlockTime == 0)\r
409             nBlockTime = GetAdjustedTime();\r
410         if (nLockTime == 0)\r
411             return true;\r
412         if (nLockTime < (nLockTime < 500000000 ? nBestHeight : nBlockTime))\r
413             return true;\r
414         foreach(const CTxIn& txin, vin)\r
415             if (!txin.IsFinal())\r
416                 return false;\r
417         return true;\r
418     }\r
419 \r
420     bool IsNewerThan(const CTransaction& old) const\r
421     {\r
422         if (vin.size() != old.vin.size())\r
423             return false;\r
424         for (int i = 0; i < vin.size(); i++)\r
425             if (vin[i].prevout != old.vin[i].prevout)\r
426                 return false;\r
427 \r
428         bool fNewer = false;\r
429         unsigned int nLowest = UINT_MAX;\r
430         for (int i = 0; i < vin.size(); i++)\r
431         {\r
432             if (vin[i].nSequence != old.vin[i].nSequence)\r
433             {\r
434                 if (vin[i].nSequence <= nLowest)\r
435                 {\r
436                     fNewer = false;\r
437                     nLowest = vin[i].nSequence;\r
438                 }\r
439                 if (old.vin[i].nSequence < nLowest)\r
440                 {\r
441                     fNewer = true;\r
442                     nLowest = old.vin[i].nSequence;\r
443                 }\r
444             }\r
445         }\r
446         return fNewer;\r
447     }\r
448 \r
449     bool IsCoinBase() const\r
450     {\r
451         return (vin.size() == 1 && vin[0].prevout.IsNull());\r
452     }\r
453 \r
454     bool CheckTransaction() const\r
455     {\r
456         // Basic checks that don't depend on any context\r
457         if (vin.empty() || vout.empty())\r
458             return error("CTransaction::CheckTransaction() : vin or vout empty");\r
459 \r
460         // Check for negative values\r
461         foreach(const CTxOut& txout, vout)\r
462             if (txout.nValue < 0)\r
463                 return error("CTransaction::CheckTransaction() : txout.nValue negative");\r
464 \r
465         if (IsCoinBase())\r
466         {\r
467             if (vin[0].scriptSig.size() < 2 || vin[0].scriptSig.size() > 100)\r
468                 return error("CTransaction::CheckTransaction() : coinbase script size");\r
469         }\r
470         else\r
471         {\r
472             foreach(const CTxIn& txin, vin)\r
473                 if (txin.prevout.IsNull())\r
474                     return error("CTransaction::CheckTransaction() : prevout is null");\r
475         }\r
476 \r
477         return true;\r
478     }\r
479 \r
480     bool IsMine() const\r
481     {\r
482         foreach(const CTxOut& txout, vout)\r
483             if (txout.IsMine())\r
484                 return true;\r
485         return false;\r
486     }\r
487 \r
488     int64 GetDebit() const\r
489     {\r
490         int64 nDebit = 0;\r
491         foreach(const CTxIn& txin, vin)\r
492             nDebit += txin.GetDebit();\r
493         return nDebit;\r
494     }\r
495 \r
496     int64 GetCredit() const\r
497     {\r
498         int64 nCredit = 0;\r
499         foreach(const CTxOut& txout, vout)\r
500             nCredit += txout.GetCredit();\r
501         return nCredit;\r
502     }\r
503 \r
504     int64 GetValueOut() const\r
505     {\r
506         int64 nValueOut = 0;\r
507         foreach(const CTxOut& txout, vout)\r
508         {\r
509             if (txout.nValue < 0)\r
510                 throw runtime_error("CTransaction::GetValueOut() : negative value");\r
511             nValueOut += txout.nValue;\r
512         }\r
513         return nValueOut;\r
514     }\r
515 \r
516     int64 GetMinFee(bool fDiscount=false) const\r
517     {\r
518         // Base fee is 1 cent per kilobyte\r
519         unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);\r
520         int64 nMinFee = (1 + (int64)nBytes / 1000) * CENT;\r
521 \r
522         // First 100 transactions in a block are free\r
523         if (fDiscount && nBytes < 10000)\r
524             nMinFee = 0;\r
525 \r
526         // To limit dust spam, require a 0.01 fee if any output is less than 0.01\r
527         if (nMinFee < CENT)\r
528             foreach(const CTxOut& txout, vout)\r
529                 if (txout.nValue < CENT)\r
530                     nMinFee = CENT;\r
531 \r
532         return nMinFee;\r
533     }\r
534 \r
535 \r
536 \r
537     bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)\r
538     {\r
539         CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");\r
540         if (!filein)\r
541             return error("CTransaction::ReadFromDisk() : OpenBlockFile failed");\r
542 \r
543         // Read transaction\r
544         if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)\r
545             return error("CTransaction::ReadFromDisk() : fseek failed");\r
546         filein >> *this;\r
547 \r
548         // Return file pointer\r
549         if (pfileRet)\r
550         {\r
551             if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)\r
552                 return error("CTransaction::ReadFromDisk() : second fseek failed");\r
553             *pfileRet = filein.release();\r
554         }\r
555         return true;\r
556     }\r
557 \r
558 \r
559     friend bool operator==(const CTransaction& a, const CTransaction& b)\r
560     {\r
561         return (a.nVersion  == b.nVersion &&\r
562                 a.vin       == b.vin &&\r
563                 a.vout      == b.vout &&\r
564                 a.nLockTime == b.nLockTime);\r
565     }\r
566 \r
567     friend bool operator!=(const CTransaction& a, const CTransaction& b)\r
568     {\r
569         return !(a == b);\r
570     }\r
571 \r
572 \r
573     string ToString() const\r
574     {\r
575         string str;\r
576         str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",\r
577             GetHash().ToString().substr(0,6).c_str(),\r
578             nVersion,\r
579             vin.size(),\r
580             vout.size(),\r
581             nLockTime);\r
582         for (int i = 0; i < vin.size(); i++)\r
583             str += "    " + vin[i].ToString() + "\n";\r
584         for (int i = 0; i < vout.size(); i++)\r
585             str += "    " + vout[i].ToString() + "\n";\r
586         return str;\r
587     }\r
588 \r
589     void print() const\r
590     {\r
591         printf("%s", ToString().c_str());\r
592     }\r
593 \r
594 \r
595 \r
596     bool DisconnectInputs(CTxDB& txdb);\r
597     bool ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx, int nHeight, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);\r
598     bool ClientConnectInputs();\r
599 \r
600     bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);\r
601 \r
602     bool AcceptTransaction(bool fCheckInputs=true, bool* pfMissingInputs=NULL)\r
603     {\r
604         CTxDB txdb("r");\r
605         return AcceptTransaction(txdb, fCheckInputs, pfMissingInputs);\r
606     }\r
607 \r
608 protected:\r
609     bool AddToMemoryPool();\r
610 public:\r
611     bool RemoveFromMemoryPool();\r
612 };\r
613 \r
614 \r
615 \r
616 \r
617 \r
618 //\r
619 // A transaction with a merkle branch linking it to the block chain\r
620 //\r
621 class CMerkleTx : public CTransaction\r
622 {\r
623 public:\r
624     uint256 hashBlock;\r
625     vector<uint256> vMerkleBranch;\r
626     int nIndex;\r
627 \r
628     // memory only\r
629     mutable bool fMerkleVerified;\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     }\r
648 \r
649     int64 GetCredit() const\r
650     {\r
651         // Must wait until coinbase is safely deep enough in the chain before valuing it\r
652         if (IsCoinBase() && GetBlocksToMaturity() > 0)\r
653             return 0;\r
654         return CTransaction::GetCredit();\r
655     }\r
656 \r
657     IMPLEMENT_SERIALIZE\r
658     (\r
659         nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);\r
660         nVersion = this->nVersion;\r
661         READWRITE(hashBlock);\r
662         READWRITE(vMerkleBranch);\r
663         READWRITE(nIndex);\r
664     )\r
665 \r
666 \r
667     int SetMerkleBranch(const CBlock* pblock=NULL);\r
668     int GetDepthInMainChain() const;\r
669     bool IsInMainChain() const { return GetDepthInMainChain() > 0; }\r
670     int GetBlocksToMaturity() const;\r
671     bool AcceptTransaction(CTxDB& txdb, bool fCheckInputs=true);\r
672     bool AcceptTransaction() { CTxDB txdb("r"); return AcceptTransaction(txdb); }\r
673 };\r
674 \r
675 \r
676 \r
677 \r
678 //\r
679 // A transaction with a bunch of additional info that only the owner cares\r
680 // about.  It includes any unrecorded transactions needed to link it back\r
681 // to the block chain.\r
682 //\r
683 class CWalletTx : public CMerkleTx\r
684 {\r
685 public:\r
686     vector<CMerkleTx> vtxPrev;\r
687     map<string, string> mapValue;\r
688     vector<pair<string, string> > vOrderForm;\r
689     unsigned int fTimeReceivedIsTxTime;\r
690     unsigned int nTimeReceived;  // time received by this node\r
691     char fFromMe;\r
692     char fSpent;\r
693     //// probably need to sign the order info so know it came from payer\r
694 \r
695     // memory only UI hints\r
696     mutable unsigned int nTimeDisplayed;\r
697     mutable int nLinesDisplayed;\r
698 \r
699 \r
700     CWalletTx()\r
701     {\r
702         Init();\r
703     }\r
704 \r
705     CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)\r
706     {\r
707         Init();\r
708     }\r
709 \r
710     CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)\r
711     {\r
712         Init();\r
713     }\r
714 \r
715     void Init()\r
716     {\r
717         fTimeReceivedIsTxTime = false;\r
718         nTimeReceived = 0;\r
719         fFromMe = false;\r
720         fSpent = false;\r
721         nTimeDisplayed = 0;\r
722         nLinesDisplayed = 0;\r
723     }\r
724 \r
725     IMPLEMENT_SERIALIZE\r
726     (\r
727         nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action);\r
728         nVersion = this->nVersion;\r
729         READWRITE(vtxPrev);\r
730         READWRITE(mapValue);\r
731         READWRITE(vOrderForm);\r
732         READWRITE(fTimeReceivedIsTxTime);\r
733         READWRITE(nTimeReceived);\r
734         READWRITE(fFromMe);\r
735         READWRITE(fSpent);\r
736     )\r
737 \r
738     bool WriteToDisk()\r
739     {\r
740         return CWalletDB().WriteTx(GetHash(), *this);\r
741     }\r
742 \r
743 \r
744     int64 GetTxTime() const;\r
745 \r
746     void AddSupportingTransactions(CTxDB& txdb);\r
747 \r
748     bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);\r
749     bool AcceptWalletTransaction() { CTxDB txdb("r"); return AcceptWalletTransaction(txdb); }\r
750 \r
751     void RelayWalletTransaction(CTxDB& txdb);\r
752     void RelayWalletTransaction() { CTxDB txdb("r"); RelayWalletTransaction(txdb); }\r
753 };\r
754 \r
755 \r
756 \r
757 \r
758 //\r
759 // A txdb record that contains the disk location of a transaction and the\r
760 // locations of transactions that spend its outputs.  vSpent is really only\r
761 // used as a flag, but having the location is very helpful for debugging.\r
762 //\r
763 class CTxIndex\r
764 {\r
765 public:\r
766     CDiskTxPos pos;\r
767     vector<CDiskTxPos> vSpent;\r
768 \r
769     CTxIndex()\r
770     {\r
771         SetNull();\r
772     }\r
773 \r
774     CTxIndex(const CDiskTxPos& posIn, unsigned int nOutputs)\r
775     {\r
776         pos = posIn;\r
777         vSpent.resize(nOutputs);\r
778     }\r
779 \r
780     IMPLEMENT_SERIALIZE\r
781     (\r
782         if (!(nType & SER_GETHASH))\r
783             READWRITE(nVersion);\r
784         READWRITE(pos);\r
785         READWRITE(vSpent);\r
786     )\r
787 \r
788     void SetNull()\r
789     {\r
790         pos.SetNull();\r
791         vSpent.clear();\r
792     }\r
793 \r
794     bool IsNull()\r
795     {\r
796         return pos.IsNull();\r
797     }\r
798 \r
799     friend bool operator==(const CTxIndex& a, const CTxIndex& b)\r
800     {\r
801         if (a.pos != b.pos || a.vSpent.size() != b.vSpent.size())\r
802             return false;\r
803         for (int i = 0; i < a.vSpent.size(); i++)\r
804             if (a.vSpent[i] != b.vSpent[i])\r
805                 return false;\r
806         return true;\r
807     }\r
808 \r
809     friend bool operator!=(const CTxIndex& a, const CTxIndex& b)\r
810     {\r
811         return !(a == b);\r
812     }\r
813 };\r
814 \r
815 \r
816 \r
817 \r
818 \r
819 //\r
820 // Nodes collect new transactions into a block, hash them into a hash tree,\r
821 // and scan through nonce values to make the block's hash satisfy proof-of-work\r
822 // requirements.  When they solve the proof-of-work, they broadcast the block\r
823 // to everyone and the block is added to the block chain.  The first transaction\r
824 // in the block is a special one that creates a new coin owned by the creator\r
825 // of the block.\r
826 //\r
827 // Blocks are appended to blk0001.dat files on disk.  Their location on disk\r
828 // is indexed by CBlockIndex objects in memory.\r
829 //\r
830 class CBlock\r
831 {\r
832 public:\r
833     // header\r
834     int nVersion;\r
835     uint256 hashPrevBlock;\r
836     uint256 hashMerkleRoot;\r
837     unsigned int nTime;\r
838     unsigned int nBits;\r
839     unsigned int nNonce;\r
840 \r
841     // network and disk\r
842     vector<CTransaction> vtx;\r
843 \r
844     // memory only\r
845     mutable vector<uint256> vMerkleTree;\r
846 \r
847 \r
848     CBlock()\r
849     {\r
850         SetNull();\r
851     }\r
852 \r
853     IMPLEMENT_SERIALIZE\r
854     (\r
855         READWRITE(this->nVersion);\r
856         nVersion = this->nVersion;\r
857         READWRITE(hashPrevBlock);\r
858         READWRITE(hashMerkleRoot);\r
859         READWRITE(nTime);\r
860         READWRITE(nBits);\r
861         READWRITE(nNonce);\r
862 \r
863         // ConnectBlock depends on vtx being last so it can calculate offset\r
864         if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))\r
865             READWRITE(vtx);\r
866         else if (fRead)\r
867             const_cast<CBlock*>(this)->vtx.clear();\r
868     )\r
869 \r
870     void SetNull()\r
871     {\r
872         nVersion = 1;\r
873         hashPrevBlock = 0;\r
874         hashMerkleRoot = 0;\r
875         nTime = 0;\r
876         nBits = 0;\r
877         nNonce = 0;\r
878         vtx.clear();\r
879         vMerkleTree.clear();\r
880     }\r
881 \r
882     bool IsNull() const\r
883     {\r
884         return (nBits == 0);\r
885     }\r
886 \r
887     uint256 GetHash() const\r
888     {\r
889         return Hash(BEGIN(nVersion), END(nNonce));\r
890     }\r
891 \r
892 \r
893     uint256 BuildMerkleTree() const\r
894     {\r
895         vMerkleTree.clear();\r
896         foreach(const CTransaction& tx, vtx)\r
897             vMerkleTree.push_back(tx.GetHash());\r
898         int j = 0;\r
899         for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)\r
900         {\r
901             for (int i = 0; i < nSize; i += 2)\r
902             {\r
903                 int i2 = min(i+1, nSize-1);\r
904                 vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),\r
905                                            BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));\r
906             }\r
907             j += nSize;\r
908         }\r
909         return (vMerkleTree.empty() ? 0 : vMerkleTree.back());\r
910     }\r
911 \r
912     vector<uint256> GetMerkleBranch(int nIndex) const\r
913     {\r
914         if (vMerkleTree.empty())\r
915             BuildMerkleTree();\r
916         vector<uint256> vMerkleBranch;\r
917         int j = 0;\r
918         for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)\r
919         {\r
920             int i = min(nIndex^1, nSize-1);\r
921             vMerkleBranch.push_back(vMerkleTree[j+i]);\r
922             nIndex >>= 1;\r
923             j += nSize;\r
924         }\r
925         return vMerkleBranch;\r
926     }\r
927 \r
928     static uint256 CheckMerkleBranch(uint256 hash, const vector<uint256>& vMerkleBranch, int nIndex)\r
929     {\r
930         if (nIndex == -1)\r
931             return 0;\r
932         foreach(const uint256& otherside, vMerkleBranch)\r
933         {\r
934             if (nIndex & 1)\r
935                 hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));\r
936             else\r
937                 hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));\r
938             nIndex >>= 1;\r
939         }\r
940         return hash;\r
941     }\r
942 \r
943 \r
944     bool WriteToDisk(bool fWriteTransactions, unsigned int& nFileRet, unsigned int& nBlockPosRet)\r
945     {\r
946         // Open history file to append\r
947         CAutoFile fileout = AppendBlockFile(nFileRet);\r
948         if (!fileout)\r
949             return error("CBlock::WriteToDisk() : AppendBlockFile failed");\r
950         if (!fWriteTransactions)\r
951             fileout.nType |= SER_BLOCKHEADERONLY;\r
952 \r
953         // Write index header\r
954         unsigned int nSize = fileout.GetSerializeSize(*this);\r
955         fileout << FLATDATA(pchMessageStart) << nSize;\r
956 \r
957         // Write block\r
958         nBlockPosRet = ftell(fileout);\r
959         if (nBlockPosRet == -1)\r
960             return error("CBlock::WriteToDisk() : ftell failed");\r
961         fileout << *this;\r
962 \r
963         return true;\r
964     }\r
965 \r
966     bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions)\r
967     {\r
968         SetNull();\r
969 \r
970         // Open history file to read\r
971         CAutoFile filein = OpenBlockFile(nFile, nBlockPos, "rb");\r
972         if (!filein)\r
973             return error("CBlock::ReadFromDisk() : OpenBlockFile failed");\r
974         if (!fReadTransactions)\r
975             filein.nType |= SER_BLOCKHEADERONLY;\r
976 \r
977         // Read block\r
978         filein >> *this;\r
979 \r
980         // Check the header\r
981         if (CBigNum().SetCompact(nBits) > bnProofOfWorkLimit)\r
982             return error("CBlock::ReadFromDisk() : nBits errors in block header");\r
983         if (GetHash() > CBigNum().SetCompact(nBits).getuint256())\r
984             return error("CBlock::ReadFromDisk() : GetHash() errors in block header");\r
985 \r
986         return true;\r
987     }\r
988 \r
989 \r
990 \r
991     void print() const\r
992     {\r
993         printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",\r
994             GetHash().ToString().substr(0,14).c_str(),\r
995             nVersion,\r
996             hashPrevBlock.ToString().substr(0,14).c_str(),\r
997             hashMerkleRoot.ToString().substr(0,6).c_str(),\r
998             nTime, nBits, nNonce,\r
999             vtx.size());\r
1000         for (int i = 0; i < vtx.size(); i++)\r
1001         {\r
1002             printf("  ");\r
1003             vtx[i].print();\r
1004         }\r
1005         printf("  vMerkleTree: ");\r
1006         for (int i = 0; i < vMerkleTree.size(); i++)\r
1007             printf("%s ", vMerkleTree[i].ToString().substr(0,6).c_str());\r
1008         printf("\n");\r
1009     }\r
1010 \r
1011 \r
1012     int64 GetBlockValue(int64 nFees) const;\r
1013     bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);\r
1014     bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);\r
1015     bool ReadFromDisk(const CBlockIndex* blockindex, bool fReadTransactions);\r
1016     bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);\r
1017     bool CheckBlock() const;\r
1018     bool AcceptBlock();\r
1019 };\r
1020 \r
1021 \r
1022 \r
1023 \r
1024 \r
1025 \r
1026 //\r
1027 // The block chain is a tree shaped structure starting with the\r
1028 // genesis block at the root, with each block potentially having multiple\r
1029 // candidates to be the next block.  pprev and pnext link a path through the\r
1030 // main/longest chain.  A blockindex may have multiple pprev pointing back\r
1031 // to it, but pnext will only point forward to the longest branch, or will\r
1032 // be null if the block is not part of the longest chain.\r
1033 //\r
1034 class CBlockIndex\r
1035 {\r
1036 public:\r
1037     const uint256* phashBlock;\r
1038     CBlockIndex* pprev;\r
1039     CBlockIndex* pnext;\r
1040     unsigned int nFile;\r
1041     unsigned int nBlockPos;\r
1042     int nHeight;\r
1043 \r
1044     // block header\r
1045     int nVersion;\r
1046     uint256 hashMerkleRoot;\r
1047     unsigned int nTime;\r
1048     unsigned int nBits;\r
1049     unsigned int nNonce;\r
1050 \r
1051 \r
1052     CBlockIndex()\r
1053     {\r
1054         phashBlock = NULL;\r
1055         pprev = NULL;\r
1056         pnext = NULL;\r
1057         nFile = 0;\r
1058         nBlockPos = 0;\r
1059         nHeight = 0;\r
1060 \r
1061         nVersion       = 0;\r
1062         hashMerkleRoot = 0;\r
1063         nTime          = 0;\r
1064         nBits          = 0;\r
1065         nNonce         = 0;\r
1066     }\r
1067 \r
1068     CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block)\r
1069     {\r
1070         phashBlock = NULL;\r
1071         pprev = NULL;\r
1072         pnext = NULL;\r
1073         nFile = nFileIn;\r
1074         nBlockPos = nBlockPosIn;\r
1075         nHeight = 0;\r
1076 \r
1077         nVersion       = block.nVersion;\r
1078         hashMerkleRoot = block.hashMerkleRoot;\r
1079         nTime          = block.nTime;\r
1080         nBits          = block.nBits;\r
1081         nNonce         = block.nNonce;\r
1082     }\r
1083 \r
1084     uint256 GetBlockHash() const\r
1085     {\r
1086         return *phashBlock;\r
1087     }\r
1088 \r
1089     bool IsInMainChain() const\r
1090     {\r
1091         return (pnext || this == pindexBest);\r
1092     }\r
1093 \r
1094     bool EraseBlockFromDisk()\r
1095     {\r
1096         // Open history file\r
1097         CAutoFile fileout = OpenBlockFile(nFile, nBlockPos, "rb+");\r
1098         if (!fileout)\r
1099             return false;\r
1100 \r
1101         // Overwrite with empty null block\r
1102         CBlock block;\r
1103         block.SetNull();\r
1104         fileout << block;\r
1105 \r
1106         return true;\r
1107     }\r
1108 \r
1109     enum { nMedianTimeSpan=11 };\r
1110 \r
1111     int64 GetMedianTimePast() const\r
1112     {\r
1113         unsigned int pmedian[nMedianTimeSpan];\r
1114         unsigned int* pbegin = &pmedian[nMedianTimeSpan];\r
1115         unsigned int* pend = &pmedian[nMedianTimeSpan];\r
1116 \r
1117         const CBlockIndex* pindex = this;\r
1118         for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)\r
1119             *(--pbegin) = pindex->nTime;\r
1120 \r
1121         sort(pbegin, pend);\r
1122         return pbegin[(pend - pbegin)/2];\r
1123     }\r
1124 \r
1125     int64 GetMedianTime() const\r
1126     {\r
1127         const CBlockIndex* pindex = this;\r
1128         for (int i = 0; i < nMedianTimeSpan/2; i++)\r
1129         {\r
1130             if (!pindex->pnext)\r
1131                 return nTime;\r
1132             pindex = pindex->pnext;\r
1133         }\r
1134         return pindex->GetMedianTimePast();\r
1135     }\r
1136 \r
1137 \r
1138 \r
1139     string ToString() const\r
1140     {\r
1141         return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",\r
1142             pprev, pnext, nFile, nBlockPos, nHeight,\r
1143             hashMerkleRoot.ToString().substr(0,6).c_str(),\r
1144             GetBlockHash().ToString().substr(0,14).c_str());\r
1145     }\r
1146 \r
1147     void print() const\r
1148     {\r
1149         printf("%s\n", ToString().c_str());\r
1150     }\r
1151 };\r
1152 \r
1153 \r
1154 \r
1155 //\r
1156 // Used to marshal pointers into hashes for db storage.\r
1157 //\r
1158 class CDiskBlockIndex : public CBlockIndex\r
1159 {\r
1160 public:\r
1161     uint256 hashPrev;\r
1162     uint256 hashNext;\r
1163 \r
1164     CDiskBlockIndex()\r
1165     {\r
1166         hashPrev = 0;\r
1167         hashNext = 0;\r
1168     }\r
1169 \r
1170     explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex)\r
1171     {\r
1172         hashPrev = (pprev ? pprev->GetBlockHash() : 0);\r
1173         hashNext = (pnext ? pnext->GetBlockHash() : 0);\r
1174     }\r
1175 \r
1176     IMPLEMENT_SERIALIZE\r
1177     (\r
1178         if (!(nType & SER_GETHASH))\r
1179             READWRITE(nVersion);\r
1180 \r
1181         READWRITE(hashNext);\r
1182         READWRITE(nFile);\r
1183         READWRITE(nBlockPos);\r
1184         READWRITE(nHeight);\r
1185 \r
1186         // block header\r
1187         READWRITE(this->nVersion);\r
1188         READWRITE(hashPrev);\r
1189         READWRITE(hashMerkleRoot);\r
1190         READWRITE(nTime);\r
1191         READWRITE(nBits);\r
1192         READWRITE(nNonce);\r
1193     )\r
1194 \r
1195     uint256 GetBlockHash() const\r
1196     {\r
1197         CBlock block;\r
1198         block.nVersion        = nVersion;\r
1199         block.hashPrevBlock   = hashPrev;\r
1200         block.hashMerkleRoot  = hashMerkleRoot;\r
1201         block.nTime           = nTime;\r
1202         block.nBits           = nBits;\r
1203         block.nNonce          = nNonce;\r
1204         return block.GetHash();\r
1205     }\r
1206 \r
1207 \r
1208     string ToString() const\r
1209     {\r
1210         string str = "CDiskBlockIndex(";\r
1211         str += CBlockIndex::ToString();\r
1212         str += strprintf("\n                hashBlock=%s, hashPrev=%s, hashNext=%s)",\r
1213             GetBlockHash().ToString().c_str(),\r
1214             hashPrev.ToString().substr(0,14).c_str(),\r
1215             hashNext.ToString().substr(0,14).c_str());\r
1216         return str;\r
1217     }\r
1218 \r
1219     void print() const\r
1220     {\r
1221         printf("%s\n", ToString().c_str());\r
1222     }\r
1223 };\r
1224 \r
1225 \r
1226 \r
1227 \r
1228 \r
1229 \r
1230 \r
1231 \r
1232 //\r
1233 // Describes a place in the block chain to another node such that if the\r
1234 // other node doesn't have the same branch, it can find a recent common trunk.\r
1235 // The further back it is, the further before the fork it may be.\r
1236 //\r
1237 class CBlockLocator\r
1238 {\r
1239 protected:\r
1240     vector<uint256> vHave;\r
1241 public:\r
1242 \r
1243     CBlockLocator()\r
1244     {\r
1245     }\r
1246 \r
1247     explicit CBlockLocator(const CBlockIndex* pindex)\r
1248     {\r
1249         Set(pindex);\r
1250     }\r
1251 \r
1252     explicit CBlockLocator(uint256 hashBlock)\r
1253     {\r
1254         map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);\r
1255         if (mi != mapBlockIndex.end())\r
1256             Set((*mi).second);\r
1257     }\r
1258 \r
1259     IMPLEMENT_SERIALIZE\r
1260     (\r
1261         if (!(nType & SER_GETHASH))\r
1262             READWRITE(nVersion);\r
1263         READWRITE(vHave);\r
1264     )\r
1265 \r
1266     void Set(const CBlockIndex* pindex)\r
1267     {\r
1268         vHave.clear();\r
1269         int nStep = 1;\r
1270         while (pindex)\r
1271         {\r
1272             vHave.push_back(pindex->GetBlockHash());\r
1273 \r
1274             // Exponentially larger steps back\r
1275             for (int i = 0; pindex && i < nStep; i++)\r
1276                 pindex = pindex->pprev;\r
1277             if (vHave.size() > 10)\r
1278                 nStep *= 2;\r
1279         }\r
1280         vHave.push_back(hashGenesisBlock);\r
1281     }\r
1282 \r
1283     CBlockIndex* GetBlockIndex()\r
1284     {\r
1285         // Find the first block the caller has in the main chain\r
1286         foreach(const uint256& hash, vHave)\r
1287         {\r
1288             map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);\r
1289             if (mi != mapBlockIndex.end())\r
1290             {\r
1291                 CBlockIndex* pindex = (*mi).second;\r
1292                 if (pindex->IsInMainChain())\r
1293                     return pindex;\r
1294             }\r
1295         }\r
1296         return pindexGenesisBlock;\r
1297     }\r
1298 \r
1299     uint256 GetBlockHash()\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 hash;\r
1310             }\r
1311         }\r
1312         return hashGenesisBlock;\r
1313     }\r
1314 \r
1315     int GetHeight()\r
1316     {\r
1317         CBlockIndex* pindex = GetBlockIndex();\r
1318         if (!pindex)\r
1319             return 0;\r
1320         return pindex->nHeight;\r
1321     }\r
1322 };\r
1323 \r
1324 \r
1325 \r
1326 \r
1327 \r
1328 \r
1329 \r
1330 \r
1331 \r
1332 \r
1333 \r
1334 \r
1335 extern map<uint256, CTransaction> mapTransactions;\r
1336 extern map<uint256, CWalletTx> mapWallet;\r
1337 extern vector<uint256> vWalletUpdated;\r
1338 extern CCriticalSection cs_mapWallet;\r
1339 extern map<vector<unsigned char>, CPrivKey> mapKeys;\r
1340 extern map<uint160, vector<unsigned char> > mapPubKeys;\r
1341 extern CCriticalSection cs_mapKeys;\r
1342 extern CKey keyUser;\r