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)
This commit is contained in:
commit
29b2be6ad7
17 changed files with 38 additions and 673 deletions
|
@ -51,6 +51,8 @@ The following outputs are affected by this change:
|
||||||
|
|
||||||
### P2P protocol and network code
|
### P2P protocol and network code
|
||||||
|
|
||||||
|
The p2p alert system has been removed in #7692 and the 'alert' message is no longer supported.
|
||||||
|
|
||||||
### Validation
|
### Validation
|
||||||
|
|
||||||
### Build system
|
### Build system
|
||||||
|
|
|
@ -87,7 +87,6 @@ endif
|
||||||
# bitcoin core #
|
# bitcoin core #
|
||||||
BITCOIN_CORE_H = \
|
BITCOIN_CORE_H = \
|
||||||
addrman.h \
|
addrman.h \
|
||||||
alert.h \
|
|
||||||
base58.h \
|
base58.h \
|
||||||
bloom.h \
|
bloom.h \
|
||||||
chain.h \
|
chain.h \
|
||||||
|
@ -176,7 +175,6 @@ libbitcoin_server_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES) $(MINIUPNPC_CP
|
||||||
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
libbitcoin_server_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
|
||||||
libbitcoin_server_a_SOURCES = \
|
libbitcoin_server_a_SOURCES = \
|
||||||
addrman.cpp \
|
addrman.cpp \
|
||||||
alert.cpp \
|
|
||||||
bloom.cpp \
|
bloom.cpp \
|
||||||
chain.cpp \
|
chain.cpp \
|
||||||
checkpoints.cpp \
|
checkpoints.cpp \
|
||||||
|
|
|
@ -29,7 +29,7 @@ JSON_TEST_FILES = \
|
||||||
test/data/tx_valid.json \
|
test/data/tx_valid.json \
|
||||||
test/data/sighash.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)
|
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
|
||||||
|
|
||||||
|
|
266
src/alert.cpp
266
src/alert.cpp
|
@ -1,266 +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 "clientversion.h"
|
|
||||||
#include "net.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/foreach.hpp>
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
using namespace 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;
|
|
||||||
BOOST_FOREACH(int n, setCancel)
|
|
||||||
strSetCancel += strprintf("%d ", n);
|
|
||||||
std::string strSetSubVer;
|
|
||||||
BOOST_FOREACH(const std::string& 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) 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)
|
|
||||||
{
|
|
||||||
pnode->PushMessage(NetMsgType::ALERT, *this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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 (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
|
|
||||||
{
|
|
||||||
const CAlert& alert = (*mi).second;
|
|
||||||
if (Cancels(alert))
|
|
||||||
{
|
|
||||||
LogPrint("alert", "cancelling alert %d\n", alert.nID);
|
|
||||||
uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
|
|
||||||
mapAlerts.erase(mi++);
|
|
||||||
}
|
|
||||||
else if (!alert.IsInEffect())
|
|
||||||
{
|
|
||||||
LogPrint("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
|
|
||||||
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
|
|
||||||
{
|
|
||||||
const CAlert& alert = item.second;
|
|
||||||
if (alert.Cancels(*this))
|
|
||||||
{
|
|
||||||
LogPrint("alert", "alert already cancelled by %d\n", alert.nID);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to mapAlerts
|
|
||||||
mapAlerts.insert(make_pair(GetHash(), *this));
|
|
||||||
// Notify UI and -alertnotify if it applies to me
|
|
||||||
if(AppliesToMe())
|
|
||||||
{
|
|
||||||
uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
|
|
||||||
Notify(strStatusBar, fThread);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LogPrint("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);
|
|
||||||
}
|
|
113
src/alert.h
113
src/alert.h
|
@ -1,113 +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 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, int nType, int nVersion) {
|
|
||||||
READWRITE(this->nVersion);
|
|
||||||
nVersion = 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, int nType, int nVersion) {
|
|
||||||
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) const;
|
|
||||||
bool CheckSignature(const std::vector<unsigned char>& alertKey) const;
|
|
||||||
bool ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread = true); // fThread means run -alertnotify in a free-running thread
|
|
||||||
static void Notify(const std::string& strMessage, bool fThread);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
|
@ -95,7 +95,6 @@ public:
|
||||||
pchMessageStart[1] = 0xbe;
|
pchMessageStart[1] = 0xbe;
|
||||||
pchMessageStart[2] = 0xb4;
|
pchMessageStart[2] = 0xb4;
|
||||||
pchMessageStart[3] = 0xd9;
|
pchMessageStart[3] = 0xd9;
|
||||||
vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
|
|
||||||
nDefaultPort = 8333;
|
nDefaultPort = 8333;
|
||||||
nPruneAfterHeight = 100000;
|
nPruneAfterHeight = 100000;
|
||||||
|
|
||||||
|
@ -176,7 +175,6 @@ public:
|
||||||
pchMessageStart[1] = 0x11;
|
pchMessageStart[1] = 0x11;
|
||||||
pchMessageStart[2] = 0x09;
|
pchMessageStart[2] = 0x09;
|
||||||
pchMessageStart[3] = 0x07;
|
pchMessageStart[3] = 0x07;
|
||||||
vAlertPubKey = ParseHex("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a");
|
|
||||||
nDefaultPort = 18333;
|
nDefaultPort = 18333;
|
||||||
nPruneAfterHeight = 1000;
|
nPruneAfterHeight = 1000;
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,6 @@ public:
|
||||||
|
|
||||||
const Consensus::Params& GetConsensus() const { return consensus; }
|
const Consensus::Params& GetConsensus() const { return consensus; }
|
||||||
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
|
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
|
||||||
const std::vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
|
|
||||||
int GetDefaultPort() const { return nDefaultPort; }
|
int GetDefaultPort() const { return nDefaultPort; }
|
||||||
|
|
||||||
const CBlock& GenesisBlock() const { return genesis; }
|
const CBlock& GenesisBlock() const { return genesis; }
|
||||||
|
@ -80,8 +79,6 @@ protected:
|
||||||
|
|
||||||
Consensus::Params consensus;
|
Consensus::Params consensus;
|
||||||
CMessageHeader::MessageStartChars pchMessageStart;
|
CMessageHeader::MessageStartChars pchMessageStart;
|
||||||
//! Raw pub key bytes for the broadcast alert signing key.
|
|
||||||
std::vector<unsigned char> vAlertPubKey;
|
|
||||||
int nDefaultPort;
|
int nDefaultPort;
|
||||||
uint64_t nPruneAfterHeight;
|
uint64_t nPruneAfterHeight;
|
||||||
std::vector<CDNSSeedData> vSeeds;
|
std::vector<CDNSSeedData> vSeeds;
|
||||||
|
|
|
@ -315,7 +315,6 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
string strUsage = HelpMessageGroup(_("Options:"));
|
string strUsage = HelpMessageGroup(_("Options:"));
|
||||||
strUsage += HelpMessageOpt("-?", _("Print this help message and exit"));
|
strUsage += HelpMessageOpt("-?", _("Print this help message and exit"));
|
||||||
strUsage += HelpMessageOpt("-version", _("Print version 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("-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)"));
|
strUsage += HelpMessageOpt("-blocknotify=<cmd>", _("Execute command when the best block changes (%s in cmd is replaced by block hash)"));
|
||||||
if (showDebug)
|
if (showDebug)
|
||||||
|
@ -1000,8 +999,6 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||||
fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
|
fAcceptDatacarrier = GetBoolArg("-datacarrier", DEFAULT_ACCEPT_DATACARRIER);
|
||||||
nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes);
|
nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes);
|
||||||
|
|
||||||
fAlerts = GetBoolArg("-alerts", DEFAULT_ALERTS);
|
|
||||||
|
|
||||||
// Option to startup with mocktime set (used for regression testing):
|
// Option to startup with mocktime set (used for regression testing):
|
||||||
SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
|
SetMockTime(GetArg("-mocktime", 0)); // SetMockTime(0) is a no-op
|
||||||
|
|
||||||
|
|
91
src/main.cpp
91
src/main.cpp
|
@ -6,7 +6,6 @@
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include "addrman.h"
|
#include "addrman.h"
|
||||||
#include "alert.h"
|
|
||||||
#include "arith_uint256.h"
|
#include "arith_uint256.h"
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
#include "checkpoints.h"
|
#include "checkpoints.h"
|
||||||
|
@ -75,7 +74,6 @@ bool fCheckBlockIndex = false;
|
||||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED;
|
||||||
size_t nCoinCacheUsage = 5000 * 300;
|
size_t nCoinCacheUsage = 5000 * 300;
|
||||||
uint64_t nPruneTarget = 0;
|
uint64_t nPruneTarget = 0;
|
||||||
bool fAlerts = DEFAULT_ALERTS;
|
|
||||||
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE;
|
||||||
bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT;
|
bool fEnableReplacement = DEFAULT_ENABLE_REPLACEMENT;
|
||||||
|
|
||||||
|
@ -1566,6 +1564,26 @@ bool fLargeWorkForkFound = false;
|
||||||
bool fLargeWorkInvalidChainFound = false;
|
bool fLargeWorkInvalidChainFound = false;
|
||||||
CBlockIndex *pindexBestForkTip = NULL, *pindexBestForkBase = NULL;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
void CheckForkWarningConditions()
|
void CheckForkWarningConditions()
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs_main);
|
AssertLockHeld(cs_main);
|
||||||
|
@ -1585,7 +1603,7 @@ void CheckForkWarningConditions()
|
||||||
{
|
{
|
||||||
std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
|
std::string warning = std::string("'Warning: Large-work fork detected, forking after block ") +
|
||||||
pindexBestForkBase->phashBlock->ToString() + std::string("'");
|
pindexBestForkBase->phashBlock->ToString() + std::string("'");
|
||||||
CAlert::Notify(warning, true);
|
AlertNotify(warning, true);
|
||||||
}
|
}
|
||||||
if (pindexBestForkTip && pindexBestForkBase)
|
if (pindexBestForkTip && pindexBestForkBase)
|
||||||
{
|
{
|
||||||
|
@ -2116,7 +2134,7 @@ void PartitionCheck(bool (*initialDownloadCheck)(), CCriticalSection& cs, const
|
||||||
if (!strWarning.empty())
|
if (!strWarning.empty())
|
||||||
{
|
{
|
||||||
strMiscWarning = strWarning;
|
strMiscWarning = strWarning;
|
||||||
CAlert::Notify(strWarning, true);
|
AlertNotify(strWarning, true);
|
||||||
lastAlertTime = now;
|
lastAlertTime = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2546,7 +2564,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
|
||||||
if (state == THRESHOLD_ACTIVE) {
|
if (state == THRESHOLD_ACTIVE) {
|
||||||
strMiscWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit);
|
strMiscWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit);
|
||||||
if (!fWarned) {
|
if (!fWarned) {
|
||||||
CAlert::Notify(strMiscWarning, true);
|
AlertNotify(strMiscWarning, true);
|
||||||
fWarned = true;
|
fWarned = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2568,7 +2586,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
|
||||||
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
|
// strMiscWarning is read by GetWarnings(), called by Qt and the JSON-RPC code to warn the user:
|
||||||
strMiscWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect");
|
strMiscWarning = _("Warning: Unknown block versions being mined! It's possible unknown rules are in effect");
|
||||||
if (!fWarned) {
|
if (!fWarned) {
|
||||||
CAlert::Notify(strMiscWarning, true);
|
AlertNotify(strMiscWarning, true);
|
||||||
fWarned = true;
|
fWarned = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4213,14 +4231,8 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams)
|
||||||
assert(nNodes == forward.size());
|
assert(nNodes == forward.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// CAlert
|
|
||||||
//
|
|
||||||
|
|
||||||
std::string GetWarnings(const std::string& strFor)
|
std::string GetWarnings(const std::string& strFor)
|
||||||
{
|
{
|
||||||
int nPriority = 0;
|
|
||||||
string strStatusBar;
|
string strStatusBar;
|
||||||
string strRPC;
|
string strRPC;
|
||||||
string strGUI;
|
string strGUI;
|
||||||
|
@ -4236,37 +4248,20 @@ std::string GetWarnings(const std::string& strFor)
|
||||||
// Misc warnings like out of disk space and clock is wrong
|
// Misc warnings like out of disk space and clock is wrong
|
||||||
if (strMiscWarning != "")
|
if (strMiscWarning != "")
|
||||||
{
|
{
|
||||||
nPriority = 1000;
|
|
||||||
strStatusBar = strGUI = strMiscWarning;
|
strStatusBar = strGUI = strMiscWarning;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fLargeWorkForkFound)
|
if (fLargeWorkForkFound)
|
||||||
{
|
{
|
||||||
nPriority = 2000;
|
|
||||||
strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.";
|
strStatusBar = strRPC = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.";
|
||||||
strGUI = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.");
|
strGUI = _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.");
|
||||||
}
|
}
|
||||||
else if (fLargeWorkInvalidChainFound)
|
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.";
|
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 = _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
|
strGUI = _("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 = strGUI = alert.strStatusBar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strFor == "gui")
|
if (strFor == "gui")
|
||||||
return strGUI;
|
return strGUI;
|
||||||
else if (strFor == "statusbar")
|
else if (strFor == "statusbar")
|
||||||
|
@ -4588,13 +4583,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relay alerts
|
|
||||||
{
|
|
||||||
LOCK(cs_mapAlerts);
|
|
||||||
BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
|
|
||||||
item.second.RelayTo(pfrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
pfrom->fSuccessfullyConnected = true;
|
pfrom->fSuccessfullyConnected = true;
|
||||||
|
|
||||||
string remoteAddr;
|
string remoteAddr;
|
||||||
|
@ -5302,37 +5290,6 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
{
|
|
||||||
LOCK(cs_vNodes);
|
|
||||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
|
||||||
alert.RelayTo(pnode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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)
|
else if (strCommand == NetMsgType::FILTERLOAD)
|
||||||
{
|
{
|
||||||
CBloomFilter filter;
|
CBloomFilter filter;
|
||||||
|
|
|
@ -42,8 +42,6 @@ class CValidationState;
|
||||||
struct CNodeStateStats;
|
struct CNodeStateStats;
|
||||||
struct LockPoints;
|
struct LockPoints;
|
||||||
|
|
||||||
/** Default for accepting alerts from the P2P network. */
|
|
||||||
static const bool DEFAULT_ALERTS = true;
|
|
||||||
/** Default for DEFAULT_WHITELISTRELAY. */
|
/** Default for DEFAULT_WHITELISTRELAY. */
|
||||||
static const bool DEFAULT_WHITELISTRELAY = true;
|
static const bool DEFAULT_WHITELISTRELAY = true;
|
||||||
/** Default for DEFAULT_WHITELISTFORCERELAY. */
|
/** Default for DEFAULT_WHITELISTFORCERELAY. */
|
||||||
|
@ -154,7 +152,6 @@ extern size_t nCoinCacheUsage;
|
||||||
extern CFeeRate minRelayTxFee;
|
extern CFeeRate minRelayTxFee;
|
||||||
/** Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendrawtransaction) */
|
/** Absolute maximum transaction fee (in satoshis) used by wallet and mempool (rejects high fee in sendrawtransaction) */
|
||||||
extern CAmount maxTxFee;
|
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. */
|
/** If the tip is older than this (in seconds), the node is considered to be in initial block download. */
|
||||||
extern int64_t nMaxTipAge;
|
extern int64_t nMaxTipAge;
|
||||||
extern bool fEnableReplacement;
|
extern bool fEnableReplacement;
|
||||||
|
|
|
@ -28,7 +28,6 @@ const char *GETADDR="getaddr";
|
||||||
const char *MEMPOOL="mempool";
|
const char *MEMPOOL="mempool";
|
||||||
const char *PING="ping";
|
const char *PING="ping";
|
||||||
const char *PONG="pong";
|
const char *PONG="pong";
|
||||||
const char *ALERT="alert";
|
|
||||||
const char *NOTFOUND="notfound";
|
const char *NOTFOUND="notfound";
|
||||||
const char *FILTERLOAD="filterload";
|
const char *FILTERLOAD="filterload";
|
||||||
const char *FILTERADD="filteradd";
|
const char *FILTERADD="filteradd";
|
||||||
|
@ -64,7 +63,6 @@ const static std::string allNetMessageTypes[] = {
|
||||||
NetMsgType::MEMPOOL,
|
NetMsgType::MEMPOOL,
|
||||||
NetMsgType::PING,
|
NetMsgType::PING,
|
||||||
NetMsgType::PONG,
|
NetMsgType::PONG,
|
||||||
NetMsgType::ALERT,
|
|
||||||
NetMsgType::NOTFOUND,
|
NetMsgType::NOTFOUND,
|
||||||
NetMsgType::FILTERLOAD,
|
NetMsgType::FILTERLOAD,
|
||||||
NetMsgType::FILTERADD,
|
NetMsgType::FILTERADD,
|
||||||
|
|
|
@ -163,13 +163,6 @@ extern const char *PING;
|
||||||
* @see https://bitcoin.org/en/developer-reference#pong
|
* @see https://bitcoin.org/en/developer-reference#pong
|
||||||
*/
|
*/
|
||||||
extern const char *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
|
* The notfound message is a reply to a getdata message which requested an
|
||||||
* object the receiving node does not have available for relay.
|
* object the receiving node does not have available for relay.
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "guiconstants.h"
|
#include "guiconstants.h"
|
||||||
#include "peertablemodel.h"
|
#include "peertablemodel.h"
|
||||||
|
|
||||||
#include "alert.h"
|
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
#include "checkpoints.h"
|
#include "checkpoints.h"
|
||||||
#include "clientversion.h"
|
#include "clientversion.h"
|
||||||
|
@ -122,20 +121,8 @@ void ClientModel::updateNumConnections(int numConnections)
|
||||||
Q_EMIT numConnectionsChanged(numConnections);
|
Q_EMIT numConnectionsChanged(numConnections);
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
Q_EMIT alertsChanged(getStatusBarWarnings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,12 +214,10 @@ static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConn
|
||||||
Q_ARG(int, newNumConnections));
|
Q_ARG(int, newNumConnections));
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
qDebug() << "NotifyAlertChanged";
|
||||||
QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
|
QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection);
|
||||||
Q_ARG(QString, QString::fromStdString(hash.GetHex())),
|
|
||||||
Q_ARG(int, status));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void BannedListChanged(ClientModel *clientmodel)
|
static void BannedListChanged(ClientModel *clientmodel)
|
||||||
|
@ -266,7 +251,7 @@ void ClientModel::subscribeToCoreSignals()
|
||||||
// Connect signals to client
|
// Connect signals to client
|
||||||
uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
|
uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
|
||||||
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, 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.BannedListChanged.connect(boost::bind(BannedListChanged, this));
|
||||||
uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2));
|
uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2));
|
||||||
}
|
}
|
||||||
|
@ -276,7 +261,7 @@ void ClientModel::unsubscribeFromCoreSignals()
|
||||||
// Disconnect signals from client
|
// Disconnect signals from client
|
||||||
uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
|
uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
|
||||||
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, 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.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
|
||||||
uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2));
|
uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2));
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ Q_SIGNALS:
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void updateTimer();
|
void updateTimer();
|
||||||
void updateNumConnections(int numConnections);
|
void updateNumConnections(int numConnections);
|
||||||
void updateAlert(const QString &hash, int status);
|
void updateAlert();
|
||||||
void updateBanlist();
|
void updateBanlist();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,193 +4,16 @@
|
||||||
|
|
||||||
// Unit tests for alert system
|
// Unit tests for alert system
|
||||||
|
|
||||||
#include "alert.h"
|
|
||||||
#include "chain.h"
|
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
#include "clientversion.h"
|
|
||||||
#include "data/alertTests.raw.h"
|
|
||||||
#include "main.h" // For PartitionCheck
|
#include "main.h" // For PartitionCheck
|
||||||
#include "serialize.h"
|
|
||||||
#include "streams.h"
|
|
||||||
#include "utilstrencodings.h"
|
|
||||||
|
|
||||||
#include "test/testutil.h"
|
#include "test/testutil.h"
|
||||||
#include "test/test_bitcoin.h"
|
#include "test/test_bitcoin.h"
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
#include <boost/filesystem/operations.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#if 0
|
BOOST_FIXTURE_TEST_SUITE(Alert_tests, TestingSetup)
|
||||||
//
|
|
||||||
// alertTests contains 7 alerts, generated with this code:
|
|
||||||
// (SignAndSave code not shown, alert signing key is secret)
|
|
||||||
//
|
|
||||||
{
|
|
||||||
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";
|
|
||||||
|
|
||||||
SignAndSave(alert, "test/alertTests");
|
|
||||||
|
|
||||||
alert.setSubVer.insert(std::string("/Satoshi:0.1.0/"));
|
|
||||||
alert.strStatusBar = "Alert 1 for Satoshi 0.1.0";
|
|
||||||
SignAndSave(alert, "test/alertTests");
|
|
||||||
|
|
||||||
alert.setSubVer.insert(std::string("/Satoshi:0.2.0/"));
|
|
||||||
alert.strStatusBar = "Alert 1 for Satoshi 0.1.0, 0.2.0";
|
|
||||||
SignAndSave(alert, "test/alertTests");
|
|
||||||
|
|
||||||
alert.setSubVer.clear();
|
|
||||||
++alert.nID;
|
|
||||||
alert.nCancel = 1;
|
|
||||||
alert.nPriority = 100;
|
|
||||||
alert.strStatusBar = "Alert 2, cancels 1";
|
|
||||||
SignAndSave(alert, "test/alertTests");
|
|
||||||
|
|
||||||
alert.nExpiration += 60;
|
|
||||||
++alert.nID;
|
|
||||||
SignAndSave(alert, "test/alertTests");
|
|
||||||
|
|
||||||
++alert.nID;
|
|
||||||
alert.nMinVer = 11;
|
|
||||||
alert.nMaxVer = 22;
|
|
||||||
SignAndSave(alert, "test/alertTests");
|
|
||||||
|
|
||||||
++alert.nID;
|
|
||||||
alert.strStatusBar = "Alert 2 for Satoshi 0.1.0";
|
|
||||||
alert.setSubVer.insert(std::string("/Satoshi:0.1.0/"));
|
|
||||||
SignAndSave(alert, "test/alertTests");
|
|
||||||
|
|
||||||
++alert.nID;
|
|
||||||
alert.nMinVer = 0;
|
|
||||||
alert.nMaxVer = 999999;
|
|
||||||
alert.strStatusBar = "Evil Alert'; /bin/ls; echo '";
|
|
||||||
alert.setSubVer.clear();
|
|
||||||
SignAndSave(alert, "test/alertTests");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct ReadAlerts : public TestingSetup
|
|
||||||
{
|
|
||||||
ReadAlerts()
|
|
||||||
{
|
|
||||||
std::vector<unsigned char> vch(alert_tests::alertTests, alert_tests::alertTests + sizeof(alert_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(boost::filesystem::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)
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(AlertApplies)
|
|
||||||
{
|
|
||||||
SetMockTime(11);
|
|
||||||
const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
|
|
||||||
|
|
||||||
BOOST_FOREACH(const CAlert& 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/"));
|
|
||||||
|
|
||||||
SetMockTime(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(AlertNotify)
|
|
||||||
{
|
|
||||||
SetMockTime(11);
|
|
||||||
const std::vector<unsigned char>& alertKey = Params(CBaseChainParams::MAIN).AlertKey();
|
|
||||||
|
|
||||||
boost::filesystem::path temp = GetTempPath() /
|
|
||||||
boost::filesystem::unique_path("alertnotify-%%%%.txt");
|
|
||||||
|
|
||||||
mapArgs["-alertnotify"] = std::string("echo %s >> ") + temp.string();
|
|
||||||
|
|
||||||
BOOST_FOREACH(CAlert 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
|
|
||||||
boost::filesystem::remove(temp);
|
|
||||||
|
|
||||||
SetMockTime(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool falseFunc() { return false; }
|
static bool falseFunc() { return false; }
|
||||||
|
|
||||||
|
@ -253,4 +76,4 @@ BOOST_AUTO_TEST_CASE(PartitionAlert)
|
||||||
SetMockTime(0);
|
SetMockTime(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
Binary file not shown.
|
@ -83,10 +83,9 @@ public:
|
||||||
boost::signals2::signal<void (int newNumConnections)> NotifyNumConnectionsChanged;
|
boost::signals2::signal<void (int newNumConnections)> NotifyNumConnectionsChanged;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* New, updated or cancelled alert.
|
* Status bar alerts changed.
|
||||||
* @note called with lock cs_mapAlerts held.
|
|
||||||
*/
|
*/
|
||||||
boost::signals2::signal<void (const uint256 &hash, ChangeType status)> NotifyAlertChanged;
|
boost::signals2::signal<void ()> NotifyAlertChanged;
|
||||||
|
|
||||||
/** A wallet has been loaded. */
|
/** A wallet has been loaded. */
|
||||||
boost::signals2::signal<void (CWallet* wallet)> LoadWallet;
|
boost::signals2::signal<void (CWallet* wallet)> LoadWallet;
|
||||||
|
|
Loading…
Reference in a new issue