Auto merge of #4369 - daira:port-strMiscraceless, r=str4d

Upstream PRs relating to strMiscWarning

This pulls in upstream PRs bitcoin/bitcoin#7114 and bitcoin/bitcoin#9236 (non-QT parts).

* Fixes bitcoin/bitcoin#6809 - run-of-the-mill exceptions should not get into `strMiscWarning` (which is reported by `getinfo`).
* Eliminate data races for `strMiscWarning` and `fLargeWork*Found`. This moves all access to these data structures through accessor functions and protects them with a lock.
This commit is contained in:
Homu 2020-02-21 19:06:29 +00:00
commit 69e0e7ee62
11 changed files with 163 additions and 95 deletions

View File

@ -222,6 +222,7 @@ BITCOIN_CORE_H = \
wallet/rpcwallet.h \
wallet/wallet.h \
wallet/walletdb.h \
warnings.h \
zmq/zmqabstractnotifier.h \
zmq/zmqconfig.h\
zmq/zmqnotificationinterface.h \
@ -385,6 +386,7 @@ libbitcoin_common_a_SOURCES = \
script/standard.cpp \
transaction_builder.cpp \
utiltest.cpp \
warnings.cpp \
$(BITCOIN_CORE_H) \
$(LIBZCASH_H)

View File

@ -14,6 +14,9 @@
#include <stdint.h>
#include <string>
/** Minimum alert priority for enabling safe mode. */
static const int ALERT_PRIORITY_SAFE_MODE = 4000;
class CAlert;
class CNode;
class uint256;

View File

@ -44,6 +44,7 @@
#include "wallet/wallet.h"
#include "wallet/walletdb.h"
#endif
#include "warnings.h"
#include <stdint.h>
#include <stdio.h>

View File

@ -31,6 +31,7 @@
#include "validationinterface.h"
#include "wallet/asyncrpcoperation_sendmany.h"
#include "wallet/asyncrpcoperation_shieldcoinbase.h"
#include "warnings.h"
#include <algorithm>
#include <atomic>
@ -116,7 +117,7 @@ namespace {
/** Abort with a message */
bool AbortNode(const std::string& strMessage, const std::string& userMessage="")
{
strMiscWarning = strMessage;
SetMiscWarning(strMessage);
LogPrintf("*** %s\n", strMessage);
uiInterface.ThreadSafeMessageBox(
userMessage.empty() ? _("Error: A fatal internal error occurred, see debug.log for details") : userMessage,
@ -1795,8 +1796,6 @@ bool IsInitialBlockDownload(const CChainParams& chainParams)
return false;
}
static bool fLargeWorkForkFound = false;
static bool fLargeWorkInvalidChainFound = false;
static CBlockIndex *pindexBestForkTip = NULL;
static CBlockIndex *pindexBestForkBase = NULL;
@ -1815,7 +1814,7 @@ void CheckForkWarningConditions(const CChainParams& chainParams)
if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (GetBlockProof(*chainActive.Tip()) * 6)))
{
if (!fLargeWorkForkFound && pindexBestForkBase)
if (!GetfLargeWorkForkFound() && pindexBestForkBase)
{
std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
pindexBestForkBase->phashBlock->ToString() + std::string("'");
@ -1826,20 +1825,20 @@ void CheckForkWarningConditions(const CChainParams& chainParams)
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());
fLargeWorkForkFound = true;
SetfLargeWorkForkFound(true);
}
else
{
std::string warning = std::string("Warning: Found invalid chain at least ~6 blocks longer than our best chain.\nChain state database corruption likely.");
LogPrintf("%s: %s\n", warning.c_str(), __func__);
CAlert::Notify(warning, true);
fLargeWorkInvalidChainFound = true;
SetfLargeWorkInvalidChainFound(true);
}
}
else
{
fLargeWorkForkFound = false;
fLargeWorkInvalidChainFound = false;
SetfLargeWorkForkFound(false);
SetfLargeWorkInvalidChainFound(false);
}
}
@ -2484,7 +2483,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(const CChainParams&),
}
if (!strWarning.empty())
{
strMiscWarning = strWarning;
SetMiscWarning(strWarning);
CAlert::Notify(strWarning, true);
lastAlertTime = now;
}
@ -5083,71 +5082,6 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams)
assert(nNodes == forward.size());
}
//////////////////////////////////////////////////////////////////////////////
//
// CAlert
//
std::string GetWarnings(const std::string& strFor)
{
int nPriority = 0;
string strStatusBar;
string strRPC;
if (!CLIENT_VERSION_IS_RELEASE)
strStatusBar = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications");
if (GetBoolArg("-testsafemode", DEFAULT_TESTSAFEMODE))
strStatusBar = strRPC = "testsafemode enabled";
// Misc warnings like out of disk space and clock is wrong
if (strMiscWarning != "")
{
nPriority = 1000;
strStatusBar = strMiscWarning;
}
if (fLargeWorkForkFound)
{
nPriority = 2000;
strStatusBar = strRPC = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.");
}
else if (fLargeWorkInvalidChainFound)
{
nPriority = 2000;
strStatusBar = strRPC = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
}
// Alerts
{
LOCK(cs_mapAlerts);
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
{
const CAlert& alert = item.second;
if (alert.AppliesToMe() && alert.nPriority > nPriority)
{
nPriority = alert.nPriority;
strStatusBar = alert.strStatusBar;
if (alert.nPriority >= ALERT_PRIORITY_SAFE_MODE) {
strRPC = alert.strRPCError;
}
}
}
}
if (strFor == "statusbar")
return strStatusBar;
else if (strFor == "rpc")
return strRPC;
assert(!"GetWarnings(): invalid parameter");
return "error";
}
//////////////////////////////////////////////////////////////////////////////

