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