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