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