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