diff --git a/doc/release-process.md b/doc/release-process.md index 93a8e8362..cde355287 100644 --- a/doc/release-process.md +++ b/doc/release-process.md @@ -24,6 +24,8 @@ Check that there are no surprising performance regressions: Ensure that new performance metrics appear on that site. +Update `src/chainparams.cpp` nMinimumChainWork with information from the getblockchaininfo rpc. + ### Protocol Safety Checks: If this release changes the behavior of the protocol or fixes a serious diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 701573bdb..948075900 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -106,6 +106,9 @@ public: consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + // The best chain should have at least this much work. + consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000281b32ff3198a1"); + /** * The message start string should be awesome! ⓩ❤ */ @@ -115,7 +118,6 @@ public: pchMessageStart[3] = 0x64; vAlertPubKey = ParseHex("04b7ecf0baa90495ceb4e4090f6b2fd37eec1e9c85fac68a487f3ce11589692e4a317479316ee814e066638e1db54e37a10689b70286e6315b1087b6615d179264"); nDefaultPort = 8233; - nMaxTipAge = 24 * 60 * 60; nPruneAfterHeight = 100000; const size_t N = 200, K = 9; BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); @@ -273,13 +275,15 @@ public: consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nProtocolVersion = 170006; consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = 252500; + // The best chain should have at least this much work. + consensus.nMinimumChainWork = uint256S("0x00000000000000000000000000000000000000000000000000000001d0c4d9cd"); + pchMessageStart[0] = 0xfa; pchMessageStart[1] = 0x1a; pchMessageStart[2] = 0xf9; pchMessageStart[3] = 0xbf; vAlertPubKey = ParseHex("044e7a1553392325c871c5ace5d6ad73501c66f4c185d6b0453cf45dec5a1322e705c672ac1a27ef7cdaf588c10effdf50ed5f95f85f2f54a5f6159fca394ed0c6"); nDefaultPort = 18233; - nMaxTipAge = 24 * 60 * 60; nPruneAfterHeight = 1000; const size_t N = 200, K = 9; BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); @@ -328,6 +332,7 @@ public: fMineBlocksOnDemand = false; fTestnetToBeDeprecatedFieldRPC = true; + checkpointData = (CCheckpointData) { boost::assign::map_list_of (0, consensus.hashGenesisBlock) @@ -391,12 +396,14 @@ public: consensus.vUpgrades[Consensus::UPGRADE_SAPLING].nActivationHeight = Consensus::NetworkUpgrade::NO_ACTIVATION_HEIGHT; + // The best chain should have at least this much work. + consensus.nMinimumChainWork = uint256S("0x00"); + pchMessageStart[0] = 0xaa; pchMessageStart[1] = 0xe8; pchMessageStart[2] = 0x3f; pchMessageStart[3] = 0x5f; nDefaultPort = 18344; - nMaxTipAge = 24 * 60 * 60; nPruneAfterHeight = 1000; const size_t N = 48, K = 5; BOOST_STATIC_ASSERT(equihash_parameters_acceptable(N, K)); diff --git a/src/chainparams.h b/src/chainparams.h index 6ee41fc4b..1e19b0e8a 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -77,7 +77,6 @@ public: bool DefaultConsistencyChecks() const { return fDefaultConsistencyChecks; } /** Policy: Filter transactions that do not match well-defined patterns */ bool RequireStandard() const { return fRequireStandard; } - int64_t MaxTipAge() const { return nMaxTipAge; } int64_t PruneAfterHeight() const { return nPruneAfterHeight; } unsigned int EquihashN() const { return nEquihashN; } unsigned int EquihashK() const { return nEquihashK; } @@ -107,7 +106,6 @@ protected: //! Raw pub key bytes for the broadcast alert signing key. std::vector vAlertPubKey; int nDefaultPort = 0; - long nMaxTipAge = 0; uint64_t nPruneAfterHeight = 0; unsigned int nEquihashN = 0; unsigned int nEquihashK = 0; diff --git a/src/consensus/params.h b/src/consensus/params.h index 38cf65fb6..c21607046 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -98,6 +98,7 @@ struct Params { int64_t AveragingWindowTimespan() const { return nPowAveragingWindow * nPowTargetSpacing; } int64_t MinActualTimespan() const { return (AveragingWindowTimespan() * (100 - nPowMaxAdjustUp )) / 100; } int64_t MaxActualTimespan() const { return (AveragingWindowTimespan() * (100 + nPowMaxAdjustDown)) / 100; } + uint256 nMinimumChainWork; }; } // namespace Consensus diff --git a/src/init.cpp b/src/init.cpp index 25f913de8..33405a31f 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -470,6 +470,7 @@ std::string HelpMessage(HelpMessageMode mode) strUsage += HelpMessageOpt("-limitfreerelay=", strprintf("Continuously rate-limit free transactions to *1000 bytes per minute (default: %u)", 15)); strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", 0)); strUsage += HelpMessageOpt("-maxsigcachesize=", strprintf("Limit size of signature cache to entries (default: %u)", 50000)); + strUsage += HelpMessageOpt("-maxtipage=", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE)); } strUsage += HelpMessageOpt("-minrelaytxfee=", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for relaying (default: %s)"), CURRENCY_UNIT, FormatMoney(::minRelayTxFee.GetFeePerK()))); @@ -1075,6 +1076,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler) if (GetBoolArg("-peerbloomfilters", true)) nLocalServices |= NODE_BLOOM; + nMaxTipAge = GetArg("-maxtipage", DEFAULT_MAX_TIP_AGE); + #ifdef ENABLE_MINING if (mapArgs.count("-mineraddress")) { CTxDestination addr = DecodeDestination(mapArgs["-mineraddress"]); diff --git a/src/main.cpp b/src/main.cpp index 5732eca83..1f1893654 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -32,6 +32,7 @@ #include "wallet/asyncrpcoperation_shieldcoinbase.h" #include +#include #include #include @@ -75,6 +76,9 @@ bool fCoinbaseEnforcedProtectionEnabled = true; size_t nCoinCacheUsage = 5000 * 300; uint64_t nPruneTarget = 0; bool fAlerts = DEFAULT_ALERTS; +/* If the tip is older than this (in seconds), the node is considered to be in initial block download. + */ +int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; unsigned int expiryDelta = DEFAULT_TX_EXPIRY_DELTA; @@ -1724,19 +1728,27 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams) bool IsInitialBlockDownload() { const CChainParams& chainParams = Params(); + + // Once this function has returned false, it must remain false. + static std::atomic latchToFalse{false}; + // Optimization: pre-test latch before taking the lock. + if (latchToFalse.load(std::memory_order_relaxed)) + return false; + LOCK(cs_main); + if (latchToFalse.load(std::memory_order_relaxed)) + return false; if (fImporting || fReindex) return true; - if (fCheckpointsEnabled && chainActive.Height() < Checkpoints::GetTotalBlocksEstimate(chainParams.Checkpoints())) + if (chainActive.Tip() == NULL) return true; - static bool lockIBDState = false; - if (lockIBDState) - return false; - bool state = (chainActive.Height() < pindexBestHeader->nHeight - 24 * 6 || - pindexBestHeader->GetBlockTime() < GetTime() - chainParams.MaxTipAge()); - if (!state) - lockIBDState = true; - return state; + if (chainActive.Tip()->nChainWork < 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; } static bool fLargeWorkForkFound = false; @@ -1748,7 +1760,7 @@ void CheckForkWarningConditions() { AssertLockHeld(cs_main); // Before we get past initial download, we cannot reliably alert about forks - // (we assume we don't get stuck on a fork before the last checkpoint) + // (we assume we don't get stuck on a fork before finishing our initial sync) if (IsInitialBlockDownload()) return; diff --git a/src/main.h b/src/main.h index 580de352a..201637ab1 100644 --- a/src/main.h +++ b/src/main.h @@ -98,6 +98,7 @@ static const unsigned int DATABASE_WRITE_INTERVAL = 60 * 60; static const unsigned int DATABASE_FLUSH_INTERVAL = 24 * 60 * 60; /** Maximum length of reject messages. */ static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; +static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60; // Sanity check the magic numbers when we change them BOOST_STATIC_ASSERT(DEFAULT_BLOCK_MAX_SIZE <= MAX_BLOCK_SIZE); @@ -137,6 +138,7 @@ extern bool fCoinbaseEnforcedProtectionEnabled; extern size_t nCoinCacheUsage; extern CFeeRate minRelayTxFee; extern bool fAlerts; +extern int64_t nMaxTipAge; /** Best header we've seen so far (used for getheaders queries' starting points). */ extern CBlockIndex *pindexBestHeader;