]> Git Repo - VerusCoin.git/blame - src/alert.cpp
Merge pull request #2336 from petertodd/invalid-opcode-coverage
[VerusCoin.git] / src / alert.cpp
CommitLineData
f35c6c4f
GA
1//
2// Alert system
3//
4
5#include <boost/foreach.hpp>
6#include <map>
7
8#include "alert.h"
9#include "key.h"
10#include "net.h"
11#include "sync.h"
12#include "ui_interface.h"
13
14using namespace std;
15
16map<uint256, CAlert> mapAlerts;
17CCriticalSection cs_mapAlerts;
18
286dbba2
GA
19static const char* pszMainKey = "04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284";
20static const char* pszTestKey = "04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a";
21
f35c6c4f
GA
22void CUnsignedAlert::SetNull()
23{
24 nVersion = 1;
25 nRelayUntil = 0;
26 nExpiration = 0;
27 nID = 0;
28 nCancel = 0;
29 setCancel.clear();
30 nMinVer = 0;
31 nMaxVer = 0;
32 setSubVer.clear();
33 nPriority = 0;
34
35 strComment.clear();
36 strStatusBar.clear();
37 strReserved.clear();
38}
39
40std::string CUnsignedAlert::ToString() const
41{
42 std::string strSetCancel;
43 BOOST_FOREACH(int n, setCancel)
44 strSetCancel += strprintf("%d ", n);
45 std::string strSetSubVer;
46 BOOST_FOREACH(std::string str, setSubVer)
47 strSetSubVer += "\"" + str + "\" ";
48 return strprintf(
49 "CAlert(\n"
50 " nVersion = %d\n"
51 " nRelayUntil = %"PRI64d"\n"
52 " nExpiration = %"PRI64d"\n"
53 " nID = %d\n"
54 " nCancel = %d\n"
55 " setCancel = %s\n"
56 " nMinVer = %d\n"
57 " nMaxVer = %d\n"
58 " setSubVer = %s\n"
59 " nPriority = %d\n"
60 " strComment = \"%s\"\n"
61 " strStatusBar = \"%s\"\n"
62 ")\n",
63 nVersion,
64 nRelayUntil,
65 nExpiration,
66 nID,
67 nCancel,
68 strSetCancel.c_str(),
69 nMinVer,
70 nMaxVer,
71 strSetSubVer.c_str(),
72 nPriority,
73 strComment.c_str(),
74 strStatusBar.c_str());
75}
76
77void CUnsignedAlert::print() const
78{
79 printf("%s", ToString().c_str());
80}
81
82void CAlert::SetNull()
83{
84 CUnsignedAlert::SetNull();
85 vchMsg.clear();
86 vchSig.clear();
87}
88
89bool CAlert::IsNull() const
90{
91 return (nExpiration == 0);
92}
93
94uint256 CAlert::GetHash() const
95{
96 return Hash(this->vchMsg.begin(), this->vchMsg.end());
97}
98
99bool CAlert::IsInEffect() const
100{
101 return (GetAdjustedTime() < nExpiration);
102}
103
104bool CAlert::Cancels(const CAlert& alert) const
105{
106 if (!IsInEffect())
107 return false; // this was a no-op before 31403
108 return (alert.nID <= nCancel || setCancel.count(alert.nID));
109}
110
111bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const
112{
113 // TODO: rework for client-version-embedded-in-strSubVer ?
114 return (IsInEffect() &&
115 nMinVer <= nVersion && nVersion <= nMaxVer &&
116 (setSubVer.empty() || setSubVer.count(strSubVerIn)));
117}
118
119bool CAlert::AppliesToMe() const
120{
121 return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
122}
123
124bool CAlert::RelayTo(CNode* pnode) const
125{
126 if (!IsInEffect())
127 return false;
128 // returns true if wasn't already contained in the set
129 if (pnode->setKnown.insert(GetHash()).second)
130 {
131 if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
132 AppliesToMe() ||
133 GetAdjustedTime() < nRelayUntil)
134 {
135 pnode->PushMessage("alert", *this);
136 return true;
137 }
138 }
139 return false;
140}
141
142bool CAlert::CheckSignature() const
143{
144 CKey key;
286dbba2 145 if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey)))
f35c6c4f
GA
146 return error("CAlert::CheckSignature() : SetPubKey failed");
147 if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
148 return error("CAlert::CheckSignature() : verify signature failed");
149
150 // Now unserialize the data
151 CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
152 sMsg >> *(CUnsignedAlert*)this;
153 return true;
154}
155
156CAlert CAlert::getAlertByHash(const uint256 &hash)
157{
158 CAlert retval;
159 {
160 LOCK(cs_mapAlerts);
161 map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
162 if(mi != mapAlerts.end())
163 retval = mi->second;
164 }
165 return retval;
166}
167
168bool CAlert::ProcessAlert()
169{
170 if (!CheckSignature())
171 return false;
172 if (!IsInEffect())
173 return false;
174
175 // alert.nID=max is reserved for if the alert key is
176 // compromised. It must have a pre-defined message,
177 // must never expire, must apply to all versions,
178 // and must cancel all previous
179 // alerts or it will be ignored (so an attacker can't
180 // send an "everything is OK, don't panic" version that
181 // cannot be overridden):
182 int maxInt = std::numeric_limits<int>::max();
183 if (nID == maxInt)
184 {
185 if (!(
186 nExpiration == maxInt &&
187 nCancel == (maxInt-1) &&
188 nMinVer == 0 &&
189 nMaxVer == maxInt &&
190 setSubVer.empty() &&
191 nPriority == maxInt &&
192 strStatusBar == "URGENT: Alert key compromised, upgrade required"
193 ))
194 return false;
195 }
196
197 {
198 LOCK(cs_mapAlerts);
199 // Cancel previous alerts
200 for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
201 {
202 const CAlert& alert = (*mi).second;
203 if (Cancels(alert))
204 {
205 printf("cancelling alert %d\n", alert.nID);
206 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
207 mapAlerts.erase(mi++);
208 }
209 else if (!alert.IsInEffect())
210 {
211 printf("expiring alert %d\n", alert.nID);
212 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
213 mapAlerts.erase(mi++);
214 }
215 else
216 mi++;
217 }
218
219 // Check if this alert has been cancelled
220 BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
221 {
222 const CAlert& alert = item.second;
223 if (alert.Cancels(*this))
224 {
225 printf("alert already cancelled by %d\n", alert.nID);
226 return false;
227 }
228 }
229
230 // Add to mapAlerts
231 mapAlerts.insert(make_pair(GetHash(), *this));
232 // Notify UI if it applies to me
233 if(AppliesToMe())
234 uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
235 }
236
237 printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
238 return true;
239}
This page took 0.04967 seconds and 4 git commands to generate.