]> Git Repo - VerusCoin.git/blame - src/alert.cpp
print the caught error instead of raising an error
[VerusCoin.git] / src / alert.cpp
CommitLineData
cd696e64 1// Copyright (c) 2010 Satoshi Nakamoto
57702541 2// Copyright (c) 2009-2014 The Bitcoin developers
b4347f60 3// Distributed under the MIT software license, see the accompanying
cd696e64 4// file COPYING or http://www.opensource.org/licenses/mit-license.php.
f35c6c4f 5
f35c6c4f 6#include "alert.h"
51ed9ec9 7
c8c52de3 8#include "chainparams.h"
71697f97 9#include "clientversion.h"
f35c6c4f 10#include "net.h"
b4347f60 11#include "pubkey.h"
14f888ca 12#include "timedata.h"
f35c6c4f 13#include "ui_interface.h"
51ed9ec9
BD
14#include "util.h"
15
74f66a5e 16#include <stdint.h>
51ed9ec9 17#include <algorithm>
51ed9ec9
BD
18#include <map>
19
20#include <boost/algorithm/string/classification.hpp>
21#include <boost/algorithm/string/replace.hpp>
22#include <boost/foreach.hpp>
ad49c256 23#include <boost/thread.hpp>
f35c6c4f
GA
24
25using namespace std;
26
27map<uint256, CAlert> mapAlerts;
28CCriticalSection cs_mapAlerts;
29
30void CUnsignedAlert::SetNull()
31{
32 nVersion = 1;
33 nRelayUntil = 0;
34 nExpiration = 0;
35 nID = 0;
36 nCancel = 0;
37 setCancel.clear();
38 nMinVer = 0;
39 nMaxVer = 0;
40 setSubVer.clear();
41 nPriority = 0;
42
43 strComment.clear();
44 strStatusBar.clear();
45 strReserved.clear();
46}
47
48std::string CUnsignedAlert::ToString() const
49{
50 std::string strSetCancel;
51 BOOST_FOREACH(int n, setCancel)
52 strSetCancel += strprintf("%d ", n);
53 std::string strSetSubVer;
54 BOOST_FOREACH(std::string str, setSubVer)
55 strSetSubVer += "\"" + str + "\" ";
56 return strprintf(
57 "CAlert(\n"
58 " nVersion = %d\n"
f48742c2
WL
59 " nRelayUntil = %d\n"
60 " nExpiration = %d\n"
f35c6c4f
GA
61 " nID = %d\n"
62 " nCancel = %d\n"
63 " setCancel = %s\n"
64 " nMinVer = %d\n"
65 " nMaxVer = %d\n"
66 " setSubVer = %s\n"
67 " nPriority = %d\n"
68 " strComment = \"%s\"\n"
69 " strStatusBar = \"%s\"\n"
70 ")\n",
71 nVersion,
72 nRelayUntil,
73 nExpiration,
74 nID,
75 nCancel,
7d9d134b 76 strSetCancel,
f35c6c4f
GA
77 nMinVer,
78 nMaxVer,
7d9d134b 79 strSetSubVer,
f35c6c4f 80 nPriority,
7d9d134b
WL
81 strComment,
82 strStatusBar);
f35c6c4f
GA
83}
84
f35c6c4f
GA
85void CAlert::SetNull()
86{
87 CUnsignedAlert::SetNull();
88 vchMsg.clear();
89 vchSig.clear();
90}
91
92bool CAlert::IsNull() const
93{
94 return (nExpiration == 0);
95}
96
97uint256 CAlert::GetHash() const
98{
99 return Hash(this->vchMsg.begin(), this->vchMsg.end());
100}
101
102bool CAlert::IsInEffect() const
103{
104 return (GetAdjustedTime() < nExpiration);
105}
106
107bool 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
114bool 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
122bool CAlert::AppliesToMe() const
123{
124 return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
125}
126
127bool CAlert::RelayTo(CNode* pnode) const
128{
129 if (!IsInEffect())
130 return false;
20a5f610
WL
131 // don't relay to nodes which haven't sent their version message
132 if (pnode->nVersion == 0)
133 return false;
f35c6c4f
GA
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
148bool CAlert::CheckSignature() const
149{
0e4b3175 150 CPubKey key(Params().AlertKey());
f35c6c4f
GA
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
160CAlert CAlert::getAlertByHash(const uint256 &hash)
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
e5f163a0 172bool CAlert::ProcessAlert(bool fThread)
f35c6c4f
GA
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 {
881a85a2 209 LogPrint("alert", "cancelling alert %d\n", alert.nID);
f35c6c4f
GA
210 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
211 mapAlerts.erase(mi++);
212 }
213 else if (!alert.IsInEffect())
214 {
881a85a2 215 LogPrint("alert", "expiring alert %d\n", alert.nID);
f35c6c4f
GA
216 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
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 {
881a85a2 229 LogPrint("alert", "alert already cancelled by %d\n", alert.nID);
f35c6c4f
GA
230 return false;
231 }
232 }
233
234 // Add to mapAlerts
235 mapAlerts.insert(make_pair(GetHash(), *this));
e5f163a0 236 // Notify UI and -alertnotify if it applies to me
f35c6c4f 237 if(AppliesToMe())
e5f163a0 238 {
f35c6c4f 239 uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
e01a7939 240 Notify(strStatusBar, fThread);
e5f163a0 241 }
f35c6c4f
GA
242 }
243
881a85a2 244 LogPrint("alert", "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
f35c6c4f
GA
245 return true;
246}
e01a7939
GA
247
248void
249CAlert::Notify(const std::string& strMessage, bool fThread)
250{
251 std::string strCmd = GetArg("-alertnotify", "");
252 if (strCmd.empty()) return;
253
254 // Alert text should be plain ascii coming from a trusted source, but to
255 // be safe we first strip anything not in safeChars, then add single quotes around
256 // the whole string before passing it to the shell:
257 std::string singleQuote("'");
258 std::string safeStatus = SanitizeString(strMessage);
259 safeStatus = singleQuote+safeStatus+singleQuote;
260 boost::replace_all(strCmd, "%s", safeStatus);
261
262 if (fThread)
263 boost::thread t(runCommand, strCmd); // thread runs free
264 else
265 runCommand(strCmd);
266}
This page took 0.138871 seconds and 4 git commands to generate.