X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.h;h=84f93f7c9fef1413c658fd0caf27976cef1f9593;hb=8d43f1482a14263a76c039c227c4383580dcc1db;hp=56ce0e4c11aed3f2c18c3b4e0f89e9d3ecbe9b96;hpb=3176e0f244d929669aa3e1d81e0787d82d9150d3;p=novacoin.git diff --git a/src/main.h b/src/main.h index 56ce0e4..84f93f7 100644 --- a/src/main.h +++ b/src/main.h @@ -1,19 +1,17 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2012 The Bitcoin developers -// Copyright (c) 2011-2013 The PPCoin developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef BITCOIN_MAIN_H #define BITCOIN_MAIN_H +#include "timestamps.h" #include "bignum.h" +#include "sync.h" #include "net.h" #include "script.h" -#include "scrypt_mine.h" - -#ifdef WIN32 -#include /* for _commit */ -#endif +#include "scrypt.h" +#include "zerocoin/Zerocoin.h" #include @@ -33,18 +31,19 @@ static const unsigned int MAX_BLOCK_SIZE = 1000000; static const unsigned int MAX_BLOCK_SIZE_GEN = MAX_BLOCK_SIZE/2; static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; static const unsigned int MAX_ORPHAN_TRANSACTIONS = MAX_BLOCK_SIZE/100; -static const int64 MIN_TX_FEE = CENT; -static const int64 MIN_RELAY_TX_FEE = CENT; +static const unsigned int MAX_INV_SZ = 50000; + +static const int64 MIN_TX_FEE = CENT/10; +static const int64 MIN_RELAY_TX_FEE = CENT/50; + static const int64 MAX_MONEY = 2000000000 * COIN; static const int64 MAX_MINT_PROOF_OF_WORK = 100 * COIN; -static const int64 MIN_TXOUT_AMOUNT = MIN_TX_FEE; +static const int64 MAX_MINT_PROOF_OF_STAKE = 1 * COIN; +static const int64 MIN_TXOUT_AMOUNT = CENT/100; + inline bool MoneyRange(int64 nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } -static const int COINBASE_MATURITY_PPC = 500; // Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. -static const int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC -static const int STAKE_TARGET_SPACING = 10 * 60; // 10-minute block spacing -static const int STAKE_MIN_AGE = 60 * 60 * 24 * 30; // minimum age for coin age -static const int STAKE_MAX_AGE = 60 * 60 * 24 * 90; // stake age of full weight +static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC #ifdef USE_UPNP static const int fHaveUPnP = true; @@ -52,28 +51,24 @@ static const int fHaveUPnP = true; static const int fHaveUPnP = false; #endif -static const uint256 hashGenesisBlockOfficial("0x00000a060336cbb72fe969666d337b87198b1add2abaa59cca226820b32933a4"); -static const uint256 hashGenesisBlockTestNet("0x00000a060336cbb72fe969666d337b87198b1add2abaa59cca226820b32933a4"); +static const uint256 hashGenesisBlock("0x00000a060336cbb72fe969666d337b87198b1add2abaa59cca226820b32933a4"); +static const uint256 hashGenesisBlockTestNet("0x000c763e402f2436da9ed36c7286f62c3f6e5dbafce9ff289bd43d7459327eb"); -static const int64 nMaxClockDrift = 2 * 60 * 60; // two hours +inline int64 PastDrift(int64 nTime) { return nTime - 2 * 60 * 60; } // up to 2 hours from the past +inline int64 FutureDrift(int64 nTime) { return nTime + 2 * 60 * 60; } // up to 2 hours from the future +extern libzerocoin::Params* ZCParams; extern CScript COINBASE_FLAGS; - - - - - - extern CCriticalSection cs_main; extern std::map mapBlockIndex; extern std::set > setStakeSeen; -extern uint256 hashGenesisBlock; +extern CBlockIndex* pindexGenesisBlock; extern unsigned int nStakeMinAge; +extern unsigned int nNodeLifespan; extern int nCoinbaseMaturity; -extern CBlockIndex* pindexGenesisBlock; extern int nBestHeight; -extern CBigNum bnBestChainTrust; -extern CBigNum bnBestInvalidTrust; +extern uint256 nBestChainTrust; +extern uint256 nBestInvalidTrust; extern uint256 hashBestChain; extern CBlockIndex* pindexBest; extern unsigned int nTransactionsUpdated; @@ -81,19 +76,22 @@ extern uint64 nLastBlockTx; extern uint64 nLastBlockSize; extern int64 nLastCoinStakeSearchInterval; extern const std::string strMessageMagic; -extern double dHashesPerSec; -extern int64 nHPSTimerStart; extern int64 nTimeBestReceived; extern CCriticalSection cs_setpwalletRegistered; extern std::set setpwalletRegistered; +extern unsigned char pchMessageStart[4]; extern std::map mapOrphanBlocks; // Settings extern int64 nTransactionFee; +extern int64 nMinimumInputValue; +extern bool fUseFastIndex; +extern unsigned int nDerivationMethodIndex; +extern bool fEnforceCanonical; - - +// Minimum disk space required - used in CheckDiskSpace() +static const uint64 nMinDiskSpace = 52428800; class CReserveKey; class CTxDB; @@ -101,30 +99,32 @@ class CTxIndex; void RegisterWallet(CWallet* pwalletIn); void UnregisterWallet(CWallet* pwalletIn); +void SyncWithWallets(const CTransaction& tx, const CBlock* pblock = NULL, bool fUpdate = false, bool fConnect = true); bool ProcessBlock(CNode* pfrom, CBlock* pblock); bool CheckDiskSpace(uint64 nAdditionalBytes=0); FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); FILE* AppendBlockFile(unsigned int& nFileRet); bool LoadBlockIndex(bool fAllowNew=true); void PrintBlockTree(); +CBlockIndex* FindBlockByHeight(int nHeight); bool ProcessMessages(CNode* pfrom); bool SendMessages(CNode* pto, bool fSendTrickle); -void GenerateBitcoins(bool fGenerate, CWallet* pwallet); -CBlock* CreateNewBlock(CWallet* pwallet, bool fProofOfStake=false); -void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& nExtraNonce); -void FormatHashBuffers(CBlock* pblock, char* pmidstate, char* pdata, char* phash1); -bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey); +bool LoadExternalBlockFile(FILE* fileIn); + bool CheckProofOfWork(uint256 hash, unsigned int nBits); -int64 GetProofOfWorkReward(unsigned int nBits); -int64 GetProofOfStakeReward(int64 nCoinAge); +unsigned int GetNextTargetRequired(const CBlockIndex* pindexLast, bool fProofOfStake); +int64 GetProofOfWorkReward(unsigned int nBits, int64 nFees=0); +int64 GetProofOfStakeReward(int64 nCoinAge, unsigned int nBits, unsigned int nTime, bool bCoinYearOnly=false); unsigned int ComputeMinWork(unsigned int nBase, int64 nTime); +unsigned int ComputeMinStake(unsigned int nBase, int64 nTime, unsigned int nBlockTime); int GetNumBlocksOfPeers(); bool IsInitialBlockDownload(); std::string GetWarnings(std::string strFor); +bool GetTransaction(const uint256 &hash, CTransaction &tx, uint256 &hashBlock); uint256 WantedByOrphan(const CBlock* pblockOrphan); const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake); -void BitcoinMiner(CWallet *pwallet, bool fProofOfStake); - +void StakeMiner(CWallet *pwallet); +void ResendWalletTransactions(); @@ -158,8 +158,8 @@ public: } IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) - void SetNull() { nFile = -1; nBlockPos = 0; nTxPos = 0; } - bool IsNull() const { return (nFile == -1); } + void SetNull() { nFile = (unsigned int) -1; nBlockPos = 0; nTxPos = 0; } + bool IsNull() const { return (nFile == (unsigned int) -1); } friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b) { @@ -173,12 +173,13 @@ public: return !(a == b); } + std::string ToString() const { if (IsNull()) return "null"; else - return strprintf("(nFile=%d, nBlockPos=%d, nTxPos=%d)", nFile, nBlockPos, nTxPos); + return strprintf("(nFile=%u, nBlockPos=%u, nTxPos=%u)", nFile, nBlockPos, nTxPos); } void print() const @@ -198,8 +199,8 @@ public: CInPoint() { SetNull(); } CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; } - void SetNull() { ptx = NULL; n = -1; } - bool IsNull() const { return (ptx == NULL && n == -1); } + void SetNull() { ptx = NULL; n = (unsigned int) -1; } + bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); } }; @@ -214,8 +215,8 @@ public: COutPoint() { SetNull(); } COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; } IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) - void SetNull() { hash = 0; n = -1; } - bool IsNull() const { return (hash == 0 && n == -1); } + void SetNull() { hash = 0; n = (unsigned int) -1; } + bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); } friend bool operator<(const COutPoint& a, const COutPoint& b) { @@ -234,7 +235,7 @@ public: std::string ToString() const { - return strprintf("COutPoint(%s, %d)", hash.ToString().substr(0,10).c_str(), n); + return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n); } void print() const @@ -430,6 +431,7 @@ typedef std::map > MapPrevTx; class CTransaction { public: + static const int CURRENT_VERSION=1; int nVersion; unsigned int nTime; std::vector vin; @@ -457,7 +459,7 @@ public: void SetNull() { - nVersion = 1; + nVersion = CTransaction::CURRENT_VERSION; nTime = GetAdjustedTime(); vin.clear(); vout.clear(); @@ -590,53 +592,7 @@ public: return dPriority > COIN * 144 / 250; } - int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=false, enum GetMinFee_mode mode=GMF_BLOCK) const - { - // Base fee is either MIN_TX_FEE or MIN_RELAY_TX_FEE - int64 nBaseFee = (mode == GMF_RELAY) ? MIN_RELAY_TX_FEE : MIN_TX_FEE; - - unsigned int nBytes = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION); - unsigned int nNewBlockSize = nBlockSize + nBytes; - int64 nMinFee = (1 + (int64)nBytes / 1000) * nBaseFee; - - if (fAllowFree) - { - if (nBlockSize == 1) - { - // Transactions under 10K are free - // (about 4500bc if made of 50bc inputs) - if (nBytes < 10000) - nMinFee = 0; - } - else - { - // Free transaction area - if (nNewBlockSize < 27000) - nMinFee = 0; - } - } - - // To limit dust spam, require MIN_TX_FEE/MIN_RELAY_TX_FEE if any output is less than 0.01 - if (nMinFee < nBaseFee) - { - BOOST_FOREACH(const CTxOut& txout, vout) - if (txout.nValue < CENT) - nMinFee = nBaseFee; - } - - // Raise the price as the block approaches full - if (nBlockSize != 1 && nNewBlockSize >= MAX_BLOCK_SIZE_GEN/2) - { - if (nNewBlockSize >= MAX_BLOCK_SIZE_GEN) - return MAX_MONEY; - nMinFee *= MAX_BLOCK_SIZE_GEN / (MAX_BLOCK_SIZE_GEN - nNewBlockSize); - } - - if (!MoneyRange(nMinFee)) - nMinFee = MAX_MONEY; - return nMinFee; - } - + int64 GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=false, enum GetMinFee_mode mode=GMF_BLOCK, unsigned int nBytes = 0) const; bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL) { @@ -679,7 +635,6 @@ public: return !(a == b); } - std::string ToStringShort() const { std::string str; @@ -691,7 +646,7 @@ public: { std::string str; str += IsCoinBase()? "Coinbase" : (IsCoinStake()? "Coinstake" : "CTransaction"); - str += strprintf("(hash=%s, nTime=%d, ver=%d, vin.size=%d, vout.size=%d, nLockTime=%d)\n", + str += strprintf("(hash=%s, nTime=%d, ver=%d, vin.size=%"PRIszu", vout.size=%"PRIszu", nLockTime=%d)\n", GetHash().ToString().substr(0,10).c_str(), nTime, nVersion, @@ -860,7 +815,7 @@ public: return !(a == b); } int GetDepthInMainChain() const; - + }; @@ -881,6 +836,7 @@ class CBlock { public: // header + static const int CURRENT_VERSION=6; int nVersion; uint256 hashPrevBlock; uint256 hashMerkleRoot; @@ -931,7 +887,7 @@ public: void SetNull() { - nVersion = 2; + nVersion = CBlock::CURRENT_VERSION; hashPrevBlock = 0; hashMerkleRoot = 0; nTime = 0; @@ -950,17 +906,9 @@ public: uint256 GetHash() const { - uint256 thash; - void * scratchbuff = scrypt_buffer_alloc(); - - scrypt_hash(CVOIDBEGIN(nVersion), sizeof(block_header), UINTBEGIN(thash), scratchbuff); - - scrypt_buffer_free(scratchbuff); - - return thash; + return scrypt_blockhash(CVOIDBEGIN(nVersion)); } - int64 GetBlockTime() const { return (int64)nTime; @@ -969,14 +917,24 @@ public: void UpdateTime(const CBlockIndex* pindexPrev); // ppcoin: entropy bit for stake modifier if chosen by modifier - unsigned int GetStakeEntropyBit() const + unsigned int GetStakeEntropyBit(unsigned int nTime) const { + // Protocol switch to support p2pool at novacoin block #9689 + if (nTime >= ENTROPY_SWITCH_TIME || fTestNet) + { + // Take last bit of block hash as entropy bit + unsigned int nEntropyBit = ((GetHash().Get64()) & 1llu); + if (fDebug && GetBoolArg("-printstakemodifier")) + printf("GetStakeEntropyBit: nTime=%u hashBlock=%s nEntropyBit=%u\n", nTime, GetHash().ToString().c_str(), nEntropyBit); + return nEntropyBit; + } + // Before novacoin block #9689 - old protocol uint160 hashSig = Hash160(vchBlockSig); if (fDebug && GetBoolArg("-printstakemodifier")) printf("GetStakeEntropyBit: hashSig=%s", hashSig.ToString().c_str()); hashSig >>= 159; // take the first bit of the hash if (fDebug && GetBoolArg("-printstakemodifier")) - printf(" entropybit=%d\n", hashSig.Get64()); + printf(" entropybit=%"PRI64d"\n", hashSig.Get64()); return hashSig.Get64(); } @@ -1064,8 +1022,6 @@ public: return error("CBlock::WriteToDisk() : AppendBlockFile failed"); // Write index header - unsigned char pchMessageStart[4]; - GetMessageStart(pchMessageStart, true); unsigned int nSize = fileout.GetSerializeSize(*this); fileout << FLATDATA(pchMessageStart) << nSize; @@ -1079,13 +1035,7 @@ public: // Flush stdio buffers and commit to disk before returning fflush(fileout); if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0) - { -#ifdef WIN32 - _commit(_fileno(fileout)); -#else - fsync(fileno(fileout)); -#endif - } + FileCommit(fileout); return true; } @@ -1120,11 +1070,11 @@ public: void print() const { - printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%d, vchBlockSig=%s)\n", - GetHash().ToString().substr(0,20).c_str(), + printf("CBlock(hash=%s, ver=%d, hashPrevBlock=%s, hashMerkleRoot=%s, nTime=%u, nBits=%08x, nNonce=%u, vtx=%"PRIszu", vchBlockSig=%s)\n", + GetHash().ToString().c_str(), nVersion, - hashPrevBlock.ToString().substr(0,20).c_str(), - hashMerkleRoot.ToString().substr(0,10).c_str(), + hashPrevBlock.ToString().c_str(), + hashMerkleRoot.ToString().c_str(), nTime, nBits, nNonce, vtx.size(), HexStr(vchBlockSig.begin(), vchBlockSig.end()).c_str()); @@ -1141,15 +1091,15 @@ public: bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex); - bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex); + bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck=false); bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true); bool SetBestChain(CTxDB& txdb, CBlockIndex* pindexNew); bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos); - bool CheckBlock() const; + bool CheckBlock(bool fCheckPOW=true, bool fCheckMerkleRoot=true, bool fCheckSig=true) const; bool AcceptBlock(); bool GetCoinAge(uint64& nCoinAge) const; // ppcoin: calculate total coin age spent in block - bool SignBlock(const CKeyStore& keystore); - bool CheckBlockSignature() const; + bool SignBlock(CWallet& keystore); + bool CheckBlockSignature(bool fProofOfStake) const; private: bool SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew); @@ -1175,8 +1125,9 @@ public: CBlockIndex* pnext; unsigned int nFile; unsigned int nBlockPos; - CBigNum bnChainTrust; // ppcoin: trust score of block chain + uint256 nChainTrust; // ppcoin: trust score of block chain int nHeight; + int64 nMint; int64 nMoneySupply; @@ -1203,7 +1154,6 @@ public: unsigned int nBits; unsigned int nNonce; - CBlockIndex() { phashBlock = NULL; @@ -1212,7 +1162,7 @@ public: nFile = 0; nBlockPos = 0; nHeight = 0; - bnChainTrust = 0; + nChainTrust = 0; nMint = 0; nMoneySupply = 0; nFlags = 0; @@ -1237,7 +1187,7 @@ public: nFile = nFileIn; nBlockPos = nBlockPosIn; nHeight = 0; - bnChainTrust = 0; + nChainTrust = 0; nMint = 0; nMoneySupply = 0; nFlags = 0; @@ -1286,14 +1236,7 @@ public: return (int64)nTime; } - CBigNum GetBlockTrust() const - { - CBigNum bnTarget; - bnTarget.SetCompact(nBits); - if (bnTarget <= 0) - return 0; - return (IsProofOfStake()? (CBigNum(1)<<256) / (bnTarget+1) : 1); - } + uint256 GetBlockTrust() const; bool IsInMainChain() const { @@ -1305,21 +1248,6 @@ public: return true; } - bool EraseBlockFromDisk() - { - // Open history file - CAutoFile fileout = CAutoFile(OpenBlockFile(nFile, nBlockPos, "rb+"), SER_DISK, CLIENT_VERSION); - if (!fileout) - return false; - - // Overwrite with empty null block - CBlock block; - block.SetNull(); - fileout << block; - - return true; - } - enum { nMedianTimeSpan=11 }; int64 GetMedianTimePast() const @@ -1348,6 +1276,14 @@ public: return pindex->GetMedianTimePast(); } + /** + * Returns true if there are nRequired or more blocks of minVersion or above + * in the last nToCheck blocks, starting at pstart and going backwards. + */ + static bool IsSuperMajority(int minVersion, const CBlockIndex* pstart, + unsigned int nRequired, unsigned int nToCheck); + + bool IsProofOfWork() const { return !(nFlags & BLOCK_PROOF_OF_STAKE); @@ -1390,15 +1326,15 @@ public: std::string ToString() const { - return strprintf("CBlockIndex(nprev=%08x, pnext=%08x, nFile=%d, nBlockPos=%-6d nHeight=%d, nMint=%s, nMoneySupply=%s, nFlags=(%s)(%d)(%s), nStakeModifier=%016"PRI64x", nStakeModifierChecksum=%08x, hashProofOfStake=%s, prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", + return strprintf("CBlockIndex(nprev=%p, pnext=%p, nFile=%u, nBlockPos=%-6d nHeight=%d, nMint=%s, nMoneySupply=%s, nFlags=(%s)(%d)(%s), nStakeModifier=%016"PRI64x", nStakeModifierChecksum=%08x, hashProofOfStake=%s, prevoutStake=(%s), nStakeTime=%d merkle=%s, hashBlock=%s)", pprev, pnext, nFile, nBlockPos, nHeight, FormatMoney(nMint).c_str(), FormatMoney(nMoneySupply).c_str(), GeneratedStakeModifier() ? "MOD" : "-", GetStakeEntropyBit(), IsProofOfStake()? "PoS" : "PoW", nStakeModifier, nStakeModifierChecksum, hashProofOfStake.ToString().c_str(), prevoutStake.ToString().c_str(), nStakeTime, - hashMerkleRoot.ToString().substr(0,10).c_str(), - GetBlockHash().ToString().substr(0,20).c_str()); + hashMerkleRoot.ToString().c_str(), + GetBlockHash().ToString().c_str()); } void print() const @@ -1412,6 +1348,9 @@ public: /** Used to marshal pointers into hashes for db storage. */ class CDiskBlockIndex : public CBlockIndex { +private: + uint256 blockHash; + public: uint256 hashPrev; uint256 hashNext; @@ -1420,6 +1359,7 @@ public: { hashPrev = 0; hashNext = 0; + blockHash = 0; } explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex) @@ -1461,10 +1401,14 @@ public: READWRITE(nTime); READWRITE(nBits); READWRITE(nNonce); + READWRITE(blockHash); ) uint256 GetBlockHash() const { + if (fUseFastIndex && (nTime < GetAdjustedTime() - 24 * 60 * 60) && blockHash != 0) + return blockHash; + CBlock block; block.nVersion = nVersion; block.hashPrevBlock = hashPrev; @@ -1472,9 +1416,11 @@ public: block.nTime = nTime; block.nBits = nBits; block.nNonce = nNonce; - return block.GetHash(); - } + const_cast(this)->blockHash = block.GetHash(); + + return blockHash; + } std::string ToString() const { @@ -1482,8 +1428,8 @@ public: str += CBlockIndex::ToString(); str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)", GetBlockHash().ToString().c_str(), - hashPrev.ToString().substr(0,20).c_str(), - hashNext.ToString().substr(0,20).c_str()); + hashPrev.ToString().c_str(), + hashNext.ToString().c_str()); return str; } @@ -1562,7 +1508,7 @@ public: if (vHave.size() > 10) nStep *= 2; } - vHave.push_back(hashGenesisBlock); + vHave.push_back((!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)); } int GetDistanceBack() @@ -1615,7 +1561,7 @@ public: return hash; } } - return hashGenesisBlock; + return (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet); } int GetHeight() @@ -1634,207 +1580,6 @@ public: - -/** Alerts are for notifying old versions if they become too obsolete and - * need to upgrade. The message is displayed in the status bar. - * Alert messages are broadcast as a vector of signed data. Unserializing may - * not read the entire buffer if the alert is for a newer version, but older - * versions can still relay the original data. - */ -class CUnsignedAlert -{ -public: - int nVersion; - int64 nRelayUntil; // when newer nodes stop relaying to newer nodes - int64 nExpiration; - int nID; - int nCancel; - std::set setCancel; - int nMinVer; // lowest version inclusive - int nMaxVer; // highest version inclusive - std::set setSubVer; // empty matches all - int nPriority; - - // Actions - std::string strComment; - std::string strStatusBar; - std::string strReserved; - - IMPLEMENT_SERIALIZE - ( - READWRITE(this->nVersion); - nVersion = this->nVersion; - READWRITE(nRelayUntil); - READWRITE(nExpiration); - READWRITE(nID); - READWRITE(nCancel); - READWRITE(setCancel); - READWRITE(nMinVer); - READWRITE(nMaxVer); - READWRITE(setSubVer); - READWRITE(nPriority); - - READWRITE(strComment); - READWRITE(strStatusBar); - READWRITE(strReserved); - ) - - void SetNull() - { - nVersion = 1; - nRelayUntil = 0; - nExpiration = 0; - nID = 0; - nCancel = 0; - setCancel.clear(); - nMinVer = 0; - nMaxVer = 0; - setSubVer.clear(); - nPriority = 0; - - strComment.clear(); - strStatusBar.clear(); - strReserved.clear(); - } - - std::string ToString() const - { - std::string strSetCancel; - BOOST_FOREACH(int n, setCancel) - strSetCancel += strprintf("%d ", n); - std::string strSetSubVer; - BOOST_FOREACH(std::string str, setSubVer) - strSetSubVer += "\"" + str + "\" "; - return strprintf( - "CAlert(\n" - " nVersion = %d\n" - " nRelayUntil = %"PRI64d"\n" - " nExpiration = %"PRI64d"\n" - " nID = %d\n" - " nCancel = %d\n" - " setCancel = %s\n" - " nMinVer = %d\n" - " nMaxVer = %d\n" - " setSubVer = %s\n" - " nPriority = %d\n" - " strComment = \"%s\"\n" - " strStatusBar = \"%s\"\n" - ")\n", - nVersion, - nRelayUntil, - nExpiration, - nID, - nCancel, - strSetCancel.c_str(), - nMinVer, - nMaxVer, - strSetSubVer.c_str(), - nPriority, - strComment.c_str(), - strStatusBar.c_str()); - } - - void print() const - { - printf("%s", ToString().c_str()); - } -}; - -/** An alert is a combination of a serialized CUnsignedAlert and a signature. */ -class CAlert : public CUnsignedAlert -{ -public: - std::vector vchMsg; - std::vector vchSig; - - CAlert() - { - SetNull(); - } - - IMPLEMENT_SERIALIZE - ( - READWRITE(vchMsg); - READWRITE(vchSig); - ) - - void SetNull() - { - CUnsignedAlert::SetNull(); - vchMsg.clear(); - vchSig.clear(); - } - - bool IsNull() const - { - return (nExpiration == 0); - } - - uint256 GetHash() const - { - return SerializeHash(*this); - } - - bool IsInEffect() const - { - return (GetAdjustedTime() < nExpiration); - } - - bool Cancels(const CAlert& alert) const - { - if (!IsInEffect()) - return false; // this was a no-op before 31403 - return (alert.nID <= nCancel || setCancel.count(alert.nID)); - } - - bool AppliesTo(int nVersion, std::string strSubVerIn) const - { - // TODO: rework for client-version-embedded-in-strSubVer ? - return (IsInEffect() && - nMinVer <= nVersion && nVersion <= nMaxVer && - (setSubVer.empty() || setSubVer.count(strSubVerIn))); - } - - bool AppliesToMe() const - { - return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector())); - } - - bool RelayTo(CNode* pnode) const - { - if (!IsInEffect()) - return false; - // returns true if wasn't already contained in the set - if (pnode->setKnown.insert(GetHash()).second) - { - if (AppliesTo(pnode->nVersion, pnode->strSubVer) || - AppliesToMe() || - GetAdjustedTime() < nRelayUntil) - { - pnode->PushMessage("alert", *this); - return true; - } - } - return false; - } - - bool CheckSignature() - { - CKey key; - if (!key.SetPubKey(ParseHex("043fa441fd4203d03f5df2b75ea14e36f20d39f43e7a61aa7552ab9bcd7ecb0e77a3be4585b13fcdaa22ef6e51f1ff6f2929bec2494385b086fb86610e33193195"))) - return error("CAlert::CheckSignature() : SetPubKey failed"); - if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) - return error("CAlert::CheckSignature() : verify signature failed"); - - // Now unserialize the data - CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION); - sMsg >> *(CUnsignedAlert*)this; - return true; - } - - bool ProcessAlert(); -}; - class CTxMemPool { public: @@ -1844,8 +1589,10 @@ public: bool accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs, bool* pfMissingInputs); - bool addUnchecked(CTransaction &tx); + bool addUnchecked(const uint256& hash, CTransaction &tx); bool remove(CTransaction &tx); + void clear(); + void queryHashes(std::vector& vtxid); unsigned long size() {