diff --git a/src/Makefile.am b/src/Makefile.am index e3a08b612..c3b2d8306 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index e3dcb433a..bd9ef26db 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -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) diff --git a/src/alert.cpp b/src/alert.cpp deleted file mode 100644 index 59c8b10b0..000000000 --- a/src/alert.cpp +++ /dev/null @@ -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 -#include -#include - -#include -#include -#include - -std::map 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())); -} - -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(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& 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::iterator mi = mapAlerts.find(hash); - if(mi != mapAlerts.end()) - retval = mi->second; - } - return retval; -} - -bool CAlert::ProcessAlert(const std::vector& 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::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::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); -} diff --git a/src/alert.h b/src/alert.h deleted file mode 100644 index edd4d862d..000000000 --- a/src/alert.h +++ /dev/null @@ -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 -#include -#include -#include - -class CAlert; -class CNode; -class CConnman; -class uint256; - -extern std::map 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 setCancel; - int nMinVer; // lowest version inclusive - int nMaxVer; // highest version inclusive - std::set setSubVer; // empty matches all - int nPriority; - - // Actions - std::string strComment; - std::string strStatusBar; - std::string strReserved; - - ADD_SERIALIZE_METHODS; - - template - 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 vchMsg; - std::vector vchSig; - - CAlert() - { - SetNull(); - } - - ADD_SERIALIZE_METHODS; - - template - 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& alertKey) const; - bool ProcessAlert(const std::vector& 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 diff --git a/src/chainparams.cpp b/src/chainparams.cpp index d4b18721f..0c1770bc5 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -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; diff --git a/src/chainparams.h b/src/chainparams.h index edcaeabfe..12e444868 100644 --- a/src/chainparams.h +++ b/src/chainparams.h @@ -58,7 +58,6 @@ public: const Consensus::Params& GetConsensus() const { return consensus; } const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; } - const std::vector& 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 vAlertPubKey; int nDefaultPort; uint64_t nPruneAfterHeight; std::vector vSeeds; diff --git a/src/init.cpp b/src/init.cpp index 20d2ff78f..95c9d900c 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -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=", _("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=", _("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 diff --git a/src/net_processing.cpp b/src/net_processing.cpp index cbc338ad1..d159917e2 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -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; diff --git a/src/protocol.cpp b/src/protocol.cpp index a81ff290e..48146ee8f 100644 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -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, diff --git a/src/protocol.h b/src/protocol.h index f4f949bf4..bce6790c6 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -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. diff --git a/src/qt/clientmodel.cpp b/src/qt/clientmodel.cpp index 5f1927d4b..1836509e1 100644 --- a/src/qt/clientmodel.cpp +++ b/src/qt/clientmodel.cpp @@ -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)); diff --git a/src/qt/clientmodel.h b/src/qt/clientmodel.h index 67ad63b41..9c86be225 100644 --- a/src/qt/clientmodel.h +++ b/src/qt/clientmodel.h @@ -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(); }; diff --git a/src/sendalert.cpp b/src/sendalert.cpp deleted file mode 100644 index 1aa8a0cbf..000000000 --- a/src/sendalert.cpp +++ /dev/null @@ -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); -} diff --git a/src/test/alert_tests.cpp b/src/test/alert_tests.cpp index a2a2d9d96..c14ba0bcd 100644 --- a/src/test/alert_tests.cpp +++ b/src/test/alert_tests.cpp @@ -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 - #include -// -// 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 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 read_lines(fs::path filepath) - { - std::vector result; - - std::ifstream f(filepath.string().c_str()); - std::string line; - while (std::getline(f,line)) - result.push_back(line); - - return result; - } - - std::vector 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& 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& 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 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() \ No newline at end of file diff --git a/src/test/data/alertTests.raw b/src/test/data/alertTests.raw deleted file mode 100644 index f58df4f18..000000000 Binary files a/src/test/data/alertTests.raw and /dev/null differ diff --git a/src/ui_interface.h b/src/ui_interface.h index 9d5ad977e..cb07bc0c8 100644 --- a/src/ui_interface.h +++ b/src/ui_interface.h @@ -90,10 +90,9 @@ public: boost::signals2::signal NotifyNetworkActiveChanged; /** - * New, updated or cancelled alert. - * @note called with lock cs_mapAlerts held. + * Status bar alerts changed. */ - boost::signals2::signal NotifyAlertChanged; + boost::signals2::signal NotifyAlertChanged; /** A wallet has been loaded. */ boost::signals2::signal LoadWallet; diff --git a/src/validation.cpp b/src/validation.cpp index e49206cf3..3a9533780 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -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 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; } } diff --git a/src/validation.h b/src/validation.h index 1982f0d12..5a9285bff 100644 --- a/src/validation.h +++ b/src/validation.h @@ -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; diff --git a/src/warnings.cpp b/src/warnings.cpp index f4f2bc548..8c5899803 100644 --- a/src/warnings.cpp +++ b/src/warnings.cpp @@ -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")