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