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