From 0a7793a3e101abf76a98a639872adaa8a771784d Mon Sep 17 00:00:00 2001 From: barrystyle Date: Sat, 17 Aug 2019 03:31:42 +0800 Subject: [PATCH] Migrate to use of nChainTrust from nChainWork. --- src/chain.cpp | 33 ++++------------- src/chain.h | 13 +++---- src/chainparams.cpp | 2 +- src/kernel.cpp | 5 ++- src/net_processing.cpp | 16 ++++---- src/pow.cpp | 7 ++++ src/pow.h | 1 + src/rpc/blockchain.cpp | 9 +++-- src/rpc/mining.cpp | 2 +- src/test/pow_tests.cpp | 2 +- src/validation.cpp | 83 +++++++++++++++++++----------------------- src/validation.h | 2 +- 12 files changed, 79 insertions(+), 96 deletions(-) diff --git a/src/chain.cpp b/src/chain.cpp index 6ef548b0ef2c3..2afa452463dcf 100644 --- a/src/chain.cpp +++ b/src/chain.cpp @@ -133,7 +133,7 @@ void CBlockIndex::BuildSkip() pskip = pprev->GetAncestor(GetSkipHeight(nHeight)); } -arith_uint256 GetBlockProof(const CBlockIndex& block) +arith_uint256 GetBlockTrust(const CBlockIndex& block) { arith_uint256 bnTarget; bool fNegative; @@ -142,23 +142,23 @@ arith_uint256 GetBlockProof(const CBlockIndex& block) if (fNegative || fOverflow || bnTarget == 0) return 0; // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 - // as it's too large for a arith_uint256. However, as 2**256 is at least as large + // as it's too large for an arith_uint256. However, as 2**256 is at least as large // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1, - // or ~bnTarget / (nTarget+1) + 1. - return (~bnTarget / (bnTarget + 1)) + 1; + // or ~bnTarget / (bnTarget+1) + 1. + return block.IsProofOfStake() ? (~bnTarget / (bnTarget + 1)) + 1 : 1; } int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params& params) { arith_uint256 r; int sign = 1; - if (to.nChainWork > from.nChainWork) { - r = to.nChainWork - from.nChainWork; + if (to.nChainTrust > from.nChainTrust) { + r = to.nChainTrust - from.nChainTrust; } else { - r = from.nChainWork - to.nChainWork; + r = from.nChainTrust - to.nChainTrust; sign = -1; } - r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockProof(tip); + r = r * arith_uint256(params.nPowTargetSpacing) / GetBlockTrust(tip); if (r.bits() > 63) { return sign * std::numeric_limits::max(); } @@ -183,20 +183,3 @@ const CBlockIndex* LastCommonAncestor(const CBlockIndex* pa, const CBlockIndex* assert(pa == pb); return pa; } - -arith_uint256 CBlockIndex::GetBlockTrust() const -{ - arith_uint256 bnTarget; - bnTarget.SetCompact(nBits); - if (bnTarget <= 0) - return 0; - - if (IsProofOfStake()) { - // Return trust score as usual - return (arith_uint256(1) << 256) / (bnTarget + 1); - } else { - // Calculate work amount for block - arith_uint256 bnPoWTrust = ((~arith_uint256(0) >> 20) / (bnTarget + 1)); - return bnPoWTrust > 1 ? bnPoWTrust : 1; - } -} diff --git a/src/chain.h b/src/chain.h index 4652c453ec41b..148ca58bac89f 100644 --- a/src/chain.h +++ b/src/chain.h @@ -181,9 +181,6 @@ class CBlockIndex //! pointer to the index of some further predecessor of this block CBlockIndex* pskip; - //ppcoin: trust score of block chain - uint256 bnChainTrust; - //! height of the entry in the chain. The genesis block has height 0 int nHeight; @@ -197,7 +194,7 @@ class CBlockIndex unsigned int nUndoPos; //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block - arith_uint256 nChainWork; + arith_uint256 nChainTrust; //! Number of transactions in this block. //! Note: in a potential headers-first mode, this number cannot be relied upon @@ -250,7 +247,7 @@ class CBlockIndex nFile = 0; nDataPos = 0; nUndoPos = 0; - nChainWork = arith_uint256(); + nChainTrust = arith_uint256(); nTx = 0; nChainTx = 0; nStatus = 0; @@ -258,11 +255,11 @@ class CBlockIndex nTimeMax = 0; nMint = 0; - bnChainTrust = uint256(); nMoneySupply = 0; nFlags = 0; nStakeModifier = 0; nStakeModifierChecksum = 0; + hashProofOfStake = uint256(); prevoutStake.SetNull(); nStakeTime = 0; @@ -289,7 +286,7 @@ class CBlockIndex nNonce = block.nNonce; //Proof of Stake - bnChainTrust = uint256(); + nChainTrust = arith_uint256(); nMint = 0; nMoneySupply = 0; nFlags = 0; @@ -440,7 +437,7 @@ class CBlockIndex const CBlockIndex* GetAncestor(int height) const; }; -arith_uint256 GetBlockProof(const CBlockIndex& block); +arith_uint256 GetBlockTrust(const CBlockIndex& block); /** Return the time it would take to redo the work difference between from and to, assuming the current hashrate corresponds to the difficulty at tip, in seconds. */ int64_t GetBlockProofEquivalentTime(const CBlockIndex& to, const CBlockIndex& from, const CBlockIndex& tip, const Consensus::Params&); diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 4e7310c78006d..c70b6d5bd510f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -284,7 +284,7 @@ class CMainParams : public CChainParams { consensus.vDeployments[Consensus::DEPLOYMENT_DIP0008].nThreshold = 3226; // 80% of 4032 // The best chain should have at least this much work. - consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000002ca70cb14917f702ff"); // #216000 + consensus.nMinimumChainWork = uint256S("0x0000000000000000000000000000000000000000000000000000000000000000"); // By default assume that the signatures in ancestors of this block are valid. consensus.defaultAssumeValid = uint256S("0x00000000000038a52e7bafb7fb091ed2989ec8bdd7a550db9925300687805d87"); // #216000 diff --git a/src/kernel.cpp b/src/kernel.cpp index 4603df94acb3b..47de3cf7bead1 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -88,7 +88,7 @@ static bool SelectBlockFromCandidates( const CBlockIndex** pindexSelected) { bool fSelected = false; - arith_uint256 hashBest; + arith_uint256 hashBest = 0; *pindexSelected = nullptr; for(const auto &item : vSortedByTimestamp) { @@ -156,7 +156,8 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexCurrent, uint64_t &nStake int64_t nModifierTime = 0; if (!GetLastStakeModifier(pindexPrev, nStakeModifier, nModifierTime)) return error("ComputeNextStakeModifier: unable to get last modifier"); - LogPrintf("ComputeNextStakeModifier: prev modifier=0x%016x time=%s epoch=%u\n", nStakeModifier, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nModifierTime).c_str(), (unsigned int)nModifierTime); + if (GetBoolArg("-debug", false)) + LogPrintf("ComputeNextStakeModifier: prev modifier=0x%016x time=%s epoch=%u\n", nStakeModifier, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", nModifierTime).c_str(), (unsigned int)nModifierTime); if (nModifierTime / params.nModifierInterval >= pindexPrev->GetBlockTime() / params.nModifierInterval) return true; diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 5d990b4882816..9585743b4d76d 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -414,8 +414,8 @@ void ProcessBlockAvailability(NodeId nodeid) { if (!state->hashLastUnknownBlock.IsNull()) { BlockMap::iterator itOld = mapBlockIndex.find(state->hashLastUnknownBlock); - if (itOld != mapBlockIndex.end() && itOld->second->nChainWork > 0) { - if (state->pindexBestKnownBlock == NULL || itOld->second->nChainWork >= state->pindexBestKnownBlock->nChainWork) + if (itOld != mapBlockIndex.end() && itOld->second->nChainTrust > 0) { + if (state->pindexBestKnownBlock == NULL || itOld->second->nChainTrust >= state->pindexBestKnownBlock->nChainTrust) state->pindexBestKnownBlock = itOld->second; state->hashLastUnknownBlock.SetNull(); } @@ -430,9 +430,9 @@ void UpdateBlockAvailability(NodeId nodeid, const uint256 &hash) { ProcessBlockAvailability(nodeid); BlockMap::iterator it = mapBlockIndex.find(hash); - if (it != mapBlockIndex.end() && it->second->nChainWork > 0) { + if (it != mapBlockIndex.end() && it->second->nChainTrust > 0) { // An actually better block was announced. - if (state->pindexBestKnownBlock == NULL || it->second->nChainWork >= state->pindexBestKnownBlock->nChainWork) + if (state->pindexBestKnownBlock == NULL || it->second->nChainTrust >= state->pindexBestKnownBlock->nChainTrust) state->pindexBestKnownBlock = it->second; } else { // An unknown block was announced; just assume that the latest one is the best one. @@ -524,7 +524,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vectorpindexBestKnownBlock == NULL || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < UintToArith256(consensusParams.nMinimumChainWork)) { + if (state->pindexBestKnownBlock == NULL || state->pindexBestKnownBlock->nChainTrust < chainActive.Tip()->nChainTrust || state->pindexBestKnownBlock->nChainTrust < UintToArith256(consensusParams.nMinimumChainWork)) { // This peer has nothing interesting. return; } @@ -2437,7 +2437,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr // If this was a new header with more work than our tip, update the // peer's last block announcement time - if (received_new_header && pindex->nChainWork > chainActive.Tip()->nChainWork) { + if (received_new_header && pindex->nChainTrust > chainActive.Tip()->nChainTrust) { nodestate->m_last_block_announcement = GetTime(); } @@ -2447,7 +2447,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr if (pindex->nStatus & BLOCK_HAVE_DATA) // Nothing to do here return true; - if (pindex->nChainWork <= chainActive.Tip()->nChainWork || // We know something better + if (pindex->nChainTrust <= chainActive.Tip()->nChainTrust || // We know something better pindex->nTx != 0) { // We had this block at some point, but pruned it if (fAlreadyInFlight) { // We requested this block for some reason, but our mempool will probably be useless @@ -2749,7 +2749,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr bool fCanDirectFetch = CanDirectFetch(chainparams.GetConsensus()); // If this set of headers is valid and ends in a block with at least as // much work as our tip, download as much as possible. - if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && chainActive.Tip()->nChainWork <= pindexLast->nChainWork) { + if (fCanDirectFetch && pindexLast->IsValid(BLOCK_VALID_TREE) && chainActive.Tip()->nChainTrust <= pindexLast->nChainTrust) { std::vector vToFetch; const CBlockIndex *pindexWalk = pindexLast; // Calculate all the blocks we'd need to switch to pindexLast, up to a limit. diff --git a/src/pow.cpp b/src/pow.cpp index 815fb42283a9d..2b9592ba245de 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -13,6 +13,13 @@ #include +const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake) +{ + while (pindex && pindex->pprev && (pindex->IsProofOfStake() != fProofOfStake)) + pindex = pindex->pprev; + return pindex; +} + unsigned int DualKGW3(const CBlockIndex* pindexLast, bool fProofOfStake, const Consensus::Params& params) { const CBlockIndex *BlockLastSolved = pindexLast; diff --git a/src/pow.h b/src/pow.h index 16035e33f21d7..41a212bac7877 100644 --- a/src/pow.h +++ b/src/pow.h @@ -14,6 +14,7 @@ class CBlockHeader; class CBlockIndex; class uint256; +const CBlockIndex* GetLastBlockIndex(const CBlockIndex* pindex, bool fProofOfStake); unsigned int DualKGW3(const CBlockIndex* pindexLast, bool fProofOfStake, const Consensus::Params& params); unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const Consensus::Params& params); unsigned int CalculateNextWorkRequired(const CBlockIndex* pindexLast, int64_t nFirstBlockTime, const Consensus::Params&); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index d08d518108fcf..724fc54536a76 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -106,7 +106,8 @@ UniValue blockheaderToJSON(const CBlockIndex* blockindex) result.push_back(Pair("nonce", (uint64_t)blockindex->nNonce)); result.push_back(Pair("bits", strprintf("%08x", blockindex->nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + result.push_back(Pair("chainwork", blockindex->nChainTrust.GetHex())); + result.push_back(Pair("nTx", (uint64_t)blockindex->nTx)); if (blockindex->pprev) result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); @@ -159,7 +160,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx result.push_back(Pair("nonce", (uint64_t)block.nNonce)); result.push_back(Pair("bits", strprintf("%08x", block.nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); - result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + result.push_back(Pair("chaintrust", blockindex->nChainTrust.GetHex())); if (blockindex->pprev) result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex())); @@ -1322,7 +1323,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request) obj.push_back(Pair("difficulty", (double)GetDifficulty())); obj.push_back(Pair("mediantime", (int64_t)chainActive.Tip()->GetMedianTimePast())); obj.push_back(Pair("verificationprogress", GuessVerificationProgress(Params().TxData(), chainActive.Tip()))); - obj.push_back(Pair("chainwork", chainActive.Tip()->nChainWork.GetHex())); + obj.push_back(Pair("chaintrust", chainActive.Tip()->nChainTrust.GetHex())); obj.push_back(Pair("pruned", fPruneMode)); const Consensus::Params& consensusParams = Params().GetConsensus(); @@ -1462,7 +1463,7 @@ UniValue getchaintips(const JSONRPCRequest& request) obj.push_back(Pair("height", block->nHeight)); obj.push_back(Pair("hash", block->phashBlock->GetHex())); obj.push_back(Pair("difficulty", GetDifficulty(block))); - obj.push_back(Pair("chainwork", block->nChainWork.GetHex())); + obj.push_back(Pair("chaintrust", block->nChainTrust.GetHex())); obj.push_back(Pair("branchlen", branchLen)); obj.push_back(Pair("forkpoint", pindexFork->phashBlock->GetHex())); diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 4999b86665f2a..de2bf6b33d556 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -76,7 +76,7 @@ UniValue GetNetworkHashPS(int lookup, int height) { if (minTime == maxTime) return 0; - arith_uint256 workDiff = pb->nChainWork - pb0->nChainWork; + arith_uint256 workDiff = pb->nChainTrust - pb0->nChainTrust; int64_t timeDiff = maxTime - minTime; return workDiff.getdouble() / timeDiff; diff --git a/src/test/pow_tests.cpp b/src/test/pow_tests.cpp index 6964fb55337a9..b1d97ab3567a4 100644 --- a/src/test/pow_tests.cpp +++ b/src/test/pow_tests.cpp @@ -195,7 +195,7 @@ BOOST_AUTO_TEST_CASE(GetBlockProofEquivalentTime_test) blocks[i].nHeight = i; blocks[i].nTime = 1269211443 + i * params.nPowTargetSpacing; blocks[i].nBits = 0x207fffff; /* target 0x7fffff000... */ - blocks[i].nChainWork = i ? blocks[i - 1].nChainWork + GetBlockProof(blocks[i - 1]) : arith_uint256(0); + blocks[i].nChainTrust = i ? blocks[i - 1].nChainTrust + GetBlockProof(blocks[i - 1]) : arith_uint256(0); } for (int j = 0; j < 1000; j++) { diff --git a/src/validation.cpp b/src/validation.cpp index f5becc4cb3b8b..23ba33de89722 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -125,8 +125,8 @@ namespace { { bool operator()(CBlockIndex *pa, CBlockIndex *pb) const { // First sort by most total work, ... - if (pa->nChainWork > pb->nChainWork) return false; - if (pa->nChainWork < pb->nChainWork) return true; + if (pa->nChainTrust > pb->nChainTrust) return false; + if (pa->nChainTrust < pb->nChainTrust) return true; // ... then by earliest time received, ... if (pa->nSequenceId < pb->nSequenceId) return false; @@ -1279,10 +1279,11 @@ bool IsInitialBlockDownload() const CChainParams& chainParams = Params(); if (chainActive.Tip() == NULL) return true; - if (chainActive.Tip()->nChainWork < UintToArith256(chainParams.GetConsensus().nMinimumChainWork)) + if (chainActive.Tip()->nChainTrust < UintToArith256(chainParams.GetConsensus().nMinimumChainWork)) return true; if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) return true; + LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); latchToFalse.store(true, std::memory_order_relaxed); return false; } @@ -1300,33 +1301,26 @@ void CheckForkWarningConditions() // If our best fork is no longer within 72 blocks (+/- 3 hours if no one mines it) // of our head, drop it if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 72) - pindexBestForkTip = NULL; + pindexBestForkTip = nullptr; - if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (GetBlockProof(*chainActive.Tip()) * 6))) + if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainTrust > chainActive.Tip()->nChainTrust + (GetBlockTrust(*GetLastBlockIndex(chainActive.Tip(), true)) * 6))) { if (!GetfLargeWorkForkFound() && pindexBestForkBase) { - if(pindexBestForkBase->phashBlock){ - std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") + - pindexBestForkBase->phashBlock->ToString() + std::string("'"); - CAlert::Notify(warning); - } + std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") + + pindexBestForkBase->phashBlock->ToString() + std::string("'"); + CAlert::Notify(warning); } if (pindexBestForkTip && pindexBestForkBase) { - if(pindexBestForkBase->phashBlock){ LogPrintf("%s: Warning: Large valid fork found\n forking the chain at height %d (%s)\n lasting to height %d (%s).\nChain state database corruption likely.\n", __func__, pindexBestForkBase->nHeight, pindexBestForkBase->phashBlock->ToString(), pindexBestForkTip->nHeight, pindexBestForkTip->phashBlock->ToString()); SetfLargeWorkForkFound(true); } - } else { - if(pindexBestInvalid->nHeight > chainActive.Height() + 6) - LogPrintf("%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__); - else - LogPrintf("%s: Warning: Found invalid chain which has higher work (at least ~6 blocks worth of work) than our best chain.\nChain state database corruption likely.\n", __func__); + LogPrintf("%s: Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.\n", __func__); SetfLargeWorkInvalidChainFound(true); } } @@ -1353,14 +1347,14 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) } // We define a condition where we should warn the user about as a fork of at least 7 blocks - // with a tip within 72 blocks (+/- 3 hours if no one mines it) of ours - // or a chain that is entirely longer than ours and invalid (note that this should be detected by both) + // with a tip within 72 blocks (+/- 12 hours if no one mines it) of ours // We use 7 blocks rather arbitrarily as it represents just under 10% of sustained network // hash rate operating on the fork. + // or a chain that is entirely longer than ours and invalid (note that this should be detected by both) // We define it this way because it allows us to only store the highest fork tip (+ base) which meets // the 7-block condition and from this always have the most-likely-to-cause-warning fork - if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) && - pindexNewForkTip->nChainWork - pfork->nChainWork > (GetBlockProof(*pfork) * 7) && + if (pfork && (!pindexBestForkTip || pindexNewForkTip->nHeight > pindexBestForkTip->nHeight) && + pindexNewForkTip->nChainTrust - pfork->nChainTrust > (GetBlockTrust(*pfork) * 7) && chainActive.Height() - pindexNewForkTip->nHeight < 72) { pindexBestForkTip = pindexNewForkTip; @@ -1372,17 +1366,17 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip) void static InvalidChainFound(CBlockIndex* pindexNew) { - if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork) + if (!pindexBestInvalid || pindexNew->nChainTrust > pindexBestInvalid->nChainTrust) pindexBestInvalid = pindexNew; LogPrintf("%s: invalid block=%s height=%d log2_work=%.8f date=%s\n", __func__, pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, - log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", + log(pindexNew->nChainTrust.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexNew->GetBlockTime())); CBlockIndex *tip = chainActive.Tip(); assert (tip); LogPrintf("%s: current best=%s height=%d log2_work=%.8f date=%s\n", __func__, - tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainWork.getdouble())/log(2.0), + tip->GetBlockHash().ToString(), chainActive.Height(), log(tip->nChainTrust.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S", tip->GetBlockTime())); CheckForkWarningConditions(); } @@ -1707,6 +1701,7 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s const CTransaction &tx = *(block.vtx[i]); uint256 hash = tx.GetHash(); bool is_coinbase = tx.IsCoinBase(); + bool is_coinstake = tx.IsCoinStake(); if (fAddressIndex) { @@ -1750,7 +1745,7 @@ static DisconnectResult DisconnectBlock(const CBlock& block, CValidationState& s COutPoint out(hash, o); Coin coin; bool is_spent = view.SpendCoin(out, &coin); - if (!is_spent || tx.vout[o] != coin.out || pindex->nHeight != coin.nHeight || is_coinbase != coin.fCoinBase) { + if (!is_spent || tx.vout[o] != coin.out || pindex->nHeight != coin.nHeight || is_coinbase != coin.fCoinBase || is_coinstake != coin.fCoinStake) { fClean = false; // transaction output mismatch } } @@ -2004,7 +1999,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd if (it != mapBlockIndex.end()) { if (it->second->GetAncestor(pindex->nHeight) == pindex && pindexBestHeader->GetAncestor(pindex->nHeight) == pindex && - pindexBestHeader->nChainWork >= UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) { + pindexBestHeader->nChainTrust >= UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) { // This block is a member of the assumed verified chain and an ancestor of the best header. // The equivalent time check discourages hash power from extorting the network via DOS attack // into accepting an invalid block through telling users they must manually set assumevalid. @@ -2034,9 +2029,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd // Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the // two in the chain that violate it. This prevents exploiting the issue against nodes during their // initial block download. - bool fEnforceBIP30 = (!pindex->phashBlock) || // Enforce on CreateNewBlock invocations which don't have a hash. - !((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256S("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) || - (pindex->nHeight==91880 && pindex->GetBlockHash() == uint256S("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"))); + bool fEnforceBIP30 = (!pindex->phashBlock); // Enforce on CreateNewBlock invocations which don't have a hash. // Once BIP34 activated it was not possible to create new duplicate coinbases and thus other than starting // with the 2 existing duplicate coinbase pairs, not possible to create overwriting txs. But by the @@ -2633,9 +2626,9 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { } } } - std::string strMessage = strprintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8f tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__, + std::string strMessage = strprintf("%s: new best=%s height=%d version=0x%08x log2_trust=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__, chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, - log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, + log(chainActive.Tip()->nChainTrust.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); strMessage += strprintf(" evodb_cache=%.1fMiB", evoDb->GetMemoryUsage() * (1.0 / (1<<20))); @@ -2846,7 +2839,7 @@ static CBlockIndex* FindMostWorkChain() { bool fMissingData = !(pindexTest->nStatus & BLOCK_HAVE_DATA); if (fFailedChain || fMissingData) { // Candidate chain is not usable (either invalid or missing data) - if (fFailedChain && (pindexBestInvalid == NULL || pindexNew->nChainWork > pindexBestInvalid->nChainWork)) + if (fFailedChain && (pindexBestInvalid == nullptr || pindexNew->nChainTrust > pindexBestInvalid->nChainTrust)) pindexBestInvalid = pindexNew; CBlockIndex *pindexFailed = pindexNew; // Remove the entire chain from the set. @@ -2939,7 +2932,7 @@ static bool ActivateBestChainStep(CValidationState& state, const CChainParams& c } } else { PruneBlockIndexCandidates(); - if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) { + if (!pindexOldTip || chainActive.Tip()->nChainTrust > pindexOldTip->nChainTrust) { // We're in a better position than we were. Return temporarily to release the lock. fContinue = false; break; @@ -3083,15 +3076,15 @@ bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIn { { LOCK(cs_main); - if (pindex->nChainWork < chainActive.Tip()->nChainWork) { + if (pindex->nChainTrust < chainActive.Tip()->nChainTrust) { // Nothing to do, this block is not at the tip. return true; } - if (chainActive.Tip()->nChainWork > nLastPreciousChainwork) { + if (chainActive.Tip()->nChainTrust > nLastPreciousChainwork) { // The chain has been extended since the last call, reset the counter. nBlockReverseSequenceId = -1; } - nLastPreciousChainwork = chainActive.Tip()->nChainWork; + nLastPreciousChainwork = chainActive.Tip()->nChainTrust; setBlockIndexCandidates.erase(pindex); pindex->nSequenceId = nBlockReverseSequenceId; if (nBlockReverseSequenceId > std::numeric_limits::min()) { @@ -3201,7 +3194,6 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block, enum BlockStatus nStatus // Construct new block index object CBlockIndex* pindexNew = new CBlockIndex(block); - assert(pindexNew); // We assign the sequence id to blocks only when the full data is available, // to avoid miners withholding blocks but broadcasting headers, to get a // competitive advantage. @@ -3221,7 +3213,7 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block, enum BlockStatus nStatus pindexNew->BuildSkip(); // ppcoin: compute chain trust score - pindexNew->bnChainTrust = (pindexNew->pprev ? pindexNew->pprev->bnChainTrust : ArithToUint256(0 + pindexNew->GetBlockTrust())); + pindexNew->nChainTrust = (pindexNew->pprev ? pindexNew->pprev->nChainTrust : 0) + GetBlockTrust(*pindexNew); // ppcoin: compute stake entropy bit for stake modifier if (!pindexNew->SetStakeEntropyBit(pindexNew->GetStakeEntropyBit())) @@ -3244,10 +3236,11 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block, enum BlockStatus nStatus if (!CheckStakeModifierCheckpoints(pindexNew->nHeight, pindexNew->nStakeModifierChecksum)) LogPrintf("AddToBlockIndex() : Rejected by stake modifier checkpoint height=%d, modifier=%s \n", pindexNew->nHeight, boost::lexical_cast(nStakeModifier)); } - pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + GetBlockProof(*pindexNew); + pindexNew->nChainTrust = (pindexNew->pprev ? pindexNew->pprev->nChainTrust : 0) + GetBlockTrust(*pindexNew); pindexNew->RaiseValidity(BLOCK_VALID_TREE); - if (pindexBestHeader == NULL || pindexBestHeader->nChainWork < pindexNew->nChainWork) + if (pindexBestHeader == nullptr || pindexBestHeader->nChainTrust < pindexNew->nChainTrust) pindexBestHeader = pindexNew; + setDirtyBlockIndex.insert(pindexNew); return pindexNew; @@ -3708,7 +3701,7 @@ static bool AcceptBlock(const std::shared_ptr& pblock, CValidation // process an unrequested block if it's new and has enough work to // advance our tip, and isn't too many blocks ahead. bool fAlreadyHave = pindex->nStatus & BLOCK_HAVE_DATA; - bool fHasMoreWork = (chainActive.Tip() ? pindex->nChainWork > chainActive.Tip()->nChainWork : true); + bool fHasMoreWork = (chainActive.Tip() ? pindex->nChainTrust > chainActive.Tip()->nChainTrust : true); // Blocks that are too out-of-order needlessly limit the effectiveness of // pruning, because pruning will not delete block files that contain any // blocks which are too close in height to the tip. Apply this test @@ -3870,7 +3863,7 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr > vSortedByHeight; vSortedByHeight.reserve(mapBlockIndex.size()); BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) @@ -4134,7 +4127,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight) { CBlockIndex* pindex = item.second; - pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + GetBlockProof(*pindex); + pindex->nChainTrust = (pindex->pprev ? pindex->pprev->nChainTrust : 0) + GetBlockTrust(*pindex); pindex->nTimeMax = (pindex->pprev ? std::max(pindex->pprev->nTimeMax, pindex->nTime) : pindex->nTime); // We can link the chain of blocks for which we've received transactions at some point. // Pruned nodes may have deleted the block. @@ -4152,7 +4145,7 @@ bool static LoadBlockIndexDB(const CChainParams& chainparams) } if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->nChainTx || pindex->pprev == NULL)) setBlockIndexCandidates.insert(pindex); - if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork)) + if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainTrust > pindexBestInvalid->nChainTrust)) pindexBestInvalid = pindex; if (pindex->pprev) pindex->BuildSkip(); @@ -4642,7 +4635,7 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams) assert((pindexFirstNeverProcessed != NULL) == (pindex->nChainTx == 0)); // nChainTx != 0 is used to signal that all parent blocks have been processed (but may have been pruned). assert((pindexFirstNotTransactionsValid != NULL) == (pindex->nChainTx == 0)); assert(pindex->nHeight == nHeight); // nHeight must be consistent. - assert(pindex->pprev == NULL || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's. + assert(pindex->pprev == NULL || pindex->nChainTrust >= pindex->pprev->nChainTrust); // For every block except the genesis block, the chainwork must be larger than the parent's. assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks. assert(pindexFirstNotTreeValid == NULL); // All mapBlockIndex entries must at least be TREE valid if ((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TREE) assert(pindexFirstNotTreeValid == NULL); // TREE valid implies all parents are TREE valid diff --git a/src/validation.h b/src/validation.h index 6aa48bcf7b4ff..363d04517faf2 100644 --- a/src/validation.h +++ b/src/validation.h @@ -89,7 +89,7 @@ static const int MAX_SCRIPTCHECK_THREADS = 16; /** -par default (number of script-checking threads, 0 = auto) */ static const int DEFAULT_SCRIPTCHECK_THREADS = 0; /** Number of blocks that can be requested at any given time from a single peer. */ -static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 16; +static const int MAX_BLOCKS_IN_TRANSIT_PER_PEER = 256; /** Timeout in seconds during which a peer must stall block download progress before being disconnected. */ static const unsigned int BLOCK_STALLING_TIMEOUT = 2; /** Number of headers sent in one getheaders result. We rely on the assumption that if a peer sends