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