Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor sporks to get rid of repeated if/else blocks #2946

Merged
merged 5 commits into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
Expand Down
111 changes: 46 additions & 65 deletions src/spork.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,34 @@

#include <string>

CSporkManager sporkManager;

const std::string CSporkManager::SERIALIZATION_VERSION_STRING = "CSporkManager-Version-2";

std::map<int, int64_t> 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<CSporkDef> 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);

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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());

Expand All @@ -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);

Expand All @@ -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)
Expand Down
68 changes: 40 additions & 28 deletions src/spork.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

static const int SPORK_START = SPORK_2_INSTANTSEND_ENABLED;
static const int SPORK_END = SPORK_20_INSTANTSEND_LLMQ_BASED;

extern std::map<int, int64_t> mapSporkDefaults;
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,

SPORK_INVALID = -1,
};
template<> struct is_serializable_enum<SporkId> : std::true_type {};

struct CSporkDef
{
SporkId sporkId{SPORK_INVALID};
int64_t defaultValue{0};
std::string name;
};

extern std::vector<CSporkDef> sporkDefs;
extern CSporkManager sporkManager;

/**
Expand All @@ -62,18 +71,18 @@ class CSporkMessage
std::vector<unsigned char> 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)
{}
Expand Down Expand Up @@ -137,9 +146,12 @@ class CSporkManager
private:
static const std::string SERIALIZATION_VERSION_STRING;

std::unordered_map<SporkId, CSporkDef*> sporkDefsById;
std::unordered_map<std::string, CSporkDef*> sporkDefsByName;

mutable CCriticalSection cs;
std::unordered_map<uint256, CSporkMessage> mapSporksByHash;
std::unordered_map<int, std::map<CKeyID, CSporkMessage> > mapSporksActive;
std::unordered_map<SporkId, std::map<CKeyID, CSporkMessage> > mapSporksActive;

std::set<CKeyID> setSporkPubKeyIDs;
int nMinSporkKeys;
Expand All @@ -149,11 +161,11 @@ class CSporkManager
* 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;

Expand Down Expand Up @@ -209,13 +221,13 @@ class CSporkManager
*
* 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
Expand All @@ -226,23 +238,23 @@ class CSporkManager
* 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.
Expand Down