diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index b226f39bd..779527971 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -253,16 +253,14 @@ UniValue spork(const JSONRPCRequest& request) std:: string strCommand = request.params[0].get_str(); if (strCommand == "show") { UniValue ret(UniValue::VOBJ); - for(int nSporkID = SPORK_START; nSporkID <= SPORK_END; nSporkID++){ - if(sporkManager.GetSporkNameByID(nSporkID) != "Unknown") - ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.GetSporkValue(nSporkID))); + for (const auto& sporkDef : sporkDefs) { + ret.push_back(Pair(sporkDef.name, sporkManager.GetSporkValue(sporkDef.sporkId))); } return ret; } else if(strCommand == "active"){ UniValue ret(UniValue::VOBJ); - for(int nSporkID = SPORK_START; nSporkID <= SPORK_END; nSporkID++){ - if(sporkManager.GetSporkNameByID(nSporkID) != "Unknown") - ret.push_back(Pair(sporkManager.GetSporkNameByID(nSporkID), sporkManager.IsSporkActive(nSporkID))); + for (const auto& sporkDef : sporkDefs) { + ret.push_back(Pair(sporkDef.name, sporkManager.IsSporkActive(sporkDef.sporkId))); } return ret; } @@ -291,8 +289,8 @@ UniValue spork(const JSONRPCRequest& request) + HelpExampleRpc("spork", "\"show\"")); } else { // advanced mode, update spork values - int nSporkID = sporkManager.GetSporkIDByName(request.params[0].get_str()); - if(nSporkID == -1) + SporkId nSporkID = sporkManager.GetSporkIDByName(request.params[0].get_str()); + if(nSporkID == SPORK_INVALID) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid spork name"); if (!g_connman) diff --git a/src/spork.cpp b/src/spork.cpp index 776b12b88..76f3df049 100644 --- a/src/spork.cpp +++ b/src/spork.cpp @@ -13,25 +13,34 @@ #include -CSporkManager sporkManager; - const std::string CSporkManager::SERIALIZATION_VERSION_STRING = "CSporkManager-Version-2"; -std::map mapSporkDefaults = { - {SPORK_2_INSTANTSEND_ENABLED, 0}, // ON - {SPORK_3_INSTANTSEND_BLOCK_FILTERING, 0}, // ON - {SPORK_5_INSTANTSEND_MAX_VALUE, 1000}, // 1000 Dash - {SPORK_6_NEW_SIGS, 4070908800ULL}, // OFF - {SPORK_9_SUPERBLOCKS_ENABLED, 4070908800ULL}, // OFF - {SPORK_12_RECONSIDER_BLOCKS, 0}, // 0 BLOCKS - {SPORK_15_DETERMINISTIC_MNS_ENABLED, 4070908800ULL}, // OFF - {SPORK_16_INSTANTSEND_AUTOLOCKS, 4070908800ULL}, // OFF - {SPORK_17_QUORUM_DKG_ENABLED, 4070908800ULL}, // OFF - {SPORK_19_CHAINLOCKS_ENABLED, 4070908800ULL}, // OFF - {SPORK_20_INSTANTSEND_LLMQ_BASED, 4070908800ULL}, // OFF +#define MAKE_SPORK_DEF(name, defaultValue) CSporkDef{name, defaultValue, #name} +std::vector sporkDefs = { + MAKE_SPORK_DEF(SPORK_2_INSTANTSEND_ENABLED, 0), // ON + MAKE_SPORK_DEF(SPORK_3_INSTANTSEND_BLOCK_FILTERING, 0), // ON + MAKE_SPORK_DEF(SPORK_5_INSTANTSEND_MAX_VALUE, 1000), // 1000 Dash + MAKE_SPORK_DEF(SPORK_6_NEW_SIGS, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_9_SUPERBLOCKS_ENABLED, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_12_RECONSIDER_BLOCKS, 0), // 0 BLOCKS + MAKE_SPORK_DEF(SPORK_15_DETERMINISTIC_MNS_ENABLED, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_16_INSTANTSEND_AUTOLOCKS, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_17_QUORUM_DKG_ENABLED, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_19_CHAINLOCKS_ENABLED, 4070908800ULL), // OFF + MAKE_SPORK_DEF(SPORK_20_INSTANTSEND_LLMQ_BASED, 4070908800ULL), // OFF }; -bool CSporkManager::SporkValueIsActive(int nSporkID, int64_t &nActiveValueRet) const +CSporkManager sporkManager; + +CSporkManager::CSporkManager() +{ + for (auto& sporkDef : sporkDefs) { + sporkDefsById.emplace(sporkDef.sporkId, &sporkDef); + sporkDefsByName.emplace(sporkDef.name, &sporkDef); + } +} + +bool CSporkManager::SporkValueIsActive(SporkId nSporkID, int64_t &nActiveValueRet) const { LOCK(cs); @@ -192,7 +201,7 @@ void CSporkManager::ProcessSpork(CNode* pfrom, const std::string& strCommand, CD } -void CSporkManager::ExecuteSpork(int nSporkID, int nValue) +void CSporkManager::ExecuteSpork(SporkId nSporkID, int nValue) { //correct fork via spork technology if(nSporkID == SPORK_12_RECONSIDER_BLOCKS && nValue > 0) { @@ -221,7 +230,7 @@ void CSporkManager::ExecuteSpork(int nSporkID, int nValue) } } -bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue, CConnman& connman) +bool CSporkManager::UpdateSpork(SporkId nSporkID, int64_t nValue, CConnman& connman) { CSporkMessage spork = CSporkMessage(nSporkID, nValue, GetAdjustedTime()); @@ -244,24 +253,13 @@ bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue, CConnman& connman) return false; } -bool CSporkManager::IsSporkActive(int nSporkID) +bool CSporkManager::IsSporkActive(SporkId nSporkID) { - LOCK(cs); - int64_t nSporkValue = -1; - - if (SporkValueIsActive(nSporkID, nSporkValue)) { - return nSporkValue < GetAdjustedTime(); - } - - if (mapSporkDefaults.count(nSporkID)) { - return mapSporkDefaults[nSporkID] < GetAdjustedTime(); - } - - LogPrint(BCLog::SPORK, "CSporkManager::IsSporkActive -- Unknown Spork ID %d\n", nSporkID); - return false; + int64_t nSporkValue = GetSporkValue(nSporkID); + return nSporkValue < GetAdjustedTime(); } -int64_t CSporkManager::GetSporkValue(int nSporkID) +int64_t CSporkManager::GetSporkValue(SporkId nSporkID) { LOCK(cs); @@ -270,50 +268,33 @@ int64_t CSporkManager::GetSporkValue(int nSporkID) return nSporkValue; } - if (mapSporkDefaults.count(nSporkID)) { - return mapSporkDefaults[nSporkID]; + auto it = sporkDefsById.find(nSporkID); + if (it != sporkDefsById.end()) { + return it->second->defaultValue; } LogPrint(BCLog::SPORK, "CSporkManager::GetSporkValue -- Unknown Spork ID %d\n", nSporkID); return -1; } -int CSporkManager::GetSporkIDByName(const std::string& strName) +SporkId CSporkManager::GetSporkIDByName(const std::string& strName) { - if (strName == "SPORK_2_INSTANTSEND_ENABLED") return SPORK_2_INSTANTSEND_ENABLED; - if (strName == "SPORK_3_INSTANTSEND_BLOCK_FILTERING") return SPORK_3_INSTANTSEND_BLOCK_FILTERING; - if (strName == "SPORK_5_INSTANTSEND_MAX_VALUE") return SPORK_5_INSTANTSEND_MAX_VALUE; - if (strName == "SPORK_6_NEW_SIGS") return SPORK_6_NEW_SIGS; - if (strName == "SPORK_9_SUPERBLOCKS_ENABLED") return SPORK_9_SUPERBLOCKS_ENABLED; - if (strName == "SPORK_12_RECONSIDER_BLOCKS") return SPORK_12_RECONSIDER_BLOCKS; - if (strName == "SPORK_15_DETERMINISTIC_MNS_ENABLED") return SPORK_15_DETERMINISTIC_MNS_ENABLED; - if (strName == "SPORK_16_INSTANTSEND_AUTOLOCKS") return SPORK_16_INSTANTSEND_AUTOLOCKS; - if (strName == "SPORK_17_QUORUM_DKG_ENABLED") return SPORK_17_QUORUM_DKG_ENABLED; - if (strName == "SPORK_19_CHAINLOCKS_ENABLED") return SPORK_19_CHAINLOCKS_ENABLED; - if (strName == "SPORK_20_INSTANTSEND_LLMQ_BASED") return SPORK_20_INSTANTSEND_LLMQ_BASED; - - LogPrint(BCLog::SPORK, "CSporkManager::GetSporkIDByName -- Unknown Spork name '%s'\n", strName); - return -1; + auto it = sporkDefsByName.find(strName); + if (it == sporkDefsByName.end()) { + LogPrint(BCLog::SPORK, "CSporkManager::GetSporkIDByName -- Unknown Spork name '%s'\n", strName); + return SPORK_INVALID; + } + return it->second->sporkId; } -std::string CSporkManager::GetSporkNameByID(int nSporkID) +std::string CSporkManager::GetSporkNameByID(SporkId nSporkID) { - switch (nSporkID) { - case SPORK_2_INSTANTSEND_ENABLED: return "SPORK_2_INSTANTSEND_ENABLED"; - case SPORK_3_INSTANTSEND_BLOCK_FILTERING: return "SPORK_3_INSTANTSEND_BLOCK_FILTERING"; - case SPORK_5_INSTANTSEND_MAX_VALUE: return "SPORK_5_INSTANTSEND_MAX_VALUE"; - case SPORK_6_NEW_SIGS: return "SPORK_6_NEW_SIGS"; - case SPORK_9_SUPERBLOCKS_ENABLED: return "SPORK_9_SUPERBLOCKS_ENABLED"; - case SPORK_12_RECONSIDER_BLOCKS: return "SPORK_12_RECONSIDER_BLOCKS"; - case SPORK_15_DETERMINISTIC_MNS_ENABLED: return "SPORK_15_DETERMINISTIC_MNS_ENABLED"; - case SPORK_16_INSTANTSEND_AUTOLOCKS: return "SPORK_16_INSTANTSEND_AUTOLOCKS"; - case SPORK_17_QUORUM_DKG_ENABLED: return "SPORK_17_QUORUM_DKG_ENABLED"; - case SPORK_19_CHAINLOCKS_ENABLED: return "SPORK_19_CHAINLOCKS_ENABLED"; - case SPORK_20_INSTANTSEND_LLMQ_BASED: return "SPORK_20_INSTANTSEND_LLMQ_BASED"; - default: - LogPrint(BCLog::SPORK, "CSporkManager::GetSporkNameByID -- Unknown Spork ID %d\n", nSporkID); - return "Unknown"; + auto it = sporkDefsById.find(nSporkID); + if (it == sporkDefsById.end()) { + LogPrint(BCLog::SPORK, "CSporkManager::GetSporkNameByID -- Unknown Spork ID %d\n", nSporkID); + return "Unknown"; } + return it->second->name; } bool CSporkManager::GetSporkByHash(const uint256& hash, CSporkMessage &sporkRet) diff --git a/src/spork.h b/src/spork.h index b28cc47a1..8e131f31d 100644 --- a/src/spork.h +++ b/src/spork.h @@ -20,22 +20,31 @@ class CSporkManager; Don't ever reuse these IDs for other sporks - This would result in old clients getting confused about which spork is for what */ -static const int SPORK_2_INSTANTSEND_ENABLED = 10001; -static const int SPORK_3_INSTANTSEND_BLOCK_FILTERING = 10002; -static const int SPORK_5_INSTANTSEND_MAX_VALUE = 10004; -static const int SPORK_6_NEW_SIGS = 10005; -static const int SPORK_9_SUPERBLOCKS_ENABLED = 10008; -static const int SPORK_12_RECONSIDER_BLOCKS = 10011; -static const int SPORK_15_DETERMINISTIC_MNS_ENABLED = 10014; -static const int SPORK_16_INSTANTSEND_AUTOLOCKS = 10015; -static const int SPORK_17_QUORUM_DKG_ENABLED = 10016; -static const int SPORK_19_CHAINLOCKS_ENABLED = 10018; -static const int SPORK_20_INSTANTSEND_LLMQ_BASED = 10019; +enum SporkId : int32_t { + SPORK_2_INSTANTSEND_ENABLED = 10001, + SPORK_3_INSTANTSEND_BLOCK_FILTERING = 10002, + SPORK_5_INSTANTSEND_MAX_VALUE = 10004, + SPORK_6_NEW_SIGS = 10005, + SPORK_9_SUPERBLOCKS_ENABLED = 10008, + SPORK_12_RECONSIDER_BLOCKS = 10011, + SPORK_15_DETERMINISTIC_MNS_ENABLED = 10014, + SPORK_16_INSTANTSEND_AUTOLOCKS = 10015, + SPORK_17_QUORUM_DKG_ENABLED = 10016, + SPORK_19_CHAINLOCKS_ENABLED = 10018, + SPORK_20_INSTANTSEND_LLMQ_BASED = 10019, -static const int SPORK_START = SPORK_2_INSTANTSEND_ENABLED; -static const int SPORK_END = SPORK_20_INSTANTSEND_LLMQ_BASED; + SPORK_INVALID = -1, +}; +template<> struct is_serializable_enum : std::true_type {}; -extern std::map mapSporkDefaults; +struct CSporkDef +{ + SporkId sporkId{SPORK_INVALID}; + int64_t defaultValue{0}; + std::string name; +}; + +extern std::vector sporkDefs; extern CSporkManager sporkManager; /** @@ -62,18 +71,18 @@ private: std::vector vchSig; public: - int nSporkID; + SporkId nSporkID; int64_t nValue; int64_t nTimeSigned; - CSporkMessage(int nSporkID, int64_t nValue, int64_t nTimeSigned) : + CSporkMessage(SporkId nSporkID, int64_t nValue, int64_t nTimeSigned) : nSporkID(nSporkID), nValue(nValue), nTimeSigned(nTimeSigned) {} CSporkMessage() : - nSporkID(0), + nSporkID((SporkId)0), nValue(0), nTimeSigned(0) {} @@ -137,9 +146,12 @@ class CSporkManager private: static const std::string SERIALIZATION_VERSION_STRING; + std::unordered_map sporkDefsById; + std::unordered_map sporkDefsByName; + mutable CCriticalSection cs; std::unordered_map mapSporksByHash; - std::unordered_map > mapSporksActive; + std::unordered_map > mapSporksActive; std::set setSporkPubKeyIDs; int nMinSporkKeys; @@ -149,11 +161,11 @@ private: * SporkValueIsActive is used to get the value agreed upon by the majority * of signed spork messages for a given Spork ID. */ - bool SporkValueIsActive(int nSporkID, int64_t& nActiveValueRet) const; + bool SporkValueIsActive(SporkId nSporkID, int64_t& nActiveValueRet) const; public: - CSporkManager() {} + CSporkManager(); ADD_SERIALIZE_METHODS; @@ -209,13 +221,13 @@ public: * * Currently only used with Spork 12. */ - void ExecuteSpork(int nSporkID, int nValue); + void ExecuteSpork(SporkId nSporkID, int nValue); /** * UpdateSpork is used by the spork RPC command to set a new spork value, sign * and broadcast the spork message. */ - bool UpdateSpork(int nSporkID, int64_t nValue, CConnman& connman); + bool UpdateSpork(SporkId nSporkID, int64_t nValue, CConnman& connman); /** * IsSporkActive returns a bool for time-based sporks, and should be used @@ -226,23 +238,23 @@ public: * instead, and therefore this method doesn't make sense and should not be * used. */ - bool IsSporkActive(int nSporkID); + bool IsSporkActive(SporkId nSporkID); /** * GetSporkValue returns the spork value given a Spork ID. If no active spork * message has yet been received by the node, it returns the default value. */ - int64_t GetSporkValue(int nSporkID); + int64_t GetSporkValue(SporkId nSporkID); /** * GetSporkIDByName returns the internal Spork ID given the spork name. */ - int GetSporkIDByName(const std::string& strName); + SporkId GetSporkIDByName(const std::string& strName); /** * GetSporkNameByID returns the spork name as a string, given a Spork ID. */ - std::string GetSporkNameByID(int nSporkID); + std::string GetSporkNameByID(SporkId nSporkID); /** * GetSporkByHash returns a spork message given a hash of the spork message.