5 #include <boost/foreach.hpp>
12 #include "ui_interface.h"
16 map<uint256, CAlert> mapAlerts;
17 CCriticalSection cs_mapAlerts;
19 static const char* pszMainKey = "043fa441fd4203d03f5df2b75ea14e36f20d39f43e7a61aa7552ab9bcd7ecb0e77a3be4585b13fcdaa22ef6e51f1ff6f2929bec2494385b086fb86610e33193195";
21 // TestNet alerts pubKey
22 static const char* pszTestKey = "0471dc165db490094d35cde15b1f5d755fa6ad6f2b5ed0f340e3f17f57389c3c2af113a8cbcc885bde73305a553b5640c83021128008ddf882e856336269080496";
24 // TestNet alerts private key
25 // "308201130201010420b665cff1884e53da26376fd1b433812c9a5a8a4d5221533b15b9629789bb7e42a081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a1440342000471dc165db490094d35cde15b1f5d755fa6ad6f2b5ed0f340e3f17f57389c3c2af113a8cbcc885bde73305a553b5640c83021128008ddf882e856336269080496"
27 void CUnsignedAlert::SetNull()
45 std::string CUnsignedAlert::ToString() const
47 std::string strSetCancel;
48 BOOST_FOREACH(int n, setCancel)
49 strSetCancel += strprintf("%d ", n);
50 std::string strSetSubVer;
51 BOOST_FOREACH(std::string str, setSubVer)
52 strSetSubVer += "\"" + str + "\" ";
56 " nRelayUntil = %"PRI64d"\n"
57 " nExpiration = %"PRI64d"\n"
65 " strComment = \"%s\"\n"
66 " strStatusBar = \"%s\"\n"
79 strStatusBar.c_str());
82 void CUnsignedAlert::print() const
84 printf("%s", ToString().c_str());
87 void CAlert::SetNull()
89 CUnsignedAlert::SetNull();
94 bool CAlert::IsNull() const
96 return (nExpiration == 0);
99 uint256 CAlert::GetHash() const
101 return Hash(this->vchMsg.begin(), this->vchMsg.end());
104 bool CAlert::IsInEffect() const
106 return (GetAdjustedTime() < nExpiration);
109 bool CAlert::Cancels(const CAlert& alert) const
112 return false; // this was a no-op before 31403
113 return (alert.nID <= nCancel || setCancel.count(alert.nID));
116 bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const
118 // TODO: rework for client-version-embedded-in-strSubVer ?
119 return (IsInEffect() &&
120 nMinVer <= nVersion && nVersion <= nMaxVer &&
121 (setSubVer.empty() || setSubVer.count(strSubVerIn)));
124 bool CAlert::AppliesToMe() const
126 return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
129 bool CAlert::RelayTo(CNode* pnode) const
133 // don't relay to nodes which haven't sent their version message
134 if (pnode->nVersion == 0)
136 // returns true if wasn't already contained in the set
137 if (pnode->setKnown.insert(GetHash()).second)
139 if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
141 GetAdjustedTime() < nRelayUntil)
143 pnode->PushMessage("alert", *this);
150 bool CAlert::CheckSignature() const
153 if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey)))
154 return error("CAlert::CheckSignature() : SetPubKey failed");
155 if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
156 return error("CAlert::CheckSignature() : verify signature failed");
158 // Now unserialize the data
159 CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
160 sMsg >> *(CUnsignedAlert*)this;
164 CAlert CAlert::getAlertByHash(const uint256 &hash)
169 map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
170 if(mi != mapAlerts.end())
176 bool CAlert::ProcessAlert()
178 if (!CheckSignature())
183 // alert.nID=max is reserved for if the alert key is
184 // compromised. It must have a pre-defined message,
185 // must never expire, must apply to all versions,
186 // and must cancel all previous
187 // alerts or it will be ignored (so an attacker can't
188 // send an "everything is OK, don't panic" version that
189 // cannot be overridden):
190 int maxInt = std::numeric_limits<int>::max();
194 nExpiration == maxInt &&
195 nCancel == (maxInt-1) &&
199 nPriority == maxInt &&
200 strStatusBar == "URGENT: Alert key compromised, upgrade required"
207 // Cancel previous alerts
208 for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
210 const CAlert& alert = (*mi).second;
213 printf("cancelling alert %d\n", alert.nID);
214 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
215 mapAlerts.erase(mi++);
217 else if (!alert.IsInEffect())
219 printf("expiring alert %d\n", alert.nID);
220 uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
221 mapAlerts.erase(mi++);
227 // Check if this alert has been cancelled
228 BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
230 const CAlert& alert = item.second;
231 if (alert.Cancels(*this))
233 printf("alert already cancelled by %d\n", alert.nID);
239 mapAlerts.insert(make_pair(GetHash(), *this));
240 // Notify UI if it applies to me
242 uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
245 printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());