Merge #7692: Remove p2p alert system
cfd519e Add release note documentation (BtcDrak) 6601ce5 protocol.h/cpp: Removes NetMsgType::ALERT (Thomas Kerin) ad72104 Formatting (BtcDrak) 1b77471 Remove alert keys (BtcDrak) 01fdfef Remove `-alerts` option (BtcDrak) 9206634 Update alert notification and GUI (BtcDrak) bbb9d1d Remove p2p alert handling (BtcDrak) manual fixes Signed-off-by: Pasta <pasta@dashboost.org> remove sendalert.cpp Signed-off-by: Pasta <pasta@dashboost.org> CAlertNotify -> AlertNotify Signed-off-by: Pasta <pasta@dashboost.org> remove alert.h Signed-off-by: Pasta <pasta@dashboost.org> remove vAlertPubKey for DevNet Signed-off-by: Pasta <pasta@dashboost.org> remove src/main.cpp
This commit is contained in:
parent
1f6e0435b4
commit
a1770b0c25
@ -105,7 +105,6 @@ BITCOIN_CORE_H = \
|
||||
addressindex.h \
|
||||
spentindex.h \
|
||||
addrman.h \
|
||||
alert.h \
|
||||
base58.h \
|
||||
batchedlogger.h \
|
||||
bip39.h \
|
||||
@ -262,7 +261,6 @@ libdash_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||
libdash_server_a_SOURCES = \
|
||||
addrdb.cpp \
|
||||
addrman.cpp \
|
||||
alert.cpp \
|
||||
batchedlogger.cpp \
|
||||
bloom.cpp \
|
||||
blockencodings.cpp \
|
||||
@ -330,7 +328,6 @@ libdash_server_a_SOURCES = \
|
||||
rpc/server.cpp \
|
||||
script/sigcache.cpp \
|
||||
script/ismine.cpp \
|
||||
sendalert.cpp \
|
||||
spork.cpp \
|
||||
timedata.cpp \
|
||||
torcontrol.cpp \
|
||||
|
@ -20,7 +20,7 @@ JSON_TEST_FILES = \
|
||||
test/data/tx_valid.json \
|
||||
test/data/sighash.json
|
||||
|
||||
RAW_TEST_FILES = test/data/alertTests.raw
|
||||
RAW_TEST_FILES =
|
||||
|
||||
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
|
||||
|
||||
|
286
src/alert.cpp
286
src/alert.cpp
@ -1,286 +0,0 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 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 "alert.h"
|
||||
|
||||
#include "base58.h"
|
||||
#include "clientversion.h"
|
||||
#include "net.h"
|
||||
#include "netmessagemaker.h"
|
||||
#include "pubkey.h"
|
||||
#include "timedata.h"
|
||||
#include "ui_interface.h"
|
||||
#include "util.h"
|
||||
#include "utilstrencodings.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
std::map<uint256, CAlert> mapAlerts;
|
||||
CCriticalSection cs_mapAlerts;
|
||||
|
||||
void CUnsignedAlert::SetNull()
|
||||
{
|
||||
nVersion = 1;
|
||||
nRelayUntil = 0;
|
||||
nExpiration = 0;
|
||||
nID = 0;
|
||||
nCancel = 0;
|
||||
setCancel.clear();
|
||||
nMinVer = 0;
|
||||
nMaxVer = 0;
|
||||
setSubVer.clear();
|
||||
nPriority = 0;
|
||||
|
||||
strComment.clear();
|
||||
strStatusBar.clear();
|
||||
strReserved.clear();
|
||||
}
|
||||
|
||||
std::string CUnsignedAlert::ToString() const
|
||||
{
|
||||
std::string strSetCancel;
|
||||
for (const auto& n : setCancel)
|
||||
strSetCancel += strprintf("%d ", n);
|
||||
std::string strSetSubVer;
|
||||
for (const auto& str : setSubVer)
|
||||
strSetSubVer += "\"" + str + "\" ";
|
||||
return strprintf(
|
||||
"CAlert(\n"
|
||||
" nVersion = %d\n"
|
||||
" nRelayUntil = %d\n"
|
||||
" nExpiration = %d\n"
|
||||
" nID = %d\n"
|
||||
" nCancel = %d\n"
|
||||
" setCancel = %s\n"
|
||||
" nMinVer = %d\n"
|
||||
" nMaxVer = %d\n"
|
||||
" setSubVer = %s\n"
|
||||
" nPriority = %d\n"
|
||||
" strComment = \"%s\"\n"
|
||||
" strStatusBar = \"%s\"\n"
|
||||
")\n",
|
||||
nVersion,
|
||||
nRelayUntil,
|
||||
nExpiration,
|
||||
nID,
|
||||
nCancel,
|
||||
strSetCancel,
|
||||
nMinVer,
|
||||
nMaxVer,
|
||||
strSetSubVer,
|
||||
nPriority,
|
||||
strComment,
|
||||
strStatusBar);
|
||||
}
|
||||
|
||||
void CAlert::SetNull()
|
||||
{
|
||||
CUnsignedAlert::SetNull();
|
||||
vchMsg.clear();
|
||||
vchSig.clear();
|
||||
}
|
||||
|
||||
bool CAlert::IsNull() const
|
||||
{
|
||||
return (nExpiration == 0);
|
||||
}
|
||||
|
||||
uint256 CAlert::GetHash() const
|
||||
{
|
||||
return Hash(this->vchMsg.begin(), this->vchMsg.end());
|
||||
}
|
||||
|
||||
bool CAlert::IsInEffect() const
|
||||
{
|
||||
return (GetAdjustedTime() < nExpiration);
|
||||
}
|
||||
|
||||
bool CAlert::Cancels(const CAlert& alert) const
|
||||
{
|
||||
if (!IsInEffect())
|
||||
return false; // this was a no-op before 31403
|
||||
return (alert.nID <= nCancel || setCancel.count(alert.nID));
|
||||
}
|
||||
|
||||
bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const
|
||||
{
|
||||
// TODO: rework for client-version-embedded-in-strSubVer ?
|
||||
return (IsInEffect() &&
|
||||
nMinVer <= nVersion && nVersion <= nMaxVer &&
|
||||
(setSubVer.empty() || setSubVer.count(strSubVerIn)));
|
||||
}
|
||||
|
||||
bool CAlert::AppliesToMe() const
|
||||
{
|
||||
return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
|
||||
}
|
||||
|
||||
bool CAlert::RelayTo(CNode* pnode, CConnman& connman) const
|
||||
{
|
||||
if (!IsInEffect())
|
||||
return false;
|
||||
// don't relay to nodes which haven't sent their version message
|
||||
if (pnode->nVersion == 0)
|
||||
return false;
|
||||
// returns true if wasn't already contained in the set
|
||||
if (pnode->setKnown.insert(GetHash()).second)
|
||||
{
|
||||
if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
|
||||
AppliesToMe() ||
|
||||
GetAdjustedTime() < nRelayUntil)
|
||||
{
|
||||
connman.PushMessage(pnode, CNetMsgMaker(pnode->GetSendVersion()).Make(NetMsgType::ALERT, *this));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CAlert::Sign()
|
||||
{
|
||||
CDataStream sMsg(SER_NETWORK, CLIENT_VERSION);
|
||||
sMsg << *(CUnsignedAlert*)this;
|
||||
vchMsg = std::vector<unsigned char>(sMsg.begin(), sMsg.end());
|
||||
CBitcoinSecret vchSecret;
|
||||
if (!vchSecret.SetString(GetArg("-alertkey", "")))
|
||||
{
|
||||
printf("CAlert::SignAlert() : vchSecret.SetString failed\n");
|
||||
return false;
|
||||
}
|
||||
CKey key = vchSecret.GetKey();
|
||||
if (!key.Sign(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
|
||||
{
|
||||
printf("CAlert::SignAlert() : key.Sign failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAlert::CheckSignature(const std::vector<unsigned char>& alertKey) const
|
||||
{
|
||||
CPubKey key(alertKey);
|
||||
if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
|
||||
return error("CAlert::CheckSignature(): verify signature failed");
|
||||
|
||||
// Now unserialize the data
|
||||
CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
|
||||
sMsg >> *(CUnsignedAlert*)this;
|
||||
return true;
|
||||
}
|
||||
|
||||
CAlert CAlert::getAlertByHash(const uint256 &hash)
|
||||
{
|
||||
CAlert retval;
|
||||
{
|
||||
LOCK(cs_mapAlerts);
|
||||
std::map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
|
||||
if(mi != mapAlerts.end())
|
||||
retval = mi->second;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool CAlert::ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread) const
|
||||
{
|
||||
if (!CheckSignature(alertKey))
|
||||
return false;
|
||||
if (!IsInEffect())
|
||||
return false;
|
||||
|
||||
// alert.nID=max is reserved for if the alert key is
|
||||
// compromised. It must have a pre-defined message,
|
||||
// must never expire, must apply to all versions,
|
||||
// and must cancel all previous
|
||||
// alerts or it will be ignored (so an attacker can't
|
||||
// send an "everything is OK, don't panic" version that
|
||||
// cannot be overridden):
|
||||
int maxInt = std::numeric_limits<int>::max();
|
||||
if (nID == maxInt)
|
||||
{
|
||||
if (!(
|
||||
nExpiration == maxInt &&
|
||||
nCancel == (maxInt-1) &&
|
||||
nMinVer == 0 &&
|
||||
nMaxVer == maxInt &&
|
||||
setSubVer.empty() &&
|
||||
nPriority == maxInt &&
|
||||
strStatusBar == "URGENT: Alert key compromised, upgrade required"
|
||||
))
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
LOCK(cs_mapAlerts);
|
||||
// Cancel previous alerts
|
||||
for (std::map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
|
||||
{
|
||||
const CAlert& alert = (*mi).second;
|
||||
if (Cancels(alert))
|
||||
{
|
||||
LogPrint(BCLog::ALERT, "cancelling alert %d\n", alert.nID);
|
||||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
|
||||
mapAlerts.erase(mi++);
|
||||
}
|
||||
else if (!alert.IsInEffect())
|
||||
{
|
||||
LogPrint(BCLog::ALERT, "expiring alert %d\n", alert.nID);
|
||||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
|
||||
mapAlerts.erase(mi++);
|
||||
}
|
||||
else
|
||||
mi++;
|
||||
}
|
||||
|
||||
// Check if this alert has been cancelled
|
||||
for (const auto& item : mapAlerts)
|
||||
{
|
||||
const CAlert& alert = item.second;
|
||||
if (alert.Cancels(*this))
|
||||
{
|
||||
LogPrint(BCLog::ALERT, "alert already cancelled by %d\n", alert.nID);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to mapAlerts
|
||||
mapAlerts.insert(std::make_pair(GetHash(), *this));
|
||||
// Notify UI and -alertnotify if it applies to me
|
||||
if(AppliesToMe())
|
||||
{
|
||||
uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
|
||||
Notify(strStatusBar, fThread);
|
||||
}
|
||||
}
|
||||
|
||||
LogPrint(BCLog::ALERT, "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CAlert::Notify(const std::string& strMessage, bool fThread)
|
||||
{
|
||||
std::string strCmd = GetArg("-alertnotify", "");
|
||||
if (strCmd.empty()) return;
|
||||
|
||||
// Alert text should be plain ascii coming from a trusted source, but to
|
||||
// be safe we first strip anything not in safeChars, then add single quotes around
|
||||
// the whole string before passing it to the shell:
|
||||
std::string singleQuote("'");
|
||||
std::string safeStatus = SanitizeString(strMessage);
|
||||
safeStatus = singleQuote+safeStatus+singleQuote;
|
||||
boost::replace_all(strCmd, "%s", safeStatus);
|
||||
|
||||
if (fThread)
|
||||
boost::thread t(runCommand, strCmd); // thread runs free
|
||||
else
|
||||
runCommand(strCmd);
|
||||
}
|
114
src/alert.h
114
src/alert.h
@ -1,114 +0,0 @@
|
||||
// Copyright (c) 2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2015 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_ALERT_H
|
||||
#define BITCOIN_ALERT_H
|
||||
|
||||
#include "serialize.h"
|
||||
#include "sync.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
class CAlert;
|
||||
class CNode;
|
||||
class CConnman;
|
||||
class uint256;
|
||||
|
||||
extern std::map<uint256, CAlert> mapAlerts;
|
||||
extern CCriticalSection cs_mapAlerts;
|
||||
|
||||
/** Alerts are for notifying old versions if they become too obsolete and
|
||||
* need to upgrade. The message is displayed in the status bar.
|
||||
* Alert messages are broadcast as a vector of signed data. Unserializing may
|
||||
* not read the entire buffer if the alert is for a newer version, but older
|
||||
* versions can still relay the original data.
|
||||
*/
|
||||
class CUnsignedAlert
|
||||
{
|
||||
public:
|
||||
int nVersion;
|
||||
int64_t nRelayUntil; // when newer nodes stop relaying to newer nodes
|
||||
int64_t nExpiration;
|
||||
int nID;
|
||||
int nCancel;
|
||||
std::set<int> setCancel;
|
||||
int nMinVer; // lowest version inclusive
|
||||
int nMaxVer; // highest version inclusive
|
||||
std::set<std::string> setSubVer; // empty matches all
|
||||
int nPriority;
|
||||
|
||||
// Actions
|
||||
std::string strComment;
|
||||
std::string strStatusBar;
|
||||
std::string strReserved;
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(this->nVersion);
|
||||
READWRITE(nRelayUntil);
|
||||
READWRITE(nExpiration);
|
||||
READWRITE(nID);
|
||||
READWRITE(nCancel);
|
||||
READWRITE(setCancel);
|
||||
READWRITE(nMinVer);
|
||||
READWRITE(nMaxVer);
|
||||
READWRITE(setSubVer);
|
||||
READWRITE(nPriority);
|
||||
|
||||
READWRITE(LIMITED_STRING(strComment, 65536));
|
||||
READWRITE(LIMITED_STRING(strStatusBar, 256));
|
||||
READWRITE(LIMITED_STRING(strReserved, 256));
|
||||
}
|
||||
|
||||
void SetNull();
|
||||
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
/** An alert is a combination of a serialized CUnsignedAlert and a signature. */
|
||||
class CAlert : public CUnsignedAlert
|
||||
{
|
||||
public:
|
||||
std::vector<unsigned char> vchMsg;
|
||||
std::vector<unsigned char> vchSig;
|
||||
|
||||
CAlert()
|
||||
{
|
||||
SetNull();
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(vchMsg);
|
||||
READWRITE(vchSig);
|
||||
}
|
||||
|
||||
void SetNull();
|
||||
bool IsNull() const;
|
||||
uint256 GetHash() const;
|
||||
bool IsInEffect() const;
|
||||
bool Cancels(const CAlert& alert) const;
|
||||
bool AppliesTo(int nVersion, const std::string& strSubVerIn) const;
|
||||
bool AppliesToMe() const;
|
||||
bool RelayTo(CNode* pnode, CConnman& connman) const;
|
||||
bool Sign();
|
||||
bool CheckSignature(const std::vector<unsigned char>& alertKey) const;
|
||||
bool ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread = true) const; // fThread means run -alertnotify in a free-running thread
|
||||
static void Notify(const std::string& strMessage, bool fThread = true);
|
||||
|
||||
/*
|
||||
* Get copy of (active) alert object by hash. Returns a null alert if it is not found.
|
||||
*/
|
||||
static CAlert getAlertByHash(const uint256 &hash);
|
||||
};
|
||||
|
||||
#endif // BITCOIN_ALERT_H
|
@ -283,7 +283,6 @@ public:
|
||||
pchMessageStart[1] = 0x0c;
|
||||
pchMessageStart[2] = 0x6b;
|
||||
pchMessageStart[3] = 0xbd;
|
||||
vAlertPubKey = ParseHex("048240a8748a80a286b270ba126705ced4f2ce5a7847b3610ea3c06513150dade2a8512ed5ea86320824683fc0818f0ac019214973e677acd1244f6d0571fc5103");
|
||||
nDefaultPort = 9999;
|
||||
nPruneAfterHeight = 100000;
|
||||
|
||||
@ -461,7 +460,6 @@ public:
|
||||
pchMessageStart[1] = 0xe2;
|
||||
pchMessageStart[2] = 0xca;
|
||||
pchMessageStart[3] = 0xff;
|
||||
vAlertPubKey = ParseHex("04517d8a699cb43d3938d7b24faaff7cda448ca4ea267723ba614784de661949bf632d6304316b244646dea079735b9a6fc4af804efb4752075b9fe2245e14e412");
|
||||
nDefaultPort = 19999;
|
||||
nPruneAfterHeight = 1000;
|
||||
|
||||
@ -620,7 +618,6 @@ public:
|
||||
pchMessageStart[1] = 0xca;
|
||||
pchMessageStart[2] = 0xff;
|
||||
pchMessageStart[3] = 0xce;
|
||||
vAlertPubKey = ParseHex("04517d8a699cb43d3938d7b24faaff7cda448ca4ea267723ba614784de661949bf632d6304316b244646dea079735b9a6fc4af804efb4752075b9fe2245e14e412");
|
||||
nDefaultPort = 19999;
|
||||
nPruneAfterHeight = 1000;
|
||||
|
||||
|
@ -58,7 +58,6 @@ public:
|
||||
|
||||
const Consensus::Params& GetConsensus() const { return consensus; }
|
||||
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
|
||||
const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
|
||||
int GetDefaultPort() const { return nDefaultPort; }
|
||||
|
||||
const CBlock& GenesisBlock() const { return genesis; }
|
||||
@ -95,8 +94,6 @@ protected:
|
||||
|
||||
Consensus::Params consensus;
|
||||
CMessageHeader::MessageStartChars pchMessageStart;
|
||||
//! Raw pub key bytes for the broadcast alert signing key.
|
||||
std::vector<unsigned char> vAlertPubKey;
|
||||
int nDefaultPort;
|
||||
uint64_t nPruneAfterHeight;
|
||||
std::vector<CDNSSeedData> vSeeds;
|
||||
|
@ -444,7 +444,6 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||
std::string strUsage = HelpMessageGroup(_("Options:"));
|
||||
strUsage += HelpMessageOpt("-?", _("Print this help message and exit"));
|
||||
strUsage += HelpMessageOpt("-version", _("Print version and exit"));
|
||||
strUsage += HelpMessageOpt("-alerts", strprintf(_("Receive and display P2P network alerts (default: %u)"), DEFAULT_ALERTS));
|
||||
strUsage += HelpMessageOpt("-alertnotify=<cmd>", _("Execute command when a relevant alert is received or we see a really long fork (%s in cmd is replaced by message)"));
|
||||
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
|
||||
if (showDebug)
|
||||
@ -1313,8 +1312,6 @@ bool AppInitParameterInteraction()
|
||||
fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
|
||||
nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes);
|
||||
|
||||
fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS);
|
||||
|
||||
// Option to startup with mocktime set (used for regression testing):
|
||||
SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
|
||||
|
||||
|
@ -5,7 +5,6 @@
|
||||
|
||||
#include "net_processing.h"
|
||||
|
||||
#include "alert.h"
|
||||
#include "addrman.h"
|
||||
#include "arith_uint256.h"
|
||||
#include "blockencodings.h"
|
||||
@ -1616,13 +1615,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
connman.MarkAddressGood(pfrom->addr);
|
||||
}
|
||||
|
||||
// Relay alerts
|
||||
{
|
||||
LOCK(cs_mapAlerts);
|
||||
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
|
||||
item.second.RelayTo(pfrom, connman);
|
||||
}
|
||||
|
||||
std::string remoteAddr;
|
||||
if (fLogIPs)
|
||||
remoteAddr = ", peeraddr=" + pfrom->addr.ToString();
|
||||
@ -2926,37 +2918,6 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||
}
|
||||
|
||||
|
||||
else if (fAlerts && strCommand == NetMsgType::ALERT)
|
||||
{
|
||||
CAlert alert;
|
||||
vRecv >> alert;
|
||||
|
||||
uint256 alertHash = alert.GetHash();
|
||||
if (pfrom->setKnown.count(alertHash) == 0)
|
||||
{
|
||||
if (alert.ProcessAlert(chainparams.AlertKey()))
|
||||
{
|
||||
// Relay
|
||||
pfrom->setKnown.insert(alertHash);
|
||||
{
|
||||
connman.ForEachNode([&alert, &connman](CNode* pnode) {
|
||||
alert.RelayTo(pnode, connman);
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Small DoS penalty so peers that send us lots of
|
||||
// duplicate/expired/invalid-signature/whatever alerts
|
||||
// eventually get banned.
|
||||
// This isn't a Misbehaving(100) (immediate ban) because the
|
||||
// peer might be an older or different implementation with
|
||||
// a different signature key, etc.
|
||||
Misbehaving(pfrom->GetId(), 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
else if (strCommand == NetMsgType::FILTERLOAD)
|
||||
{
|
||||
CBloomFilter filter;
|
||||
|
@ -28,7 +28,6 @@ const char *GETADDR="getaddr";
|
||||
const char *MEMPOOL="mempool";
|
||||
const char *PING="ping";
|
||||
const char *PONG="pong";
|
||||
const char *ALERT="alert";
|
||||
const char *NOTFOUND="notfound";
|
||||
const char *FILTERLOAD="filterload";
|
||||
const char *FILTERADD="filteradd";
|
||||
@ -132,7 +131,6 @@ const static std::string allNetMessageTypes[] = {
|
||||
NetMsgType::MEMPOOL,
|
||||
NetMsgType::PING,
|
||||
NetMsgType::PONG,
|
||||
NetMsgType::ALERT,
|
||||
NetMsgType::NOTFOUND,
|
||||
NetMsgType::FILTERLOAD,
|
||||
NetMsgType::FILTERADD,
|
||||
|
@ -160,13 +160,6 @@ extern const char *PING;
|
||||
* @see https://bitcoin.org/en/developer-reference#pong
|
||||
*/
|
||||
extern const char *PONG;
|
||||
/**
|
||||
* The alert message warns nodes of problems that may affect them or the rest
|
||||
* of the network.
|
||||
* @since protocol version 311.
|
||||
* @see https://bitcoin.org/en/developer-reference#alert
|
||||
*/
|
||||
extern const char *ALERT;
|
||||
/**
|
||||
* The notfound message is a reply to a getdata message which requested an
|
||||
* object the receiving node does not have available for relay.
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "guiutil.h"
|
||||
#include "peertablemodel.h"
|
||||
|
||||
#include "alert.h"
|
||||
#include "chain.h"
|
||||
#include "chainparams.h"
|
||||
#include "checkpoints.h"
|
||||
@ -202,20 +201,8 @@ void ClientModel::updateNetworkActive(bool networkActive)
|
||||
Q_EMIT networkActiveChanged(networkActive);
|
||||
}
|
||||
|
||||
void ClientModel::updateAlert(const QString &hash, int status)
|
||||
void ClientModel::updateAlert()
|
||||
{
|
||||
// Show error message notification for new alert
|
||||
if(status == CT_NEW)
|
||||
{
|
||||
uint256 hash_256;
|
||||
hash_256.SetHex(hash.toStdString());
|
||||
CAlert alert = CAlert::getAlertByHash(hash_256);
|
||||
if(!alert.IsNull())
|
||||
{
|
||||
Q_EMIT message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
Q_EMIT alertsChanged(getStatusBarWarnings());
|
||||
}
|
||||
|
||||
@ -323,12 +310,10 @@ static void NotifyNetworkActiveChanged(ClientModel *clientmodel, bool networkAct
|
||||
Q_ARG(bool, networkActive));
|
||||
}
|
||||
|
||||
static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
|
||||
static void NotifyAlertChanged(ClientModel *clientmodel)
|
||||
{
|
||||
qDebug() << "NotifyAlertChanged: " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status);
|
||||
QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
|
||||
Q_ARG(QString, QString::fromStdString(hash.GetHex())),
|
||||
Q_ARG(int, status));
|
||||
qDebug() << "NotifyAlertChanged";
|
||||
QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
static void BannedListChanged(ClientModel *clientmodel)
|
||||
@ -382,7 +367,7 @@ void ClientModel::subscribeToCoreSignals()
|
||||
uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
|
||||
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
||||
uiInterface.NotifyNetworkActiveChanged.connect(boost::bind(NotifyNetworkActiveChanged, this, _1));
|
||||
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
||||
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this));
|
||||
uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
|
||||
uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2, false));
|
||||
uiInterface.NotifyHeaderTip.connect(boost::bind(BlockTipChanged, this, _1, _2, true));
|
||||
@ -396,7 +381,7 @@ void ClientModel::unsubscribeFromCoreSignals()
|
||||
uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
|
||||
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
||||
uiInterface.NotifyNetworkActiveChanged.disconnect(boost::bind(NotifyNetworkActiveChanged, this, _1));
|
||||
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
||||
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this));
|
||||
uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
|
||||
uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, false));
|
||||
uiInterface.NotifyHeaderTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, true));
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
void setMasternodeList(const CDeterministicMNList& mnList);
|
||||
CDeterministicMNList getMasternodeList() const;
|
||||
void refreshMasternodeList();
|
||||
|
||||
|
||||
quint64 getTotalBytesRecv() const;
|
||||
quint64 getTotalBytesSent() const;
|
||||
|
||||
@ -134,7 +134,7 @@ public Q_SLOTS:
|
||||
void updateTimer();
|
||||
void updateNumConnections(int numConnections);
|
||||
void updateNetworkActive(bool networkActive);
|
||||
void updateAlert(const QString &hash, int status);
|
||||
void updateAlert();
|
||||
void updateBanlist();
|
||||
};
|
||||
|
||||
|
@ -1,112 +0,0 @@
|
||||
#include "alert.h"
|
||||
#include "clientversion.h"
|
||||
#include "chainparams.h"
|
||||
#include "init.h"
|
||||
#include "net.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "utiltime.h"
|
||||
|
||||
/*
|
||||
If you need to broadcast an alert, here's what to do:
|
||||
|
||||
1. Modify alert parameters below, see alert.* and comments in the code
|
||||
for what does what.
|
||||
|
||||
2. run dashd with -printalert or -sendalert like this:
|
||||
/path/to/dashd -printalert
|
||||
|
||||
One minute after starting up the alert will be broadcast. It is then
|
||||
flooded through the network until the nRelayUntil time, and will be
|
||||
active until nExpiration OR the alert is cancelled.
|
||||
|
||||
If you screw up something, send another alert with nCancel set to cancel
|
||||
the bad alert.
|
||||
*/
|
||||
|
||||
void ThreadSendAlert(CConnman& connman)
|
||||
{
|
||||
if (!IsArgSet("-sendalert") && !IsArgSet("-printalert"))
|
||||
return;
|
||||
|
||||
// Wait one minute so we get well connected. If we only need to print
|
||||
// but not to broadcast - do this right away.
|
||||
if (IsArgSet("-sendalert"))
|
||||
MilliSleep(60*1000);
|
||||
|
||||
//
|
||||
// Alerts are relayed around the network until nRelayUntil, flood
|
||||
// filling to every node.
|
||||
// After the relay time is past, new nodes are told about alerts
|
||||
// when they connect to peers, until either nExpiration or
|
||||
// the alert is cancelled by a newer alert.
|
||||
// Nodes never save alerts to disk, they are in-memory-only.
|
||||
//
|
||||
CAlert alert;
|
||||
alert.nRelayUntil = GetAdjustedTime() + 15 * 60;
|
||||
alert.nExpiration = GetAdjustedTime() + 30 * 60 * 60;
|
||||
alert.nID = 1; // keep track of alert IDs somewhere
|
||||
alert.nCancel = 0; // cancels previous messages up to this ID number
|
||||
|
||||
// These versions are protocol versions
|
||||
alert.nMinVer = 70000;
|
||||
alert.nMaxVer = 70103;
|
||||
|
||||
//
|
||||
// 1000 for Misc warnings like out of disk space and clock is wrong
|
||||
// 2000 for longer invalid proof-of-work chain
|
||||
// Higher numbers mean higher priority
|
||||
alert.nPriority = 5000;
|
||||
alert.strComment = "";
|
||||
alert.strStatusBar = "URGENT: Upgrade required: see https://www.dash.org";
|
||||
|
||||
// Set specific client version/versions here. If setSubVer is empty, no filtering on subver is done:
|
||||
// alert.setSubVer.insert(std::string("/Dash Core:0.12.0.58/"));
|
||||
|
||||
// Sign
|
||||
if(!alert.Sign())
|
||||
{
|
||||
LogPrintf("ThreadSendAlert() : could not sign alert\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Test
|
||||
CDataStream sBuffer(SER_NETWORK, CLIENT_VERSION);
|
||||
sBuffer << alert;
|
||||
CAlert alert2;
|
||||
sBuffer >> alert2;
|
||||
if (!alert2.CheckSignature(Params().AlertKey()))
|
||||
{
|
||||
printf("ThreadSendAlert() : CheckSignature failed\n");
|
||||
return;
|
||||
}
|
||||
assert(alert2.vchMsg == alert.vchMsg);
|
||||
assert(alert2.vchSig == alert.vchSig);
|
||||
alert.SetNull();
|
||||
printf("\nThreadSendAlert:\n");
|
||||
printf("hash=%s\n", alert2.GetHash().ToString().c_str());
|
||||
printf("%s", alert2.ToString().c_str());
|
||||
printf("vchMsg=%s\n", HexStr(alert2.vchMsg).c_str());
|
||||
printf("vchSig=%s\n", HexStr(alert2.vchSig).c_str());
|
||||
|
||||
// Confirm
|
||||
if (!IsArgSet("-sendalert"))
|
||||
return;
|
||||
while (connman.GetNodeCount(CConnman::CONNECTIONS_ALL) == 0 && !ShutdownRequested())
|
||||
MilliSleep(500);
|
||||
if (ShutdownRequested())
|
||||
return;
|
||||
|
||||
// Send
|
||||
printf("ThreadSendAlert() : Sending alert\n");
|
||||
int nSent = 0;
|
||||
{
|
||||
connman.ForEachNode([&alert2, &connman, &nSent](CNode* pnode) {
|
||||
if (alert2.RelayTo(pnode, connman))
|
||||
{
|
||||
printf("ThreadSendAlert() : Sent alert to %s\n", pnode->addr.ToString().c_str());
|
||||
nSent++;
|
||||
}
|
||||
});
|
||||
}
|
||||
printf("ThreadSendAlert() : Alert sent to %d nodes\n", nSent);
|
||||
}
|
@ -4,232 +4,77 @@
|
||||
|
||||
// Unit tests for alert system
|
||||
|
||||
#include "alert.h"
|
||||
#include "chain.h"
|
||||
#include "chainparams.h"
|
||||
#include "clientversion.h"
|
||||
#include "data/alertTests.raw.h"
|
||||
#include "fs.h"
|
||||
#include "serialize.h"
|
||||
#include "streams.h"
|
||||
#include "utilstrencodings.h"
|
||||
#include "main.h" // For PartitionCheck
|
||||
|
||||
#include "test/testutil.h"
|
||||
#include "test/test_dash.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
//
|
||||
// Sign a CAlert and serialize it
|
||||
//
|
||||
bool SignAndSave(CAlert &alert)
|
||||
BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup)
|
||||
|
||||
|
||||
static bool falseFunc() { return false; }
|
||||
|
||||
BOOST_AUTO_TEST_CASE(PartitionAlert)
|
||||
{
|
||||
// Sign
|
||||
if(!alert.Sign())
|
||||
// Test PartitionCheck
|
||||
CCriticalSection csDummy;
|
||||
CBlockIndex indexDummy[100];
|
||||
CChainParams& params = Params(CBaseChainParams::MAIN);
|
||||
int64_t nPowTargetSpacing = params.GetConsensus().nPowTargetSpacing;
|
||||
|
||||
// Generate fake blockchain timestamps relative to
|
||||
// an arbitrary time:
|
||||
int64_t now = 1427379054;
|
||||
SetMockTime(now);
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
printf("SignAndSave() : could not sign alert:\n%s", alert.ToString().c_str());
|
||||
return false;
|
||||
indexDummy[i].phashBlock = NULL;
|
||||
if (i == 0) indexDummy[i].pprev = NULL;
|
||||
else indexDummy[i].pprev = &indexDummy[i-1];
|
||||
indexDummy[i].nHeight = i;
|
||||
indexDummy[i].nTime = now - (100-i)*nPowTargetSpacing;
|
||||
// Other members don't matter, the partition check code doesn't
|
||||
// use them
|
||||
}
|
||||
|
||||
std::string strFilePath = "src/test/data/alertTests.raw";
|
||||
// open output file and associate it with CAutoFile
|
||||
FILE *file = fopen(strFilePath.c_str(), "ab+");
|
||||
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
|
||||
if (fileout.IsNull())
|
||||
return error("%s: Failed to open file %s", __func__, strFilePath);
|
||||
strMiscWarning = "";
|
||||
|
||||
try {
|
||||
fileout << alert;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
return error("%s: Serialize or I/O error - %s", __func__, e.what());
|
||||
}
|
||||
fileout.fclose();
|
||||
return true;
|
||||
}
|
||||
// Test 1: chain with blocks every nPowTargetSpacing seconds,
|
||||
// as normal, no worries:
|
||||
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
|
||||
BOOST_CHECK_MESSAGE(strMiscWarning.empty(), strMiscWarning);
|
||||
|
||||
//
|
||||
// alertTests contains 8 alerts, generated with this code
|
||||
//
|
||||
void GenerateAlertTests()
|
||||
{
|
||||
CAlert alert;
|
||||
alert.nRelayUntil = 60;
|
||||
alert.nExpiration = 24 * 60 * 60;
|
||||
alert.nID = 1;
|
||||
alert.nCancel = 0; // cancels previous messages up to this ID number
|
||||
alert.nMinVer = 0; // These versions are protocol versions
|
||||
alert.nMaxVer = 999001;
|
||||
alert.nPriority = 1;
|
||||
alert.strComment = "Alert comment";
|
||||
alert.strStatusBar = "Alert 1";
|
||||
// Test 2: go 3.5 hours without a block, expect a warning:
|
||||
now += 3*60*60+30*60;
|
||||
SetMockTime(now);
|
||||
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
|
||||
BOOST_CHECK(!strMiscWarning.empty());
|
||||
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
|
||||
strMiscWarning = "";
|
||||
|
||||
SignAndSave(alert);
|
||||
// Test 3: test the "partition alerts only go off once per day"
|
||||
// code:
|
||||
now += 60*10;
|
||||
SetMockTime(now);
|
||||
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
|
||||
BOOST_CHECK(strMiscWarning.empty());
|
||||
|
||||
alert.setSubVer.insert(std::string("/Satoshi:0.1.0/"));
|
||||
alert.strStatusBar = "Alert 1 for Satoshi 0.1.0";
|
||||
SignAndSave(alert);
|
||||
|
||||
alert.setSubVer.insert(std::string("/Satoshi:0.2.0/"));
|
||||
alert.strStatusBar = "Alert 1 for Satoshi 0.1.0, 0.2.0";
|
||||
SignAndSave(alert);
|
||||
|
||||
alert.setSubVer.clear();
|
||||
++alert.nID;
|
||||
alert.nCancel = 1;
|
||||
alert.nPriority = 100;
|
||||
alert.strStatusBar = "Alert 2, cancels 1";
|
||||
SignAndSave(alert);
|
||||
|
||||
alert.nExpiration += 60;
|
||||
++alert.nID;
|
||||
SignAndSave(alert);
|
||||
|
||||
++alert.nID;
|
||||
alert.nMinVer = 11;
|
||||
alert.nMaxVer = 22;
|
||||
SignAndSave(alert);
|
||||
|
||||
++alert.nID;
|
||||
alert.strStatusBar = "Alert 2 for Satoshi 0.1.0";
|
||||
alert.setSubVer.insert(std::string("/Satoshi:0.1.0/"));
|
||||
SignAndSave(alert);
|
||||
|
||||
++alert.nID;
|
||||
alert.nMinVer = 0;
|
||||
alert.nMaxVer = 999999;
|
||||
alert.strStatusBar = "Evil Alert'; /bin/ls; echo '";
|
||||
alert.setSubVer.clear();
|
||||
SignAndSave(alert);
|
||||
}
|
||||
|
||||
struct ReadAlerts : public TestingSetup
|
||||
{
|
||||
ReadAlerts()
|
||||
{
|
||||
std::vector<unsigned char> vch(raw_tests::alertTests, raw_tests::alertTests + sizeof(raw_tests::alertTests));
|
||||
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
|
||||
try {
|
||||
while (!stream.eof())
|
||||
{
|
||||
CAlert alert;
|
||||
stream >> alert;
|
||||
alerts.push_back(alert);
|
||||
}
|
||||
}
|
||||
catch (const std::exception&) { }
|
||||
}
|
||||
~ReadAlerts() { }
|
||||
|
||||
static std::vector<std::string> read_lines(fs::path filepath)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
std::ifstream f(filepath.string().c_str());
|
||||
std::string line;
|
||||
while (std::getline(f,line))
|
||||
result.push_back(line);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<CAlert> alerts;
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(Alert_tests, ReadAlerts)
|
||||
|
||||
// Steps to generate alert tests:
|
||||
// - update alerts in GenerateAlertTests() (optional)
|
||||
// - enable code below (#if 1)
|
||||
// - replace "fffffffffffffffffffffffffffffffffffffffffffffffffff" with the actual MAINNET privkey
|
||||
// - recompile and run "/path/to/test_dash -t Alert_test"
|
||||
//
|
||||
// NOTE: make sure to disable code and remove alert privkey when you're done!
|
||||
//
|
||||
#if 0
|
||||
BOOST_AUTO_TEST_CASE(GenerateAlerts)
|
||||
{
|
||||
SoftSetArg("-alertkey", "fffffffffffffffffffffffffffffffffffffffffffffffffff");
|
||||
GenerateAlertTests();
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AlertApplies)
|
||||
{
|
||||
SetMockTime(11);
|
||||
const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
|
||||
|
||||
for (const auto& alert : alerts)
|
||||
{
|
||||
BOOST_CHECK(alert.CheckSignature(alertKey));
|
||||
}
|
||||
|
||||
BOOST_CHECK(alerts.size() >= 3);
|
||||
|
||||
// Matches:
|
||||
BOOST_CHECK(alerts[0].AppliesTo(1, ""));
|
||||
BOOST_CHECK(alerts[0].AppliesTo(999001, ""));
|
||||
BOOST_CHECK(alerts[0].AppliesTo(1, "/Satoshi:11.11.11/"));
|
||||
|
||||
BOOST_CHECK(alerts[1].AppliesTo(1, "/Satoshi:0.1.0/"));
|
||||
BOOST_CHECK(alerts[1].AppliesTo(999001, "/Satoshi:0.1.0/"));
|
||||
|
||||
BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.1.0/"));
|
||||
BOOST_CHECK(alerts[2].AppliesTo(1, "/Satoshi:0.2.0/"));
|
||||
|
||||
// Don't match:
|
||||
BOOST_CHECK(!alerts[0].AppliesTo(-1, ""));
|
||||
BOOST_CHECK(!alerts[0].AppliesTo(999002, ""));
|
||||
|
||||
BOOST_CHECK(!alerts[1].AppliesTo(1, ""));
|
||||
BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0"));
|
||||
BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.1.0"));
|
||||
BOOST_CHECK(!alerts[1].AppliesTo(1, "Satoshi:0.1.0/"));
|
||||
BOOST_CHECK(!alerts[1].AppliesTo(-1, "/Satoshi:0.1.0/"));
|
||||
BOOST_CHECK(!alerts[1].AppliesTo(999002, "/Satoshi:0.1.0/"));
|
||||
BOOST_CHECK(!alerts[1].AppliesTo(1, "/Satoshi:0.2.0/"));
|
||||
|
||||
BOOST_CHECK(!alerts[2].AppliesTo(1, "/Satoshi:0.3.0/"));
|
||||
// Test 4: get 2.5 times as many blocks as expected:
|
||||
now += 60*60*24; // Pretend it is a day later
|
||||
SetMockTime(now);
|
||||
int64_t quickSpacing = nPowTargetSpacing*2/5;
|
||||
for (int i = 0; i < 100; i++) // Tweak chain timestamps:
|
||||
indexDummy[i].nTime = now - (100-i)*quickSpacing;
|
||||
PartitionCheck(falseFunc, csDummy, &indexDummy[99], nPowTargetSpacing);
|
||||
BOOST_CHECK(!strMiscWarning.empty());
|
||||
BOOST_TEST_MESSAGE(std::string("Got alert text: ")+strMiscWarning);
|
||||
strMiscWarning = "";
|
||||
|
||||
SetMockTime(0);
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AlertNotify)
|
||||
{
|
||||
SetMockTime(11);
|
||||
const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
|
||||
|
||||
fs::path temp = GetTempPath() /
|
||||
fs::unique_path("alertnotify-%%%%.txt");
|
||||
|
||||
ForceSetArg("-alertnotify", std::string("echo %s >> ") + temp.string());
|
||||
|
||||
for (const auto& alert : alerts)
|
||||
alert.ProcessAlert(alertKey, false);
|
||||
|
||||
std::vector<std::string> r = read_lines(temp);
|
||||
BOOST_CHECK_EQUAL(r.size(), 4u);
|
||||
|
||||
// Windows built-in echo semantics are different than posixy shells. Quotes and
|
||||
// whitespace are printed literally.
|
||||
|
||||
#ifndef WIN32
|
||||
BOOST_CHECK_EQUAL(r[0], "Alert 1");
|
||||
BOOST_CHECK_EQUAL(r[1], "Alert 2, cancels 1");
|
||||
BOOST_CHECK_EQUAL(r[2], "Alert 2, cancels 1");
|
||||
BOOST_CHECK_EQUAL(r[3], "Evil Alert; /bin/ls; echo "); // single-quotes should be removed
|
||||
#else
|
||||
BOOST_CHECK_EQUAL(r[0], "'Alert 1' ");
|
||||
BOOST_CHECK_EQUAL(r[1], "'Alert 2, cancels 1' ");
|
||||
BOOST_CHECK_EQUAL(r[2], "'Alert 2, cancels 1' ");
|
||||
BOOST_CHECK_EQUAL(r[3], "'Evil Alert; /bin/ls; echo ' ");
|
||||
#endif
|
||||
fs::remove(temp);
|
||||
|
||||
SetMockTime(0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
Binary file not shown.
@ -90,10 +90,9 @@ public:
|
||||
boost::signals2::signal<void (bool networkActive)> NotifyNetworkActiveChanged;
|
||||
|
||||
/**
|
||||
* New, updated or cancelled alert.
|
||||
* @note called with lock cs_mapAlerts held.
|
||||
* Status bar alerts changed.
|
||||
*/
|
||||
boost::signals2::signal<void (const uint256 &hash, ChangeType status)> NotifyAlertChanged;
|
||||
boost::signals2::signal<void ()> NotifyAlertChanged;
|
||||
|
||||
/** A wallet has been loaded. */
|
||||
boost::signals2::signal<void (CWallet* wallet)> LoadWallet;
|
||||
|
@ -6,7 +6,6 @@
|
||||
|
||||
#include "validation.h"
|
||||
|
||||
#include "alert.h"
|
||||
#include "arith_uint256.h"
|
||||
#include "blockencodings.h"
|
||||
#include "chain.h"
|
||||
@ -92,7 +91,6 @@ bool fCheckBlockIndex = false;
|
||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
||||
size_t nCoinCacheUsage = 5000 * 300;
|
||||
uint64_t nPruneTarget = 0;
|
||||
bool fAlerts = DEFAULT_ALERTS;
|
||||
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
||||
|
||||
std::atomic<bool> fDIP0001ActiveAtTip{false};
|
||||
@ -1206,6 +1204,26 @@ bool IsInitialBlockDownload()
|
||||
|
||||
CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
|
||||
|
||||
static void AlertNotify(const std::string& strMessage, bool fThread)
|
||||
{
|
||||
uiInterface.NotifyAlertChanged();
|
||||
std::string strCmd = GetArg("-alertnotify", "");
|
||||
if (strCmd.empty()) return;
|
||||
|
||||
// Alert text should be plain ascii coming from a trusted source, but to
|
||||
// be safe we first strip anything not in safeChars, then add single quotes around
|
||||
// the whole string before passing it to the shell:
|
||||
std::string singleQuote("'");
|
||||
std::string safeStatus = SanitizeString(strMessage);
|
||||
safeStatus = singleQuote+safeStatus+singleQuote;
|
||||
boost::replace_all(strCmd, "%s", safeStatus);
|
||||
|
||||
if (fThread)
|
||||
boost::thread t(runCommand, strCmd); // thread runs free
|
||||
else
|
||||
runCommand(strCmd);
|
||||
}
|
||||
|
||||
static void CheckForkWarningConditions()
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
@ -1226,7 +1244,7 @@ static void CheckForkWarningConditions()
|
||||
if(pindexBestForkBase->phashBlock){
|
||||
std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
|
||||
pindexBestForkBase->phashBlock->ToString() + std::string("'");
|
||||
CAlert::Notify(warning);
|
||||
AlertNotify(warning);
|
||||
}
|
||||
}
|
||||
if (pindexBestForkTip && pindexBestForkBase)
|
||||
@ -2462,7 +2480,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
|
||||
std::string strWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit);
|
||||
SetMiscWarning(strWarning);
|
||||
if (!fWarned) {
|
||||
CAlert::Notify(strWarning);
|
||||
AlertNotify(strWarning);
|
||||
fWarned = true;
|
||||
}
|
||||
} else {
|
||||
@ -2486,7 +2504,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) {
|
||||
// notify GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
|
||||
SetMiscWarning(strWarning);
|
||||
if (!fWarned) {
|
||||
CAlert::Notify(strWarning);
|
||||
AlertNotify(strWarning);
|
||||
fWarned = true;
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,6 @@ struct ChainTxData;
|
||||
|
||||
struct LockPoints;
|
||||
|
||||
/** Default for accepting alerts from the P2P network. */
|
||||
static const bool DEFAULT_ALERTS = true;
|
||||
/** Default for DEFAULT_WHITELISTRELAY. */
|
||||
static const bool DEFAULT_WHITELISTRELAY = true;
|
||||
/** Default for DEFAULT_WHITELISTFORCERELAY. */
|
||||
@ -184,7 +182,6 @@ extern size_t nCoinCacheUsage;
|
||||
extern CFeeRate minRelayTxFee;
|
||||
/** Absolute maximum transaction fee (in duffs) used by wallet and mempool (rejects high fee in sendrawtransaction) */
|
||||
extern CAmount maxTxFee;
|
||||
extern bool fAlerts;
|
||||
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
|
||||
extern int64_t nMaxTipAge;
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "clientversion.h"
|
||||
#include "util.h"
|
||||
#include "warnings.h"
|
||||
#include "alert.h"
|
||||
#include "hash.h"
|
||||
|
||||
CCriticalSection cs_warnings;
|
||||
@ -47,7 +46,6 @@ bool GetfLargeWorkInvalidChainFound()
|
||||
|
||||
std::string GetWarnings(const std::string& strFor)
|
||||
{
|
||||
int nPriority = 0;
|
||||
std::string strStatusBar;
|
||||
std::string strRPC;
|
||||
std::string strGUI;
|
||||
@ -66,38 +64,21 @@ std::string GetWarnings(const std::string& strFor)
|
||||
// Misc warnings like out of disk space and clock is wrong
|
||||
if (strMiscWarning != "")
|
||||
{
|
||||
nPriority = 1000;
|
||||
strStatusBar = strMiscWarning;
|
||||
strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + strMiscWarning;
|
||||
}
|
||||
|
||||
if (fLargeWorkForkFound)
|
||||
{
|
||||
nPriority = 2000;
|
||||
strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.";
|
||||
strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("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.";
|
||||
strGUI += (strGUI.empty() ? "" : uiAlertSeperator) + _("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 auto& item : mapAlerts)
|
||||
{
|
||||
const CAlert& alert = item.second;
|
||||
if (alert.AppliesToMe() && alert.nPriority > nPriority)
|
||||
{
|
||||
nPriority = alert.nPriority;
|
||||
strStatusBar = strGUI = alert.strStatusBar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strFor == "gui")
|
||||
return strGUI;
|
||||
else if (strFor == "statusbar")
|
||||
|
Loading…
Reference in New Issue
Block a user