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