Skip to content

Commit 0311836

Browse files
committed
Allow setting nMinimumChainWork on command line
1 parent e0e3cbb commit 0311836

File tree

7 files changed

+68
-5
lines changed

7 files changed

+68
-5
lines changed

src/init.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,9 @@ std::string HelpMessage(HelpMessageMode mode)
354354
strUsage += HelpMessageOpt("-maxorphantx=<n>", strprintf(_("Keep at most <n> unconnectable transactions in memory (default: %u)"), DEFAULT_MAX_ORPHAN_TRANSACTIONS));
355355
strUsage += HelpMessageOpt("-maxmempool=<n>", strprintf(_("Keep the transaction memory pool below <n> megabytes (default: %u)"), DEFAULT_MAX_MEMPOOL_SIZE));
356356
strUsage += HelpMessageOpt("-mempoolexpiry=<n>", strprintf(_("Do not keep transactions in the mempool longer than <n> hours (default: %u)"), DEFAULT_MEMPOOL_EXPIRY));
357+
if (showDebug) {
358+
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()));
359+
}
357360
strUsage += HelpMessageOpt("-persistmempool", strprintf(_("Whether to save the mempool on shutdown and load on restart (default: %u)"), DEFAULT_PERSIST_MEMPOOL));
358361
strUsage += HelpMessageOpt("-blockreconstructionextratxn=<n>", strprintf(_("Extra transactions to keep in memory for compact block reconstructions (default: %u)"), DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN));
359362
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()
970973
else
971974
LogPrintf("Validating signatures for all blocks.\n");
972975

976+
if (gArgs.IsArgSet("-minimumchainwork")) {
977+
const std::string minChainWorkStr = gArgs.GetArg("-minimumchainwork", "");
978+
if (!IsHexNumber(minChainWorkStr)) {
979+
return InitError(strprintf("Invalid non-hex (%s) minimum chain work value specified", minChainWorkStr));
980+
}
981+
nMinimumChainWork = UintToArith256(uint256S(minChainWorkStr));
982+
} else {
983+
nMinimumChainWork = UintToArith256(chainparams.GetConsensus().nMinimumChainWork);
984+
}
985+
LogPrintf("Setting nMinimumChainWork=%s\n", nMinimumChainWork.GetHex());
986+
if (nMinimumChainWork < UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) {
987+
LogPrintf("Warning: nMinimumChainWork set below default value of %s\n", chainparams.GetConsensus().nMinimumChainWork.GetHex());
988+
}
989+
973990
// mempool limits
974991
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
975992
int64_t nMempoolSizeMin = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40;

src/net_processing.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vector<con
466466
// Make sure pindexBestKnownBlock is up to date, we'll need it.
467467
ProcessBlockAvailability(nodeid);
468468

469-
if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < UintToArith256(consensusParams.nMinimumChainWork)) {
469+
if (state->pindexBestKnownBlock == nullptr || state->pindexBestKnownBlock->nChainWork < chainActive.Tip()->nChainWork || state->pindexBestKnownBlock->nChainWork < nMinimumChainWork) {
470470
// This peer has nothing interesting.
471471
return;
472472
}

src/test/util_tests.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,31 @@ BOOST_AUTO_TEST_CASE(util_IsHex)
253253
BOOST_CHECK(!IsHex("0x0000"));
254254
}
255255

256+
BOOST_AUTO_TEST_CASE(util_IsHexNumber)
257+
{
258+
BOOST_CHECK(IsHexNumber("0x0"));
259+
BOOST_CHECK(IsHexNumber("0"));
260+
BOOST_CHECK(IsHexNumber("0x10"));
261+
BOOST_CHECK(IsHexNumber("10"));
262+
BOOST_CHECK(IsHexNumber("0xff"));
263+
BOOST_CHECK(IsHexNumber("ff"));
264+
BOOST_CHECK(IsHexNumber("0xFfa"));
265+
BOOST_CHECK(IsHexNumber("Ffa"));
266+
BOOST_CHECK(IsHexNumber("0x00112233445566778899aabbccddeeffAABBCCDDEEFF"));
267+
BOOST_CHECK(IsHexNumber("00112233445566778899aabbccddeeffAABBCCDDEEFF"));
268+
269+
BOOST_CHECK(!IsHexNumber("")); // empty string not allowed
270+
BOOST_CHECK(!IsHexNumber("0x")); // empty string after prefix not allowed
271+
BOOST_CHECK(!IsHexNumber("0x0 ")); // no spaces at end,
272+
BOOST_CHECK(!IsHexNumber(" 0x0")); // or beginning,
273+
BOOST_CHECK(!IsHexNumber("0x 0")); // or middle,
274+
BOOST_CHECK(!IsHexNumber(" ")); // etc.
275+
BOOST_CHECK(!IsHexNumber("0x0ga")); // invalid character
276+
BOOST_CHECK(!IsHexNumber("x0")); // broken prefix
277+
BOOST_CHECK(!IsHexNumber("0x0x00")); // two prefixes not allowed
278+
279+
}
280+
256281
BOOST_AUTO_TEST_CASE(util_seed_insecure_rand)
257282
{
258283
SeedInsecureRand(true);

src/utilstrencodings.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ bool IsHex(const std::string& str)
6565
return (str.size() > 0) && (str.size()%2 == 0);
6666
}
6767

