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