5 #include <boost/foreach.hpp>
12 #include "ui_interface.h"
16 map<uint256, CAlert> mapAlerts;
17 CCriticalSection cs_mapAlerts;
19 static const char* pszMainKey = "04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284";
20 static const char* pszTestKey = "04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a";
22 void CUnsignedAlert::SetNull()
40 std::string CUnsignedAlert::ToString() const
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 + "\" ";
51 " nRelayUntil = %"PRI64d"\n"
52 " nExpiration = %"PRI64d"\n"
60 " strComment = \"%s\"\n"
61 " strStatusBar = \"%s\"\n"
74 strStatusBar.c_str());
77 void CUnsignedAlert::print() const
79 printf("%s", ToString().c_str());
82 void CAlert::SetNull()
84 CUnsignedAlert::SetNull();
89 bool CAlert::IsNull() const
91 return (nExpiration == 0);
94 uint256 CAlert::GetHash() const
96 return Hash(this->vchMsg.begin(), this->vchMsg.end());
99 bool CAlert::IsInEffect() const
101 return (GetAdjustedTime() < nExpiration);
104 bool CAlert::Cancels(const CAlert& alert) const
107 return false; // this was a no-op before 31403
108 return (alert.nID <= nCancel || setCancel.count(alert.nID));
111 bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const
113 // TODO: rework for client-version-embedded-in-strSubVer ?
114 return (IsInEffect() &&
115 nMinVer <= nVersion && nVersion <= nMaxVer &&
116 (setSubVer.empty() || setSubVer.count(strSubVerIn)));
119 bool CAlert::AppliesToMe() const
121 return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
124 bool CAlert::RelayTo(CNode* pnode) const
128 // returns true if wasn't already contained in the set
129 if (pnode->setKnown.insert(GetHash()).second)
131 if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
133 GetAdjustedTime() < nRelayUntil)
135 pnode->PushMessage("alert", *this);
142 bool CAlert::CheckSignature() const
145 if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey)))
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");
150 // Now unserialize the data
151 CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
152 sMsg >> *(CUnsignedAlert*)this;
156 CAlert CAlert::getAlertByHash(const uint256 &hash)
161 map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
162 if(mi != mapAlerts.end())
168 bool CAlert::ProcessAlert()
170 if (!CheckSignature())
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();
186 nExpiration == maxInt &&
187 nCancel == (maxInt-1) &&
191 nPriority == maxInt &&
192 strStatusBar == "URGENT: Alert key compromised, upgrade required"
199 // Cancel previous alerts
200 for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
202 const CAlert& alert = (*mi).second;
205 printf("cancelling alert %d\n", alert.nID);
206 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
207 mapAlerts.erase(mi++);
209 else if (!alert.IsInEffect())
211 printf("expiring alert %d\n", alert.nID);
212 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
213 mapAlerts.erase(mi++);
219 // Check if this alert has been cancelled
220 BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
222 const CAlert& alert = item.second;
223 if (alert.Cancels(*this))
225 printf("alert already cancelled by %d\n", alert.nID);
231 mapAlerts.insert(make_pair(GetHash(), *this));
232 // Notify UI if it applies to me
234 uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
237 printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());