68+
bool IsHexNumber(const std::string& str)
69+
{
70+
size_t starting_location = 0;
71+
if (str.size() > 2 && *str.begin() == '0' && *(str.begin()+1) == 'x') {
72+
starting_location = 2;
73+
}
74+
for (auto c : str.substr(starting_location)) {
75+
if (HexDigit(c) < 0) return false;
76+
}
77+
// Return false for empty string or "0x".
78+
return (str.size() > starting_location);
79+
}
80+
6881
std::vector<unsigned char> ParseHex(const char* psz)
6982
{
7083
// convert hex dump to vector

src/utilstrencodings.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ std::string SanitizeString(const std::string& str, int rule = SAFE_CHARS_DEFAULT
3838
std::vector<unsigned char> ParseHex(const char* psz);
3939
std::vector<unsigned char> ParseHex(const std::string& str);
4040
signed char HexDigit(char c);
41+
/* Returns true if each character in str is a hex character, and has an even
42+
* number of hex digits.*/
4143
bool IsHex(const std::string& str);
44+
/**
45+
* Return true if the string is a hex number, optionally prefixed with "0x"
46+
*/
47+
bool IsHexNumber(const std::string& str);
4248
std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = nullptr);
4349
std::string DecodeBase64(const std::string& str);
4450
std::string EncodeBase64(const unsigned char* pch, size_t len);

src/validation.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
8383
bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT;
8484

8585
uint256 hashAssumeValid;
86+
arith_uint256 nMinimumChainWork;
8687

8788
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
8889
CAmount maxTxFee = DEFAULT_TRANSACTION_MAXFEE;
@@ -1035,8 +1036,6 @@ CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams)
10351036

10361037
bool IsInitialBlockDownload()
10371038
{
1038-
const CChainParams& chainParams = Params();
1039-
10401039
// Once this function has returned false, it must remain false.
10411040
static std::atomic<bool> latchToFalse{false};
10421041
// Optimization: pre-test latch before taking the lock.
@@ -1050,7 +1049,7 @@ bool IsInitialBlockDownload()
10501049
return true;
10511050
if (chainActive.Tip() == nullptr)
10521051
return true;
1053-
if (chainActive.Tip()->nChainWork < UintToArith256(chainParams.GetConsensus().nMinimumChainWork))
1052+
if (chainActive.Tip()->nChainWork < nMinimumChainWork)
10541053
return true;
10551054
if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge))
10561055
return true;
@@ -1670,7 +1669,7 @@ static bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockInd
16701669
if (it != mapBlockIndex.end()) {
16711670
if (it->second->GetAncestor(pindex->nHeight) == pindex &&
16721671
pindexBestHeader->GetAncestor(pindex->nHeight) == pindex &&
1673-
pindexBestHeader->nChainWork >= UintToArith256(chainparams.GetConsensus().nMinimumChainWork)) {
1672+
pindexBestHeader->nChainWork >= nMinimumChainWork) {
16741673
// This block is a member of the assumed verified chain and an ancestor of the best header.
16751674
// The equivalent time check discourages hash power from extorting the network via DOS attack
16761675
// into accepting an invalid block through telling users they must manually set assumevalid.

src/validation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,9 @@ extern bool fEnableReplacement;
186186
/** Block hash whose ancestors we will assume to have valid scripts without checking them. */
187187
extern uint256 hashAssumeValid;
188188

189+
/** Minimum work we will assume exists on some valid chain. */
190+
extern arith_uint256 nMinimumChainWork;
191+
189192
/** Best header we've seen so far (used for getheaders queries' starting points). */
190193
extern CBlockIndex *pindexBestHeader;
191194

0 commit comments

Comments
 (0)