Browse Source
0.13cfd519e
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)
Wladimir J. van der Laan
9 years ago
17 changed files with 38 additions and 673 deletions
@ -1,266 +0,0 @@
@@ -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); |
||||
} |
@ -1,113 +0,0 @@
@@ -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
|
Binary file not shown.
Loading…
Reference in new issue