-
+ 4337C61164B29806836FB0A4114D3BF42A18BF7B99A087E091B1FB523E6B9159C63EA265692A4A2D8FAE60339C7C093B9DB35B978D794BFAC2A3BBF72D240A25
bitcoin/src/main.h
(0 . 0)(1 . 1602)
13614 // /****************************\
13615 // * EXPERIMENTAL BRANCH. *
13616 // * FOR LABORATORY USE ONLY. *
13617 // ********************************
13618 // ************
13619 // **************
13620 // ****************
13621 // **** **** ****
13622 // *** *** ***
13623 // *** *** ***
13624 // *** * * **
13625 // ******** ********
13626 // ******* ******
13627 // *** **
13628 // * ******* **
13629 // ** * * * * *
13630 // ** * * ***
13631 // **** * * * * ****
13632 // **** *** * * ** ***
13633 // **** ********* ******
13634 // ******* ***** *******
13635 // ********* ****** **
13636 // ** ****** ******
13637 // ** ******* **
13638 // ** ******* ***
13639 // **** ******** ************
13640 // ************ ************
13641 // ******** *******
13642 // ****** ****
13643 // *** ***
13644 // ********************************
13645 // Copyright (c) 2009-2010 Satoshi Nakamoto
13646 // Copyright (c) 2009-2012 The Bitcoin developers
13647 // Distributed under the MIT/X11 software license, see the accompanying
13648 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
13649 #ifndef BITCOIN_MAIN_H
13650 #define BITCOIN_MAIN_H
13651
13652 #include "bignum.h"
13653 #include "net.h"
13654 #include "key.h"
13655 #include "script.h"
13656 #include "db.h"
13657
13658 #include <list>
13659
13660 class CBlock;
13661 class CBlockIndex;
13662 class CWalletTx;
13663 class CWallet;
13664 class CKeyItem;
13665 class CReserveKey;
13666 class CWalletDB;
13667
13668 class CAddress;
13669 class CInv;
13670 class CRequestTracker;
13671 class CNode;
13672 class CBlockIndex;
13673
13674 static const unsigned int MAX_BLOCK_SIZE = 1000000;
13675 static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2;
13676 static const int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50;
13677 static const int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100;
13678 static const int64 COIN = 100000000;
13679 static const int64 CENT = 1000000;
13680 static const int64 MIN_TX_FEE = 50000;
13681 static const int64 MIN_RELAY_TX_FEE = 10000;
13682 static const int64 MAX_MONEY = 21000000 * COIN;
13683 inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); }
13684 static const int COINBASE_MATURITY = 100;
13685 // Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp.
13686 static const int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC
13687 #ifdef USE_UPNP
13688 static const int fHaveUPnP = true;
13689 #else
13690 static const int fHaveUPnP = false;
13691 #endif
13692
13693
13694
13695
13696
13697
13698 extern CCriticalSection cs_main;
13699 extern std::map<uint256, CBlockIndex*> mapBlockIndex;
13700 extern uint256 hashGenesisBlock;
13701 extern CBlockIndex* pindexGenesisBlock;
13702 extern int nBestHeight;
13703 extern CBigNum bnBestChainWork;
13704 extern CBigNum bnBestInvalidWork;
13705 extern uint256 hashBestChain;
13706 extern CBlockIndex* pindexBest;
13707 extern unsigned int nTransactionsUpdated;
13708 extern double dHashesPerSec;
13709 extern int64 nHPSTimerStart;
13710 extern int64 nTimeBestReceived;
13711 extern CCriticalSection cs_setpwalletRegistered;
13712 extern std::set<CWallet*> setpwalletRegistered;
13713
13714 // Settings
13715 extern int fGenerateBitcoins;
13716 extern int64 nTransactionFee;
13717 extern int fLimitProcessors;
13718 extern int nLimitProcessors;
13719 extern int fMinimizeToTray;
13720 extern int fMinimizeOnClose;
13721 extern int fUseUPnP;
13722
13723
13724
13725
13726
13727 class CReserveKey;
13728 class CTxDB;
13729 class CTxIndex;
13730
13731 void RegisterWallet(CWallet* pwalletIn);
13732 void UnregisterWallet(CWallet* pwalletIn);
13733 bool ProcessBlock(CNode* pfrom, CBlock* pblock);
13734 bool CheckDiskSpace(uint64 nAdditionalBytes=0);
13735 FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb");
13736 FILE* AppendBlockFile(unsigned int& nFileRet);
13737 bool LoadBlockIndex(bool fAllowNew=true);
13738 void PrintBlockTree();
13739 bool ProcessMessages(CNode* pfrom);
13740 bool SendMessages(CNode* pto, bool fSendTrickle);
13741 void GenerateBitcoins(bool fGenerate, CWallet* pwallet);
13742 CBlock* CreateNewBlock(CReserveKey& reservekey);
13743 void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce);
13744 void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1);
13745 bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey);
13746 bool CheckProofOfWork(uint256 hash, unsigned int nBits);
13747 unsigned int ComputeMinWork(unsigned int nBase, int64 nTime);
13748 int GetNumBlocksOfPeers();
13749 bool IsInitialBlockDownload();
13750 std::string GetWarnings(std::string strFor);
13751
13752
13753
13754
13755
13756
13757
13758
13759
13760
13761
13762
13763 bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut);
13764
13765 template<typename T>
13766 bool WriteSetting(const std::string& strKey, const T& value)
13767 {
13768 bool fOk = false;
13769 BOOST_FOREACH(CWallet* pwallet, setpwalletRegistered)
13770 {
13771 std::string strWalletFile;
13772 if (!GetWalletFile(pwallet, strWalletFile))
13773 continue;
13774 fOk |= CWalletDB(strWalletFile).WriteSetting(strKey, value);
13775 }
13776 return fOk;
13777 }
13778
13779
13780 class CDiskTxPos
13781 {
13782 public:
13783 unsigned int nFile;
13784 unsigned int nBlockPos;
13785 unsigned int nTxPos;
13786
13787 CDiskTxPos()
13788 {
13789 SetNull();
13790 }
13791
13792 CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn)
13793 {
13794 nFile = nFileIn;
13795 nBlockPos = nBlockPosIn;
13796 nTxPos = nTxPosIn;
13797 }
13798
13799 IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
13800 void SetNull() { nFile = -1; nBlockPos = 0; nTxPos = 0; }
13801 bool IsNull() const { return (nFile == -1); }
13802
13803 friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b)
13804 {
13805 return (a.nFile == b.nFile &&
13806 a.nBlockPos == b.nBlockPos &&
13807 a.nTxPos == b.nTxPos);
13808 }
13809
13810 friend bool operator!=(const CDiskTxPos& a, const CDiskTxPos& b)
13811 {
13812 return !(a == b);
13813 }
13814
13815 std::string ToString() const
13816 {
13817 if (IsNull())
13818 return strprintf("null");
13819 else
13820 return strprintf("(nFile=%d, nBlockPos=%d, nTxPos=%d)", nFile, nBlockPos, nTxPos);
13821 }
13822
13823 void print() const
13824 {
13825 printf("%s", ToString().c_str());
13826 }
13827 };
13828
13829
13830
13831
13832 class CInPoint
13833 {
13834 public:
13835 CTransaction* ptx;
13836 unsigned int n;
13837
13838 CInPoint() { SetNull(); }
13839 CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; }
13840 void SetNull() { ptx = NULL; n = -1; }
13841 bool IsNull() const { return (ptx == NULL && n == -1); }
13842 };
13843
13844
13845
13846
13847 class COutPoint
13848 {
13849 public:
13850 uint256 hash;
13851 unsigned int n;
13852
13853 COutPoint() { SetNull(); }
13854 COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; }
13855 IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); )
13856 void SetNull() { hash = 0; n = -1; }
13857 bool IsNull() const { return (hash == 0 && n == -1); }
13858
13859 friend bool operator<(const COutPoint& a, const COutPoint& b)
13860 {
13861 return (a.hash < b.hash || (a.hash == b.hash && a.n < b.n));
13862 }
13863
13864 friend bool operator==(const COutPoint& a, const COutPoint& b)
13865 {
13866 return (a.hash == b.hash && a.n == b.n);
13867 }
13868
13869 friend bool operator!=(const COutPoint& a, const COutPoint& b)
13870 {
13871 return !(a == b);
13872 }
13873
13874 std::string ToString() const
13875 {
13876 return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,10).c_str(), n);
13877 }
13878
13879 void print() const
13880 {
13881 printf("%s\n", ToString().c_str());
13882 }
13883 };
13884
13885
13886
13887
13888 //
13889 // An input of a transaction. It contains the location of the previous
13890 // transaction's output that it claims and a signature that matches the
13891 // output's public key.
13892 //
13893 class CTxIn
13894 {
13895 public:
13896 COutPoint prevout;
13897 CScript scriptSig;
13898 unsigned int nSequence;
13899
13900 CTxIn()
13901 {
13902 nSequence = UINT_MAX;
13903 }
13904
13905 explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
13906 {
13907 prevout = prevoutIn;
13908 scriptSig = scriptSigIn;
13909 nSequence = nSequenceIn;
13910 }
13911
13912 CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=UINT_MAX)
13913 {
13914 prevout = COutPoint(hashPrevTx, nOut);
13915 scriptSig = scriptSigIn;
13916 nSequence = nSequenceIn;
13917 }
13918
13919 IMPLEMENT_SERIALIZE
13920 (
13921 READWRITE(prevout);
13922 READWRITE(scriptSig);
13923 READWRITE(nSequence);
13924 )
13925
13926 bool IsFinal() const
13927 {
13928 return (nSequence == UINT_MAX);
13929 }
13930
13931 friend bool operator==(const CTxIn& a, const CTxIn& b)
13932 {
13933 return (a.prevout == b.prevout &&
13934 a.scriptSig == b.scriptSig &&
13935 a.nSequence == b.nSequence);
13936 }
13937
13938 friend bool operator!=(const CTxIn& a, const CTxIn& b)
13939 {
13940 return !(a == b);
13941 }
13942
13943 std::string ToString() const
13944 {
13945 std::string str;
13946 str += strprintf("CTxIn(");
13947 str += prevout.ToString();
13948 if (prevout.IsNull())
13949 str += strprintf(", coinbase %s", HexStr(scriptSig).c_str());
13950 else
13951 str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str());
13952 if (nSequence != UINT_MAX)
13953 str += strprintf(", nSequence=%u", nSequence);
13954 str += ")";
13955 return str;
13956 }
13957
13958 void print() const
13959 {
13960 printf("%s\n", ToString().c_str());
13961 }
13962 };
13963
13964
13965
13966
13967 //
13968 // An output of a transaction. It contains the public key that the next input
13969 // must be able to sign with to claim it.
13970 //
13971 class CTxOut
13972 {
13973 public:
13974 int64 nValue;
13975 CScript scriptPubKey;
13976
13977 CTxOut()
13978 {
13979 SetNull();
13980 }
13981
13982 CTxOut(int64 nValueIn, CScript scriptPubKeyIn)
13983 {
13984 nValue = nValueIn;
13985 scriptPubKey = scriptPubKeyIn;
13986 }
13987
13988 IMPLEMENT_SERIALIZE
13989 (
13990 READWRITE(nValue);
13991 READWRITE(scriptPubKey);
13992 )
13993
13994 void SetNull()
13995 {
13996 nValue = -1;
13997 scriptPubKey.clear();
13998 }
13999
14000 bool IsNull()
14001 {
14002 return (nValue == -1);
14003 }
14004
14005 uint256 GetHash() const
14006 {
14007 return SerializeHash(*this);
14008 }
14009
14010 friend bool operator==(const CTxOut& a, const CTxOut& b)
14011 {
14012 return (a.nValue == b.nValue &&
14013 a.scriptPubKey == b.scriptPubKey);
14014 }
14015
14016 friend bool operator!=(const CTxOut& a, const CTxOut& b)
14017 {
14018 return !(a == b);
14019 }
14020
14021 std::string ToString() const
14022 {
14023 if (scriptPubKey.size() < 6)
14024 return "CTxOut(error)";
14025 return strprintf("CTxOut(nValue=%"PRI64d".%08"PRI64d", scriptPubKey=%s)", nValue / COIN, nValue % COIN, scriptPubKey.ToString().substr(0,30).c_str());
14026 }
14027
14028 void print() const
14029 {
14030 printf("%s\n", ToString().c_str());
14031 }
14032 };
14033
14034
14035
14036
14037 //
14038 // The basic transaction that is broadcasted on the network and contained in
14039 // blocks. A transaction can contain multiple inputs and outputs.
14040 //
14041 class CTransaction
14042 {
14043 public:
14044 int nVersion;
14045 std::vector<CTxIn> vin;
14046 std::vector<CTxOut> vout;
14047 unsigned int nLockTime;
14048
14049 // Denial-of-service detection:
14050 mutable int nDoS;
14051 bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
14052
14053 CTransaction()
14054 {
14055 SetNull();
14056 }
14057
14058 IMPLEMENT_SERIALIZE
14059 (
14060 READWRITE(this->nVersion);
14061 nVersion = this->nVersion;
14062 READWRITE(vin);
14063 READWRITE(vout);
14064 READWRITE(nLockTime);
14065 )
14066
14067 void SetNull()
14068 {
14069 nVersion = 1;
14070 vin.clear();
14071 vout.clear();
14072 nLockTime = 0;
14073 nDoS = 0; // Denial-of-service prevention
14074 }
14075
14076 bool IsNull() const
14077 {
14078 return (vin.empty() && vout.empty());
14079 }
14080
14081 uint256 GetHash() const
14082 {
14083 return SerializeHash(*this);
14084 }
14085
14086 bool IsFinal(int nBlockHeight=0, int64 nBlockTime=0) const
14087 {
14088 // Time based nLockTime implemented in 0.1.6
14089 if (nLockTime == 0)
14090 return true;
14091 if (nBlockHeight == 0)
14092 nBlockHeight = nBestHeight;
14093 if (nBlockTime == 0)
14094 nBlockTime = GetAdjustedTime();
14095 if ((int64)nLockTime < (nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
14096 return true;
14097 BOOST_FOREACH(const CTxIn& txin, vin)
14098 if (!txin.IsFinal())
14099 return false;
14100 return true;
14101 }
14102
14103 bool IsNewerThan(const CTransaction& old) const
14104 {
14105 if (vin.size() != old.vin.size())
14106 return false;
14107 for (int i = 0; i < vin.size(); i++)
14108 if (vin[i].prevout != old.vin[i].prevout)
14109 return false;
14110
14111 bool fNewer = false;
14112 unsigned int nLowest = UINT_MAX;
14113 for (int i = 0; i < vin.size(); i++)
14114 {
14115 if (vin[i].nSequence != old.vin[i].nSequence)
14116 {
14117 if (vin[i].nSequence <= nLowest)
14118 {
14119 fNewer = false;
14120 nLowest = vin[i].nSequence;
14121 }
14122 if (old.vin[i].nSequence < nLowest)
14123 {
14124 fNewer = true;
14125 nLowest = old.vin[i].nSequence;
14126 }
14127 }
14128 }
14129 return fNewer;
14130 }
14131
14132 bool IsCoinBase() const
14133 {
14134 return (vin.size() == 1 && vin[0].prevout.IsNull());
14135 }
14136
14137 int GetSigOpCount() const
14138 {
14139 int n = 0;
14140 BOOST_FOREACH(const CTxIn& txin, vin)
14141 n += txin.scriptSig.GetSigOpCount();
14142 BOOST_FOREACH(const CTxOut& txout, vout)
14143 n += txout.scriptPubKey.GetSigOpCount();
14144 return n;
14145 }
14146
14147 bool IsStandard() const
14148 {
14149 BOOST_FOREACH(const CTxIn& txin, vin)
14150 if (!txin.scriptSig.IsPushOnly())
14151 return error("nonstandard txin: %s", txin.scriptSig.ToString().c_str());
14152 BOOST_FOREACH(const CTxOut& txout, vout)
14153 if (!::IsStandard(txout.scriptPubKey))
14154 return error("nonstandard txout: %s", txout.scriptPubKey.ToString().c_str());
14155 return true;
14156 }
14157
14158 int64 GetValueOut() const
14159 {
14160 int64 nValueOut = 0;
14161 BOOST_FOREACH(const CTxOut& txout, vout)
14162 {
14163 nValueOut += txout.nValue;
14164 if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
14165 throw std::runtime_error("CTransaction::GetValueOut() : value out of range");
14166 }
14167 return nValueOut;
14168 }
14169
14170 static bool AllowFree(double dPriority)
14171 {
14172 // Large (in bytes) low-priority (new, small-coin) transactions
14173 // need a fee.
14174 return dPriority > COIN * 144 / 250;
14175 }
14176
14177 int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=true, bool fForRelay=false) const
14178 {
14179 // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE
14180 int64 nBaseFee = fForRelay ? MIN_RELAY_TX_FEE : MIN_TX_FEE;
14181
14182 unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK);
14183 unsigned int nNewBlockSize = nBlockSize + nBytes;
14184 int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee;
14185
14186 if (fAllowFree)
14187 {
14188 if (nBlockSize == 1)
14189 {
14190 // Transactions under 10K are free
14191 // (about 4500bc if made of 50bc inputs)
14192 if (nBytes < 10000)
14193 nMinFee = 0;
14194 }
14195 else
14196 {
14197 // Free transaction area
14198 if (nNewBlockSize < 27000)
14199 nMinFee = 0;
14200 }
14201 }
14202
14203 // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01
14204 if (nMinFee < nBaseFee)
14205 BOOST_FOREACH(const CTxOut& txout, vout)
14206 if (txout.nValue < CENT)
14207 nMinFee = nBaseFee;
14208
14209 // Raise the price as the block approaches full
14210 if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2)
14211 {
14212 if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN)
14213 return MAX_MONEY;
14214 nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize);
14215 }
14216
14217 if (!MoneyRange(nMinFee))
14218 nMinFee = MAX_MONEY;
14219 return nMinFee;
14220 }
14221
14222
14223 bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL)
14224 {
14225 CAutoFile filein = OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb");
14226 if (!filein)
14227 return error("CTransaction::ReadFromDisk() : OpenBlockFile failed");
14228
14229 // Read transaction
14230 if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
14231 return error("CTransaction::ReadFromDisk() : fseek failed");
14232 filein >> *this;
14233
14234 // Return file pointer
14235 if (pfileRet)
14236 {
14237 if (fseek(filein, pos.nTxPos, SEEK_SET) != 0)
14238 return error("CTransaction::ReadFromDisk() : second fseek failed");
14239 *pfileRet = filein.release();
14240 }
14241 return true;
14242 }
14243
14244 friend bool operator==(const CTransaction& a, const CTransaction& b)
14245 {
14246 return (a.nVersion == b.nVersion &&
14247 a.vin == b.vin &&
14248 a.vout == b.vout &&
14249 a.nLockTime == b.nLockTime);
14250 }
14251
14252 friend bool operator!=(const CTransaction& a, const CTransaction& b)
14253 {
14254 return !(a == b);
14255 }
14256
14257
14258 std::string ToString() const
14259 {
14260 std::string str;
14261 str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n",
14262 GetHash().ToString().substr(0,10).c_str(),
14263 nVersion,
14264 vin.size(),
14265 vout.size(),
14266 nLockTime);
14267 for (int i = 0; i < vin.size(); i++)
14268 str += " " + vin[i].ToString() + "\n";
14269 for (int i = 0; i < vout.size(); i++)
14270 str += " " + vout[i].ToString() + "\n";
14271 return str;
14272 }
14273
14274 void print() const
14275 {
14276 printf("%s", ToString().c_str());
14277 }
14278
14279
14280 bool ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet);
14281 bool ReadFromDisk(CTxDB& txdb, COutPoint prevout);
14282 bool ReadFromDisk(COutPoint prevout);
14283 bool DisconnectInputs(CTxDB& txdb);
14284 bool ConnectInputs(CTxDB& txdb, std::map<uint256, CTxIndex>& mapTestPool, CDiskTxPos posThisTx,
14285 CBlockIndex* pindexBlock, int64& nFees, bool fBlock, bool fMiner, int64 nMinFee,
14286 bool& fInvalid);
14287 bool ClientConnectInputs();
14288 bool CheckTransaction() const;
14289 bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL);
14290 bool AcceptToMemoryPool(bool fCheckInputs=true, bool* pfMissingInputs=NULL);
14291 protected:
14292 bool AddToMemoryPoolUnchecked();
14293 public:
14294 bool RemoveFromMemoryPool();
14295 };
14296
14297
14298
14299
14300
14301 //
14302 // A transaction with a merkle branch linking it to the block chain
14303 //
14304 class CMerkleTx : public CTransaction
14305 {
14306 public:
14307 uint256 hashBlock;
14308 std::vector<uint256> vMerkleBranch;
14309 int nIndex;
14310
14311 // memory only
14312 mutable char fMerkleVerified;
14313
14314
14315 CMerkleTx()
14316 {
14317 Init();
14318 }
14319
14320 CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
14321 {
14322 Init();
14323 }
14324
14325 void Init()
14326 {
14327 hashBlock = 0;
14328 nIndex = -1;
14329 fMerkleVerified = false;
14330 }
14331
14332
14333 IMPLEMENT_SERIALIZE
14334 (
14335 nSerSize += SerReadWrite(s, *(CTransaction*)this, nType, nVersion, ser_action);
14336 nVersion = this->nVersion;
14337 READWRITE(hashBlock);
14338 READWRITE(vMerkleBranch);
14339 READWRITE(nIndex);
14340 )
14341
14342
14343 int SetMerkleBranch(const CBlock* pblock=NULL);
14344 int GetDepthInMainChain(int& nHeightRet) const;
14345 int GetDepthInMainChain() const { int nHeight; return GetDepthInMainChain(nHeight); }
14346 bool IsInMainChain() const { return GetDepthInMainChain() > 0; }
14347 int GetBlocksToMaturity() const;
14348 bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true);
14349 bool AcceptToMemoryPool();
14350 };
14351
14352
14353
14354
14355 //
14356 // A txdb record that contains the disk location of a transaction and the
14357 // locations of transactions that spend its outputs. vSpent is really only
14358 // used as a flag, but having the location is very helpful for debugging.
14359 //
14360 class CTxIndex
14361 {
14362 public:
14363 CDiskTxPos pos;
14364 std::vector<CDiskTxPos> vSpent;
14365
14366 CTxIndex()
14367 {
14368 SetNull();
14369 }
14370
14371 CTxIndex(const CDiskTxPos& posIn, unsigned int nOutputs)
14372 {
14373 pos = posIn;
14374 vSpent.resize(nOutputs);
14375 }
14376
14377 IMPLEMENT_SERIALIZE
14378 (
14379 if (!(nType & SER_GETHASH))
14380 READWRITE(nVersion);
14381 READWRITE(pos);
14382 READWRITE(vSpent);
14383 )
14384
14385 void SetNull()
14386 {
14387 pos.SetNull();
14388 vSpent.clear();
14389 }
14390
14391 bool IsNull()
14392 {
14393 return pos.IsNull();
14394 }
14395
14396 friend bool operator==(const CTxIndex& a, const CTxIndex& b)
14397 {
14398 return (a.pos == b.pos &&
14399 a.vSpent == b.vSpent);
14400 }
14401
14402 friend bool operator!=(const CTxIndex& a, const CTxIndex& b)
14403 {
14404 return !(a == b);
14405 }
14406 int GetDepthInMainChain() const;
14407 };
14408
14409
14410
14411
14412
14413 //
14414 // Nodes collect new transactions into a block, hash them into a hash tree,
14415 // and scan through nonce values to make the block's hash satisfy proof-of-work
14416 // requirements. When they solve the proof-of-work, they broadcast the block
14417 // to everyone and the block is added to the block chain. The first transaction
14418 // in the block is a special one that creates a new coin owned by the creator
14419 // of the block.
14420 //
14421 // Blocks are appended to blk0001.dat files on disk. Their location on disk
14422 // is indexed by CBlockIndex objects in memory.
14423 //
14424 class CBlock
14425 {
14426 public:
14427 // header
14428 int nVersion;
14429 uint256 hashPrevBlock;
14430 uint256 hashMerkleRoot;
14431 unsigned int nTime;
14432 unsigned int nBits;
14433 unsigned int nNonce;
14434
14435 // network and disk
14436 std::vector<CTransaction> vtx;
14437
14438 // memory only
14439 mutable std::vector<uint256> vMerkleTree;
14440
14441 // Denial-of-service detection:
14442 mutable int nDoS;
14443 bool DoS(int nDoSIn, bool fIn) const { nDoS += nDoSIn; return fIn; }
14444
14445 CBlock()
14446 {
14447 SetNull();
14448 }
14449
14450 IMPLEMENT_SERIALIZE
14451 (
14452 READWRITE(this->nVersion);
14453 nVersion = this->nVersion;
14454 READWRITE(hashPrevBlock);
14455 READWRITE(hashMerkleRoot);
14456 READWRITE(nTime);
14457 READWRITE(nBits);
14458 READWRITE(nNonce);
14459
14460 // ConnectBlock depends on vtx being last so it can calculate offset
14461 if (!(nType & (SER_GETHASH|SER_BLOCKHEADERONLY)))
14462 READWRITE(vtx);
14463 else if (fRead)
14464 const_cast<CBlock*>(this)->vtx.clear();
14465 )
14466
14467 void SetNull()
14468 {
14469 nVersion = 1;
14470 hashPrevBlock = 0;
14471 hashMerkleRoot = 0;
14472 nTime = 0;
14473 nBits = 0;
14474 nNonce = 0;
14475 vtx.clear();
14476 vMerkleTree.clear();
14477 nDoS = 0;
14478 }
14479
14480 bool IsNull() const
14481 {
14482 return (nBits == 0);
14483 }
14484
14485 uint256 GetHash() const
14486 {
14487 return Hash(BEGIN(nVersion), END(nNonce));
14488 }
14489
14490 int64 GetBlockTime() const
14491 {
14492 return (int64)nTime;
14493 }
14494
14495 int GetSigOpCount() const
14496 {
14497 int n = 0;
14498 BOOST_FOREACH(const CTransaction& tx, vtx)
14499 n += tx.GetSigOpCount();
14500 return n;
14501 }
14502
14503
14504 uint256 BuildMerkleTree() const
14505 {
14506 vMerkleTree.clear();
14507 BOOST_FOREACH(const CTransaction& tx, vtx)
14508 vMerkleTree.push_back(tx.GetHash());
14509 int j = 0;
14510 for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
14511 {
14512 for (int i = 0; i < nSize; i += 2)
14513 {
14514 int i2 = std::min(i+1, nSize-1);
14515 vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]),
14516 BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2])));
14517 }
14518 j += nSize;
14519 }
14520 return (vMerkleTree.empty() ? 0 : vMerkleTree.back());
14521 }
14522
14523 std::vector<uint256> GetMerkleBranch(int nIndex) const
14524 {
14525 if (vMerkleTree.empty())
14526 BuildMerkleTree();
14527 std::vector<uint256> vMerkleBranch;
14528 int j = 0;
14529 for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2)
14530 {
14531 int i = std::min(nIndex^1, nSize-1);
14532 vMerkleBranch.push_back(vMerkleTree[j+i]);
14533 nIndex >>= 1;
14534 j += nSize;
14535 }
14536 return vMerkleBranch;
14537 }
14538
14539 static uint256 CheckMerkleBranch(uint256 hash, const std::vector<uint256>& vMerkleBranch, int nIndex)
14540 {
14541 if (nIndex == -1)
14542 return 0;
14543 BOOST_FOREACH(const uint256& otherside, vMerkleBranch)
14544 {
14545 if (nIndex & 1)
14546 hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash));
14547 else
14548 hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside));
14549 nIndex >>= 1;
14550 }
14551 return hash;
14552 }
14553
14554
14555 bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet)
14556 {
14557 // Open history file to append
14558 CAutoFile fileout = AppendBlockFile(nFileRet);
14559 if (!fileout)
14560 return error("CBlock::WriteToDisk() : AppendBlockFile failed");
14561
14562 // Write index header
14563 unsigned int nSize = fileout.GetSerializeSize(*this);
14564 fileout << FLATDATA(pchMessageStart) << nSize;
14565
14566 // Write block
14567 nBlockPosRet = ftell(fileout);
14568 if (nBlockPosRet == -1)
14569 return error("CBlock::WriteToDisk() : ftell failed");
14570 fileout << *this;
14571
14572 // Flush stdio buffers and commit to disk before returning
14573 fflush(fileout);
14574 if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0)
14575 {
14576 #ifdef WIN32
14577 _commit(_fileno(fileout));
14578 #else
14579 fsync(fileno(fileout));
14580 #endif
14581 }
14582
14583 return true;
14584 }
14585
14586 bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true)
14587 {
14588 SetNull();
14589
14590 // Open history file to read
14591 CAutoFile filein = OpenBlockFile(nFile, nBlockPos, "rb");
14592 if (!filein)
14593 return error("CBlock::ReadFromDisk() : OpenBlockFile failed");
14594 if (!fReadTransactions)
14595 filein.nType |= SER_BLOCKHEADERONLY;
14596
14597 // Read block
14598 filein >> *this;
14599
14600 // Check the header
14601 if (!CheckProofOfWork(GetHash(), nBits))
14602 return error("CBlock::ReadFromDisk() : errors in block header");
14603
14604 return true;
14605 }
14606
14607
14608
14609 void print() const
14610 {
14611 printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d)\n",
14612 GetHash().ToString().substr(0,20).c_str(),
14613 nVersion,
14614 hashPrevBlock.ToString().substr(0,20).c_str(),
14615 hashMerkleRoot.ToString().substr(0,10).c_str(),
14616 nTime, nBits, nNonce,
14617 vtx.size());
14618 for (int i = 0; i < vtx.size(); i++)
14619 {
14620 printf(" ");
14621 vtx[i].print();
14622 }
14623 printf(" vMerkleTree: ");
14624 for (int i = 0; i < vMerkleTree.size(); i++)
14625 printf("%s ", vMerkleTree[i].ToString().substr(0,10).c_str());
14626 printf("\n");
14627 }
14628
14629
14630 bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex);
14631 bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex);
14632 bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true);
14633 bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew);
14634 bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos);
14635 bool CheckBlock() const;
14636 bool AcceptBlock();
14637 };
14638
14639
14640
14641
14642
14643
14644 //
14645 // The block chain is a tree shaped structure starting with the
14646 // genesis block at the root, with each block potentially having multiple
14647 // candidates to be the next block. pprev and pnext link a path through the
14648 // main/longest chain. A blockindex may have multiple pprev pointing back
14649 // to it, but pnext will only point forward to the longest branch, or will
14650 // be null if the block is not part of the longest chain.
14651 //
14652 class CBlockIndex
14653 {
14654 public:
14655 const uint256* phashBlock;
14656 CBlockIndex* pprev;
14657 CBlockIndex* pnext;
14658 unsigned int nFile;
14659 unsigned int nBlockPos;
14660 int nHeight;
14661 CBigNum bnChainWork;
14662
14663 // block header
14664 int nVersion;
14665 uint256 hashMerkleRoot;
14666 unsigned int nTime;
14667 unsigned int nBits;
14668 unsigned int nNonce;
14669
14670
14671 CBlockIndex()
14672 {
14673 phashBlock = NULL;
14674 pprev = NULL;
14675 pnext = NULL;
14676 nFile = 0;
14677 nBlockPos = 0;
14678 nHeight = 0;
14679 bnChainWork = 0;
14680
14681 nVersion = 0;
14682 hashMerkleRoot = 0;
14683 nTime = 0;
14684 nBits = 0;
14685 nNonce = 0;
14686 }
14687
14688 CBlockIndex(unsigned int nFileIn, unsigned int nBlockPosIn, CBlock& block)
14689 {
14690 phashBlock = NULL;
14691 pprev = NULL;
14692 pnext = NULL;
14693 nFile = nFileIn;
14694 nBlockPos = nBlockPosIn;
14695 nHeight = 0;
14696 bnChainWork = 0;
14697
14698 nVersion = block.nVersion;
14699 hashMerkleRoot = block.hashMerkleRoot;
14700 nTime = block.nTime;
14701 nBits = block.nBits;
14702 nNonce = block.nNonce;
14703 }
14704
14705 CBlock GetBlockHeader() const
14706 {
14707 CBlock block;
14708 block.nVersion = nVersion;
14709 if (pprev)
14710 block.hashPrevBlock = pprev->GetBlockHash();
14711 block.hashMerkleRoot = hashMerkleRoot;
14712 block.nTime = nTime;
14713 block.nBits = nBits;
14714 block.nNonce = nNonce;
14715 return block;
14716 }
14717
14718 uint256 GetBlockHash() const
14719 {
14720 return *phashBlock;
14721 }
14722
14723 int64 GetBlockTime() const
14724 {
14725 return (int64)nTime;
14726 }
14727
14728 CBigNum GetBlockWork() const
14729 {
14730 CBigNum bnTarget;
14731 bnTarget.SetCompact(nBits);
14732 if (bnTarget <= 0)
14733 return 0;
14734 return (CBigNum(1)<<256) / (bnTarget+1);
14735 }
14736
14737 bool IsInMainChain() const
14738 {
14739 return (pnext || this == pindexBest);
14740 }
14741
14742 bool CheckIndex() const
14743 {
14744 return CheckProofOfWork(GetBlockHash(), nBits);
14745 }
14746
14747 bool EraseBlockFromDisk()
14748 {
14749 // Open history file
14750 CAutoFile fileout = OpenBlockFile(nFile, nBlockPos, "rb+");
14751 if (!fileout)
14752 return false;
14753
14754 // Overwrite with empty null block
14755 CBlock block;
14756 block.SetNull();
14757 fileout << block;
14758
14759 return true;
14760 }
14761
14762 enum { nMedianTimeSpan=11 };
14763
14764 int64 GetMedianTimePast() const
14765 {
14766 int64 pmedian[nMedianTimeSpan];
14767 int64* pbegin = &pmedian[nMedianTimeSpan];
14768 int64* pend = &pmedian[nMedianTimeSpan];
14769
14770 const CBlockIndex* pindex = this;
14771 for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev)
14772 *(--pbegin) = pindex->GetBlockTime();
14773
14774 std::sort(pbegin, pend);
14775 return pbegin[(pend - pbegin)/2];
14776 }
14777
14778 int64 GetMedianTime() const
14779 {
14780 const CBlockIndex* pindex = this;
14781 for (int i = 0; i < nMedianTimeSpan/2; i++)
14782 {
14783 if (!pindex->pnext)
14784 return GetBlockTime();
14785 pindex = pindex->pnext;
14786 }
14787 return pindex->GetMedianTimePast();
14788 }
14789
14790
14791
14792 std::string ToString() const
14793 {
14794 return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, merkle=%s, hashBlock=%s)",
14795 pprev, pnext, nFile, nBlockPos, nHeight,
14796 hashMerkleRoot.ToString().substr(0,10).c_str(),
14797 GetBlockHash().ToString().substr(0,20).c_str());
14798 }
14799
14800 void print() const
14801 {
14802 printf("%s\n", ToString().c_str());
14803 }
14804 };
14805
14806
14807
14808 //
14809 // Used to marshal pointers into hashes for db storage.
14810 //
14811 class CDiskBlockIndex : public CBlockIndex
14812 {
14813 public:
14814 uint256 hashPrev;
14815 uint256 hashNext;
14816
14817 CDiskBlockIndex()
14818 {
14819 hashPrev = 0;
14820 hashNext = 0;
14821 }
14822
14823 explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex)
14824 {
14825 hashPrev = (pprev ? pprev->GetBlockHash() : 0);
14826 hashNext = (pnext ? pnext->GetBlockHash() : 0);
14827 }
14828
14829 IMPLEMENT_SERIALIZE
14830 (
14831 if (!(nType & SER_GETHASH))
14832 READWRITE(nVersion);
14833
14834 READWRITE(hashNext);
14835 READWRITE(nFile);
14836 READWRITE(nBlockPos);
14837 READWRITE(nHeight);
14838
14839 // block header
14840 READWRITE(this->nVersion);
14841 READWRITE(hashPrev);
14842 READWRITE(hashMerkleRoot);
14843 READWRITE(nTime);
14844 READWRITE(nBits);
14845 READWRITE(nNonce);
14846 )
14847
14848 uint256 GetBlockHash() const
14849 {
14850 CBlock block;
14851 block.nVersion = nVersion;
14852 block.hashPrevBlock = hashPrev;
14853 block.hashMerkleRoot = hashMerkleRoot;
14854 block.nTime = nTime;
14855 block.nBits = nBits;
14856 block.nNonce = nNonce;
14857 return block.GetHash();
14858 }
14859
14860
14861 std::string ToString() const
14862 {
14863 std::string str = "CDiskBlockIndex(";
14864 str += CBlockIndex::ToString();
14865 str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)",
14866 GetBlockHash().ToString().c_str(),
14867 hashPrev.ToString().substr(0,20).c_str(),
14868 hashNext.ToString().substr(0,20).c_str());
14869 return str;
14870 }
14871
14872 void print() const
14873 {
14874 printf("%s\n", ToString().c_str());
14875 }
14876 };
14877
14878
14879
14880
14881
14882
14883
14884
14885 //
14886 // Describes a place in the block chain to another node such that if the
14887 // other node doesn't have the same branch, it can find a recent common trunk.
14888 // The further back it is, the further before the fork it may be.
14889 //
14890 class CBlockLocator
14891 {
14892 protected:
14893 std::vector<uint256> vHave;
14894 public:
14895
14896 CBlockLocator()
14897 {
14898 }
14899
14900 explicit CBlockLocator(const CBlockIndex* pindex)
14901 {
14902 Set(pindex);
14903 }
14904
14905 explicit CBlockLocator(uint256 hashBlock)
14906 {
14907 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hashBlock);
14908 if (mi != mapBlockIndex.end())
14909 Set((*mi).second);
14910 }
14911
14912 IMPLEMENT_SERIALIZE
14913 (
14914 if (!(nType & SER_GETHASH))
14915 READWRITE(nVersion);
14916 READWRITE(vHave);
14917 )
14918
14919 void SetNull()
14920 {
14921 vHave.clear();
14922 }
14923
14924 bool IsNull()
14925 {
14926 return vHave.empty();
14927 }
14928
14929 void Set(const CBlockIndex* pindex)
14930 {
14931 vHave.clear();
14932 int nStep = 1;
14933 while (pindex)
14934 {
14935 vHave.push_back(pindex->GetBlockHash());
14936
14937 // Exponentially larger steps back
14938 for (int i = 0; pindex && i < nStep; i++)
14939 pindex = pindex->pprev;
14940 if (vHave.size() > 10)
14941 nStep *= 2;
14942 }
14943 vHave.push_back(hashGenesisBlock);
14944 }
14945
14946 int GetDistanceBack()
14947 {
14948 // Retrace how far back it was in the sender's branch
14949 int nDistance = 0;
14950 int nStep = 1;
14951 BOOST_FOREACH(const uint256& hash, vHave)
14952 {
14953 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
14954 if (mi != mapBlockIndex.end())
14955 {
14956 CBlockIndex* pindex = (*mi).second;
14957 if (pindex->IsInMainChain())
14958 return nDistance;
14959 }
14960 nDistance += nStep;
14961 if (nDistance > 10)
14962 nStep *= 2;
14963 }
14964 return nDistance;
14965 }
14966
14967 CBlockIndex* GetBlockIndex()
14968 {
14969 // Find the first block the caller has in the main chain
14970 BOOST_FOREACH(const uint256& hash, vHave)
14971 {
14972 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
14973 if (mi != mapBlockIndex.end())
14974 {
14975 CBlockIndex* pindex = (*mi).second;
14976 if (pindex->IsInMainChain())
14977 return pindex;
14978 }
14979 }
14980 return pindexGenesisBlock;
14981 }
14982
14983 uint256 GetBlockHash()
14984 {
14985 // Find the first block the caller has in the main chain
14986 BOOST_FOREACH(const uint256& hash, vHave)
14987 {
14988 std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(hash);
14989 if (mi != mapBlockIndex.end())
14990 {
14991 CBlockIndex* pindex = (*mi).second;
14992 if (pindex->IsInMainChain())
14993 return hash;
14994 }
14995 }
14996 return hashGenesisBlock;
14997 }
14998
14999 int GetHeight()
15000 {
15001 CBlockIndex* pindex = GetBlockIndex();
15002 if (!pindex)
15003 return 0;
15004 return pindex->nHeight;
15005 }
15006 };
15007
15008
15009
15010
15011
15012
15013
15014
15015
15016 //
15017 // Alerts are for notifying old versions if they become too obsolete and
15018 // need to upgrade. The message is displayed in the status bar.
15019 // Alert messages are broadcast as a vector of signed data. Unserializing may
15020 // not read the entire buffer if the alert is for a newer version, but older
15021 // versions can still relay the original data.
15022 //
15023 class CUnsignedAlert
15024 {
15025 public:
15026 int nVersion;
15027 int64 nRelayUntil; // when newer nodes stop relaying to newer nodes
15028 int64 nExpiration;
15029 int nID;
15030 int nCancel;
15031 std::set<int> setCancel;
15032 int nMinVer; // lowest version inclusive
15033 int nMaxVer; // highest version inclusive
15034 std::set<std::string> setSubVer; // empty matches all
15035 int nPriority;
15036
15037 // Actions
15038 std::string strComment;
15039 std::string strStatusBar;
15040 std::string strReserved;
15041
15042 IMPLEMENT_SERIALIZE
15043 (
15044 READWRITE(this->nVersion);
15045 nVersion = this->nVersion;
15046 READWRITE(nRelayUntil);
15047 READWRITE(nExpiration);
15048 READWRITE(nID);
15049 READWRITE(nCancel);
15050 READWRITE(setCancel);
15051 READWRITE(nMinVer);
15052 READWRITE(nMaxVer);
15053 READWRITE(setSubVer);
15054 READWRITE(nPriority);
15055
15056 READWRITE(strComment);
15057 READWRITE(strStatusBar);
15058 READWRITE(strReserved);
15059 )
15060
15061 void SetNull()
15062 {
15063 nVersion = 1;
15064 nRelayUntil = 0;
15065 nExpiration = 0;
15066 nID = 0;
15067 nCancel = 0;
15068 setCancel.clear();
15069 nMinVer = 0;
15070 nMaxVer = 0;
15071 setSubVer.clear();
15072 nPriority = 0;
15073
15074 strComment.clear();
15075 strStatusBar.clear();
15076 strReserved.clear();
15077 }
15078
15079 std::string ToString() const
15080 {
15081 std::string strSetCancel;
15082 BOOST_FOREACH(int n, setCancel)
15083 strSetCancel += strprintf("%d ", n);
15084 std::string strSetSubVer;
15085 BOOST_FOREACH(std::string str, setSubVer)
15086 strSetSubVer += "\"" + str + "\" ";
15087 return strprintf(
15088 "CAlert(\n"
15089 " nVersion = %d\n"
15090 " nRelayUntil = %"PRI64d"\n"
15091 " nExpiration = %"PRI64d"\n"
15092 " nID = %d\n"
15093 " nCancel = %d\n"
15094 " setCancel = %s\n"
15095 " nMinVer = %d\n"
15096 " nMaxVer = %d\n"
15097 " setSubVer = %s\n"
15098 " nPriority = %d\n"
15099 " strComment = \"%s\"\n"
15100 " strStatusBar = \"%s\"\n"
15101 ")\n",
15102 nVersion,
15103 nRelayUntil,
15104 nExpiration,
15105 nID,
15106 nCancel,
15107 strSetCancel.c_str(),
15108 nMinVer,
15109 nMaxVer,
15110 strSetSubVer.c_str(),
15111 nPriority,
15112 strComment.c_str(),
15113 strStatusBar.c_str());
15114 }
15115
15116 void print() const
15117 {
15118 printf("%s", ToString().c_str());
15119 }
15120 };
15121
15122 class CAlert : public CUnsignedAlert
15123 {
15124 public:
15125 std::vector<unsigned char> vchMsg;
15126 std::vector<unsigned char> vchSig;
15127
15128 CAlert()
15129 {
15130 SetNull();
15131 }
15132
15133 IMPLEMENT_SERIALIZE
15134 (
15135 READWRITE(vchMsg);
15136 READWRITE(vchSig);
15137 )
15138
15139 void SetNull()
15140 {
15141 CUnsignedAlert::SetNull();
15142 vchMsg.clear();
15143 vchSig.clear();
15144 }
15145
15146 bool IsNull() const
15147 {
15148 return (nExpiration == 0);
15149 }
15150
15151 uint256 GetHash() const
15152 {
15153 return SerializeHash(*this);
15154 }
15155
15156 bool IsInEffect() const
15157 {
15158 return (GetAdjustedTime() < nExpiration);
15159 }
15160
15161 bool Cancels(const CAlert& alert) const
15162 {
15163 if (!IsInEffect())
15164 return false; // this was a no-op before 31403
15165 return (alert.nID <= nCancel || setCancel.count(alert.nID));
15166 }
15167
15168 bool AppliesTo(int nVersion, std::string strSubVerIn) const
15169 {
15170 return (IsInEffect() &&
15171 nMinVer <= nVersion && nVersion <= nMaxVer &&
15172 (setSubVer.empty() || setSubVer.count(strSubVerIn)));
15173 }
15174
15175 bool AppliesToMe() const
15176 {
15177 return AppliesTo(VERSION, ::pszSubVer);
15178 }
15179
15180 bool RelayTo(CNode* pnode) const
15181 {
15182 if (!IsInEffect())
15183 return false;
15184 // returns true if wasn't already contained in the set
15185 if (pnode->setKnown.insert(GetHash()).second)
15186 {
15187 if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
15188 AppliesToMe() ||
15189 GetAdjustedTime() < nRelayUntil)
15190 {
15191 pnode->PushMessage("alert", *this);
15192 return true;
15193 }
15194 }
15195 return false;
15196 }
15197
15198 bool CheckSignature()
15199 {
15200 CKey key;
15201 if (!key.SetPubKey(ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284")))
15202 return error("CAlert::CheckSignature() : SetPubKey failed");
15203 if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
15204 return error("CAlert::CheckSignature() : verify signature failed");
15205
15206 // Now unserialize the data
15207 CDataStream sMsg(vchMsg);
15208 sMsg >> *(CUnsignedAlert*)this;
15209 return true;
15210 }
15211
15212 bool ProcessAlert();
15213 };
15214
15215 #endif