]> Git Repo - VerusCoin.git/blame - src/alert.cpp
Merge pull request #557 from jl777/kolo-assets-new
[VerusCoin.git] / src / alert.cpp
CommitLineData
cd696e64 1// Copyright (c) 2010 Satoshi Nakamoto
f914f1a7 2// Copyright (c) 2009-2014 The Bitcoin Core 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
71697f97 8#include "clientversion.h"
f35c6c4f 9#include "net.h"
b4347f60 10#include "pubkey.h"
14f888ca 11#include "timedata.h"
f35c6c4f 12#include "ui_interface.h"
51ed9ec9
BD
13#include "util.h"
14
74f66a5e 15#include <stdint.h>
51ed9ec9 16#include <algorithm>
51ed9ec9
BD
17#include <map>
18
19#include <boost/algorithm/string/classification.hpp>
20#include <boost/algorithm/string/replace.hpp>
21#include <boost/foreach.hpp>
ad49c256 22#include <boost/thread.hpp>
f35c6c4f
GA
23
24using namespace std;
25
26map<uint256, CAlert> mapAlerts;
27CCriticalSection cs_mapAlerts;
28
29void CUnsignedAlert::SetNull()
30{
31 nVersion = 1;
32 nRelayUntil = 0;
33 nExpiration = 0;
34 nID = 0;
35 nCancel = 0;
36 setCancel.clear();
37 nMinVer = 0;
38 nMaxVer = 0;
39 setSubVer.clear();
40 nPriority = 0;
41
42 strComment.clear();
43 strStatusBar.clear();
a40034f7 44 strRPCError.clear();
f35c6c4f
GA
45}
46
47std::string CUnsignedAlert::ToString() const
48{
49 std::string strSetCancel;
50 BOOST_FOREACH(int n, setCancel)
51 strSetCancel += strprintf("%d ", n);
52 std::string strSetSubVer;
db954a65 53 BOOST_FOREACH(const std::string& str, setSubVer)
f35c6c4f
GA
54 strSetSubVer += "\"" + str + "\" ";
55 return strprintf(
56 "CAlert(\n"
57 " nVersion = %d\n"
f48742c2
WL
58 " nRelayUntil = %d\n"
59 " nExpiration = %d\n"
f35c6c4f
GA
60 " nID = %d\n"
61 " nCancel = %d\n"
62 " setCancel = %s\n"
63 " nMinVer = %d\n"
64 " nMaxVer = %d\n"
65 " setSubVer = %s\n"
66 " nPriority = %d\n"
67 " strComment = \"%s\"\n"
68 " strStatusBar = \"%s\"\n"
a40034f7 69 " strRPCError = \"%s\"\n"
f35c6c4f
GA
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 81 strComment,
a40034f7
JG
82 strStatusBar,
83 strRPCError);
f35c6c4f
GA
84}
85
f35c6c4f
GA
86void CAlert::SetNull()
87{
88 CUnsignedAlert::SetNull();
89 vchMsg.clear();
90 vchSig.clear();
91}
92
93bool CAlert::IsNull() const
94{
95 return (nExpiration == 0);
96}
97
98uint256 CAlert::GetHash() const
99{
100 return Hash(this->vchMsg.begin(), this->vchMsg.end());
101}
102
103bool CAlert::IsInEffect() const
104{
105 return (GetAdjustedTime() < nExpiration);
106}
107
108bool 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
db954a65 115bool CAlert::AppliesTo(int nVersion, const std::string& strSubVerIn) const
f35c6c4f
GA
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
123bool CAlert::AppliesToMe() const
124{
125 return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
126}
127
128bool CAlert::RelayTo(CNode* pnode) const
129{
130 if (!IsInEffect())
131 return false;
20a5f610
WL
132 // don't relay to nodes which haven't sent their version message
133 if (pnode->nVersion == 0)
134 return false;
f35c6c4f
GA
135 // returns true if wasn't already contained in the set
136 if (pnode->setKnown.insert(GetHash()).second)
137 {
138 if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
139 AppliesToMe() ||
140 GetAdjustedTime() < nRelayUntil)
141 {
142 pnode->PushMessage("alert", *this);
143 return true;
144 }
145 }
146 return false;
147}
148
f14e687f 149bool CAlert::CheckSignature(const std::vector<unsigned char>& alertKey) const
f35c6c4f 150{
f14e687f 151 CPubKey key(alertKey);
f35c6c4f 152 if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
5262fde0 153 return error("CAlert::CheckSignature(): verify signature failed");
f35c6c4f
GA
154
155 // Now unserialize the data
156 CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
157 sMsg >> *(CUnsignedAlert*)this;
158 return true;
159}
160
161CAlert CAlert::getAlertByHash(const uint256 &hash)
162{
163 CAlert retval;
164 {
165 LOCK(cs_mapAlerts);
166 map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
167 if(mi != mapAlerts.end())
168 retval = mi->second;
169 }
170 return retval;
171}
172
f14e687f 173bool CAlert::ProcessAlert(const std::vector<unsigned char>& alertKey, bool fThread)
f35c6c4f 174{
f14e687f 175 if (!CheckSignature(alertKey))
f35c6c4f
GA
176 return false;
177 if (!IsInEffect())
178 return false;
179
180 // alert.nID=max is reserved for if the alert key is
181 // compromised. It must have a pre-defined message,
182 // must never expire, must apply to all versions,
183 // and must cancel all previous
184 // alerts or it will be ignored (so an attacker can't
185 // send an "everything is OK, don't panic" version that
186 // cannot be overridden):
187 int maxInt = std::numeric_limits<int>::max();
188 if (nID == maxInt)
189 {
190 if (!(
191 nExpiration == maxInt &&
192 nCancel == (maxInt-1) &&
193 nMinVer == 0 &&
194 nMaxVer == maxInt &&
195 setSubVer.empty() &&
196 nPriority == maxInt &&
197 strStatusBar == "URGENT: Alert key compromised, upgrade required"
198 ))
199 return false;
200 }
201
202 {
203 LOCK(cs_mapAlerts);
204 // Cancel previous alerts
205 for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
206 {
207 const CAlert& alert = (*mi).second;
208 if (Cancels(alert))
209 {
881a85a2 210 LogPrint("alert", "cancelling alert %d\n", alert.nID);
f35c6c4f
GA
211 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
212 mapAlerts.erase(mi++);
213 }
214 else if (!alert.IsInEffect())
215 {
881a85a2 216 LogPrint("alert", "expiring alert %d\n", alert.nID);
f35c6c4f
GA
217 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
218 mapAlerts.erase(mi++);
219 }
220 else
221 mi++;
222 }
223
224 // Check if this alert has been cancelled
225 BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
226 {
227 const CAlert& alert = item.second;
228 if (alert.Cancels(*this))
229 {
881a85a2 230 LogPrint("alert", "alert already cancelled by %d\n", alert.nID);
f35c6c4f
GA
231 return false;
232 }
233 }
234
235 // Add to mapAlerts
236 mapAlerts.insert(make_pair(GetHash(), *this));
e5f163a0 237 // Notify UI and -alertnotify if it applies to me
f35c6c4f 238 if(AppliesToMe())
e5f163a0 239 {
f35c6c4f 240 uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
e01a7939 241 Notify(strStatusBar, fThread);
e5f163a0 242 }
f35c6c4f
GA
243 }
244
881a85a2 245 LogPrint("alert", "accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
f35c6c4f
GA
246 return true;
247}
e01a7939
GA
248
249void
250CAlert::Notify(const std::string& strMessage, bool fThread)
251{
252 std::string strCmd = GetArg("-alertnotify", "");
253 if (strCmd.empty()) return;
254
255 // Alert text should be plain ascii coming from a trusted source, but to
256 // be safe we first strip anything not in safeChars, then add single quotes around
257 // the whole string before passing it to the shell:
258 std::string singleQuote("'");
259 std::string safeStatus = SanitizeString(strMessage);
260 safeStatus = singleQuote+safeStatus+singleQuote;
261 boost::replace_all(strCmd, "%s", safeStatus);
262
263 if (fThread)
264 boost::thread t(runCommand, strCmd); // thread runs free
265 else
266 runCommand(strCmd);
267}
This page took 0.171257 seconds and 4 git commands to generate.