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