-paytxfee is now per KB,
[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
26
27
28
29
30
31 extern CCriticalSection cs_main;
32 extern map<uint256, CBlockIndex*> mapBlockIndex;
33 extern uint256 hashGenesisBlock;
34 extern CBigNum bnProofOfWorkLimit;
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, CReserveKey& reservekey, int64& nFeeRet);
80 bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
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,10).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,30).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     int GetSigOpCount() const
473     {
474         int n = 0;
475         foreach(const CTxIn& txin, vin)
476             n += txin.scriptSig.GetSigOpCount();
477         foreach(const CTxOut& txout, vout)
478             n += txout.scriptPubKey.GetSigOpCount();
479         return n;
480     }
481
482     bool IsMine() const
483     {
484         foreach(const CTxOut& txout, vout)
485             if (txout.IsMine())
486                 return true;
487         return false;
488     }
489
490     int64 GetDebit() const
491     {
492         int64 nDebit = 0;
493         foreach(const CTxIn& txin, vin)
494         {
495             nDebit += txin.GetDebit();
496             if (!MoneyRange(nDebit))
497                 throw runtime_error("CTransaction::GetDebit() : value out of range");
498         }
499         return nDebit;
500     }
501
502     int64 GetCredit() const
503     {
504         int64 nCredit = 0;
505         foreach(const CTxOut& txout, vout)
506         {
507             nCredit += txout.GetCredit();
508             if (!MoneyRange(nCredit))
509                 throw runtime_error("CTransaction::GetCredit() : value out of range");
510         }
511         return nCredit;
512     }
513
514     int64 GetValueOut() const
515     {
516         int64 nValueOut = 0;
517         foreach(const CTxOut& txout, vout)
518         {
519             nValueOut += txout.nValue;
520             if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
521                 throw runtime_error("CTransaction::GetValueOut() : value out of range");
522         }
523         return nValueOut;
524     }
525
526     int64 GetMinFee(unsigned int nBlockSize=1) const
527     {
528         // Base fee is 1 cent per kilobyte
529         unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
530         unsigned int nNewBlockSize = nBlockSize + nBytes;
531         int64 nMinFee = (1 + (int64)nBytes / 1000) * CENT;
532
533         // Transactions under 25K are free as long as block size is under 40K
534         // (about 11,000bc if made of 50bc inputs)
535         if (nBytes < 25000 && nNewBlockSize < 40000)
536             nMinFee = 0;
537
538         // Transactions under 3K are free as long as block size is under 50K
539         if (nBytes < 3000 && nNewBlockSize < 50000)
540             nMinFee = 0;
541
542         // To limit dust spam, require a 0.01 fee if any output is less than 0.01
543         if (nMinFee < CENT)
544             foreach(const CTxOut& txout, vout)
545                 if (txout.nValue < CENT)
546                     nMinFee = CENT;
547
548         // Raise the price as the block approaches full
549         if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
550         {
551             if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN)
552                 return MAX_MONEY;
553             nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize);
554         }
555
556         if (!MoneyRange(nMinFee))
557             nMinFee = MAX_MONEY;
558         return nMinFee;
559     }
560
561
562     bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
563     {
564         CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");
565         if (!filein)
566             return error("CTransaction::ReadFromDisk() : OpenBlockFile failed");
567
568         // Read transaction
569         if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
570             return error("CTransaction::ReadFromDisk() : fseek failed");
571         filein >> *this;
572
573         // Return file pointer
574         if (pfileRet)
575         {
576             if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
577                 return error("CTransaction::ReadFromDisk() : second fseek failed");
578             *pfileRet = filein.release();
579         }
580         return true;
581     }
582
583     friend bool operator==(const CTransaction& a, const CTransaction& b)
584     {
585         return (a.nVersion  == b.nVersion &&
586                 a.vin       == b.vin &&
587                 a.vout      == b.vout &&
588                 a.nLockTime == b.nLockTime);
589     }
590
591     friend bool operator!=(const CTransaction& a, const CTransaction& b)
592     {
593         return !(a == b);
594     }
595
596
597     string ToString() const
598     {
599         string str;
600         str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
601             GetHash().ToString().substr(0,10).c_str(),
602             nVersion,
603             vin.size(),
604             vout.size(),
605             nLockTime);
606         for (int i = 0; i < vin.size(); i++)
607             str += "    " + vin[i].ToString() + "\n";
608         for (int i = 0; i < vout.size(); i++)
609             str += "    " + vout[i].ToString() + "\n";
610         return str;
611     }
612
613     void print() const
614     {
615         printf("%s", ToString().c_str());
616     }
617
618
619     bool ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet);
620     bool ReadFromDisk(CTxDB& txdb, COutPoint prevout);
621     bool ReadFromDisk(COutPoint prevout);
622     bool DisconnectInputs(CTxDB& txdb);
623     bool ConnectInputs(CTxDB& txdb, map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
624                        CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee=0);
625     bool ClientConnectInputs();
626     bool CheckTransaction() const;
627     bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
628     bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL)
629     {
630         CTxDB txdb("r");
631         return AcceptToMemoryPool(txdb, fCheckInputs, pfMissingInputs);
632     }
633 protected:
634     bool AddToMemoryPoolUnchecked();
635 public:
636     bool RemoveFromMemoryPool();
637 };
638
639
640
641
642
643 //
644 // A transaction with a merkle branch linking it to the block chain
645 //
646 class CMerkleTx : public CTransaction
647 {
648 public:
649     uint256 hashBlock;
650     vector<uint256> vMerkleBranch;
651     int nIndex;
652
653     // memory only
654     mutable char fMerkleVerified;
655
656
657     CMerkleTx()
658     {
659         Init();
660     }
661
662     CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
663     {
664         Init();
665     }
666
667     void Init()
668     {
669         hashBlock = 0;
670         nIndex = -1;
671         fMerkleVerified = false;
672     }
673
674     IMPLEMENT_SERIALIZE
675     (
676         nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
677         nVersion = this->nVersion;
678         READWRITE(hashBlock);
679         READWRITE(vMerkleBranch);
680         READWRITE(nIndex);
681     )
682
683
684     int SetMerkleBranch(const CBlock* pblock=NULL);
685     int GetDepthInMainChain(int& nHeightRet) const;
686     int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }
687     bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
688     int GetBlocksToMaturity() const;
689     bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
690     bool AcceptToMemoryPool() { CTxDB txdb("r"); return AcceptToMemoryPool(txdb); }
691 };
692
693
694
695
696 //
697 // A transaction with a bunch of additional info that only the owner cares
698 // about.  It includes any unrecorded transactions needed to link it back
699 // to the block chain.
700 //
701 class CWalletTx : public CMerkleTx
702 {
703 public:
704     vector<CMerkleTx> vtxPrev;
705     map<string, string> mapValue;
706     vector<pair<string, string> > vOrderForm;
707     unsigned int fTimeReceivedIsTxTime;
708     unsigned int nTimeReceived;  // time received by this node
709     char fFromMe;
710     char fSpent;
711     //// probably need to sign the order info so know it came from payer
712
713     // memory only
714     mutable char fDebitCached;
715     mutable char fCreditCached;
716     mutable int64 nDebitCached;
717     mutable int64 nCreditCached;
718
719     // memory only UI hints
720     mutable unsigned int nTimeDisplayed;
721     mutable int nLinesDisplayed;
722     mutable char fConfirmedDisplayed;
723
724
725     CWalletTx()
726     {
727         Init();
728     }
729
730     CWalletTx(const CMerkleTx& txIn) : CMerkleTx(txIn)
731     {
732         Init();
733     }
734
735     CWalletTx(const CTransaction& txIn) : CMerkleTx(txIn)
736     {
737         Init();
738     }
739
740     void Init()
741     {
742         fTimeReceivedIsTxTime = false;
743         nTimeReceived = 0;
744         fFromMe = false;
745         fSpent = false;
746         fDebitCached = false;
747         fCreditCached = false;
748         nDebitCached = 0;
749         nCreditCached = 0;
750         nTimeDisplayed = 0;
751         nLinesDisplayed = 0;
752     }
753
754     IMPLEMENT_SERIALIZE
755     (
756         nSerSize += SerReadWrite(s, *(CMerkleTx*)this, nType, nVersion, ser_action);
757         nVersion = this->nVersion;
758         READWRITE(vtxPrev);
759         READWRITE(mapValue);
760         READWRITE(vOrderForm);
761         READWRITE(fTimeReceivedIsTxTime);
762         READWRITE(nTimeReceived);
763         READWRITE(fFromMe);
764         READWRITE(fSpent);
765     )
766
767     int64 GetDebit() const
768     {
769         if (vin.empty())
770             return 0;
771         if (fDebitCached)
772             return nDebitCached;
773         nDebitCached = CTransaction::GetDebit();
774         fDebitCached = true;
775         return nDebitCached;
776     }
777
778     int64 GetCredit(bool fUseCache=false) const
779     {
780         // Must wait until coinbase is safely deep enough in the chain before valuing it
781         if (IsCoinBase() && GetBlocksToMaturity() > 0)
782             return 0;
783
784         // GetBalance can assume transactions in mapWallet won't change
785         if (fUseCache && fCreditCached)
786             return nCreditCached;
787         nCreditCached = CTransaction::GetCredit();
788         fCreditCached = true;
789         return nCreditCached;
790     }
791
792     bool IsConfirmed() const
793     {
794         map<uint256, const CMerkleTx*> mapPrev;
795         vector<const CMerkleTx*> vWorkQueue;
796         vWorkQueue.reserve(vtxPrev.size()+1);
797         vWorkQueue.push_back(this);
798         for (int i = 0; i < vWorkQueue.size(); i++)
799         {
800             const CMerkleTx* ptx = vWorkQueue[i];
801
802             if (!ptx->IsFinal())
803                 return false;
804             if (ptx->GetDepthInMainChain() >= 1)
805                 return true;
806             if (ptx->GetDebit() <= 0)
807                 return false;
808
809             if (mapPrev.empty())
810                 foreach(const CMerkleTx& tx, vtxPrev)
811                     mapPrev[tx.GetHash()] = &tx;
812
813             foreach(const CTxIn& txin, ptx->vin)
814             {
815                 if (!mapPrev.count(txin.prevout.hash))
816                     return false;
817                 vWorkQueue.push_back(mapPrev[txin.prevout.hash]);
818             }
819         }
820         return true;
821     }
822
823     bool WriteToDisk()
824     {
825         return CWalletDB().WriteTx(GetHash(), *this);
826     }
827
828
829     int64 GetTxTime() const;
830     int GetRequestCount() const;
831
832     void AddSupportingTransactions(CTxDB& txdb);
833
834     bool AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs=true);
835     bool AcceptWalletTransaction() { CTxDB txdb("r"); return AcceptWalletTransaction(txdb); }
836
837     void RelayWalletTransaction(CTxDB& txdb);
838     void RelayWalletTransaction() { CTxDB txdb("r"); RelayWalletTransaction(txdb); }
839 };
840
841
842
843
844 //
845 // A txdb record that contains the disk location of a transaction and the
846 // locations of transactions that spend its outputs.  vSpent is really only
847 // used as a flag, but having the location is very helpful for debugging.
848 //
849 class CTxIndex
850 {
851 public:
852     CDiskTxPos pos;
853     vector<CDiskTxPos> vSpent;
854
855     CTxIndex()
856     {
857         SetNull();
858     }
859
860     CTxIndex(const CDiskTxPos& posIn, unsigned int nOutputs)
861     {
862         pos = posIn;
863         vSpent.resize(nOutputs);
864     }
865
866     IMPLEMENT_SERIALIZE
867     (
868         if (!(nType & SER_GETHASH))
869             READWRITE(nVersion);
870         READWRITE(pos);
871         READWRITE(vSpent);
872     )
873
874     void SetNull()
875     {
876         pos.SetNull();
877         vSpent.clear();
878     }
879
880     bool IsNull()
881     {
882         return pos.IsNull();
883     }
884
885     friend bool operator==(const CTxIndex& a, const CTxIndex& b)
886     {
887         return (a.pos    == b.pos &&
888                 a.vSpent == b.vSpent);
889     }
890
891     friend bool operator!=(const CTxIndex& a, const CTxIndex& b)
892     {
893         return !(a == b);
894     }
895 };
896
897
898
899
900
901 //
902 // Nodes collect new transactions into a block, hash them into a hash tree,
903 // and scan through nonce values to make the block's hash satisfy proof-of-work
904 // requirements.  When they solve the proof-of-work, they broadcast the block
905 // to everyone and the block is added to the block chain.  The first transaction
906 // in the block is a special one that creates a new coin owned by the creator
907 // of the block.
908 //
909 // Blocks are appended to blk0001.dat files on disk.  Their location on disk
910 // is indexed by CBlockIndex objects in memory.
911 //
912 class CBlock
913 {
914 public:
915     // header
916     int nVersion;
917     uint256 hashPrevBlock;
918     uint256 hashMerkleRoot;
919     unsigned int nTime;
920     unsigned int nBits;
921     unsigned int nNonce;
922
923     // network and disk
924     vector<CTransaction> vtx;
925
926     // memory only
927     mutable vector<uint256> vMerkleTree;
928
929
930     CBlock()
931     {
932         SetNull();
933     }
934
935     IMPLEMENT_SERIALIZE
936     (
937         READWRITE(this->nVersion);
938         nVersion = this->nVersion;
939         READWRITE(hashPrevBlock);
940         READWRITE(hashMerkleRoot);
941         READWRITE(nTime);
942         READWRITE(nBits);
943         READWRITE(nNonce);
944
945         // ConnectBlock depends on vtx being last so it can calculate offset
946         if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))
947             READWRITE(vtx);
948         else if (fRead)
949             const_cast<CBlock*>(this)->vtx.clear();
950     )
951
952     void SetNull()
953     {
954         nVersion = 1;
955         hashPrevBlock = 0;
956         hashMerkleRoot = 0;
957         nTime = 0;
958         nBits = 0;
959         nNonce = 0;
960         vtx.clear();
961         vMerkleTree.clear();
962     }
963
964     bool IsNull() const
965     {
966         return (nBits == 0);
967     }
968
969     uint256 GetHash() const
970     {
971         return Hash(BEGIN(nVersion), END(nNonce));
972     }
973
974     int64 GetBlockTime() const
975     {
976         return (int64)nTime;
977     }
978
979     int GetSigOpCount() const
980     {
981         int n = 0;
982         foreach(const CTransaction& tx, vtx)
983             n += tx.GetSigOpCount();
984         return n;
985     }
986
987
988     uint256 BuildMerkleTree() const
989     {
990         vMerkleTree.clear();
991         foreach(const CTransaction& tx, vtx)
992             vMerkleTree.push_back(tx.GetHash());
993         int j = 0;
994         for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
995         {
996             for (int i = 0; i < nSize; i += 2)
997             {
998                 int i2 = min(i+1, nSize-1);
999                 vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]),  END(vMerkleTree[j+i]),
1000                                            BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
1001             }
1002             j += nSize;
1003         }
1004         return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
1005     }
1006
1007     vector<uint256> GetMerkleBranch(int nIndex) const
1008     {
1009         if (vMerkleTree.empty())
1010             BuildMerkleTree();
1011         vector<uint256> vMerkleBranch;
1012         int j = 0;
1013         for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
1014         {
1015             int i = min(nIndex^1, nSize-1);
1016             vMerkleBranch.push_back(vMerkleTree[j+i]);
1017             nIndex >>= 1;
1018             j += nSize;
1019         }
1020         return vMerkleBranch;
1021     }
1022
1023     static uint256 CheckMerkleBranch(uint256 hash, const vector<uint256>& vMerkleBranch, int nIndex)
1024     {
1025         if (nIndex == -1)
1026             return 0;
1027         foreach(const uint256& otherside, vMerkleBranch)
1028         {
1029             if (nIndex & 1)
1030                 hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
1031             else
1032                 hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
1033             nIndex >>= 1;
1034         }
1035         return hash;
1036     }
1037
1038
1039     bool WriteToDisk(bool fWriteTransactions, unsigned int& nFileRet, unsigned int& nBlockPosRet)
1040     {
1041         // Open history file to append
1042         CAutoFile fileout = AppendBlockFile(nFileRet);
1043         if (!fileout)
1044             return error("CBlock::WriteToDisk() : AppendBlockFile failed");
1045         if (!fWriteTransactions)
1046             fileout.nType |= SER_BLOCKHEADERONLY;
1047
1048         // Write index header
1049         unsigned int nSize = fileout.GetSerializeSize(*this);
1050         fileout << FLATDATA(pchMessageStart) << nSize;
1051
1052         // Write block
1053         nBlockPosRet = ftell(fileout);
1054         if (nBlockPosRet == -1)
1055             return error("CBlock::WriteToDisk() : ftell failed");
1056         fileout << *this;
1057
1058         // Flush stdio buffers and commit to disk before returning
1059         fflush(fileout);
1060         if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0)
1061         {
1062 #ifdef __WXMSW__
1063             _commit(_fileno(fileout));
1064 #else
1065             fsync(fileno(fileout));
1066 #endif
1067         }
1068
1069         return true;
1070     }
1071
1072     bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true)
1073     {
1074         SetNull();
1075
1076         // Open history file to read
1077         CAutoFile filein = OpenBlockFile(nFile, nBlockPos, "rb");
1078         if (!filein)
1079             return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
1080         if (!fReadTransactions)
1081             filein.nType |= SER_BLOCKHEADERONLY;
1082
1083         // Read block
1084         filein >> *this;
1085
1086         // Check the header
1087         if (!CheckProofOfWork(GetHash(), nBits))
1088             return error("CBlock::ReadFromDisk() : errors in block header");
1089
1090         return true;
1091     }
1092
1093
1094
1095     void print() const
1096     {
1097         printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
1098             GetHash().ToString().substr(0,20).c_str(),
1099             nVersion,
1100             hashPrevBlock.ToString().substr(0,20).c_str(),
1101             hashMerkleRoot.ToString().substr(0,10).c_str(),
1102             nTime, nBits, nNonce,
1103             vtx.size());
1104         for (int i = 0; i < vtx.size(); i++)
1105         {
1106             printf("  ");
1107             vtx[i].print();
1108         }
1109         printf("  vMerkleTree: ");
1110         for (int i = 0; i < vMerkleTree.size(); i++)
1111             printf("%s ", vMerkleTree[i].ToString().substr(0,10).c_str());
1112         printf("\n");
1113     }
1114
1115
1116     bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
1117     bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
1118     bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
1119     bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew);
1120     bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
1121     bool CheckBlock() const;
1122     bool AcceptBlock();
1123 };
1124
1125
1126
1127
1128
1129
1130 //
1131 // The block chain is a tree shaped structure starting with the
1132 // genesis block at the root, with each block potentially having multiple
1133 // candidates to be the next block.  pprev and pnext link a path through the
1134 // main/longest chain.  A blockindex may have multiple pprev pointing back
1135 // to it, but pnext will only point forward to the longest branch, or will
1136 // be null if the block is not part of the longest chain.
1137 //
1138 class CBlockIndex
1139 {
1140 public:
1141     const uint256* phashBlock;
1142     CBlockIndex* pprev;
1143     CBlockIndex* pnext;
1144     unsigned int nFile;
1145     unsigned int nBlockPos;
1146     int nHeight;
1147     CBigNum bnChainWork;
1148
1149     // block header
1150     int nVersion;
1151     uint256 hashMerkleRoot;
1152     unsigned int nTime;
1153     unsigned int nBits;
1154     unsigned int nNonce;
1155
1156
1157     CBlockIndex()
1158     {
1159         phashBlock = NULL;
1160         pprev = NULL;
1161         pnext = NULL;
1162         nFile = 0;
1163         nBlockPos = 0;
1164         nHeight = 0;
1165         bnChainWork = 0;
1166
1167         nVersion       = 0;
1168         hashMerkleRoot = 0;
1169         nTime          = 0;
1170         nBits          = 0;
1171         nNonce         = 0;
1172     }
1173
1174     CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block)
1175     {
1176         phashBlock = NULL;
1177         pprev = NULL;
1178         pnext = NULL;
1179         nFile = nFileIn;
1180         nBlockPos = nBlockPosIn;
1181         nHeight = 0;
1182         bnChainWork = 0;
1183
1184         nVersion       = block.nVersion;
1185         hashMerkleRoot = block.hashMerkleRoot;
1186         nTime          = block.nTime;
1187         nBits          = block.nBits;
1188         nNonce         = block.nNonce;
1189     }
1190
1191     uint256 GetBlockHash() const
1192     {
1193         return *phashBlock;
1194     }
1195
1196     int64 GetBlockTime() const
1197     {
1198         return (int64)nTime;
1199     }
1200
1201     CBigNum GetBlockWork() const
1202     {
1203         CBigNum bnTarget;
1204         bnTarget.SetCompact(nBits);
1205         if (bnTarget <= 0)
1206             return 0;
1207         return (CBigNum(1)<<256) / (bnTarget+1);
1208     }
1209
1210     bool IsInMainChain() const
1211     {
1212         return (pnext || this == pindexBest);
1213     }
1214
1215     bool CheckIndex() const
1216     {
1217         return CheckProofOfWork(GetBlockHash(), nBits);
1218     }
1219
1220     bool EraseBlockFromDisk()
1221     {
1222         // Open history file
1223         CAutoFile fileout = OpenBlockFile(nFile, nBlockPos, "rb+");
1224         if (!fileout)
1225             return false;
1226
1227         // Overwrite with empty null block
1228         CBlock block;
1229         block.SetNull();
1230         fileout << block;
1231
1232         return true;
1233     }
1234
1235     enum { nMedianTimeSpan=11 };
1236
1237     int64 GetMedianTimePast() const
1238     {
1239         int64 pmedian[nMedianTimeSpan];
1240         int64* pbegin = &pmedian[nMedianTimeSpan];
1241         int64* pend = &pmedian[nMedianTimeSpan];
1242
1243         const CBlockIndex* pindex = this;
1244         for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
1245             *(--pbegin) = pindex->GetBlockTime();
1246
1247         sort(pbegin, pend);
1248         return pbegin[(pend - pbegin)/2];
1249     }
1250
1251     int64 GetMedianTime() const
1252     {
1253         const CBlockIndex* pindex = this;
1254         for (int i = 0; i < nMedianTimeSpan/2; i++)
1255         {
1256             if (!pindex->pnext)
1257                 return GetBlockTime();
1258             pindex = pindex->pnext;
1259         }
1260         return pindex->GetMedianTimePast();
1261     }
1262
1263
1264
1265     string ToString() const
1266     {
1267         return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
1268             pprev, pnext, nFile, nBlockPos, nHeight,
1269             hashMerkleRoot.ToString().substr(0,10).c_str(),
1270             GetBlockHash().ToString().substr(0,20).c_str());
1271     }
1272
1273     void print() const
1274     {
1275         printf("%s\n", ToString().c_str());
1276     }
1277 };
1278
1279
1280
1281 //
1282 // Used to marshal pointers into hashes for db storage.
1283 //
1284 class CDiskBlockIndex : public CBlockIndex
1285 {
1286 public:
1287     uint256 hashPrev;
1288     uint256 hashNext;
1289
1290     CDiskBlockIndex()
1291     {
1292         hashPrev = 0;
1293         hashNext = 0;
1294     }
1295
1296     explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex)
1297     {
1298         hashPrev = (pprev ? pprev->GetBlockHash() : 0);
1299         hashNext = (pnext ? pnext->GetBlockHash() : 0);
1300     }
1301
1302     IMPLEMENT_SERIALIZE
1303     (
1304         if (!(nType & SER_GETHASH))
1305             READWRITE(nVersion);
1306
1307         READWRITE(hashNext);
1308         READWRITE(nFile);
1309         READWRITE(nBlockPos);
1310         READWRITE(nHeight);
1311
1312         // block header
1313         READWRITE(this->nVersion);
1314         READWRITE(hashPrev);
1315         READWRITE(hashMerkleRoot);
1316         READWRITE(nTime);
1317         READWRITE(nBits);
1318         READWRITE(nNonce);
1319     )
1320
1321     uint256 GetBlockHash() const
1322     {
1323         CBlock block;
1324         block.nVersion        = nVersion;
1325         block.hashPrevBlock   = hashPrev;
1326         block.hashMerkleRoot  = hashMerkleRoot;
1327         block.nTime           = nTime;
1328         block.nBits           = nBits;
1329         block.nNonce          = nNonce;
1330         return block.GetHash();
1331     }
1332
1333
1334     string ToString() const
1335     {
1336         string str = "CDiskBlockIndex(";
1337         str += CBlockIndex::ToString();
1338         str += strprintf("\n                hashBlock=%s, hashPrev=%s, hashNext=%s)",
1339             GetBlockHash().ToString().c_str(),
1340             hashPrev.ToString().substr(0,20).c_str(),
1341             hashNext.ToString().substr(0,20).c_str());
1342         return str;
1343     }
1344
1345     void print() const
1346     {
1347         printf("%s\n", ToString().c_str());
1348     }
1349 };
1350
1351
1352
1353
1354
1355
1356
1357
1358 //
1359 // Describes a place in the block chain to another node such that if the
1360 // other node doesn't have the same branch, it can find a recent common trunk.
1361 // The further back it is, the further before the fork it may be.
1362 //
1363 class CBlockLocator
1364 {
1365 protected:
1366     vector<uint256> vHave;
1367 public:
1368
1369     CBlockLocator()
1370     {
1371     }
1372
1373     explicit CBlockLocator(const CBlockIndex* pindex)
1374     {
1375         Set(pindex);
1376     }
1377
1378     explicit CBlockLocator(uint256 hashBlock)
1379     {
1380         map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
1381         if (mi != mapBlockIndex.end())
1382             Set((*mi).second);
1383     }
1384
1385     IMPLEMENT_SERIALIZE
1386     (
1387         if (!(nType & SER_GETHASH))
1388             READWRITE(nVersion);
1389         READWRITE(vHave);
1390     )
1391
1392     void Set(const CBlockIndex* pindex)
1393     {
1394         vHave.clear();
1395         int nStep = 1;
1396         while (pindex)
1397         {
1398             vHave.push_back(pindex->GetBlockHash());
1399
1400             // Exponentially larger steps back
1401             for (int i = 0; pindex && i < nStep; i++)
1402                 pindex = pindex->pprev;
1403             if (vHave.size() > 10)
1404                 nStep *= 2;
1405         }
1406         vHave.push_back(hashGenesisBlock);
1407     }
1408
1409     int GetDistanceBack()
1410     {
1411         // Retrace how far back it was in the sender's branch
1412         int nDistance = 0;
1413         int nStep = 1;
1414         foreach(const uint256& hash, vHave)
1415         {
1416             map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
1417             if (mi != mapBlockIndex.end())
1418             {
1419                 CBlockIndex* pindex = (*mi).second;
1420                 if (pindex->IsInMainChain())
1421                     return nDistance;
1422             }
1423             nDistance += nStep;
1424             if (nDistance > 10)
1425                 nStep *= 2;
1426         }
1427         return nDistance;
1428     }
1429
1430     CBlockIndex* GetBlockIndex()
1431     {
1432         // Find the first block the caller has in the main chain
1433         foreach(const uint256& hash, vHave)
1434         {
1435             map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
1436             if (mi != mapBlockIndex.end())
1437             {
1438                 CBlockIndex* pindex = (*mi).second;
1439                 if (pindex->IsInMainChain())
1440                     return pindex;
1441             }
1442         }
1443         return pindexGenesisBlock;
1444     }
1445
1446     uint256 GetBlockHash()
1447     {
1448         // Find the first block the caller has in the main chain
1449         foreach(const uint256& hash, vHave)
1450         {
1451             map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
1452             if (mi != mapBlockIndex.end())
1453             {
1454                 CBlockIndex* pindex = (*mi).second;
1455                 if (pindex->IsInMainChain())
1456                     return hash;
1457             }
1458         }
1459         return hashGenesisBlock;
1460     }
1461
1462     int GetHeight()
1463     {
1464         CBlockIndex* pindex = GetBlockIndex();
1465         if (!pindex)
1466             return 0;
1467         return pindex->nHeight;
1468     }
1469 };
1470
1471
1472
1473
1474
1475
1476 //
1477 // Private key that includes an expiration date in case it never gets used.
1478 //
1479 class CWalletKey
1480 {
1481 public:
1482     CPrivKey vchPrivKey;
1483     int64 nTimeCreated;
1484     int64 nTimeExpires;
1485     string strComment;
1486     //// todo: add something to note what created it (user, getnewaddress, change)
1487     ////   maybe should have a map<string, string> property map
1488
1489     CWalletKey(int64 nExpires=0)
1490     {
1491         nTimeCreated = (nExpires ? GetTime() : 0);
1492         nTimeExpires = nExpires;
1493     }
1494
1495     IMPLEMENT_SERIALIZE
1496     (
1497         if (!(nType & SER_GETHASH))
1498             READWRITE(nVersion);
1499         READWRITE(vchPrivKey);
1500         READWRITE(nTimeCreated);
1501         READWRITE(nTimeExpires);
1502         READWRITE(strComment);
1503     )
1504 };
1505
1506
1507
1508
1509
1510
1511 //
1512 // Alert messages are broadcast as a vector of signed data.  Unserializing may
1513 // not read the entire buffer if the alert is for a newer version, but older
1514 // versions can still relay the original data.
1515 //
1516 class CUnsignedAlert
1517 {
1518 public:
1519     int nVersion;
1520     int64 nRelayUntil;      // when newer nodes stop relaying to newer nodes
1521     int64 nExpiration;
1522     int nID;
1523     int nCancel;
1524     set<int> setCancel;
1525     int nMinVer;            // lowest version inclusive
1526     int nMaxVer;            // highest version inclusive
1527     set<string> setSubVer;  // empty matches all
1528     int nPriority;
1529
1530     // Actions
1531     string strComment;
1532     string strStatusBar;
1533     string strRPCError;
1534
1535     IMPLEMENT_SERIALIZE
1536     (
1537         READWRITE(this->nVersion);
1538         nVersion = this->nVersion;
1539         READWRITE(nRelayUntil);
1540         READWRITE(nExpiration);
1541         READWRITE(nID);
1542         READWRITE(nCancel);
1543         READWRITE(setCancel);
1544         READWRITE(nMinVer);
1545         READWRITE(nMaxVer);
1546         READWRITE(setSubVer);
1547         READWRITE(nPriority);
1548
1549         READWRITE(strComment);
1550         READWRITE(strStatusBar);
1551         READWRITE(strRPCError);
1552     )
1553
1554     void SetNull()
1555     {
1556         nVersion = 1;
1557         nRelayUntil = 0;
1558         nExpiration = 0;
1559         nID = 0;
1560         nCancel = 0;
1561         setCancel.clear();
1562         nMinVer = 0;
1563         nMaxVer = 0;
1564         setSubVer.clear();
1565         nPriority = 0;
1566
1567         strComment.clear();
1568         strStatusBar.clear();
1569         strRPCError.clear();
1570     }
1571
1572     string ToString() const
1573     {
1574         string strSetCancel;
1575         foreach(int n, setCancel)
1576             strSetCancel += strprintf("%d ", n);
1577         string strSetSubVer;
1578         foreach(string str, setSubVer)
1579             strSetSubVer += "\"" + str + "\" ";
1580         return strprintf(
1581                 "CAlert(\n"
1582                 "    nVersion     = %d\n"
1583                 "    nRelayUntil  = %"PRI64d"\n"
1584                 "    nExpiration  = %"PRI64d"\n"
1585                 "    nID          = %d\n"
1586                 "    nCancel      = %d\n"
1587                 "    setCancel    = %s\n"
1588                 "    nMinVer      = %d\n"
1589                 "    nMaxVer      = %d\n"
1590                 "    setSubVer    = %s\n"
1591                 "    nPriority    = %d\n"
1592                 "    strComment   = \"%s\"\n"
1593                 "    strStatusBar = \"%s\"\n"
1594                 "    strRPCError  = \"%s\"\n"
1595                 ")\n",
1596             nVersion,
1597             nRelayUntil,
1598             nExpiration,
1599             nID,
1600             nCancel,
1601             strSetCancel.c_str(),
1602             nMinVer,
1603             nMaxVer,
1604             strSetSubVer.c_str(),
1605             nPriority,
1606             strComment.c_str(),
1607             strStatusBar.c_str(),
1608             strRPCError.c_str());
1609     }
1610
1611     void print() const
1612     {
1613         printf("%s", ToString().c_str());
1614     }
1615 };
1616
1617 class CAlert : public CUnsignedAlert
1618 {
1619 public:
1620     vector<unsigned char> vchMsg;
1621     vector<unsigned char> vchSig;
1622
1623     CAlert()
1624     {
1625         SetNull();
1626     }
1627
1628     IMPLEMENT_SERIALIZE
1629     (
1630         READWRITE(vchMsg);
1631         READWRITE(vchSig);
1632     )
1633
1634     void SetNull()
1635     {
1636         CUnsignedAlert::SetNull();
1637         vchMsg.clear();
1638         vchSig.clear();
1639     }
1640
1641     bool IsNull() const
1642     {
1643         return (nExpiration == 0);
1644     }
1645
1646     uint256 GetHash() const
1647     {
1648         return SerializeHash(*this);
1649     }
1650
1651     bool IsInEffect() const
1652     {
1653         return (GetAdjustedTime() < nExpiration);
1654     }
1655
1656     bool Cancels(const CAlert& alert) const
1657     {
1658         if (!IsInEffect())
1659             return false; // this was a no-op before 31403
1660         return (alert.nID <= nCancel || setCancel.count(alert.nID));
1661     }
1662
1663     bool AppliesTo(int nVersion, string strSubVerIn) const
1664     {
1665         return (IsInEffect() &&
1666                 nMinVer <= nVersion && nVersion <= nMaxVer &&
1667                 (setSubVer.empty() || setSubVer.count(strSubVerIn)));
1668     }
1669
1670     bool AppliesToMe() const
1671     {
1672         return AppliesTo(VERSION, ::pszSubVer);
1673     }
1674
1675     bool RelayTo(CNode* pnode) const
1676     {
1677         if (!IsInEffect())
1678             return false;
1679         // returns true if wasn't already contained in the set
1680         if (pnode->setKnown.insert(GetHash()).second)
1681         {
1682             if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
1683                 AppliesToMe() ||
1684                 GetAdjustedTime() < nRelayUntil)
1685             {
1686                 pnode->PushMessage("alert", *this);
1687                 return true;
1688             }
1689         }
1690         return false;
1691     }
1692
1693     bool CheckSignature()
1694     {
1695         CKey key;
1696         if (!key.SetPubKey(ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284")))
1697             return error("CAlert::CheckSignature() : SetPubKey failed");
1698         if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
1699             return error("CAlert::CheckSignature() : verify signature failed");
1700
1701         // Now unserialize the data
1702         CDataStream sMsg(vchMsg);
1703         sMsg >> *(CUnsignedAlert*)this;
1704         return true;
1705     }
1706
1707     bool ProcessAlert();
1708 };
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719 extern map<uint256, CTransaction> mapTransactions;
1720 extern map<uint256, CWalletTx> mapWallet;
1721 extern vector<uint256> vWalletUpdated;
1722 extern CCriticalSection cs_mapWallet;
1723 extern map<vector<unsigned char>, CPrivKey> mapKeys;
1724 extern map<uint160, vector<unsigned char> > mapPubKeys;
1725 extern CCriticalSection cs_mapKeys;
1726 extern CKey keyUser;