Allow setting nMinimumChainWork on command line
This commit is contained in:
parent
e0e3cbbf08
commit
0311836f69
7 changed files with 68 additions and 5 deletions
17
src/init.cpp
17
src/init.cpp
|
@ -354,6 +354,9 @@ std::string HelpMessage(HelpMessageMode mode)
|
|||
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
|
||||
strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
|
||||
strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
|
||||
if (showDebug) {
|
||||
strUsage += HelpMessageOpt("-minimumchainwork=<hex>", strprintf("Minimum work assumed to exist on a valid chain in hex (default: %s, testnet: %s)", defaultChainParams->GetConsensus().nMinimumChainWork.GetHex(), testnetChainParams->GetConsensus().nMinimumChainWork.GetHex()));
|
||||
}
|
||||
strUsage += HelpMessageOpt("-persistmempool", strprintf(_("Whether to save the mempool on shutdown and load on restart (default: %u)"), DEFAULT_PERSIST_MEMPOOL));
|
||||
strUsage += HelpMessageOpt("-blockreconstructionextratxn=<n>", strprintf(_("Extra transactions to keep in memory for compact block reconstructions (default: %u)"), DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN));
|
||||
strUsage += HelpMessageOpt("-par=<n>", strprintf(_("Set the number of script verification threads (%u to %d, 0 = auto, <0 = leave that many cores free, default: %d)"),
|
||||
|
@ -970,6 +973,20 @@ bool AppInitParameterInteraction()
|
|||
else
|
||||
LogPrintf("Validating signatures for all blocks.\n");
|
||||
|
||||
if (gArgs.IsArgSet("-minimumchainwork")) {
|
||||
const std::string minChainWorkStr = gArgs.GetArg("-minimumchainwork", "");
|
||||
if (!IsHexNumber(minChainWorkStr)) {
|
||||
return InitError(strprintf("Invalid non-hex (%s) minimum chain work value specified", minChainWorkStr));
|
||||
}
|
||||
nMinimumChainWork = UintToArith256(uint256S(minChainWorkStr));
|
||||
} else {
|
||||
nMinimumChainWork = UintToArith256(chainparams.GetConsensus().nMinimumChainWork);
|
||||
}
|
||||
LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex());
|
||||
if (nMinimumChainWork < UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) {
|
||||
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainparams.GetConsensus().nMinimumChainWork.GetHex());
|
||||
}
|
||||
|
||||
// mempool limits
|
||||
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
|
||||
int64_t nMempoolSizeMin = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40;
|
||||
|
|
|
@ -466,7 +466,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<con
|
|||
// Make sure pindexBestKnownBlock is up to date, we'll need it.
|
||||
ProcessBlockAvailability(nodeid);
|
||||
|
||||
if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < UintToArith256(consensusParams.nMinimumChainWork)) {
|
||||
if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
|
||||
// This peer has nothing interesting.
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -253,6 +253,31 @@ BOOST_AUTO_TEST_CASE(util_IsHex)
|
|||
BOOST_CHECK(!IsHex("0x0000"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(util_IsHexNumber)
|
||||
{
|
||||
BOOST_CHECK(IsHexNumber("0x0"));
|
||||
BOOST_CHECK(IsHexNumber("0"));
|
||||
BOOST_CHECK(IsHexNumber("0x10"));
|
||||
BOOST_CHECK(IsHexNumber("10"));
|
||||
BOOST_CHECK(IsHexNumber("0xff"));
|
||||
BOOST_CHECK(IsHexNumber("ff"));
|
||||
BOOST_CHECK(IsHexNumber("0xFfa"));
|
||||
BOOST_CHECK(IsHexNumber("Ffa"));
|
||||
BOOST_CHECK(IsHexNumber("0x00112233445566778899aabbccddeeffAABBCCDDEEFF"));
|
||||
BOOST_CHECK(IsHexNumber("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
|
||||
|
||||
BOOST_CHECK(!IsHexNumber("")); // empty string not allowed
|
||||
BOOST_CHECK(!IsHexNumber("0x")); // empty string after prefix not allowed
|
||||
BOOST_CHECK(!IsHexNumber("0x0 ")); // no spaces at end,
|
||||
BOOST_CHECK(!IsHexNumber(" 0x0")); // or beginning,
|
||||
BOOST_CHECK(!IsHexNumber("0x 0")); // or middle,
|
||||
BOOST_CHECK(!IsHexNumber(" ")); // etc.
|
||||
BOOST_CHECK(!IsHexNumber("0x0ga")); // invalid character
|
||||
BOOST_CHECK(!IsHexNumber("x0")); // broken prefix
|
||||
BOOST_CHECK(!IsHexNumber("0x0x00")); // two prefixes not allowed
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
|
||||
{
|
||||
SeedInsecureRand(true);
|
||||
|
|
|
@ -65,6 +65,19 @@ bool IsHex(const std::string& str)
|
|||
return (str.size() > 0) && (str.size()%2 == 0);
|
||||
}
|
||||
|
||||
bool IsHexNumber(const std::string& str)
|
||||
{
|
||||
size_t starting_location = 0;
|
||||
if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
|
||||
starting_location = 2;
|
||||
}
|
||||
for (auto c : str.substr(starting_location)) {
|
||||
if (HexDigit(c) < 0) return false;
|
||||
}
|
||||
// Return false for empty string or "0x".
|
||||
return (str.size() > starting_location);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> ParseHex(const char* psz)
|
||||
{
|
||||
// convert hex dump to vector
|
||||
|
|
|
@ -38,7 +38,13 @@ std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT
|
|||
std::vector<unsigned char> ParseHex(const char* psz);
|
||||
std::vector<unsigned char> ParseHex(const std::string& str);
|
||||
signed char HexDigit(char c);
|
||||
/* Returns true if each character in str is a hex character, and has an even
|
||||
* number of hex digits.*/
|
||||
bool IsHex(const std::string& str);
|
||||
/**
|
||||
* Return true if the string is a hex number, optionally prefixed with "0x"
|
||||
*/
|
||||
bool IsHexNumber(const std::string& str);
|
||||
std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = nullptr);
|
||||
std::string DecodeBase64(const std::string& str);
|
||||
std::string EncodeBase64(const unsigned char* pch, size_t len);
|
||||
|
|
|
@ -83,6 +83,7 @@ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
|||
bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT;
|
||||
|
||||
uint256 hashAssumeValid;
|
||||
arith_uint256 nMinimumChainWork;
|
||||
|
||||
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
|
||||
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
|
||||
|
@ -1035,8 +1036,6 @@ 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<bool> latchToFalse{false};
|
||||
// Optimization: pre-test latch before taking the lock.
|
||||
|
@ -1050,7 +1049,7 @@ bool IsInitialBlockDownload()
|
|||
return true;
|
||||
if (chainActive.Tip() == nullptr)
|
||||
return true;
|
||||
if (chainActive.Tip()->nChainWork < UintToArith256(chainParams.GetConsensus().nMinimumChainWork))
|
||||
if (chainActive.Tip()->nChainWork < nMinimumChainWork)
|
||||
return true;
|
||||
if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
|
||||
return true;
|
||||
|
@ -1670,7 +1669,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->nChainWork >= 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.
|
||||
|
|
|
@ -186,6 +186,9 @@ extern bool fEnableReplacement;
|
|||
/** Block hash whose ancestors we will assume to have valid scripts without checking them. */
|
||||
extern uint256 hashAssumeValid;
|
||||
|
||||
/** Minimum work we will assume exists on some valid chain. */
|
||||
extern arith_uint256 nMinimumChainWork;
|
||||
|
||||
/** Best header we've seen so far (used for getheaders queries' starting points). */
|
||||
extern CBlockIndex *pindexBestHeader;
|
||||
|
||||
|
|
Loading…
Reference in a new issue