View File

@ -55,8 +55,6 @@ struct CNodeStateStats;
/** Default for accepting alerts from the P2P network. */
static const bool DEFAULT_ALERTS = true;
/** Minimum alert priority for enabling safe mode. */
static const int ALERT_PRIORITY_SAFE_MODE = 4000;
/** Maximum reorg length we will accept before we shut down and alert the user. */
static const unsigned int MAX_REORG_LENGTH = COINBASE_MATURITY - 1;
/** Default for -minrelaytxfee, minimum relay fee for transactions */
@ -113,8 +111,6 @@ static const bool DEFAULT_CHECKPOINTS_ENABLED = true;
static const bool DEFAULT_TXINDEX = false;
static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
static const bool DEFAULT_TESTSAFEMODE = false;
#define equihash_parameters_acceptable(N, K) \
((CBlockHeader::HEADER_SIZE + equihash_solution_size(N, K))*MAX_HEADERS_RESULTS < \
MAX_PROTOCOL_MESSAGE_LENGTH-1000)

View File

@ -20,6 +20,7 @@
#include "util.h"
#include "utilstrencodings.h"
#include "utiltest.h"
#include "warnings.h"
#include "test/test_bitcoin.h"
@ -435,26 +436,26 @@ void PartitionAlertTestImpl(const Consensus::Params& params, int startTime, int
// Test 1: chain with blocks every nPowTargetSpacing seconds,
// as normal, no worries:
strMiscWarning = "";
SetMiscWarning("");
PartitionCheck(falseFunc, csDummy, &indexDummy[799]);
BOOST_CHECK_EQUAL("", strMiscWarning);
BOOST_CHECK_EQUAL("", GetMiscWarning());
// Test 2: go 3.5 hours without a block, expect a warning:
now += 3*60*60+30*60;
SetMockTime(now);
strMiscWarning = "";
SetMiscWarning("");
PartitionCheck(falseFunc, csDummy, &indexDummy[799]);
std::string expectedSlowErr = strprintf("WARNING: check your network connection, %d blocks received in the last 4 hours (%d expected)", expectedSlow, expectedTotal);
BOOST_CHECK_EQUAL(expectedSlowErr, strMiscWarning);
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
BOOST_CHECK_EQUAL(expectedSlowErr, GetMiscWarning());
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+GetMiscWarning());
// Test 3: test the "partition alerts only go off once per day"
// code:
now += 60*10;
SetMockTime(now);
strMiscWarning = "";
SetMiscWarning("");
PartitionCheck(falseFunc, csDummy, &indexDummy[799]);
BOOST_CHECK_EQUAL("", strMiscWarning);
BOOST_CHECK_EQUAL("", GetMiscWarning());
// Test 4: get 2.5 times as many blocks as expected:
start = now + 60*60*24; // Pretend it is a day later
@ -465,12 +466,12 @@ void PartitionAlertTestImpl(const Consensus::Params& params, int startTime, int
now = indexDummy[799].nTime + params.PoWTargetSpacing(0) * 2/5;
SetMockTime(now);
strMiscWarning = "";
SetMiscWarning("");
PartitionCheck(falseFunc, csDummy, &indexDummy[799]);
std::string expectedFastErr = strprintf("WARNING: abnormally high number of blocks generated, %d blocks received in the last 4 hours (%d expected)", expectedFast, expectedTotal);
BOOST_CHECK_EQUAL(expectedFastErr, strMiscWarning);
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
strMiscWarning = "";
BOOST_CHECK_EQUAL(expectedFastErr, GetMiscWarning());
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+GetMiscWarning());
SetMiscWarning("");
SetMockTime(0);
}

View File

