Merge pull request #4559 from kittywhiskers/auxbps

merge bitcoin#16566...#18004: auxillary backports
This commit is contained in:
UdjinM6 2021-11-02 13:09:07 +03:00 committed by GitHub
commit c679fd9ab6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 123 additions and 49 deletions

View File

@ -13,7 +13,7 @@ define $(package)_preprocess_cmds
endef endef
define $(package)_config_cmds define $(package)_config_cmds
$(host_prefix)/bin/cmake -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix) .. $(host_prefix)/bin/cmake -DCMAKE_INSTALL_PREFIX:PATH=$(build_prefix) -DCMAKE_C_FLAGS="-Wl,--build-id=none" ..
endef endef
define $(package)_build_cmds define $(package)_build_cmds

View File

@ -100,7 +100,7 @@ bool CProposalValidator::ValidateName()
static constexpr std::string_view strAllowedChars{"-_abcdefghijklmnopqrstuvwxyz0123456789"}; static constexpr std::string_view strAllowedChars{"-_abcdefghijklmnopqrstuvwxyz0123456789"};
std::transform(strName.begin(), strName.end(), strName.begin(), ToLower); strName = ToLower(strName);
if (strName.find_first_not_of(strAllowedChars) != std::string::npos) { if (strName.find_first_not_of(strAllowedChars) != std::string::npos) {
strErrorMessages += "name contains invalid characters;"; strErrorMessages += "name contains invalid characters;";

View File

@ -261,10 +261,32 @@ std::string BCLog::Logger::LogTimestampStr(const std::string& str)
return strStamped; return strStamped;
} }
namespace BCLog {
/** Belts and suspenders: make sure outgoing log messages don't contain
* potentially suspicious characters, such as terminal control codes.
*
* This escapes control characters except newline ('\n') in C syntax.
* It escapes instead of removes them to still allow for troubleshooting
* issues where they accidentally end up in strings.
*/
std::string LogEscapeMessage(const std::string& str) {
std::string ret;
for (char ch_in : str) {
uint8_t ch = (uint8_t)ch_in;
if ((ch >= 32 || ch == '\n') && ch != '\x7f') {
ret += ch_in;
} else {
ret += strprintf("\\x%02x", ch);
}
}
return ret;
}
}
void BCLog::Logger::LogPrintStr(const std::string& str) void BCLog::Logger::LogPrintStr(const std::string& str)
{ {
StdLockGuard scoped_lock(m_cs); StdLockGuard scoped_lock(m_cs);
std::string str_prefixed = str; std::string str_prefixed = LogEscapeMessage(str);
if (m_log_threadnames && m_started_new_line) { if (m_log_threadnames && m_started_new_line) {
// 16 chars total, "dash-" is 5 of them and another 1 is a NUL terminator // 16 chars total, "dash-" is 5 of them and another 1 is a NUL terminator

View File

@ -42,8 +42,8 @@ bool fNameLookup = DEFAULT_NAME_LOOKUP;
static const int SOCKS5_RECV_TIMEOUT = 20 * 1000; static const int SOCKS5_RECV_TIMEOUT = 20 * 1000;
static std::atomic<bool> interruptSocks5Recv(false); static std::atomic<bool> interruptSocks5Recv(false);
enum Network ParseNetwork(std::string net) { enum Network ParseNetwork(const std::string& net_in) {
Downcase(net); std::string net = ToLower(net_in);
if (net == "ipv4") return NET_IPV4; if (net == "ipv4") return NET_IPV4;
if (net == "ipv6") return NET_IPV6; if (net == "ipv6") return NET_IPV6;
if (net == "onion") return NET_ONION; if (net == "onion") return NET_ONION;

View File

@ -38,7 +38,7 @@ public:
bool randomize_credentials; bool randomize_credentials;
}; };
enum Network ParseNetwork(std::string net); enum Network ParseNetwork(const std::string& net);
std::string GetNetworkName(enum Network net); std::string GetNetworkName(enum Network net);
bool SetProxy(enum Network net, const proxyType &addrProxy); bool SetProxy(enum Network net, const proxyType &addrProxy);
bool GetProxy(enum Network net, proxyType &proxyInfoOut); bool GetProxy(enum Network net, proxyType &proxyInfoOut);

View File

@ -29,6 +29,7 @@
#include <stdint.h> #include <stdint.h>
#include <QDebug> #include <QDebug>
#include <QThread>
#include <QTimer> #include <QTimer>
static int64_t nLastHeaderTipUpdateNotification = 0; static int64_t nLastHeaderTipUpdateNotification = 0;
@ -40,23 +41,37 @@ ClientModel::ClientModel(interfaces::Node& node, OptionsModel *_optionsModel, QO
optionsModel(_optionsModel), optionsModel(_optionsModel),
peerTableModel(nullptr), peerTableModel(nullptr),
banTableModel(nullptr), banTableModel(nullptr),
pollTimer(nullptr) m_thread(new QThread(this))
{ {
cachedBestHeaderHeight = -1; cachedBestHeaderHeight = -1;
cachedBestHeaderTime = -1; cachedBestHeaderTime = -1;
peerTableModel = new PeerTableModel(m_node, this); peerTableModel = new PeerTableModel(m_node, this);
banTableModel = new BanTableModel(m_node, this); banTableModel = new BanTableModel(m_node, this);
pollTimer = new QTimer(this);
connect(pollTimer, &QTimer::timeout, this, &ClientModel::updateTimer);
pollTimer->start(MODEL_UPDATE_DELAY);
mnListCached = std::make_shared<CDeterministicMNList>(); mnListCached = std::make_shared<CDeterministicMNList>();
QTimer* timer = new QTimer;
timer->setInterval(MODEL_UPDATE_DELAY);
connect(timer, &QTimer::timeout, [this] {
// no locking required at this point
// the following calls will acquire the required lock
Q_EMIT mempoolSizeChanged(m_node.getMempoolSize(), m_node.getMempoolDynamicUsage());
Q_EMIT islockCountChanged(m_node.llmq().getInstantSentLockCount());
});
connect(m_thread, &QThread::finished, timer, &QObject::deleteLater);
connect(m_thread, &QThread::started, [timer] { timer->start(); });
// move timer to thread so that polling doesn't disturb main event loop
timer->moveToThread(m_thread);
m_thread->start();
subscribeToCoreSignals(); subscribeToCoreSignals();
} }
ClientModel::~ClientModel() ClientModel::~ClientModel()
{ {
unsubscribeFromCoreSignals(); unsubscribeFromCoreSignals();
m_thread->quit();
m_thread->wait();
} }
int ClientModel::getNumConnections(unsigned int flags) const int ClientModel::getNumConnections(unsigned int flags) const
@ -128,14 +143,6 @@ std::vector<const CGovernanceObject*> ClientModel::getAllGovernanceObjects()
return m_node.gov().getAllNewerThan(0); return m_node.gov().getAllNewerThan(0);
} }
void ClientModel::updateTimer()
{
// no locking required at this point
// the following calls will acquire the required lock
Q_EMIT mempoolSizeChanged(m_node.getMempoolSize(), m_node.getMempoolDynamicUsage());
Q_EMIT islockCountChanged(m_node.llmq().getInstantSentLockCount());
}
void ClientModel::updateNumConnections(int numConnections) void ClientModel::updateNumConnections(int numConnections)
{ {
Q_EMIT numConnectionsChanged(numConnections); Q_EMIT numConnectionsChanged(numConnections);

View File

@ -104,7 +104,8 @@ private:
PeerTableModel *peerTableModel; PeerTableModel *peerTableModel;
BanTableModel *banTableModel; BanTableModel *banTableModel;
QTimer *pollTimer; //! A thread to interact with m_node asynchronously
QThread* const m_thread;
// The cache for mn list is not technically needed because CDeterministicMNManager // The cache for mn list is not technically needed because CDeterministicMNManager
// caches it internally for recent blocks but it's not enough to get consistent // caches it internally for recent blocks but it's not enough to get consistent
@ -133,7 +134,6 @@ Q_SIGNALS:
void showProgress(const QString &title, int nProgress); void showProgress(const QString &title, int nProgress);
public Q_SLOTS: public Q_SLOTS:
void updateTimer();
void updateNumConnections(int numConnections); void updateNumConnections(int numConnections);
void updateNetworkActive(bool networkActive); void updateNetworkActive(bool networkActive);
void updateAlert(); void updateAlert();

View File

@ -470,16 +470,19 @@ int GuiMain(int argc, char* argv[])
BitcoinApplication app(*node, argc, argv); BitcoinApplication app(*node, argc, argv);
// Register meta types used for QMetaObject::invokeMethod // Register meta types used for QMetaObject::invokeMethod and Qt::QueuedConnection
qRegisterMetaType<bool*>(); qRegisterMetaType<bool*>();
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
qRegisterMetaType<WalletModel*>(); qRegisterMetaType<WalletModel*>();
#endif #endif
// Need to pass name here as CAmount is a typedef (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType) // Register typedefs (see http://qt-project.org/doc/qt-5/qmetatype.html#qRegisterMetaType)
// IMPORTANT if it is no longer a typedef use the normal variant above // IMPORTANT: if CAmount is no longer a typedef use the normal variant above (see https://doc.qt.io/qt-5/qmetatype.html#qRegisterMetaType-1)
qRegisterMetaType<CAmount>("CAmount"); qRegisterMetaType<CAmount>("CAmount");
qRegisterMetaType<size_t>("size_t");
qRegisterMetaType<std::function<void()>>("std::function<void()>"); qRegisterMetaType<std::function<void()>>("std::function<void()>");
qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon"); qRegisterMetaType<QMessageBox::Icon>("QMessageBox::Icon");
/// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these /// 2. Parse command-line options. We do this after qt in order to show an error if there are problems parsing these
// Command-line options take precedence: // Command-line options take precedence:
node->setupServerArgs(); node->setupServerArgs();

View File

@ -564,7 +564,7 @@ static UniValue masternodelist(const JSONRPCRequest& request)
if (!request.params[0].isNull()) strMode = request.params[0].get_str(); if (!request.params[0].isNull()) strMode = request.params[0].get_str();
if (!request.params[1].isNull()) strFilter = request.params[1].get_str(); if (!request.params[1].isNull()) strFilter = request.params[1].get_str();
std::transform(strMode.begin(), strMode.end(), strMode.begin(), ToLower); strMode = ToLower(strMode);
if (request.fHelp || ( if (request.fHelp || (
strMode != "addr" && strMode != "full" && strMode != "info" && strMode != "json" && strMode != "addr" && strMode != "full" && strMode != "info" && strMode != "json" &&

View File

@ -188,7 +188,7 @@ bool ParseBoolV(const UniValue& v, const std::string &strName)
else if (v.isStr()) else if (v.isStr())
strBool = v.get_str(); strBool = v.get_str();
std::transform(strBool.begin(), strBool.end(), strBool.begin(), ToLower); strBool = ToLower(strBool);
if (strBool == "true" || strBool == "yes" || strBool == "1") { if (strBool == "true" || strBool == "yes" || strBool == "1") {
return true; return true;

View File

@ -25,6 +25,11 @@
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
/* defined in logging.cpp */
namespace BCLog {
std::string LogEscapeMessage(const std::string& str);
}
BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup) BOOST_FIXTURE_TEST_SUITE(util_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(util_criticalsection) BOOST_AUTO_TEST_CASE(util_criticalsection)
@ -1325,17 +1330,9 @@ BOOST_AUTO_TEST_CASE(test_ToLower)
BOOST_CHECK_EQUAL(ToLower(0), 0); BOOST_CHECK_EQUAL(ToLower(0), 0);
BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff'); BOOST_CHECK_EQUAL(ToLower('\xff'), '\xff');
std::string testVector; BOOST_CHECK_EQUAL(ToLower(""), "");
Downcase(testVector); BOOST_CHECK_EQUAL(ToLower("#HODL"), "#hodl");
BOOST_CHECK_EQUAL(testVector, ""); BOOST_CHECK_EQUAL(ToLower("\x00\xfe\xff"), "\x00\xfe\xff");
testVector = "#HODL";
Downcase(testVector);
BOOST_CHECK_EQUAL(testVector, "#hodl");
testVector = "\x00\xfe\xff";
Downcase(testVector);
BOOST_CHECK_EQUAL(testVector, "\x00\xfe\xff");
} }
BOOST_AUTO_TEST_CASE(test_ToUpper) BOOST_AUTO_TEST_CASE(test_ToUpper)
@ -1346,6 +1343,10 @@ BOOST_AUTO_TEST_CASE(test_ToUpper)
BOOST_CHECK_EQUAL(ToUpper('{'), '{'); BOOST_CHECK_EQUAL(ToUpper('{'), '{');
BOOST_CHECK_EQUAL(ToUpper(0), 0); BOOST_CHECK_EQUAL(ToUpper(0), 0);
BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff'); BOOST_CHECK_EQUAL(ToUpper('\xff'), '\xff');
BOOST_CHECK_EQUAL(ToUpper(""), "");
BOOST_CHECK_EQUAL(ToUpper("#hodl"), "#HODL");
BOOST_CHECK_EQUAL(ToUpper("\x00\xfe\xff"), "\x00\xfe\xff");
} }
BOOST_AUTO_TEST_CASE(test_Capitalize) BOOST_AUTO_TEST_CASE(test_Capitalize)
@ -1478,4 +1479,17 @@ BOOST_AUTO_TEST_CASE(test_spanparsing)
BOOST_CHECK_EQUAL(SpanToStr(results[3]), ""); BOOST_CHECK_EQUAL(SpanToStr(results[3]), "");
} }
BOOST_AUTO_TEST_CASE(test_LogEscapeMessage)
{
// ASCII and UTF-8 must pass through unaltered.
BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Valid log message貓"), "Valid log message貓");
// Newlines must pass through unaltered.
BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("Message\n with newlines\n"), "Message\n with newlines\n");
// Other control characters are escaped in C syntax.
BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage("\x01\x7f Corrupted log message\x0d"), R"(\x01\x7f Corrupted log message\x0d)");
// Embedded NULL characters are escaped too.
const std::string NUL("O\x00O", 3);
BOOST_CHECK_EQUAL(BCLog::LogEscapeMessage(NUL), R"(O\x00O)");
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -630,9 +630,18 @@ std::string HexStr(const Span<const uint8_t> s)
return rv; return rv;
} }
void Downcase(std::string& str) std::string ToLower(const std::string& str)
{ {
std::transform(str.begin(), str.end(), str.begin(), [](char c){return ToLower(c);}); std::string r;
for (auto ch : str) r += ToLower((unsigned char)ch);
return r;
}
std::string ToUpper(const std::string& str)
{
std::string r;
for (auto ch : str) r += ToUpper((unsigned char)ch);
return r;
} }
std::string Capitalize(std::string str) std::string Capitalize(std::string str)

View File

@ -203,6 +203,8 @@ bool ConvertBits(const O& outfn, I it, I end) {
* Converts the given character to its lowercase equivalent. * Converts the given character to its lowercase equivalent.
* This function is locale independent. It only converts uppercase * This function is locale independent. It only converts uppercase
* characters in the standard 7-bit ASCII range. * characters in the standard 7-bit ASCII range.
* This is a feature, not a limitation.
*
* @param[in] c the character to convert to lowercase. * @param[in] c the character to convert to lowercase.
* @return the lowercase equivalent of c; or the argument * @return the lowercase equivalent of c; or the argument
* if no conversion is possible. * if no conversion is possible.
@ -213,17 +215,22 @@ constexpr char ToLower(char c)
} }
/** /**
* Converts the given string to its lowercase equivalent. * Returns the lowercase equivalent of the given string.
* This function is locale independent. It only converts uppercase * This function is locale independent. It only converts uppercase
* characters in the standard 7-bit ASCII range. * characters in the standard 7-bit ASCII range.
* @param[in,out] str the string to convert to lowercase. * This is a feature, not a limitation.
*
* @param[in] str the string to convert to lowercase.
* @returns lowercased equivalent of str
*/ */
void Downcase(std::string& str); std::string ToLower(const std::string& str);
/** /**
* Converts the given character to its uppercase equivalent. * Converts the given character to its uppercase equivalent.
* This function is locale independent. It only converts lowercase * This function is locale independent. It only converts lowercase
* characters in the standard 7-bit ASCII range. * characters in the standard 7-bit ASCII range.
* This is a feature, not a limitation.
*
* @param[in] c the character to convert to uppercase. * @param[in] c the character to convert to uppercase.
* @return the uppercase equivalent of c; or the argument * @return the uppercase equivalent of c; or the argument
* if no conversion is possible. * if no conversion is possible.
@ -233,13 +240,25 @@ constexpr char ToUpper(char c)
return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c); return (c >= 'a' && c <= 'z' ? (c - 'a') + 'A' : c);
} }
/**
* Returns the uppercase equivalent of the given string.
* This function is locale independent. It only converts lowercase
* characters in the standard 7-bit ASCII range.
* This is a feature, not a limitation.
*
* @param[in] str the string to convert to uppercase.
* @returns UPPERCASED EQUIVALENT OF str
*/
std::string ToUpper(const std::string& str);
/** /**
* Capitalizes the first character of the given string. * Capitalizes the first character of the given string.
* This function is locale independent. It only capitalizes the * This function is locale independent. It only converts lowercase
* first character of the argument if it has an uppercase equivalent * characters in the standard 7-bit ASCII range.
* in the standard 7-bit ASCII range. * This is a feature, not a limitation.
*
* @param[in] str the string to capitalize. * @param[in] str the string to capitalize.
* @return string with the first letter capitalized. * @returns string with the first letter capitalized.
*/ */
std::string Capitalize(std::string str); std::string Capitalize(std::string str);

View File

@ -427,7 +427,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
key.erase(is_index); key.erase(is_index);
} }
#ifdef WIN32 #ifdef WIN32
std::transform(key.begin(), key.end(), key.begin(), ToLower); key = ToLower(key);
if (key[0] == '/') if (key[0] == '/')
key[0] = '-'; key[0] = '-';
#endif #endif