X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fmain.h;h=58596dcfbff5bfd80d884c2227b521f7858ded2d;hb=299b11aaf81f7559b7870cb6aedc8b094f740004;hp=7497bfa898d23416fe6a2418fe644fde59f16448;hpb=9a452adf035d90d341142ed0a164b4e716cdbe84;p=novacoin.git diff --git a/src/main.h b/src/main.h index 7497bfa..58596dc 100644 --- a/src/main.h +++ b/src/main.h @@ -5,15 +5,20 @@ #ifndef BITCOIN_MAIN_H #define BITCOIN_MAIN_H +#include + #include "timestamps.h" #include "bignum.h" #include "sync.h" #include "net.h" #include "script.h" #include "scrypt.h" -#include "zerocoin/Zerocoin.h" +#include "ui_interface.h" +#include #include +#include + class CWallet; class CBlock; @@ -27,43 +32,43 @@ class CInv; class CRequestTracker; class CNode; +// +// Global state +// + 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 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_t MIN_TX_FEE = CENT/10; +static const int64_t MIN_RELAY_TX_FEE = CENT/50; + +static const int64_t MAX_MONEY = std::numeric_limits::max(); +static const int64_t MAX_MINT_PROOF_OF_WORK = 100 * COIN; +static const int64_t MAX_MINT_PROOF_OF_STAKE = 1 * COIN; +static const int64_t MIN_TXOUT_AMOUNT = CENT/100; -static const int64 MAX_MONEY = 2000000000 * COIN; -static const int64 MAX_MINT_PROOF_OF_WORK = 100 * COIN; -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); } +inline bool MoneyRange(int64_t nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } +inline bool MoneyRange(CBigNum nValue) { return (nValue >= 0 && nValue <= MAX_MONEY); } // Threshold for nLockTime: below this value it is interpreted as block number, otherwise as UNIX timestamp. static const unsigned int LOCKTIME_THRESHOLD = 500000000; // Tue Nov 5 00:53:20 1985 UTC - -#ifdef USE_UPNP -static const int fHaveUPnP = true; -#else -static const int fHaveUPnP = false; -#endif +// Maximum number of script-checking threads allowed +static const int MAX_SCRIPTCHECK_THREADS = 16; static const uint256 hashGenesisBlock("0x00000a060336cbb72fe969666d337b87198b1add2abaa59cca226820b32933a4"); static const uint256 hashGenesisBlockTestNet("0x000c763e402f2436da9ed36c7286f62c3f6e5dbafce9ff289bd43d7459327eb"); -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 +inline int64_t PastDrift(int64_t nTime) { return nTime - 2 * nOneHour; } // up to 2 hours from the past +inline int64_t FutureDrift(int64_t nTime) { return nTime + 2 * nOneHour; } // 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 CBlockIndex* pindexGenesisBlock; -extern unsigned int nStakeMinAge; extern unsigned int nNodeLifespan; extern int nCoinbaseMaturity; extern int nBestHeight; @@ -72,92 +77,87 @@ extern uint256 nBestInvalidTrust; extern uint256 hashBestChain; extern CBlockIndex* pindexBest; extern unsigned int nTransactionsUpdated; -extern uint64 nLastBlockTx; -extern uint64 nLastBlockSize; -extern int64 nLastCoinStakeSearchInterval; +extern uint64_t nLastBlockTx; +extern uint64_t nLastBlockSize; +extern uint32_t nLastCoinStakeSearchInterval; extern const std::string strMessageMagic; -extern int64 nTimeBestReceived; +extern int64_t nTimeBestReceived; extern CCriticalSection cs_setpwalletRegistered; extern std::set setpwalletRegistered; -extern unsigned char pchMessageStart[4]; +extern uint32_t nNetworkID; extern std::map mapOrphanBlocks; // Settings -extern int64 nTransactionFee; -extern int64 nMinimumInputValue; +extern int64_t nTransactionFee; +extern int64_t nMinimumInputValue; extern bool fUseFastIndex; -extern unsigned int nDerivationMethodIndex; +extern int nScriptCheckThreads; +extern const uint256 entropyStore[38]; // Minimum disk space required - used in CheckDiskSpace() -static const uint64 nMinDiskSpace = 52428800; +static const uint64_t nMinDiskSpace = 52428800; class CReserveKey; class CTxDB; class CTxIndex; +class CScriptCheck; 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); +bool CheckDiskSpace(uint64_t nAdditionalBytes=0); FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszMode="rb"); FILE* AppendBlockFile(unsigned int& nFileRet); + +void UnloadBlockIndex(); bool LoadBlockIndex(bool fAllowNew=true); void PrintBlockTree(); CBlockIndex* FindBlockByHeight(int nHeight); bool ProcessMessages(CNode* pfrom); -bool SendMessages(CNode* pto, bool fSendTrickle); -bool LoadExternalBlockFile(FILE* fileIn); +bool SendMessages(CNode* pto); +bool LoadExternalBlockFile(FILE* fileIn, CClientUIInterface& uiInterface); + +// Run an instance of the script checking thread +void ThreadScriptCheck(void* parg); +// Stop the script checking threads +void ThreadScriptCheckQuit(); bool CheckProofOfWork(uint256 hash, unsigned int nBits); 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); +int64_t GetProofOfWorkReward(unsigned int nBits, int64_t nFees=0); +int64_t GetProofOfStakeReward(int64_t nCoinAge, unsigned int nBits, int64_t nTime, bool bCoinYearOnly=false); +unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime); +unsigned int ComputeMinStake(unsigned int nBase, int64_t 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 StakeMiner(CWallet *pwallet); -void ResendWalletTransactions(); - - - - - +void ResendWalletTransactions(bool fForceResend=false); +bool VerifySignature(const CTransaction& txFrom, const CTransaction& txTo, uint32_t nIn, unsigned int flags, int nHashType); bool GetWalletFile(CWallet* pwallet, std::string &strWalletFileOut); -/** Position on disk for a particular transaction. */ +// Position on disk for a particular transaction. class CDiskTxPos { public: - unsigned int nFile; - unsigned int nBlockPos; - unsigned int nTxPos; + uint32_t nFile; + uint32_t nBlockPos; + uint32_t nTxPos; - CDiskTxPos() - { - SetNull(); - } - - CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn) - { - nFile = nFileIn; - nBlockPos = nBlockPosIn; - nTxPos = nTxPosIn; - } + CDiskTxPos() { SetNull(); } + CDiskTxPos(unsigned int nFileIn, unsigned int nBlockPosIn, unsigned int nTxPosIn) : nFile(nFileIn), nBlockPos(nBlockPosIn), nTxPos(nTxPosIn) {} IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) - void SetNull() { nFile = (unsigned int) -1; nBlockPos = 0; nTxPos = 0; } - bool IsNull() const { return (nFile == (unsigned int) -1); } + void SetNull() { nFile = std::numeric_limits::max(); nBlockPos = 0; nTxPos = 0; } + bool IsNull() const { return (nFile == std::numeric_limits::max()); } friend bool operator==(const CDiskTxPos& a, const CDiskTxPos& b) { @@ -177,7 +177,7 @@ public: if (IsNull()) return "null"; else - return strprintf("(nFile=%u, nBlockPos=%u, nTxPos=%u)", nFile, nBlockPos, nTxPos); + return strprintf("(nFile=%" PRIu32 ", nBlockPos=%" PRIu32 ", nTxPos=%" PRIu32 ")", nFile, nBlockPos, nTxPos); } void print() const @@ -188,33 +188,33 @@ public: -/** An inpoint - a combination of a transaction and an index n into its vin */ +// An inpoint - a combination of a transaction and an index n into its vin class CInPoint { public: CTransaction* ptx; - unsigned int n; + uint32_t n; CInPoint() { SetNull(); } - CInPoint(CTransaction* ptxIn, unsigned int nIn) { ptx = ptxIn; n = nIn; } - void SetNull() { ptx = NULL; n = (unsigned int) -1; } - bool IsNull() const { return (ptx == NULL && n == (unsigned int) -1); } + CInPoint(CTransaction* ptxIn, uint32_t nIn) : ptx(ptxIn), n(nIn) {} + void SetNull() { ptx = NULL; n = std::numeric_limits::max(); } + bool IsNull() const { return (ptx == NULL && n == std::numeric_limits::max()); } }; -/** An outpoint - a combination of a transaction hash and an index n into its vout */ +// An outpoint - a combination of a transaction hash and an index n into its vout class COutPoint { public: uint256 hash; - unsigned int n; + uint32_t n; COutPoint() { SetNull(); } - COutPoint(uint256 hashIn, unsigned int nIn) { hash = hashIn; n = nIn; } + COutPoint(uint256 hashIn, uint32_t nIn) : hash(hashIn), n(nIn) {} IMPLEMENT_SERIALIZE( READWRITE(FLATDATA(*this)); ) - void SetNull() { hash = 0; n = (unsigned int) -1; } - bool IsNull() const { return (hash == 0 && n == (unsigned int) -1); } + void SetNull() { hash = 0; n = std::numeric_limits::max(); } + bool IsNull() const { return (hash == 0 && n == std::numeric_limits::max()); } friend bool operator<(const COutPoint& a, const COutPoint& b) { @@ -233,7 +233,7 @@ public: std::string ToString() const { - return strprintf("COutPoint(%s, %u)", hash.ToString().substr(0,10).c_str(), n); + return strprintf("COutPoint(%s, %" PRIu32 ")", hash.ToString().substr(0,10).c_str(), n); } void print() const @@ -244,36 +244,22 @@ public: - -/** An input of a transaction. It contains the location of the previous - * transaction's output that it claims and a signature that matches the - * output's public key. - */ +// An input of a transaction. It contains the location of the previous +// transaction's output that it claims and a signature that matches the +// output's public key. +// class CTxIn { public: COutPoint prevout; CScript scriptSig; - unsigned int nSequence; - - CTxIn() - { - nSequence = std::numeric_limits::max(); - } + uint32_t nSequence; + CTxIn() : nSequence(std::numeric_limits::max()) {} explicit CTxIn(COutPoint prevoutIn, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits::max()) - { - prevout = prevoutIn; - scriptSig = scriptSigIn; - nSequence = nSequenceIn; - } - + : prevout(prevoutIn), scriptSig(scriptSigIn), nSequence(nSequenceIn) {} CTxIn(uint256 hashPrevTx, unsigned int nOut, CScript scriptSigIn=CScript(), unsigned int nSequenceIn=std::numeric_limits::max()) - { - prevout = COutPoint(hashPrevTx, nOut); - scriptSig = scriptSigIn; - nSequence = nSequenceIn; - } + : prevout(COutPoint(hashPrevTx, nOut)), scriptSig(scriptSigIn), nSequence(nSequenceIn) {} IMPLEMENT_SERIALIZE ( @@ -304,20 +290,7 @@ public: return strprintf(" %s %d", prevout.hash.ToString().c_str(), prevout.n); } - std::string ToString() const - { - std::string str; - str += "CTxIn("; - str += prevout.ToString(); - if (prevout.IsNull()) - str += strprintf(", coinbase %s", HexStr(scriptSig).c_str()); - else - str += strprintf(", scriptSig=%s", scriptSig.ToString().substr(0,24).c_str()); - if (nSequence != std::numeric_limits::max()) - str += strprintf(", nSequence=%u", nSequence); - str += ")"; - return str; - } + std::string ToString() const; void print() const { @@ -327,26 +300,17 @@ public: - -/** An output of a transaction. It contains the public key that the next input - * must be able to sign with to claim it. - */ +// An output of a transaction. It contains the public key that the next input +// must be able to sign with to claim it. +// class CTxOut { public: - int64 nValue; + int64_t nValue; CScript scriptPubKey; - CTxOut() - { - SetNull(); - } - - CTxOut(int64 nValueIn, CScript scriptPubKeyIn) - { - nValue = nValueIn; - scriptPubKey = scriptPubKeyIn; - } + CTxOut() { SetNull(); } + CTxOut(int64_t nValueIn, CScript scriptPubKeyIn) : nValue(nValueIn), scriptPubKey(scriptPubKeyIn) {} IMPLEMENT_SERIALIZE ( @@ -418,7 +382,7 @@ enum GetMinFee_mode { GMF_BLOCK, GMF_RELAY, - GMF_SEND, + GMF_SEND }; typedef std::map > MapPrevTx; @@ -431,10 +395,10 @@ class CTransaction public: static const int CURRENT_VERSION=1; int nVersion; - unsigned int nTime; + uint32_t nTime; std::vector vin; std::vector vout; - unsigned int nLockTime; + uint32_t nLockTime; // Denial-of-service detection: mutable int nDoS; @@ -458,7 +422,7 @@ public: void SetNull() { nVersion = CTransaction::CURRENT_VERSION; - nTime = GetAdjustedTime(); + nTime = (uint32_t) GetAdjustedTime(); vin.clear(); vout.clear(); nLockTime = 0; @@ -475,51 +439,8 @@ public: return SerializeHash(*this); } - bool IsFinal(int nBlockHeight=0, int64 nBlockTime=0) const - { - // Time based nLockTime implemented in 0.1.6 - if (nLockTime == 0) - return true; - if (nBlockHeight == 0) - nBlockHeight = nBestHeight; - if (nBlockTime == 0) - nBlockTime = GetAdjustedTime(); - if ((int64)nLockTime < ((int64)nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime)) - return true; - BOOST_FOREACH(const CTxIn& txin, vin) - if (!txin.IsFinal()) - return false; - return true; - } - - bool IsNewerThan(const CTransaction& old) const - { - if (vin.size() != old.vin.size()) - return false; - for (unsigned int i = 0; i < vin.size(); i++) - if (vin[i].prevout != old.vin[i].prevout) - return false; - - bool fNewer = false; - unsigned int nLowest = std::numeric_limits::max(); - for (unsigned int i = 0; i < vin.size(); i++) - { - if (vin[i].nSequence != old.vin[i].nSequence) - { - if (vin[i].nSequence <= nLowest) - { - fNewer = false; - nLowest = vin[i].nSequence; - } - if (old.vin[i].nSequence < nLowest) - { - fNewer = true; - nLowest = old.vin[i].nSequence; - } - } - } - return fNewer; - } + bool IsFinal(int nBlockHeight=0, int64_t nBlockTime=0) const; + bool IsNewerThan(const CTransaction& old) const; bool IsCoinBase() const { @@ -535,7 +456,12 @@ public: /** Check for standard transaction types @return True if all outputs (scriptPubKeys) use only standard transaction forms */ - bool IsStandard() const; + bool IsStandard(std::string& strReason) const; + bool IsStandard() const + { + std::string strReason; + return IsStandard(strReason); + } /** Check for standard transaction types @param[in] mapInputs Map of previous transactions that have outputs we're spending @@ -561,17 +487,7 @@ public: /** Amount of bitcoins spent by this transaction. @return sum of all outputs (note: does not include fees) */ - int64 GetValueOut() const - { - int64 nValueOut = 0; - BOOST_FOREACH(const CTxOut& txout, vout) - { - nValueOut += txout.nValue; - if (!MoneyRange(txout.nValue) || !MoneyRange(nValueOut)) - throw std::runtime_error("CTransaction::GetValueOut() : value out of range"); - } - return nValueOut; - } + int64_t GetValueOut() const; /** Amount of bitcoins coming in to this transaction Note that lightweight clients may not know anything besides the hash of previous transactions, @@ -581,7 +497,7 @@ public: @return Sum of value of all inputs (scriptSigs) @see CTransaction::FetchInputs */ - int64 GetValueIn(const MapPrevTx& mapInputs) const; + int64_t GetValueIn(const MapPrevTx& mapInputs) const; static bool AllowFree(double dPriority) { @@ -590,34 +506,7 @@ public: return dPriority > COIN * 144 / 250; } - 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) - { - CAutoFile filein = CAutoFile(OpenBlockFile(pos.nFile, 0, pfileRet ? "rb+" : "rb"), SER_DISK, CLIENT_VERSION); - if (!filein) - return error("CTransaction::ReadFromDisk() : OpenBlockFile failed"); - - // Read transaction - if (fseek(filein, pos.nTxPos, SEEK_SET) != 0) - return error("CTransaction::ReadFromDisk() : fseek failed"); - - try { - filein >> *this; - } - catch (std::exception &e) { - return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); - } - - // Return file pointer - if (pfileRet) - { - if (fseek(filein, pos.nTxPos, SEEK_SET) != 0) - return error("CTransaction::ReadFromDisk() : second fseek failed"); - *pfileRet = filein.release(); - } - return true; - } + int64_t GetMinFee(unsigned int nBlockSize=1, bool fAllowFree=false, enum GetMinFee_mode mode=GMF_BLOCK, unsigned int nBytes = 0) const; friend bool operator==(const CTransaction& a, const CTransaction& b) { @@ -633,37 +522,15 @@ public: return !(a == b); } - std::string ToStringShort() const - { - std::string str; - str += strprintf("%s %s", GetHash().ToString().c_str(), IsCoinBase()? "base" : (IsCoinStake()? "stake" : "user")); - return str; - } - - std::string ToString() const - { - std::string str; - str += IsCoinBase()? "Coinbase" : (IsCoinStake()? "Coinstake" : "CTransaction"); - 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, - vin.size(), - vout.size(), - nLockTime); - for (unsigned int i = 0; i < vin.size(); i++) - str += " " + vin[i].ToString() + "\n"; - for (unsigned int i = 0; i < vout.size(); i++) - str += " " + vout[i].ToString() + "\n"; - return str; - } + std::string ToStringShort() const; + std::string ToString() const; void print() const { printf("%s", ToString().c_str()); } - + bool ReadFromDisk(CDiskTxPos pos, FILE** pfileRet=NULL); bool ReadFromDisk(CTxDB& txdb, COutPoint prevout, CTxIndex& txindexRet); bool ReadFromDisk(CTxDB& txdb, COutPoint prevout); bool ReadFromDisk(COutPoint prevout); @@ -691,16 +558,18 @@ public: @param[in] pindexBlock @param[in] fBlock true if called from ConnectBlock @param[in] fMiner true if called from CreateNewBlock - @param[in] fStrictPayToScriptHash true if fully validating p2sh transactions + @param[in] fScriptChecks enable scripts validation? + @param[in] flags STRICT_FLAGS script validation flags + @param[in] pvChecks NULL If pvChecks is not NULL, script checks are pushed onto it instead of being performed inline. @return Returns true if all checks succeed */ - bool ConnectInputs(CTxDB& txdb, MapPrevTx inputs, - std::map& mapTestPool, const CDiskTxPos& posThisTx, - const CBlockIndex* pindexBlock, bool fBlock, bool fMiner, bool fStrictPayToScriptHash=true); + bool ConnectInputs(CTxDB& txdb, MapPrevTx inputs, std::map& mapTestPool, const CDiskTxPos& posThisTx, const CBlockIndex* pindexBlock, + bool fBlock, bool fMiner, bool fScriptChecks=true, + unsigned int flags=STRICT_FLAGS, std::vector *pvChecks = NULL); bool ClientConnectInputs(); bool CheckTransaction() const; bool AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs=true, bool* pfMissingInputs=NULL); - bool GetCoinAge(CTxDB& txdb, uint64& nCoinAge) const; // ppcoin: get transaction coin age + bool GetCoinAge(CTxDB& txdb, uint64_t& nCoinAge) const; // ppcoin: get transaction coin age protected: const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const; @@ -709,14 +578,13 @@ protected: - /** A transaction with a merkle branch linking it to the block chain. */ class CMerkleTx : public CTransaction { public: uint256 hashBlock; std::vector vMerkleBranch; - int nIndex; + int32_t nIndex; // memory only mutable bool fMerkleVerified; @@ -817,9 +685,6 @@ public: }; - - - /** Nodes collect new transactions into a block, hash them into a hash tree, * and scan through nonce values to make the block's hash satisfy proof-of-work * requirements. When they solve the proof-of-work, they broadcast the block @@ -835,12 +700,12 @@ class CBlock public: // header static const int CURRENT_VERSION=6; - int nVersion; + int32_t nVersion; uint256 hashPrevBlock; uint256 hashMerkleRoot; - unsigned int nTime; - unsigned int nBits; - unsigned int nNonce; + uint32_t nTime; + uint32_t nBits; + uint32_t nNonce; // network and disk std::vector vtx; @@ -904,37 +769,18 @@ public: uint256 GetHash() const { - return scrypt_blockhash(CVOIDBEGIN(nVersion)); + return scrypt_blockhash((const uint8_t*)&nVersion); } - int64 GetBlockTime() const + int64_t GetBlockTime() const { - return (int64)nTime; + return (int64_t)nTime; } void UpdateTime(const CBlockIndex* pindexPrev); // ppcoin: entropy bit for stake modifier if chosen by modifier - 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=%"PRI64d"\n", hashSig.Get64()); - return hashSig.Get64(); - } + unsigned int GetStakeEntropyBit(unsigned int nHeight) const; // ppcoin: two types of block: proof-of-work or proof-of-stake bool IsProofOfStake() const @@ -949,145 +795,19 @@ public: std::pair GetProofOfStake() const { - return IsProofOfStake()? std::make_pair(vtx[1].vin[0].prevout, vtx[1].nTime) : std::make_pair(COutPoint(), (unsigned int)0); + if (IsProofOfStake()) + return { vtx[1].vin[0].prevout, vtx[1].nTime }; + return { COutPoint(), (unsigned int)0 }; } // ppcoin: get max transaction timestamp - int64 GetMaxTransactionTime() const - { - int64 maxTransactionTime = 0; - BOOST_FOREACH(const CTransaction& tx, vtx) - maxTransactionTime = std::max(maxTransactionTime, (int64)tx.nTime); - return maxTransactionTime; - } - - uint256 BuildMerkleTree() const - { - vMerkleTree.clear(); - BOOST_FOREACH(const CTransaction& tx, vtx) - vMerkleTree.push_back(tx.GetHash()); - int j = 0; - for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) - { - for (int i = 0; i < nSize; i += 2) - { - int i2 = std::min(i+1, nSize-1); - vMerkleTree.push_back(Hash(BEGIN(vMerkleTree[j+i]), END(vMerkleTree[j+i]), - BEGIN(vMerkleTree[j+i2]), END(vMerkleTree[j+i2]))); - } - j += nSize; - } - return (vMerkleTree.empty() ? 0 : vMerkleTree.back()); - } - - std::vector GetMerkleBranch(int nIndex) const - { - if (vMerkleTree.empty()) - BuildMerkleTree(); - std::vector vMerkleBranch; - int j = 0; - for (int nSize = vtx.size(); nSize > 1; nSize = (nSize + 1) / 2) - { - int i = std::min(nIndex^1, nSize-1); - vMerkleBranch.push_back(vMerkleTree[j+i]); - nIndex >>= 1; - j += nSize; - } - return vMerkleBranch; - } - - static uint256 CheckMerkleBranch(uint256 hash, const std::vector& vMerkleBranch, int nIndex) - { - if (nIndex == -1) - return 0; - BOOST_FOREACH(const uint256& otherside, vMerkleBranch) - { - if (nIndex & 1) - hash = Hash(BEGIN(otherside), END(otherside), BEGIN(hash), END(hash)); - else - hash = Hash(BEGIN(hash), END(hash), BEGIN(otherside), END(otherside)); - nIndex >>= 1; - } - return hash; - } - - - bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet) - { - // Open history file to append - CAutoFile fileout = CAutoFile(AppendBlockFile(nFileRet), SER_DISK, CLIENT_VERSION); - if (!fileout) - return error("CBlock::WriteToDisk() : AppendBlockFile failed"); - - // Write index header - unsigned int nSize = fileout.GetSerializeSize(*this); - fileout << FLATDATA(pchMessageStart) << nSize; - - // Write block - long fileOutPos = ftell(fileout); - if (fileOutPos < 0) - return error("CBlock::WriteToDisk() : ftell failed"); - nBlockPosRet = fileOutPos; - fileout << *this; - - // Flush stdio buffers and commit to disk before returning - fflush(fileout); - if (!IsInitialBlockDownload() || (nBestHeight+1) % 500 == 0) - FileCommit(fileout); - - return true; - } - - bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true) - { - SetNull(); - - // Open history file to read - CAutoFile filein = CAutoFile(OpenBlockFile(nFile, nBlockPos, "rb"), SER_DISK, CLIENT_VERSION); - if (!filein) - return error("CBlock::ReadFromDisk() : OpenBlockFile failed"); - if (!fReadTransactions) - filein.nType |= SER_BLOCKHEADERONLY; - - // Read block - try { - filein >> *this; - } - catch (std::exception &e) { - return error("%s() : deserialize or I/O error", __PRETTY_FUNCTION__); - } - - // Check the header - if (fReadTransactions && IsProofOfWork() && !CheckProofOfWork(GetHash(), nBits)) - return error("CBlock::ReadFromDisk() : errors in block header"); - - return true; - } - - - - void print() const - { - 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().c_str(), - hashMerkleRoot.ToString().c_str(), - nTime, nBits, nNonce, - vtx.size(), - HexStr(vchBlockSig.begin(), vchBlockSig.end()).c_str()); - for (unsigned int i = 0; i < vtx.size(); i++) - { - printf(" "); - vtx[i].print(); - } - printf(" vMerkleTree: "); - for (unsigned int i = 0; i < vMerkleTree.size(); i++) - printf("%s ", vMerkleTree[i].ToString().substr(0,10).c_str()); - printf("\n"); - } - - + int64_t GetMaxTransactionTime() const; + uint256 BuildMerkleTree() const; + std::vector GetMerkleBranch(int nIndex) const; + static uint256 CheckMerkleBranch(uint256 hash, const std::vector& vMerkleBranch, int nIndex); + bool WriteToDisk(unsigned int& nFileRet, unsigned int& nBlockPosRet); + bool ReadFromDisk(unsigned int nFile, unsigned int nBlockPos, bool fReadTransactions=true); + void print() const; bool DisconnectBlock(CTxDB& txdb, CBlockIndex* pindex); bool ConnectBlock(CTxDB& txdb, CBlockIndex* pindex, bool fJustCheck=false); bool ReadFromDisk(const CBlockIndex* pindex, bool fReadTransactions=true); @@ -1095,9 +815,8 @@ public: bool AddToBlockIndex(unsigned int nFile, unsigned int nBlockPos); 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(CWallet& keystore); - bool CheckBlockSignature(bool fProofOfStake) const; + bool GetCoinAge(uint64_t& nCoinAge) const; // ppcoin: calculate total coin age spent in block + bool CheckBlockSignature() const; private: bool SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew); @@ -1121,36 +840,36 @@ public: const uint256* phashBlock; CBlockIndex* pprev; CBlockIndex* pnext; - unsigned int nFile; - unsigned int nBlockPos; + uint32_t nFile; + uint32_t nBlockPos; uint256 nChainTrust; // ppcoin: trust score of block chain - int nHeight; + int32_t nHeight; - int64 nMint; - int64 nMoneySupply; + int64_t nMint; + int64_t nMoneySupply; - unsigned int nFlags; // ppcoin: block index flags + uint32_t nFlags; // ppcoin: block index flags enum { BLOCK_PROOF_OF_STAKE = (1 << 0), // is proof-of-stake block BLOCK_STAKE_ENTROPY = (1 << 1), // entropy bit for stake modifier - BLOCK_STAKE_MODIFIER = (1 << 2), // regenerated stake modifier + BLOCK_STAKE_MODIFIER = (1 << 2) // regenerated stake modifier }; - uint64 nStakeModifier; // hash modifier for proof-of-stake - unsigned int nStakeModifierChecksum; // checksum of index; in-memeory only + uint64_t nStakeModifier; // hash modifier for proof-of-stake + uint32_t nStakeModifierChecksum; // checksum of index; in-memeory only // proof-of-stake specific fields COutPoint prevoutStake; - unsigned int nStakeTime; + uint32_t nStakeTime; uint256 hashProofOfStake; // block header - int nVersion; - uint256 hashMerkleRoot; - unsigned int nTime; - unsigned int nBits; - unsigned int nNonce; + int32_t nVersion; + uint256 hashMerkleRoot; + uint32_t nTime; + uint32_t nBits; + uint32_t nNonce; CBlockIndex() { @@ -1211,27 +930,16 @@ public: nNonce = block.nNonce; } - CBlock GetBlockHeader() const - { - CBlock block; - block.nVersion = nVersion; - if (pprev) - block.hashPrevBlock = pprev->GetBlockHash(); - block.hashMerkleRoot = hashMerkleRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - return block; - } + CBlock GetBlockHeader() const; uint256 GetBlockHash() const { return *phashBlock; } - int64 GetBlockTime() const + int64_t GetBlockTime() const { - return (int64)nTime; + return (int64_t)nTime; } uint256 GetBlockTrust() const; @@ -1246,33 +954,8 @@ public: return true; } - enum { nMedianTimeSpan=11 }; - - int64 GetMedianTimePast() const - { - int64 pmedian[nMedianTimeSpan]; - int64* pbegin = &pmedian[nMedianTimeSpan]; - int64* pend = &pmedian[nMedianTimeSpan]; - - const CBlockIndex* pindex = this; - for (int i = 0; i < nMedianTimeSpan && pindex; i++, pindex = pindex->pprev) - *(--pbegin) = pindex->GetBlockTime(); - - std::sort(pbegin, pend); - return pbegin[(pend - pbegin)/2]; - } - - int64 GetMedianTime() const - { - const CBlockIndex* pindex = this; - for (int i = 0; i < nMedianTimeSpan/2; i++) - { - if (!pindex->pnext) - return GetBlockTime(); - pindex = pindex->pnext; - } - return pindex->GetMedianTimePast(); - } + int64_t GetMedianTimePast() const; + int64_t GetMedianTime() const; /** * Returns true if there are nRequired or more blocks of minVersion or above @@ -1302,38 +985,15 @@ public: return ((nFlags & BLOCK_STAKE_ENTROPY) >> 1); } - bool SetStakeEntropyBit(unsigned int nEntropyBit) - { - if (nEntropyBit > 1) - return false; - nFlags |= (nEntropyBit? BLOCK_STAKE_ENTROPY : 0); - return true; - } + bool SetStakeEntropyBit(unsigned int nEntropyBit); bool GeneratedStakeModifier() const { - return (nFlags & BLOCK_STAKE_MODIFIER); + return (nFlags & BLOCK_STAKE_MODIFIER) != 0; } - void SetStakeModifier(uint64 nModifier, bool fGeneratedStakeModifier) - { - nStakeModifier = nModifier; - if (fGeneratedStakeModifier) - nFlags |= BLOCK_STAKE_MODIFIER; - } - - std::string ToString() const - { - 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().c_str(), - GetBlockHash().ToString().c_str()); - } + void SetStakeModifier(uint64_t nModifier, bool fGeneratedStakeModifier); + std::string ToString() const; void print() const { @@ -1343,7 +1003,7 @@ public: -/** Used to marshal pointers into hashes for db storage. */ +// Used to marshal pointers into hashes for db storage. class CDiskBlockIndex : public CBlockIndex { private: @@ -1353,13 +1013,7 @@ public: uint256 hashPrev; uint256 hashNext; - CDiskBlockIndex() - { - hashPrev = 0; - hashNext = 0; - blockHash = 0; - } - + CDiskBlockIndex() : blockHash(0), hashPrev(0), hashNext(0) {} explicit CDiskBlockIndex(CBlockIndex* pindex) : CBlockIndex(*pindex) { hashPrev = (pprev ? pprev->GetBlockHash() : 0); @@ -1402,34 +1056,8 @@ public: READWRITE(blockHash); ) - uint256 GetBlockHash() const - { - if (fUseFastIndex && (nTime < GetAdjustedTime() - 24 * 60 * 60) && blockHash != 0) - return blockHash; - - CBlock block; - block.nVersion = nVersion; - block.hashPrevBlock = hashPrev; - block.hashMerkleRoot = hashMerkleRoot; - block.nTime = nTime; - block.nBits = nBits; - block.nNonce = nNonce; - - const_cast(this)->blockHash = block.GetHash(); - - return blockHash; - } - - std::string ToString() const - { - std::string str = "CDiskBlockIndex("; - str += CBlockIndex::ToString(); - str += strprintf("\n hashBlock=%s, hashPrev=%s, hashNext=%s)", - GetBlockHash().ToString().c_str(), - hashPrev.ToString().c_str(), - hashNext.ToString().c_str()); - return str; - } + uint256 GetBlockHash() const; + std::string ToString() const; void print() const { @@ -1439,24 +1067,18 @@ public: - - - - - -/** Describes a place in the block chain to another node such that if the - * other node doesn't have the same branch, it can find a recent common trunk. - * The further back it is, the further before the fork it may be. - */ +// Describes a place in the block chain to another node such that if the +// other node doesn't have the same branch, it can find a recent common trunk. +// The further back it is, the further before the fork it may be. +// class CBlockLocator { protected: std::vector vHave; public: - CBlockLocator() - { - } + CBlockLocator() { } + CBlockLocator(const std::vector& vHaveIn) : vHave(vHaveIn) { } explicit CBlockLocator(const CBlockIndex* pindex) { @@ -1465,16 +1087,11 @@ public: explicit CBlockLocator(uint256 hashBlock) { - std::map::iterator mi = mapBlockIndex.find(hashBlock); + auto mi = mapBlockIndex.find(hashBlock); if (mi != mapBlockIndex.end()) Set((*mi).second); } - CBlockLocator(const std::vector& vHaveIn) - { - vHave = vHaveIn; - } - IMPLEMENT_SERIALIZE ( if (!(nType & SER_GETHASH)) @@ -1492,92 +1109,15 @@ public: return vHave.empty(); } - void Set(const CBlockIndex* pindex) - { - vHave.clear(); - int nStep = 1; - while (pindex) - { - vHave.push_back(pindex->GetBlockHash()); - - // Exponentially larger steps back - for (int i = 0; pindex && i < nStep; i++) - pindex = pindex->pprev; - if (vHave.size() > 10) - nStep *= 2; - } - vHave.push_back((!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet)); - } - - int GetDistanceBack() - { - // Retrace how far back it was in the sender's branch - int nDistance = 0; - int nStep = 1; - BOOST_FOREACH(const uint256& hash, vHave) - { - std::map::iterator mi = mapBlockIndex.find(hash); - if (mi != mapBlockIndex.end()) - { - CBlockIndex* pindex = (*mi).second; - if (pindex->IsInMainChain()) - return nDistance; - } - nDistance += nStep; - if (nDistance > 10) - nStep *= 2; - } - return nDistance; - } - - CBlockIndex* GetBlockIndex() - { - // Find the first block the caller has in the main chain - BOOST_FOREACH(const uint256& hash, vHave) - { - std::map::iterator mi = mapBlockIndex.find(hash); - if (mi != mapBlockIndex.end()) - { - CBlockIndex* pindex = (*mi).second; - if (pindex->IsInMainChain()) - return pindex; - } - } - return pindexGenesisBlock; - } - - uint256 GetBlockHash() - { - // Find the first block the caller has in the main chain - BOOST_FOREACH(const uint256& hash, vHave) - { - std::map::iterator mi = mapBlockIndex.find(hash); - if (mi != mapBlockIndex.end()) - { - CBlockIndex* pindex = (*mi).second; - if (pindex->IsInMainChain()) - return hash; - } - } - return (!fTestNet ? hashGenesisBlock : hashGenesisBlockTestNet); - } - - int GetHeight() - { - CBlockIndex* pindex = GetBlockIndex(); - if (!pindex) - return 0; - return pindex->nHeight; - } + void Set(const CBlockIndex* pindex); + int GetDistanceBack(); + CBlockIndex* GetBlockIndex(); + uint256 GetBlockHash(); + int GetHeight(); }; - - - - - class CTxMemPool { public: @@ -1592,18 +1132,18 @@ public: void clear(); void queryHashes(std::vector& vtxid); - unsigned long size() + size_t size() { LOCK(cs); return mapTx.size(); } - bool exists(uint256 hash) + bool exists(const uint256 &hash) { return (mapTx.count(hash) != 0); } - CTransaction& lookup(uint256 hash) + CTransaction& lookup(const uint256 &hash) { return mapTx[hash]; }