@ -9,6 +9,7 @@
#include "ui_interface.h"
#include "util.h"
#include "utilstrencodings.h"
#include "warnings.h"
#include <boost/foreach.hpp>
@ -99,8 +100,8 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
if (!fMatch)
{
fDone = true;
string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Zcash will not work properly.");
strMiscWarning = strMessage;
std::string strMessage = _("Warning: Please check that your computer's date and time are correct! If your clock is wrong Zcash will not work properly.");
SetMiscWarning(strMessage);
LogPrintf("*** %s\n", strMessage);
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
}

View File

@ -1,5 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin Core developers
// Copyright (c) 2015-2020 The Zcash developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
@ -109,7 +110,7 @@ bool fPrintToConsole = false;
bool fPrintToDebugLog = true;
bool fDaemon = false;
bool fServer = false;
string strMiscWarning;
bool fLogTimestamps = DEFAULT_LOGTIMESTAMPS;
bool fLogTimeMicros = DEFAULT_LOGTIMEMICROS;
bool fLogIPs = DEFAULT_LOGIPS;
@ -449,7 +450,6 @@ void PrintExceptionContinue(const std::exception* pex, const char* pszThread)
std::string message = FormatException(pex, pszThread);
LogPrintf("\n\n************************\n%s\n", message);
fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
strMiscWarning = message;
}
boost::filesystem::path GetDefaultDataDir()
@ -923,4 +923,3 @@ int GetNumCores()
{
return boost::thread::physical_concurrency();
}

View File

@ -47,7 +47,7 @@ extern bool fDebug;
extern bool fPrintToConsole;
extern bool fPrintToDebugLog;
extern bool fServer;
extern std::string strMiscWarning;
extern bool fLogTimestamps;
extern bool fLogIPs;
extern std::atomic<bool> fReopenDebugLog;

109
src/warnings.cpp Normal file
View File

@ -0,0 +1,109 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "sync.h"
#include "clientversion.h"
#include "util.h"
#include "warnings.h"
#include "alert.h"
#include "uint256.h"
CCriticalSection cs_warnings;
std::string strMiscWarning;
bool fLargeWorkForkFound = false;
bool fLargeWorkInvalidChainFound = false;
void SetMiscWarning(const std::string& strWarning)
{
LOCK(cs_warnings);
strMiscWarning = strWarning;
}
std::string GetMiscWarning()
{
LOCK(cs_warnings);
return strMiscWarning;
}
void SetfLargeWorkForkFound(bool flag)
{
LOCK(cs_warnings);
fLargeWorkForkFound = flag;
}
bool GetfLargeWorkForkFound()
{
LOCK(cs_warnings);
return fLargeWorkForkFound;
}
void SetfLargeWorkInvalidChainFound(bool flag)
{
LOCK(cs_warnings);
fLargeWorkInvalidChainFound = flag;
}
bool GetfLargeWorkInvalidChainFound()
{
LOCK(cs_warnings);
return fLargeWorkInvalidChainFound;
}
std::string GetWarnings(const std::string& strFor)
{
int nPriority = 0;
std::string strStatusBar;
std::string strRPC;
LOCK(cs_warnings);
if (!CLIENT_VERSION_IS_RELEASE)
strStatusBar = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications");
if (GetBoolArg("-testsafemode", DEFAULT_TESTSAFEMODE))
strStatusBar = strRPC = "testsafemode enabled";
// Misc warnings like out of disk space and clock is wrong
if (strMiscWarning != "")
{
nPriority = 1000;
strStatusBar = strMiscWarning;
}
if (fLargeWorkForkFound)
{
nPriority = 2000;
strStatusBar = strRPC = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.");
}
else if (fLargeWorkInvalidChainFound)
{
nPriority = 2000;
strStatusBar = strRPC = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
}
// Alerts
{
LOCK(cs_mapAlerts);
for (const std::pair<uint256, CAlert>& item : mapAlerts)
{
const CAlert& alert = item.second;
if (alert.AppliesToMe() && alert.nPriority > nPriority)
{
nPriority = alert.nPriority;
strStatusBar = alert.strStatusBar;
if (alert.nPriority >= ALERT_PRIORITY_SAFE_MODE) {
strRPC = alert.strRPCError;
}
}
}
}
if (strFor == "statusbar")
return strStatusBar;
else if (strFor == "rpc")
return strRPC;
assert(!"GetWarnings(): invalid parameter");
return "error";
}

22
src/warnings.h Normal file
View File

@ -0,0 +1,22 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_WARNINGS_H
#define BITCOIN_WARNINGS_H
#include <stdlib.h>
#include <string>
void SetMiscWarning(const std::string& strWarning);
std::string GetMiscWarning();
void SetfLargeWorkForkFound(bool flag);
bool GetfLargeWorkForkFound();
void SetfLargeWorkInvalidChainFound(bool flag);
bool GetfLargeWorkInvalidChainFound();
std::string GetWarnings(const std::string& strFor);
static const bool DEFAULT_TESTSAFEMODE = false;
#endif // BITCOIN_WARNINGS_H