Master Core  v0.0.9 - 2abfd2849db8ba7a83957c64eb976b406713c123
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
alert.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "alert.h"
7 
8 #include "key.h"
9 #include "net.h"
10 #include "ui_interface.h"
11 #include "util.h"
12 
13 #include <stdint.h>
14 #include <algorithm>
15 #include <map>
16 
17 #include <boost/algorithm/string/classification.hpp>
18 #include <boost/algorithm/string/replace.hpp>
19 #include <boost/foreach.hpp>
20 
21 using namespace std;
22 
23 map<uint256, CAlert> mapAlerts;
25 
26 void CUnsignedAlert::SetNull()
27 {
28  nVersion = 1;
29  nRelayUntil = 0;
30  nExpiration = 0;
31  nID = 0;
32  nCancel = 0;
33  setCancel.clear();
34  nMinVer = 0;
35  nMaxVer = 0;
36  setSubVer.clear();
37  nPriority = 0;
38 
39  strComment.clear();
40  strStatusBar.clear();
41  strReserved.clear();
42 }
43 
44 std::string CUnsignedAlert::ToString() const
45 {
46  std::string strSetCancel;
47  BOOST_FOREACH(int n, setCancel)
48  strSetCancel += strprintf("%d ", n);
49  std::string strSetSubVer;
50  BOOST_FOREACH(std::string str, setSubVer)
51  strSetSubVer += "\"" + str + "\" ";
52  return strprintf(
53  "CAlert(\n"
54  " nVersion = %d\n"
55  " nRelayUntil = %d\n"
56  " nExpiration = %d\n"
57  " nID = %d\n"
58  " nCancel = %d\n"
59  " setCancel = %s\n"
60  " nMinVer = %d\n"
61  " nMaxVer = %d\n"
62  " setSubVer = %s\n"
63  " nPriority = %d\n"
64  " strComment = \"%s\"\n"
65  " strStatusBar = \"%s\"\n"
66  ")\n",
67  nVersion,
68  nRelayUntil,
69  nExpiration,
70  nID,
71  nCancel,
72  strSetCancel,
73  nMinVer,
74  nMaxVer,
75  strSetSubVer,
76  nPriority,
77  strComment,
78  strStatusBar);
79 }
80 
82 {
83  LogPrintf("%s", ToString());
84 }
85 
86 void CAlert::SetNull()
87 {
88  CUnsignedAlert::SetNull();
89  vchMsg.clear();
90  vchSig.clear();
91 }
92 
93 bool CAlert::IsNull() const
94 {
95  return (nExpiration == 0);
96 }
97 
99 {
100  return Hash(this->vchMsg.begin(), this->vchMsg.end());
101 }
102 
103 bool CAlert::IsInEffect() const
104 {
105  return (GetAdjustedTime() < nExpiration);
106 }
107 
108 bool CAlert::Cancels(const CAlert& alert) const
109 {
110  if (!IsInEffect())
111  return false; // this was a no-op before 31403
112  return (alert.nID <= nCancel || setCancel.count(alert.nID));
113 }
114 
115 bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const
116 {
117  // TODO: rework for client-version-embedded-in-strSubVer ?
118  return (IsInEffect() &&
119  nMinVer <= nVersion && nVersion <= nMaxVer &&
120  (setSubVer.empty() || setSubVer.count(strSubVerIn)));
121 }
122 
124 {
125  return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
126 }
127 
128 bool CAlert::RelayTo(CNode* pnode) const
129 {
130  if (!IsInEffect())
131  return false;
132  // returns true if wasn't already contained in the set
133  if (pnode->setKnown.insert(GetHash()).second)
134  {
135  if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
136  AppliesToMe() ||
137  GetAdjustedTime() < nRelayUntil)
138  {
139  pnode->PushMessage("alert", *this);
140  return true;
141  }
142  }
143  return false;
144 }
145 
147 {
148  CPubKey key(Params().AlertKey());
149  if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
150  return error("CAlert::CheckSignature() : verify signature failed");
151 
152  // Now unserialize the data
154  sMsg >> *(CUnsignedAlert*)this;
155  return true;
156 }
157 
159 {
160  CAlert retval;
161  {
162  LOCK(cs_mapAlerts);
163  map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
164  if(mi != mapAlerts.end())
165  retval = mi->second;
166  }
167  return retval;
168 }
169 
170 bool CAlert::ProcessAlert(bool fThread)
171 {
172  if (!CheckSignature())
173  return false;
174  if (!IsInEffect())
175  return false;
176 
177  // alert.nID=max is reserved for if the alert key is
178  // compromised. It must have a pre-defined message,
179  // must never expire, must apply to all versions,
180  // and must cancel all previous
181  // alerts or it will be ignored (so an attacker can't
182  // send an "everything is OK, don't panic" version that
183  // cannot be overridden):
184  int maxInt = std::numeric_limits<int>::max();
185  if (nID == maxInt)
186  {
187  if (!(
188  nExpiration == maxInt &&
189  nCancel == (maxInt-1) &&
190  nMinVer == 0 &&
191  nMaxVer == maxInt &&
192  setSubVer.empty() &&
193  nPriority == maxInt &&
194  strStatusBar == "URGENT: Alert key compromised, upgrade required"
195  ))
196  return false;
197  }
198 
199  {
200  LOCK(cs_mapAlerts);
201  // Cancel previous alerts
202  for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
203  {
204  const CAlert& alert = (*mi).second;
205  if (Cancels(alert))
206  {
207  LogPrint("alert", "cancelling alert %d\n", alert.nID);
209  mapAlerts.erase(mi++);
210  }
211  else if (!alert.IsInEffect())
212  {
213  LogPrint("alert", "expiring alert %d\n", alert.nID);
215  mapAlerts.erase(mi++);
216  }
217  else
218  mi++;
219  }
220 
221  // Check if this alert has been cancelled
222  BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
223  {
224  const CAlert& alert = item.second;
225  if (alert.Cancels(*this))
226  {
227  LogPrint("alert", "alert already cancelled by %d\n", alert.nID);
228  return false;
229  }
230  }
231 
232  // Add to mapAlerts
233  mapAlerts.insert(make_pair(GetHash(), *this));
234  // Notify UI and -alertnotify if it applies to me
235  if(AppliesToMe())
236  {
238  std::string strCmd = GetArg("-alertnotify", "");
239  if (!strCmd.empty())
240  {
241  // Alert text should be plain ascii coming from a trusted source, but to
242  // be safe we first strip anything not in safeChars, then add single quotes around
243  // the whole string before passing it to the shell:
244  std::string singleQuote("'");
245  std::string safeStatus = SanitizeString(strStatusBar);
246  safeStatus = singleQuote+safeStatus+singleQuote;
247  boost::replace_all(strCmd, "%s", safeStatus);
248 
249  if (fThread)
250  boost::thread t(runCommand, strCmd); // thread runs free
251  else
252  runCommand(strCmd);
253  }
254  }
255  }
256 
257  LogPrint("alert", "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
258  return true;
259 }
CClientUIInterface uiInterface
Definition: util.cpp:100
void PushMessage(const char *pszCommand)
Definition: net.h:522
#define PAIRTYPE(t1, t2)
Definition: util.h:48
const std::string CLIENT_NAME
static const int CLIENT_VERSION
Definition: version.h:15
bool AppliesTo(int nVersion, std::string strSubVerIn) const
Definition: alert.cpp:115
#define strprintf
Definition: util.h:116
STL namespace.
bool ProcessAlert(bool fThread=true)
Definition: alert.cpp:170
Double ended buffer combining vector and stream-like interfaces.
Definition: serialize.h:839
bool IsInEffect() const
Definition: alert.cpp:103
void print() const
Definition: alert.cpp:81
bool IsNull() const
Definition: alert.cpp:93
std::set< uint256 > setKnown
Definition: net.h:262
std::string strSubVer
Definition: net.h:224
#define LogPrintf(...)
Definition: util.h:117
int64_t GetAdjustedTime()
Definition: util.cpp:1236
std::string FormatSubVersion(const std::string &name, int nClientVersion, const std::vector< std::string > &comments)
Definition: util.cpp:1331
string SanitizeString(const string &str)
Definition: util.cpp:380
static int LogPrint(const char *category, const char *format)
Definition: util.h:143
An alert is a combination of a serialized CUnsignedAlert and a signature.
Definition: alert.h:75
#define LOCK(cs)
Definition: sync.h:156
uint256 GetHash() const
Definition: alert.cpp:98
std::string ToString() const
Definition: alert.cpp:44
Alerts are for notifying old versions if they become too obsolete and need to upgrade.
Definition: alert.h:30
An encapsulated public key.
Definition: key.h:42
static bool error(const char *format)
Definition: util.h:148
map< uint256, CAlert > mapAlerts
Definition: alert.cpp:23
CCriticalSection cs_mapAlerts
Definition: alert.cpp:24
uint256 Hash(const T1 pbegin, const T1 pend)
Definition: hash.h:19
256-bit unsigned integer
Definition: uint256.h:531
bool RelayTo(CNode *pnode) const
Definition: alert.cpp:128
boost::signals2::signal< void(const uint256 &hash, ChangeType status)> NotifyAlertChanged
New, updated or cancelled alert.
Definition: ui_interface.h:93
const CChainParams & Params()
Return the currently selected parameters.
static const int PROTOCOL_VERSION
Definition: version.h:29
static CAlert getAlertByHash(const uint256 &hash)
Definition: alert.cpp:158
bool CheckSignature() const
Definition: alert.cpp:146
bool Cancels(const CAlert &alert) const
Definition: alert.cpp:108
int nVersion
Definition: net.h:219
std::string GetArg(const std::string &strArg, const std::string &strDefault)
Return string argument or default value.
Definition: util.cpp:505
Information about a peer.
Definition: net.h:193
bool Verify(const uint256 &hash, const std::vector< unsigned char > &vchSig) const
Definition: key.cpp:437
bool AppliesToMe() const
Definition: alert.cpp:123
void runCommand(std::string strCommand)
Definition: util.cpp:1381