PPCoin: bug fix of GetBlockTrust() introduced with 32ad4f42
[novacoin.git] / src / main.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2011 The Bitcoin developers
3 // Copyright (c) 2011 The PPCoin developers
4 // Distributed under the MIT/X11 software license, see the accompanying
5 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
6 #ifndef BITCOIN_MAIN_H
7 #define BITCOIN_MAIN_H
8
9 #include "bignum.h"
10 #include "net.h"
11 #include "key.h"
12 #include "script.h"
13 #include "db.h"
14
15 #include <list>
16
17 class CBlock;
18 class CBlockIndex;
19 class CWalletTx;
20 class CWallet;
21 class CKeyItem;
22 class CReserveKey;
23 class CWalletDB;
24
25 class CAddress;
26 class CInv;
27 class CRequestTracker;
28 class CNode;
29 class CBlockIndex;
30
31 static const unsigned int MAX_BLOCK_SIZE = 1000000;
32 static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
33 static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
34 static const int64 COIN = 10000;
35 static const int64 CENT = 100;
36 static const int64 MIN_TX_FEE = 10000;
37 static const int64 MIN_RELAY_TX_FEE = 10000;
38 static const int64 MAX_MONEY = 800000000000000 * COIN;
39 inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
40 static const int COINBASE_MATURITY = 100;
41 // Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp.
42 static const int LOCKTIME_THRESHOLD = 500000000; // Tue Nov  5 00:53:20 1985 UTC
43 #ifdef USE_UPNP
44 static const int fHaveUPnP = true;
45 #else
46 static const int fHaveUPnP = false;
47 #endif
48
49
50
51
52
53
54 extern CCriticalSection cs_main;
55 extern std::map<uint256, CBlockIndex*> mapBlockIndex;
56 extern uint256 hashGenesisBlock;
57 extern CBlockIndex* pindexGenesisBlock;
58 extern int nBestHeight;
59 extern uint64 nBestChainTrust;
60 extern uint64 nBestInvalidTrust;
61 extern uint256 hashBestChain;
62 extern CBlockIndex* pindexBest;
63 extern unsigned int nTransactionsUpdated;
64 extern double dHashesPerSec;
65 extern int64 nHPSTimerStart;
66 extern int64 nTimeBestReceived;
67 extern CCriticalSection cs_setpwalletRegistered;
68 extern std::set<CWallet*> setpwalletRegistered;
69
70 // Settings
71 extern int fGenerateBitcoins;
72 extern int64 nTransactionFee;
73 extern int fLimitProcessors;
74 extern int nLimitProcessors;
75 extern int fMinimizeToTray;
76 extern int fMinimizeOnClose;
77 extern int fUseUPnP;
78
79
80
81
82
83 class CReserveKey;
84 class CTxDB;
85 class CTxIndex;
86
87 void RegisterWallet(CWallet* pwalletIn);
88 void UnregisterWallet(CWallet* pwalletIn);
89 bool ProcessBlock(CNode* pfrom, CBlock* pblock);
90 bool CheckDiskSpace(uint64 nAdditionalBytes=0);
91 FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
92 FILE* AppendBlockFile(unsigned int& nFileRet);
93 bool LoadBlockIndex(bool fAllowNew=true);
94 void PrintBlockTree();
95 bool ProcessMessages(CNode* pfrom);
96 bool SendMessages(CNode* pto, bool fSendTrickle);
97 void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
98 CBlock* CreateNewBlock(CReserveKey& reservekey);
99 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
100 void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
101 bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
102 bool CheckProofOfWork(uint256 hash, unsigned int nBits);
103 unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
104 int GetNumBlocksOfPeers();
105 bool IsInitialBlockDownload();
106 std::string GetWarnings(std::string strFor);
107
108
109
110
111
112
113
114
115
116
117
118
119 bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
120
121 template<typename T>
122 bool WriteSetting(const std::string& strKey, const T& value)
123 {
124     bool fOk = false;
125     BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
126     {
127         std::string strWalletFile;
128         if (!GetWalletFile(pwallet, strWalletFile))
129             continue;
130         fOk |= CWalletDB(strWalletFile).WriteSetting(strKey, value);
131     }
132     return fOk;
133 }
134
135
136 class CDiskTxPos
137 {
138 public:
139     unsigned int nFile;
140     unsigned int nBlockPos;
141     unsigned int nTxPos;
142
143     CDiskTxPos()
144     {
145         SetNull();
146     }
147
148     CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn)
149     {
150         nFile = nFileIn;
151         nBlockPos = nBlockPosIn;
152         nTxPos = nTxPosIn;
153     }
154
155     IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
156     void SetNull() { nFile = -1; nBlockPos = 0; nTxPos = 0; }
157     bool IsNull() const { return (nFile == -1); }
158
159     friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b)
160     {
161         return (a.nFile     == b.nFile &&
162                 a.nBlockPos == b.nBlockPos &&
163                 a.nTxPos    == b.nTxPos);
164     }
165
166     friend bool operator!=(const CDiskTxPos& a, const CDiskTxPos& b)
167     {
168         return !(a == b);
169     }
170
171     std::string ToString() const
172     {
173         if (IsNull())
174             return strprintf("null");
175         else
176             return strprintf("(nFile=%d, nBlockPos=%d, nTxPos=%d)", nFile, nBlockPos, nTxPos);
177     }
178
179     void print() const
180     {
181         printf("%s", ToString().c_str());
182     }
183 };
184
185
186
187
188 class CInPoint
189 {
190 public:
191     CTransaction* ptx;
192     unsigned int n;
193
194     CInPoint() { SetNull(); }
195     CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
196     void SetNull() { ptx = NULL; n = -1; }
197     bool IsNull() const { return (ptx == NULL && n == -1); }
198 };
199
200
201
202
203 class COutPoint
204 {
205 public:
206     uint256 hash;
207     unsigned int n;
208
209     COutPoint() { SetNull(); }
210     COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
211     IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
212     void SetNull() { hash = 0; n = -1; }
213     bool IsNull() const { return (hash == 0 && n == -1); }
214
215     friend bool operator<(const COutPoint& a, const COutPoint& b)
216     {
217         return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
218     }
219
220     friend bool operator==(const COutPoint& a, const COutPoint& b)
221     {
222         return (a.hash == b.hash && a.n == b.n);
223     }
224
225     friend bool operator!=(const COutPoint& a, const COutPoint& b)
226     {
227         return !(a == b);
228     }
229
230     std::string ToString() const
231     {
232         return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,10).c_str(), n);
233     }
234
235     void print() const
236     {
237         printf("%s\n", ToString().c_str());
238     }
239 };
240
241
242
243
244 //
245 // An input of a transaction.  It contains the location of the previous
246 // transaction's output that it claims and a signature that matches the
247 // output's public key.
248 //
249 class CTxIn
250 {
251 public:
252     COutPoint prevout;
253     CScript scriptSig;
254     unsigned int nSequence;
255
256     CTxIn()
257     {
258         nSequence = UINT_MAX;
259     }
260
261     explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
262     {
263         prevout = prevoutIn;
264         scriptSig = scriptSigIn;
265         nSequence = nSequenceIn;
266     }
267
268     CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
269     {
270         prevout = COutPoint(hashPrevTx, nOut);
271         scriptSig = scriptSigIn;
272         nSequence = nSequenceIn;
273     }
274
275     IMPLEMENT_SERIALIZE
276     (
277         READWRITE(prevout);
278         READWRITE(scriptSig);
279         READWRITE(nSequence);
280     )
281
282     bool IsFinal() const
283     {
284         return (nSequence == UINT_MAX);
285     }
286
287     friend bool operator==(const CTxIn& a, const CTxIn& b)
288     {
289         return (a.prevout   == b.prevout &&
290                 a.scriptSig == b.scriptSig &&
291                 a.nSequence == b.nSequence);
292     }
293
294     friend bool operator!=(const CTxIn& a, const CTxIn& b)
295     {
296         return !(a == b);
297     }
298
299     std::string ToString() const
300     {
301         std::string str;
302         str += strprintf("CTxIn(");
303         str += prevout.ToString();
304         if (prevout.IsNull())
305             str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
306         else
307             str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
308         if (nSequence != UINT_MAX)
309             str += strprintf(", nSequence=%u", nSequence);
310         str += ")";
311         return str;
312     }
313
314     void print() const
315     {
316         printf("%s\n", ToString().c_str());
317     }
318 };
319
320
321
322
323 //
324 // An output of a transaction.  It contains the public key that the next input
325 // must be able to sign with to claim it.
326 //
327 class CTxOut
328 {
329 public:
330     int64 nValue;
331     CScript scriptPubKey;
332
333     CTxOut()
334     {
335         SetNull();
336     }
337
338     CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
339     {
340         nValue = nValueIn;
341         scriptPubKey = scriptPubKeyIn;
342     }
343
344     IMPLEMENT_SERIALIZE
345     (
346         READWRITE(nValue);
347         READWRITE(scriptPubKey);
348     )
349
350     void SetNull()
351     {
352         nValue = -1;
353         scriptPubKey.clear();
354     }
355
356     bool IsNull()
357     {
358         return (nValue == -1);
359     }
360
361     uint256 GetHash() const
362     {
363         return SerializeHash(*this);
364     }
365
366     friend bool operator==(const CTxOut& a, const CTxOut& b)
367     {
368         return (a.nValue       == b.nValue &&
369                 a.scriptPubKey == b.scriptPubKey);
370     }
371
372     friend bool operator!=(const CTxOut& a, const CTxOut& b)
373     {
374         return !(a == b);
375     }
376
377     std::string ToString() const
378     {
379         if (scriptPubKey.size() < 6)
380             return "CTxOut(error)";
381         return strprintf("CTxOut(nValue=%s, scriptPubKey=%s)", FormatMoney(nValue).c_str(), scriptPubKey.ToString().substr(0,30).c_str());
382     }
383
384     void print() const
385     {
386         printf("%s\n", ToString().c_str());
387     }
388 };
389
390
391
392
393 //
394 // The basic transaction that is broadcasted on the network and contained in
395 // blocks.  A transaction can contain multiple inputs and outputs.
396 //
397 class CTransaction
398 {
399 public:
400     int nVersion;
401     unsigned int nTime;
402     std::vector<CTxIn> vin;
403     std::vector<CTxOut> vout;
404     unsigned int nLockTime;
405
406     // Denial-of-service detection:
407     mutable int nDoS;
408     bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
409
410     CTransaction()
411     {
412         SetNull();
413     }
414
415     IMPLEMENT_SERIALIZE
416     (
417         READWRITE(this->nVersion);
418         nVersion = this->nVersion;
419         READWRITE(nTime);
420         READWRITE(vin);
421         READWRITE(vout);
422         READWRITE(nLockTime);
423     )
424
425     void SetNull()
426     {
427         nVersion = 1;
428         nTime = GetAdjustedTime();
429         vin.clear();
430         vout.clear();
431         nLockTime = 0;
432         nDoS = 0;  // Denial-of-service prevention
433     }
434
435     bool IsNull() const
436     {
437         return (vin.empty() && vout.empty());
438     }
439
440     uint256 GetHash() const
441     {
442         return SerializeHash(*this);
443     }
444
445     bool IsFinal(int nBlockHeight=0, int64 nBlockTime=0) const
446     {
447         // Time based nLockTime implemented in 0.1.6
448         if (nLockTime == 0)
449             return true;
450         if (nBlockHeight == 0)
451             nBlockHeight = nBestHeight;
452         if (nBlockTime == 0)
453             nBlockTime = GetAdjustedTime();
454         if ((int64)nLockTime < (nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
455             return true;
456         BOOST_FOREACH(const CTxIn& txin, vin)
457             if (!txin.IsFinal())
458                 return false;
459         return true;
460     }
461
462     bool IsNewerThan(const CTransaction& old) const
463     {
464         if (vin.size() != old.vin.size())
465             return false;
466         for (int i = 0; i < vin.size(); i++)
467             if (vin[i].prevout != old.vin[i].prevout)
468                 return false;
469
470         bool fNewer = false;
471         unsigned int nLowest = UINT_MAX;
472         for (int i = 0; i < vin.size(); i++)
473         {
474             if (vin[i].nSequence != old.vin[i].nSequence)
475             {
476                 if (vin[i].nSequence <= nLowest)
477                 {
478                     fNewer = false;
479                     nLowest = vin[i].nSequence;
480                 }
481                 if (old.vin[i].nSequence < nLowest)
482                 {
483                     fNewer = true;
484                     nLowest = old.vin[i].nSequence;
485                 }
486             }
487         }
488         return fNewer;
489     }
490
491     bool IsCoinBase() const
492     {
493         return (vin.size() == 1 && vin[0].prevout.IsNull());
494     }
495
496     int GetSigOpCount() const
497     {
498         int n = 0;
499         BOOST_FOREACH(const CTxIn& txin, vin)
500             n += txin.scriptSig.GetSigOpCount();
501         BOOST_FOREACH(const CTxOut& txout, vout)
502             n += txout.scriptPubKey.GetSigOpCount();
503         return n;
504     }
505
506     bool IsStandard() const
507     {
508         BOOST_FOREACH(const CTxIn& txin, vin)
509             if (!txin.scriptSig.IsPushOnly())
510                 return error("nonstandard txin: %s", txin.scriptSig.ToString().c_str());
511         BOOST_FOREACH(const CTxOut& txout, vout)
512             if (!::IsStandard(txout.scriptPubKey))
513                 return error("nonstandard txout: %s", txout.scriptPubKey.ToString().c_str());
514         return true;
515     }
516
517     int64 GetValueOut() const
518     {
519         int64 nValueOut = 0;
520         BOOST_FOREACH(const CTxOut& txout, vout)
521         {
522             nValueOut += txout.nValue;
523             if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
524                 throw std::runtime_error("CTransaction::GetValueOut() : value out of range");
525         }
526         return nValueOut;
527     }
528
529     static bool AllowFree(double dPriority)
530     {
531         // Large (in bytes) low-priority (new, small-coin) transactions
532         // need a fee.
533         return dPriority > COIN * 144 / 250;
534     }
535
536     int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, bool fForRelay=false) const
537     {
538         // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
539         int64 nBaseFee = fForRelay ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
540
541         unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
542         unsigned int nNewBlockSize = nBlockSize + nBytes;
543         int64 nMinFee = nBaseFee;          // ppcoin: simplify transaction fee
544
545         if (fAllowFree)
546         {
547             if (nBlockSize == 1)
548             {
549                 // Transactions under 10K are free
550                 // (about 4500bc if made of 50bc inputs)
551                 if (nBytes < 10000)
552                     nMinFee = 0;
553             }
554             else
555             {
556                 // Free transaction area
557                 if (nNewBlockSize < 27000)
558                     nMinFee = 0;
559             }
560         }
561
562         // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01
563         if (nMinFee < nBaseFee)
564             BOOST_FOREACH(const CTxOut& txout, vout)
565                 if (txout.nValue < CENT)
566                     nMinFee = nBaseFee;
567
568         // Raise the price as the block approaches full
569         if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
570         {
571             if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN)
572                 return MAX_MONEY;
573             nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize);
574         }
575
576         if (!MoneyRange(nMinFee))
577             nMinFee = MAX_MONEY;
578         return nMinFee;
579     }
580
581
582     bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
583     {
584         CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");
585         if (!filein)
586             return error("CTransaction::ReadFromDisk() : OpenBlockFile failed");
587
588         // Read transaction
589         if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
590             return error("CTransaction::ReadFromDisk() : fseek failed");
591         filein >> *this;
592
593         // Return file pointer
594         if (pfileRet)
595         {
596             if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
597                 return error("CTransaction::ReadFromDisk() : second fseek failed");
598             *pfileRet = filein.release();
599         }
600         return true;
601     }
602
603     friend bool operator==(const CTransaction& a, const CTransaction& b)
604     {
605         return (a.nVersion  == b.nVersion &&
606                 a.nTime     == b.nTime &&
607                 a.vin       == b.vin &&
608                 a.vout      == b.vout &&
609                 a.nLockTime == b.nLockTime);
610     }
611
612     friend bool operator!=(const CTransaction& a, const CTransaction& b)
613     {
614         return !(a == b);
615     }
616
617
618     std::string ToString() const
619     {
620         std::string str;
621         str += strprintf("CTransaction(hash=%s, nTime=%d, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
622             GetHash().ToString().substr(0,10).c_str(),
623             nTime,
624             nVersion,
625             vin.size(),
626             vout.size(),
627             nLockTime);
628         for (int i = 0; i < vin.size(); i++)
629             str += "    " + vin[i].ToString() + "\n";
630         for (int i = 0; i < vout.size(); i++)
631             str += "    " + vout[i].ToString() + "\n";
632         return str;
633     }
634
635     void print() const
636     {
637         printf("%s", ToString().c_str());
638     }
639
640
641     bool ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet);
642     bool ReadFromDisk(CTxDB& txdb, COutPoint prevout);
643     bool ReadFromDisk(COutPoint prevout);
644     bool DisconnectInputs(CTxDB& txdb);
645     bool ConnectInputs(CTxDB& txdb, std::map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
646                        CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);
647     bool ClientConnectInputs();
648     bool CheckTransaction() const;
649     bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
650     bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
651 protected:
652     bool AddToMemoryPoolUnchecked();
653 public:
654     bool RemoveFromMemoryPool();
655 };
656
657
658
659
660
661 //
662 // A transaction with a merkle branch linking it to the block chain
663 //
664 class CMerkleTx : public CTransaction
665 {
666 public:
667     uint256 hashBlock;
668     std::vector<uint256> vMerkleBranch;
669     int nIndex;
670
671     // memory only
672     mutable char fMerkleVerified;
673
674
675     CMerkleTx()
676     {
677         Init();
678     }
679
680     CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
681     {
682         Init();
683     }
684
685     void Init()
686     {
687         hashBlock = 0;
688         nIndex = -1;
689         fMerkleVerified = false;
690     }
691
692
693     IMPLEMENT_SERIALIZE
694     (
695         nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
696         nVersion = this->nVersion;
697         READWRITE(hashBlock);
698         READWRITE(vMerkleBranch);
699         READWRITE(nIndex);
700     )
701
702
703     int SetMerkleBranch(const CBlock* pblock=NULL);
704     int GetDepthInMainChain(int& nHeightRet) const;
705     int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }
706     bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
707     int GetBlocksToMaturity() const;
708     bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
709     bool AcceptToMemoryPool();
710 };
711
712
713
714
715 //
716 // A txdb record that contains the disk location of a transaction and the
717 // locations of transactions that spend its outputs.  vSpent is really only
718 // used as a flag, but having the location is very helpful for debugging.
719 //
720 class CTxIndex
721 {
722 public:
723     CDiskTxPos pos;
724     std::vector<CDiskTxPos> vSpent;
725
726     CTxIndex()
727     {
728         SetNull();
729     }
730
731     CTxIndex(const CDiskTxPos& posIn, unsigned int nOutputs)
732     {
733         pos = posIn;
734         vSpent.resize(nOutputs);
735     }
736
737     IMPLEMENT_SERIALIZE
738     (
739         if (!(nType & SER_GETHASH))
740             READWRITE(nVersion);
741         READWRITE(pos);
742         READWRITE(vSpent);
743     )
744
745     void SetNull()
746     {
747         pos.SetNull();
748         vSpent.clear();
749     }
750
751     bool IsNull()
752     {
753         return pos.IsNull();
754     }
755
756     friend bool operator==(const CTxIndex& a, const CTxIndex& b)
757     {
758         return (a.pos    == b.pos &&
759                 a.vSpent == b.vSpent);
760     }
761
762     friend bool operator!=(const CTxIndex& a, const CTxIndex& b)
763     {
764         return !(a == b);
765     }
766     int GetDepthInMainChain() const;
767 };
768
769
770
771
772
773 //
774 // Nodes collect new transactions into a block, hash them into a hash tree,
775 // and scan through nonce values to make the block's hash satisfy proof-of-work
776 // requirements.  When they solve the proof-of-work, they broadcast the block
777 // to everyone and the block is added to the block chain.  The first transaction
778 // in the block is a special one that creates a new coin owned by the creator
779 // of the block.
780 //
781 // Blocks are appended to blk0001.dat files on disk.  Their location on disk
782 // is indexed by CBlockIndex objects in memory.
783 //
784 class CBlock
785 {
786 public:
787     // header
788     int nVersion;
789     uint256 hashPrevBlock;
790     uint256 hashMerkleRoot;
791     unsigned int nTime;
792     unsigned int nBits;
793     unsigned int nNonce;
794
795     // network and disk
796     std::vector<CTransaction> vtx;
797
798     // memory only
799     mutable std::vector<uint256> vMerkleTree;
800
801     // Denial-of-service detection:
802     mutable int nDoS;
803     bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
804
805     CBlock()
806     {
807         SetNull();
808     }
809
810     IMPLEMENT_SERIALIZE
811     (
812         READWRITE(this->nVersion);
813         nVersion = this->nVersion;
814         READWRITE(hashPrevBlock);
815         READWRITE(hashMerkleRoot);
816         READWRITE(nTime);
817         READWRITE(nBits);
818         READWRITE(nNonce);
819
820         // ConnectBlock depends on vtx being last so it can calculate offset
821         if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))
822             READWRITE(vtx);
823         else if (fRead)
824             const_cast<CBlock*>(this)->vtx.clear();
825     )
826
827     void SetNull()
828     {
829         nVersion = 1;
830         hashPrevBlock = 0;
831         hashMerkleRoot = 0;
832         nTime = 0;
833         nBits = 0;
834         nNonce = 0;
835         vtx.clear();
836         vMerkleTree.clear();
837         nDoS = 0;
838     }
839
840     bool IsNull() const
841     {
842         return (nBits == 0);
843     }
844
845     uint256 GetHash() const
846     {
847         return Hash(BEGIN(nVersion), END(nNonce));
848     }
849
850     int64 GetBlockTime() const
851     {
852         return (int64)nTime;
853     }
854
855     // ppcoin: get max transaction timestamp
856     int64 GetMaxTransactionTime() const
857     {
858         int64 maxTransactionTime = 0;
859         BOOST_FOREACH(const CTransaction& tx, vtx)
860             maxTransactionTime = std::max(maxTransactionTime, (int64)tx.nTime);
861         return maxTransactionTime;
862     }
863
864     int GetSigOpCount() const
865     {
866         int n = 0;
867         BOOST_FOREACH(const CTransaction& tx, vtx)
868             n += tx.GetSigOpCount();
869         return n;
870     }
871
872
873     uint256 BuildMerkleTree() const
874     {
875         vMerkleTree.clear();
876         BOOST_FOREACH(const CTransaction& tx, vtx)
877             vMerkleTree.push_back(tx.GetHash());
878         int j = 0;
879         for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
880         {
881             for (int i = 0; i < nSize; i += 2)
882             {
883                 int i2 = std::min(i+1, nSize-1);
884                 vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
885                                            BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
886             }
887             j += nSize;
888         }
889         return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
890     }
891
892     std::vector<uint256> GetMerkleBranch(int nIndex) const
893     {
894         if (vMerkleTree.empty())
895             BuildMerkleTree();
896         std::vector<uint256> vMerkleBranch;
897         int j = 0;
898         for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
899         {
900             int i = std::min(nIndex^1, nSize-1);
901             vMerkleBranch.push_back(vMerkleTree[j+i]);
902             nIndex >>= 1;
903             j += nSize;
904         }
905         return vMerkleBranch;
906     }
907
908     static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
909     {
910         if (nIndex == -1)
911             return 0;
912         BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
913         {
914             if (nIndex & 1)
915                 hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
916             else
917                 hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
918             nIndex >>= 1;
919         }
920         return hash;
921     }
922
923
924     bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet)
925     {
926         // Open history file to append
927         CAutoFile fileout = AppendBlockFile(nFileRet);
928         if (!fileout)
929             return error("CBlock::WriteToDisk() : AppendBlockFile failed");
930
931         // Write index header
932         unsigned int nSize = fileout.GetSerializeSize(*this);
933         fileout << FLATDATA(pchMessageStart) << nSize;
934
935         // Write block
936         nBlockPosRet = ftell(fileout);
937         if (nBlockPosRet == -1)
938             return error("CBlock::WriteToDisk() : ftell failed");
939         fileout << *this;
940
941         // Flush stdio buffers and commit to disk before returning
942         fflush(fileout);
943         if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0)
944         {
945 #ifdef WIN32
946             _commit(_fileno(fileout));
947 #else
948             fsync(fileno(fileout));
949 #endif
950         }
951
952         return true;
953     }
954
955     bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true)
956     {
957         SetNull();
958
959         // Open history file to read
960         CAutoFile filein = OpenBlockFile(nFile, nBlockPos, "rb");
961         if (!filein)
962             return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
963         if (!fReadTransactions)
964             filein.nType |= SER_BLOCKHEADERONLY;
965
966         // Read block
967         filein >> *this;
968
969         // Check the header
970         if (!CheckProofOfWork(GetHash(), nBits))
971             return error("CBlock::ReadFromDisk() : errors in block header");
972
973         return true;
974     }
975
976
977
978     void print() const
979     {
980         printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
981             GetHash().ToString().substr(0,20).c_str(),
982             nVersion,
983             hashPrevBlock.ToString().substr(0,20).c_str(),
984             hashMerkleRoot.ToString().substr(0,10).c_str(),
985             nTime, nBits, nNonce,
986             vtx.size());
987         for (int i = 0; i < vtx.size(); i++)
988         {
989             printf("  ");
990             vtx[i].print();
991         }
992         printf("  vMerkleTree: ");
993         for (int i = 0; i < vMerkleTree.size(); i++)
994             printf("%s ", vMerkleTree[i].ToString().substr(0,10).c_str());
995         printf("\n");
996     }
997
998
999     bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
1000     bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
1001     bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
1002     bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew);
1003     bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
1004     bool CheckBlock() const;
1005     bool AcceptBlock();
1006     uint64 GetBlockCoinAge(); // ppcoin: calculate total coin age spent in block
1007 };
1008
1009
1010
1011
1012
1013
1014 //
1015 // The block chain is a tree shaped structure starting with the
1016 // genesis block at the root, with each block potentially having multiple
1017 // candidates to be the next block.  pprev and pnext link a path through the
1018 // main/longest chain.  A blockindex may have multiple pprev pointing back
1019 // to it, but pnext will only point forward to the longest branch, or will
1020 // be null if the block is not part of the longest chain.
1021 //
1022 class CBlockIndex
1023 {
1024 public:
1025     const uint256* phashBlock;
1026     CBlockIndex* pprev;
1027     CBlockIndex* pnext;
1028     unsigned int nFile;
1029     unsigned int nBlockPos;
1030     uint64 nChainTrust;// ppcoin: trust score of chain, in the unit of coin-days
1031     int nHeight;
1032     int nCheckpoint;    // ppcoin: chain auto checkpoint height
1033
1034     // block header
1035     int nVersion;
1036     uint256 hashMerkleRoot;
1037     unsigned int nTime;
1038     unsigned int nBits;
1039     unsigned int nNonce;
1040
1041
1042     CBlockIndex()
1043     {
1044         phashBlock = NULL;
1045         pprev = NULL;
1046         pnext = NULL;
1047         nFile = 0;
1048         nBlockPos = 0;
1049         nHeight = 0;
1050         nChainTrust = 0;
1051         nCheckpoint = 0;
1052
1053         nVersion       = 0;
1054         hashMerkleRoot = 0;
1055         nTime          = 0;
1056         nBits          = 0;
1057         nNonce         = 0;
1058     }
1059
1060     CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block)
1061     {
1062         phashBlock = NULL;
1063         pprev = NULL;
1064         pnext = NULL;
1065         nFile = nFileIn;
1066         nBlockPos = nBlockPosIn;
1067         nHeight = 0;
1068         nChainTrust = 0;
1069         nCheckpoint = 0;
1070
1071         nVersion       = block.nVersion;
1072         hashMerkleRoot = block.hashMerkleRoot;
1073         nTime          = block.nTime;
1074         nBits          = block.nBits;
1075         nNonce         = block.nNonce;
1076     }
1077
1078     CBlock GetBlockHeader() const
1079     {
1080         CBlock block;
1081         block.nVersion       = nVersion;
1082         if (pprev)
1083             block.hashPrevBlock = pprev->GetBlockHash();
1084         block.hashMerkleRoot = hashMerkleRoot;
1085         block.nTime          = nTime;
1086         block.nBits          = nBits;
1087         block.nNonce         = nNonce;
1088         return block;
1089     }
1090
1091     uint256 GetBlockHash() const
1092     {
1093         return *phashBlock;
1094     }
1095
1096     int64 GetBlockTime() const
1097     {
1098         return (int64)nTime;
1099     }
1100
1101     int64 GetBlockTrust() const
1102     {
1103         return (nChainTrust - (pprev? pprev->nChainTrust : 0));
1104     }
1105
1106     bool IsInMainChain() const
1107     {
1108         return (pnext || this == pindexBest);
1109     }
1110
1111     bool CheckIndex() const
1112     {
1113         return CheckProofOfWork(GetBlockHash(), nBits);
1114     }
1115
1116     bool EraseBlockFromDisk()
1117     {
1118         // Open history file
1119         CAutoFile fileout = OpenBlockFile(nFile, nBlockPos, "rb+");
1120         if (!fileout)
1121             return false;
1122
1123         // Overwrite with empty null block
1124         CBlock block;
1125         block.SetNull();
1126         fileout << block;
1127
1128         return true;
1129     }
1130
1131     enum { nMedianTimeSpan=11 };
1132
1133     int64 GetMedianTimePast() const
1134     {
1135         int64 pmedian[nMedianTimeSpan];
1136         int64* pbegin = &pmedian[nMedianTimeSpan];
1137         int64* pend = &pmedian[nMedianTimeSpan];
1138
1139         const CBlockIndex* pindex = this;
1140         for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
1141             *(--pbegin) = pindex->GetBlockTime();
1142
1143         std::sort(pbegin, pend);
1144         return pbegin[(pend - pbegin)/2];
1145     }
1146
1147     int64 GetMedianTime() const
1148     {
1149         const CBlockIndex* pindex = this;
1150         for (int i = 0; i < nMedianTimeSpan/2; i++)
1151         {
1152             if (!pindex->pnext)
1153                 return GetBlockTime();
1154             pindex = pindex->pnext;
1155         }
1156         return pindex->GetMedianTimePast();
1157     }
1158
1159
1160
1161     std::string ToString() const
1162     {
1163         return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nChainTrust=%"PRI64d" nHeight=%d, nCheckpoint=%d, merkle=%s, hashBlock=%s)",
1164             pprev, pnext, nFile, nBlockPos, nChainTrust, nHeight, nCheckpoint,
1165             hashMerkleRoot.ToString().substr(0,10).c_str(),
1166             GetBlockHash().ToString().substr(0,20).c_str());
1167     }
1168
1169     void print() const
1170     {
1171         printf("%s\n", ToString().c_str());
1172     }
1173 };
1174
1175
1176
1177 //
1178 // Used to marshal pointers into hashes for db storage.
1179 //
1180 class CDiskBlockIndex : public CBlockIndex
1181 {
1182 public:
1183     uint256 hashPrev;
1184     uint256 hashNext;
1185
1186     CDiskBlockIndex()
1187     {
1188         hashPrev = 0;
1189         hashNext = 0;
1190     }
1191
1192     explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex)
1193     {
1194         hashPrev = (pprev ? pprev->GetBlockHash() : 0);
1195         hashNext = (pnext ? pnext->GetBlockHash() : 0);
1196     }
1197
1198     IMPLEMENT_SERIALIZE
1199     (
1200         if (!(nType & SER_GETHASH))
1201             READWRITE(nVersion);
1202
1203         READWRITE(hashNext);
1204         READWRITE(nFile);
1205         READWRITE(nBlockPos);
1206         READWRITE(nChainTrust);
1207         READWRITE(nHeight);
1208         READWRITE(nCheckpoint);
1209
1210         // block header
1211         READWRITE(this->nVersion);
1212         READWRITE(hashPrev);
1213         READWRITE(hashMerkleRoot);
1214         READWRITE(nTime);
1215         READWRITE(nBits);
1216         READWRITE(nNonce);
1217     )
1218
1219     uint256 GetBlockHash() const
1220     {
1221         CBlock block;
1222         block.nVersion        = nVersion;
1223         block.hashPrevBlock   = hashPrev;
1224         block.hashMerkleRoot  = hashMerkleRoot;
1225         block.nTime           = nTime;
1226         block.nBits           = nBits;
1227         block.nNonce          = nNonce;
1228         return block.GetHash();
1229     }
1230
1231
1232     std::string ToString() const
1233     {
1234         std::string str = "CDiskBlockIndex(";
1235         str += CBlockIndex::ToString();
1236         str += strprintf("\n                hashBlock=%s, hashPrev=%s, hashNext=%s)",
1237             GetBlockHash().ToString().c_str(),
1238             hashPrev.ToString().substr(0,20).c_str(),
1239             hashNext.ToString().substr(0,20).c_str());
1240         return str;
1241     }
1242
1243     void print() const
1244     {
1245         printf("%s\n", ToString().c_str());
1246     }
1247 };
1248
1249
1250
1251
1252
1253
1254
1255
1256 //
1257 // Describes a place in the block chain to another node such that if the
1258 // other node doesn't have the same branch, it can find a recent common trunk.
1259 // The further back it is, the further before the fork it may be.
1260 //
1261 class CBlockLocator
1262 {
1263 protected:
1264     std::vector<uint256> vHave;
1265 public:
1266
1267     CBlockLocator()
1268     {
1269     }
1270
1271     explicit CBlockLocator(const CBlockIndex* pindex)
1272     {
1273         Set(pindex);
1274     }
1275
1276     explicit CBlockLocator(uint256 hashBlock)
1277     {
1278         std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
1279         if (mi != mapBlockIndex.end())
1280             Set((*mi).second);
1281     }
1282
1283     IMPLEMENT_SERIALIZE
1284     (
1285         if (!(nType & SER_GETHASH))
1286             READWRITE(nVersion);
1287         READWRITE(vHave);
1288     )
1289
1290     void SetNull()
1291     {
1292         vHave.clear();
1293     }
1294
1295     bool IsNull()
1296     {
1297         return vHave.empty();
1298     }
1299
1300     void Set(const CBlockIndex* pindex)
1301     {
1302         vHave.clear();
1303         int nStep = 1;
1304         while (pindex)
1305         {
1306             vHave.push_back(pindex->GetBlockHash());
1307
1308             // Exponentially larger steps back
1309             for (int i = 0; pindex && i < nStep; i++)
1310                 pindex = pindex->pprev;
1311             if (vHave.size() > 10)
1312                 nStep *= 2;
1313         }
1314         vHave.push_back(hashGenesisBlock);
1315     }
1316
1317     int GetDistanceBack()
1318     {
1319         // Retrace how far back it was in the sender's branch
1320         int nDistance = 0;
1321         int nStep = 1;
1322         BOOST_FOREACH(const uint256& hash, vHave)
1323         {
1324             std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
1325             if (mi != mapBlockIndex.end())
1326             {
1327                 CBlockIndex* pindex = (*mi).second;
1328                 if (pindex->IsInMainChain())
1329                     return nDistance;
1330             }
1331             nDistance += nStep;
1332             if (nDistance > 10)
1333                 nStep *= 2;
1334         }
1335         return nDistance;
1336     }
1337
1338     CBlockIndex* GetBlockIndex()
1339     {
1340         // Find the first block the caller has in the main chain
1341         BOOST_FOREACH(const uint256& hash, vHave)
1342         {
1343             std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
1344             if (mi != mapBlockIndex.end())
1345             {
1346                 CBlockIndex* pindex = (*mi).second;
1347                 if (pindex->IsInMainChain())
1348                     return pindex;
1349             }
1350         }
1351         return pindexGenesisBlock;
1352     }
1353
1354     uint256 GetBlockHash()
1355     {
1356         // Find the first block the caller has in the main chain
1357         BOOST_FOREACH(const uint256& hash, vHave)
1358         {
1359             std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
1360             if (mi != mapBlockIndex.end())
1361             {
1362                 CBlockIndex* pindex = (*mi).second;
1363                 if (pindex->IsInMainChain())
1364                     return hash;
1365             }
1366         }
1367         return hashGenesisBlock;
1368     }
1369
1370     int GetHeight()
1371     {
1372         CBlockIndex* pindex = GetBlockIndex();
1373         if (!pindex)
1374             return 0;
1375         return pindex->nHeight;
1376     }
1377 };
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387 //
1388 // Alerts are for notifying old versions if they become too obsolete and
1389 // need to upgrade.  The message is displayed in the status bar.
1390 // Alert messages are broadcast as a vector of signed data.  Unserializing may
1391 // not read the entire buffer if the alert is for a newer version, but older
1392 // versions can still relay the original data.
1393 //
1394 class CUnsignedAlert
1395 {
1396 public:
1397     int nVersion;
1398     int64 nRelayUntil;      // when newer nodes stop relaying to newer nodes
1399     int64 nExpiration;
1400     int nID;
1401     int nCancel;
1402     std::set<int> setCancel;
1403     int nMinVer;            // lowest version inclusive
1404     int nMaxVer;            // highest version inclusive
1405     std::set<std::string> setSubVer;  // empty matches all
1406     int nPriority;
1407
1408     // Actions
1409     std::string strComment;
1410     std::string strStatusBar;
1411     std::string strReserved;
1412
1413     IMPLEMENT_SERIALIZE
1414     (
1415         READWRITE(this->nVersion);
1416         nVersion = this->nVersion;
1417         READWRITE(nRelayUntil);
1418         READWRITE(nExpiration);
1419         READWRITE(nID);
1420         READWRITE(nCancel);
1421         READWRITE(setCancel);
1422         READWRITE(nMinVer);
1423         READWRITE(nMaxVer);
1424         READWRITE(setSubVer);
1425         READWRITE(nPriority);
1426
1427         READWRITE(strComment);
1428         READWRITE(strStatusBar);
1429         READWRITE(strReserved);
1430     )
1431
1432     void SetNull()
1433     {
1434         nVersion = 1;
1435         nRelayUntil = 0;
1436         nExpiration = 0;
1437         nID = 0;
1438         nCancel = 0;
1439         setCancel.clear();
1440         nMinVer = 0;
1441         nMaxVer = 0;
1442         setSubVer.clear();
1443         nPriority = 0;
1444
1445         strComment.clear();
1446         strStatusBar.clear();
1447         strReserved.clear();
1448     }
1449
1450     std::string ToString() const
1451     {
1452         std::string strSetCancel;
1453         BOOST_FOREACH(int n, setCancel)
1454             strSetCancel += strprintf("%d ", n);
1455         std::string strSetSubVer;
1456         BOOST_FOREACH(std::string str, setSubVer)
1457             strSetSubVer += "\"" + str + "\" ";
1458         return strprintf(
1459                 "CAlert(\n"
1460                 "    nVersion     = %d\n"
1461                 "    nRelayUntil  = %"PRI64d"\n"
1462                 "    nExpiration  = %"PRI64d"\n"
1463                 "    nID          = %d\n"
1464                 "    nCancel      = %d\n"
1465                 "    setCancel    = %s\n"
1466                 "    nMinVer      = %d\n"
1467                 "    nMaxVer      = %d\n"
1468                 "    setSubVer    = %s\n"
1469                 "    nPriority    = %d\n"
1470                 "    strComment   = \"%s\"\n"
1471                 "    strStatusBar = \"%s\"\n"
1472                 ")\n",
1473             nVersion,
1474             nRelayUntil,
1475             nExpiration,
1476             nID,
1477             nCancel,
1478             strSetCancel.c_str(),
1479             nMinVer,
1480             nMaxVer,
1481             strSetSubVer.c_str(),
1482             nPriority,
1483             strComment.c_str(),
1484             strStatusBar.c_str());
1485     }
1486
1487     void print() const
1488     {
1489         printf("%s", ToString().c_str());
1490     }
1491 };
1492
1493 class CAlert : public CUnsignedAlert
1494 {
1495 public:
1496     std::vector<unsigned char> vchMsg;
1497     std::vector<unsigned char> vchSig;
1498
1499     CAlert()
1500     {
1501         SetNull();
1502     }
1503
1504     IMPLEMENT_SERIALIZE
1505     (
1506         READWRITE(vchMsg);
1507         READWRITE(vchSig);
1508     )
1509
1510     void SetNull()
1511     {
1512         CUnsignedAlert::SetNull();
1513         vchMsg.clear();
1514         vchSig.clear();
1515     }
1516
1517     bool IsNull() const
1518     {
1519         return (nExpiration == 0);
1520     }
1521
1522     uint256 GetHash() const
1523     {
1524         return SerializeHash(*this);
1525     }
1526
1527     bool IsInEffect() const
1528     {
1529         return (GetAdjustedTime() < nExpiration);
1530     }
1531
1532     bool Cancels(const CAlert& alert) const
1533     {
1534         if (!IsInEffect())
1535             return false; // this was a no-op before 31403
1536         return (alert.nID <= nCancel || setCancel.count(alert.nID));
1537     }
1538
1539     bool AppliesTo(int nVersion, std::string strSubVerIn) const
1540     {
1541         return (IsInEffect() &&
1542                 nMinVer <= nVersion && nVersion <= nMaxVer &&
1543                 (setSubVer.empty() || setSubVer.count(strSubVerIn)));
1544     }
1545
1546     bool AppliesToMe() const
1547     {
1548         return AppliesTo(VERSION, ::pszSubVer);
1549     }
1550
1551     bool RelayTo(CNode* pnode) const
1552     {
1553         if (!IsInEffect())
1554             return false;
1555         // returns true if wasn't already contained in the set
1556         if (pnode->setKnown.insert(GetHash()).second)
1557         {
1558             if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
1559                 AppliesToMe() ||
1560                 GetAdjustedTime() < nRelayUntil)
1561             {
1562                 pnode->PushMessage("alert", *this);
1563                 return true;
1564             }
1565         }
1566         return false;
1567     }
1568
1569     bool CheckSignature()
1570     {
1571         CKey key;
1572         if (!key.SetPubKey(ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284")))
1573             return error("CAlert::CheckSignature() : SetPubKey failed");
1574         if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
1575             return error("CAlert::CheckSignature() : verify signature failed");
1576
1577         // Now unserialize the data
1578         CDataStream sMsg(vchMsg);
1579         sMsg >> *(CUnsignedAlert*)this;
1580         return true;
1581     }
1582
1583     bool ProcessAlert();
1584 };
1585
1586 #endif