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