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