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