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