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