alert.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net)
  2. #include <boost/foreach.hpp>
  3. #include <map>
  4. #include "alert.h"
  5. #include "key.h"
  6. #include "net.h"
  7. #include "sync.h"
  8. #include "ui_interface.h"
  9. using namespace std;
  10. map<uint256, CAlert> mapAlerts;
  11. CCriticalSection cs_mapAlerts;
  12. static const char* pszMainKey = "045d0773e7224ee40c6e69755c0343022b8f125f218a5ec5f6e57b31c00e182e048807d7e66548148795c1dfa4c972b6792ad41efea33111c5fc0d6c86fc0383f1";
  13. static const char* pszTestKey = "044d5253cb7c6fcb7b790365ac5aeeef359fc52de23f1ce9bffc092c16dd0372444b75ba328ddf4ebb73257e7c882c9bf81d86d1938ad36ac280214ba72aa9aca6";
  14. void CUnsignedAlert::SetNull()
  15. {
  16. nVersion = 1;
  17. nRelayUntil = 0;
  18. nExpiration = 0;
  19. nID = 0;
  20. nCancel = 0;
  21. setCancel.clear();
  22. nMinVer = 0;
  23. nMaxVer = 0;
  24. setSubVer.clear();
  25. nPriority = 0;
  26. strComment.clear();
  27. strStatusBar.clear();
  28. strReserved.clear();
  29. }
  30. std::string CUnsignedAlert::ToString() const
  31. {
  32. std::string strSetCancel;
  33. BOOST_FOREACH(int n, setCancel)
  34. strSetCancel += strprintf("%d ", n);
  35. std::string strSetSubVer;
  36. BOOST_FOREACH(std::string str, setSubVer)
  37. strSetSubVer += "\"" + str + "\" ";
  38. return strprintf(
  39. "CAlert(\n"
  40. " nVersion = %d\n"
  41. " nRelayUntil = %" PRI64d"\n"
  42. " nExpiration = %" PRI64d"\n"
  43. " nID = %d\n"
  44. " nCancel = %d\n"
  45. " setCancel = %s\n"
  46. " nMinVer = %d\n"
  47. " nMaxVer = %d\n"
  48. " setSubVer = %s\n"
  49. " nPriority = %d\n"
  50. " strComment = \"%s\"\n"
  51. " strStatusBar = \"%s\"\n"
  52. ")\n",
  53. nVersion,
  54. nRelayUntil,
  55. nExpiration,
  56. nID,
  57. nCancel,
  58. strSetCancel.c_str(),
  59. nMinVer,
  60. nMaxVer,
  61. strSetSubVer.c_str(),
  62. nPriority,
  63. strComment.c_str(),
  64. strStatusBar.c_str());
  65. }
  66. void CUnsignedAlert::print() const
  67. {
  68. printf("%s", ToString().c_str());
  69. }
  70. void CAlert::SetNull()
  71. {
  72. CUnsignedAlert::SetNull();
  73. vchMsg.clear();
  74. vchSig.clear();
  75. }
  76. bool CAlert::IsNull() const
  77. {
  78. return (nExpiration == 0);
  79. }
  80. uint256 CAlert::GetHash() const
  81. {
  82. return Hash(this->vchMsg.begin(), this->vchMsg.end());
  83. }
  84. bool CAlert::IsInEffect() const
  85. {
  86. return (GetAdjustedTime() < nExpiration);
  87. }
  88. bool CAlert::Cancels(const CAlert& alert) const
  89. {
  90. if (!IsInEffect())
  91. return false; // this was a no-op before 31403
  92. return (alert.nID <= nCancel || setCancel.count(alert.nID));
  93. }
  94. bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const
  95. {
  96. return (IsInEffect() &&
  97. nMinVer <= nVersion && nVersion <= nMaxVer &&
  98. (setSubVer.empty() || setSubVer.count(strSubVerIn)));
  99. }
  100. bool CAlert::AppliesToMe() const
  101. {
  102. return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<std::string>()));
  103. }
  104. bool CAlert::RelayTo(CNode* pnode) const
  105. {
  106. if (!IsInEffect())
  107. return false;
  108. // returns true if wasn't already contained in the set
  109. if (pnode->setKnown.insert(GetHash()).second)
  110. {
  111. if (AppliesTo(pnode->nVersion, pnode->strSubVer) ||
  112. AppliesToMe() ||
  113. GetAdjustedTime() < nRelayUntil)
  114. {
  115. pnode->PushMessage("alert", *this);
  116. return true;
  117. }
  118. }
  119. return false;
  120. }
  121. bool CAlert::CheckSignature() const
  122. {
  123. CKey key;
  124. if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey)))
  125. return error("CAlert::CheckSignature() : SetPubKey failed");
  126. if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig))
  127. return error("CAlert::CheckSignature() : verify signature failed");
  128. // Now unserialize the data
  129. CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION);
  130. sMsg >> *(CUnsignedAlert*)this;
  131. return true;
  132. }
  133. CAlert CAlert::getAlertByHash(const uint256 &hash)
  134. {
  135. CAlert retval;
  136. {
  137. LOCK(cs_mapAlerts);
  138. map<uint256, CAlert>::iterator mi = mapAlerts.find(hash);
  139. if(mi != mapAlerts.end())
  140. retval = mi->second;
  141. }
  142. return retval;
  143. }
  144. bool CAlert::ProcessAlert()
  145. {
  146. if (!CheckSignature())
  147. return false;
  148. if (!IsInEffect())
  149. return false;
  150. int maxInt = std::numeric_limits<int>::max();
  151. if (nID == maxInt)
  152. {
  153. if (!(
  154. nExpiration == maxInt &&
  155. nCancel == (maxInt-1) &&
  156. nMinVer == 0 &&
  157. nMaxVer == maxInt &&
  158. setSubVer.empty() &&
  159. nPriority == maxInt &&
  160. strStatusBar == "URGENT: Alert key compromised, upgrade required"
  161. ))
  162. return false;
  163. }
  164. {
  165. LOCK(cs_mapAlerts);
  166. // Cancel previous alerts
  167. for (map<uint256, CAlert>::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();)
  168. {
  169. const CAlert& alert = (*mi).second;
  170. if (Cancels(alert))
  171. {
  172. printf("cancelling alert %d\n", alert.nID);
  173. uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
  174. mapAlerts.erase(mi++);
  175. }
  176. else if (!alert.IsInEffect())
  177. {
  178. printf("expiring alert %d\n", alert.nID);
  179. uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED);
  180. mapAlerts.erase(mi++);
  181. }
  182. else
  183. mi++;
  184. }
  185. // Check if this alert has been cancelled
  186. BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts)
  187. {
  188. const CAlert& alert = item.second;
  189. if (alert.Cancels(*this))
  190. {
  191. printf("alert already cancelled by %d\n", alert.nID);
  192. return false;
  193. }
  194. }
  195. // Add to mapAlerts
  196. mapAlerts.insert(make_pair(GetHash(), *this));
  197. // Notify UI if it applies to me
  198. if(AppliesToMe())
  199. uiInterface.NotifyAlertChanged(GetHash(), CT_NEW);
  200. }
  201. printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe());
  202. return true;
  203. }