Allow setting nMinimumChainWork on command line

This commit is contained in:
Suhas Daftuar 2017-05-07 14:10:19 -04:00 committed by Suhas Daftuar
parent e0e3cbbf08
commit 0311836f69
7 changed files with 68 additions and 5 deletions

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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.

View file

@ -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;