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