// ECOin - Copyright (c) - 2014/2021 - GPLv3 - epsylon@riseup.net (https://03c8.net) #include #include #include "alert.h" #include "key.h" #include "net.h" #include "sync.h" #include "ui_interface.h" using namespace std; map mapAlerts; CCriticalSection cs_mapAlerts; static const char* pszMainKey = "045d0773e7224ee40c6e69755c0343022b8f125f218a5ec5f6e57b31c00e182e048807d7e66548148795c1dfa4c972b6792ad41efea33111c5fc0d6c86fc0383f1"; static const char* pszTestKey = "044d5253cb7c6fcb7b790365ac5aeeef359fc52de23f1ce9bffc092c16dd0372444b75ba328ddf4ebb73257e7c882c9bf81d86d1938ad36ac280214ba72aa9aca6"; void CUnsignedAlert::SetNull() { nVersion = 1; nRelayUntil = 0; nExpiration = 0; nID = 0; nCancel = 0; setCancel.clear(); nMinVer = 0; nMaxVer = 0; setSubVer.clear(); nPriority = 0; strComment.clear(); strStatusBar.clear(); strReserved.clear(); } std::string CUnsignedAlert::ToString() const { std::string strSetCancel; BOOST_FOREACH(int n, setCancel) strSetCancel += strprintf("%d ", n); std::string strSetSubVer; BOOST_FOREACH(std::string str, setSubVer) strSetSubVer += "\"" + str + "\" "; return strprintf( "CAlert(\n" " nVersion = %d\n" " nRelayUntil = %" PRI64d"\n" " nExpiration = %" PRI64d"\n" " nID = %d\n" " nCancel = %d\n" " setCancel = %s\n" " nMinVer = %d\n" " nMaxVer = %d\n" " setSubVer = %s\n" " nPriority = %d\n" " strComment = \"%s\"\n" " strStatusBar = \"%s\"\n" ")\n", nVersion, nRelayUntil, nExpiration, nID, nCancel, strSetCancel.c_str(), nMinVer, nMaxVer, strSetSubVer.c_str(), nPriority, strComment.c_str(), strStatusBar.c_str()); } void CUnsignedAlert::print() const { printf("%s", ToString().c_str()); } void CAlert::SetNull() { CUnsignedAlert::SetNull(); vchMsg.clear(); vchSig.clear(); } bool CAlert::IsNull() const { return (nExpiration == 0); } uint256 CAlert::GetHash() const { return Hash(this->vchMsg.begin(), this->vchMsg.end()); } bool CAlert::IsInEffect() const { return (GetAdjustedTime() < nExpiration); } bool CAlert::Cancels(const CAlert& alert) const { if (!IsInEffect()) return false; // this was a no-op before 31403 return (alert.nID <= nCancel || setCancel.count(alert.nID)); } bool CAlert::AppliesTo(int nVersion, std::string strSubVerIn) const { return (IsInEffect() && nMinVer <= nVersion && nVersion <= nMaxVer && (setSubVer.empty() || setSubVer.count(strSubVerIn))); } bool CAlert::AppliesToMe() const { return AppliesTo(PROTOCOL_VERSION, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector())); } bool CAlert::RelayTo(CNode* pnode) const { if (!IsInEffect()) return false; // returns true if wasn't already contained in the set if (pnode->setKnown.insert(GetHash()).second) { if (AppliesTo(pnode->nVersion, pnode->strSubVer) || AppliesToMe() || GetAdjustedTime() < nRelayUntil) { pnode->PushMessage("alert", *this); return true; } } return false; } bool CAlert::CheckSignature() const { CKey key; if (!key.SetPubKey(ParseHex(fTestNet ? pszTestKey : pszMainKey))) return error("CAlert::CheckSignature() : SetPubKey failed"); if (!key.Verify(Hash(vchMsg.begin(), vchMsg.end()), vchSig)) return error("CAlert::CheckSignature() : verify signature failed"); // Now unserialize the data CDataStream sMsg(vchMsg, SER_NETWORK, PROTOCOL_VERSION); sMsg >> *(CUnsignedAlert*)this; return true; } CAlert CAlert::getAlertByHash(const uint256 &hash) { CAlert retval; { LOCK(cs_mapAlerts); map::iterator mi = mapAlerts.find(hash); if(mi != mapAlerts.end()) retval = mi->second; } return retval; } bool CAlert::ProcessAlert() { if (!CheckSignature()) return false; if (!IsInEffect()) return false; int maxInt = std::numeric_limits::max(); if (nID == maxInt) { if (!( nExpiration == maxInt && nCancel == (maxInt-1) && nMinVer == 0 && nMaxVer == maxInt && setSubVer.empty() && nPriority == maxInt && strStatusBar == "URGENT: Alert key compromised, upgrade required" )) return false; } { LOCK(cs_mapAlerts); // Cancel previous alerts for (map::iterator mi = mapAlerts.begin(); mi != mapAlerts.end();) { const CAlert& alert = (*mi).second; if (Cancels(alert)) { printf("cancelling alert %d\n", alert.nID); uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); mapAlerts.erase(mi++); } else if (!alert.IsInEffect()) { printf("expiring alert %d\n", alert.nID); uiInterface.NotifyAlertChanged((*mi).first, CT_DELETED); mapAlerts.erase(mi++); } else mi++; } // Check if this alert has been cancelled BOOST_FOREACH(PAIRTYPE(const uint256, CAlert)& item, mapAlerts) { const CAlert& alert = item.second; if (alert.Cancels(*this)) { printf("alert already cancelled by %d\n", alert.nID); return false; } } // Add to mapAlerts mapAlerts.insert(make_pair(GetHash(), *this)); // Notify UI if it applies to me if(AppliesToMe()) uiInterface.NotifyAlertChanged(GetHash(), CT_NEW); } printf("accepted alert %d, AppliesToMe()=%d\n", nID, AppliesToMe()); return true; }