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