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