diff --git a/src/chainparams.cpp b/src/chainparams.cpp index bd9c93d0e8..70109d4246 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -585,7 +585,6 @@ class CTestNetParams : public CChainParams { {300000, uint256S("205b522772ce34206a08a635c800f99d2fc4e9696ab8c470dad7f5fa51dfea1a")}, {1445000, uint256S("6fd0cafbbd2262d5cecd2e07e73fe6703bac364e5d4986da3fe512b0eccf944d")}, {1471000, uint256S("dcf4a5fb69c004d0921710e09a09d10f275b3bc696e45ca03f6c322bb32f41bc")}, - {1910000, uint256S("83b9b52e7f22ae6e9bb44e9b01aecf9bbf1bd9c93a7d09a6c1a1f1e6aafbdbf1")}, } }; diff --git a/src/dfi/consensus/governance.cpp b/src/dfi/consensus/governance.cpp index 99188cc7e5..6ea5753350 100644 --- a/src/dfi/consensus/governance.cpp +++ b/src/dfi/consensus/governance.cpp @@ -29,7 +29,21 @@ Res CGovernanceConsensus::operator()(const CGovernanceMessage &obj) const { govVar->evmQueueId = evmQueueId; auto newVar = std::dynamic_pointer_cast(var); - assert(newVar); + if (!newVar) { + return Res::Err("Failed to cast Gov var to ATTRIBUTES"); + } + + if (height >= static_cast(consensus.DF22MetachainHeight)) { + res = newVar->CheckKeys(); + if (!res) { + return res; + } + + const auto newExport = newVar->Export(); + if (newExport.empty()) { + return Res::Err("Cannot export empty attribute map"); + } + } CDataStructureV0 key{AttributeTypes::Param, ParamIDs::Foundation, DFIPKeys::Members}; auto memberRemoval = newVar->GetValue(key, std::set{}); @@ -167,6 +181,23 @@ Res CGovernanceConsensus::operator()(const CGovernanceHeightMessage &obj) const return Res::Err("%s: %s", obj.govVar->GetName(), "Failed to get existing ATTRIBUTES"); } + if (height >= static_cast(consensus.DF22MetachainHeight)) { + auto newVar = std::dynamic_pointer_cast(obj.govVar); + if (!newVar) { + return Res::Err("Failed to cast Gov var to ATTRIBUTES"); + } + + auto res = newVar->CheckKeys(); + if (!res) { + return res; + } + + const auto newExport = newVar->Export(); + if (newExport.empty()) { + return Res::Err("Cannot export empty attribute map"); + } + } + auto storedGovVars = mnview.GetStoredVariablesRange(height, obj.startHeight); Res res{}; diff --git a/src/dfi/errors.h b/src/dfi/errors.h index 152d9bf428..01d70c0415 100644 --- a/src/dfi/errors.h +++ b/src/dfi/errors.h @@ -188,6 +188,14 @@ class DeFiErrors { return Res::Err(error); } + static Res GovVarVariableInvalidKey(const std::string &key, const std::map &keys) { + std::string error{"Unrecognised " + key + " argument provided, valid " + key + "s are:"}; + for (const auto &pair : keys) { + error += ' ' + pair.second + ','; + } + return Res::Err(error); + } + static Res GovVarVariableUnsupportedType(const unsigned char type) { return Res::Err("Unsupported type {%d}", type); } diff --git a/src/dfi/govvariables/attributes.cpp b/src/dfi/govvariables/attributes.cpp index 366745c3df..c51ec6e2c8 100644 --- a/src/dfi/govvariables/attributes.cpp +++ b/src/dfi/govvariables/attributes.cpp @@ -107,6 +107,26 @@ const std::map &ATTRIBUTES::allowedParamIDs() { return params; } +const std::map &ATTRIBUTES::allowedExportParamsIDs() { + static const std::map params{ + {ParamIDs::DFIP2201, "dfip2201" }, + {ParamIDs::DFIP2203, "dfip2203" }, + {ParamIDs::DFIP2206A, "dfip2206a" }, + {ParamIDs::DFIP2206F, "dfip2206f" }, + {ParamIDs::Feature, "feature" }, + {ParamIDs::Foundation, "foundation"}, + }; + return params; +} + +const std::map &ATTRIBUTES::displayParamsIDs() { + static auto params = allowedExportParamsIDs(); + params[ParamIDs::Auction] = "auction"; + params[ParamIDs::Economy] = "economy"; + params[ParamIDs::TokenID] = "token"; + return params; +} + const std::map &ATTRIBUTES::allowedLocksIDs() { static const std::map params{ {"token", ParamIDs::TokenID}, @@ -114,19 +134,9 @@ const std::map &ATTRIBUTES::allowedLocksIDs() { return params; } -const std::map &ATTRIBUTES::displayParamsIDs() { +const std::map &ATTRIBUTES::displayLocksIDs() { static const std::map params{ - {ParamIDs::DFIP2201, "dfip2201" }, - {ParamIDs::DFIP2203, "dfip2203" }, - {ParamIDs::DFIP2206A, "dfip2206a" }, - // Note: DFIP2206F is currently in beta testing - // for testnet. May not be enabled on mainnet until testing is complete. - {ParamIDs::DFIP2206F, "dfip2206f" }, - {ParamIDs::TokenID, "token" }, - {ParamIDs::Economy, "economy" }, - {ParamIDs::Feature, "feature" }, - {ParamIDs::Auction, "auction" }, - {ParamIDs::Foundation, "foundation"}, + {ParamIDs::TokenID, "token"}, }; return params; } @@ -947,6 +957,98 @@ Res StoreGovVars(const CGovernanceHeightMessage &obj, CCustomCSView &view) { return view.SetStoredVariables(storedGovVars, obj.startHeight); } +static Res CheckValidAttrV0Key(const uint8_t type, const uint32_t typeId, const uint32_t typeKey) { + if (type == AttributeTypes::Param) { + if (typeId == ParamIDs::DFIP2201) { + if (typeKey != DFIPKeys::Active && typeKey != DFIPKeys::Premium && typeKey != DFIPKeys::MinSwap) { + return Res::Err("Unsupported type for DFIP2201 {%d}", typeKey); + } + } else if (typeId == ParamIDs::DFIP2203 || typeId == ParamIDs::DFIP2206F) { + if (typeKey != DFIPKeys::Active && typeKey != DFIPKeys::RewardPct && typeKey != DFIPKeys::BlockPeriod && + typeKey != DFIPKeys::StartBlock) { + return Res::Err("Unsupported type for this DFIP {%d}", typeKey); + } + } else if (typeId == ParamIDs::DFIP2206A) { + if (typeKey != DFIPKeys::DUSDInterestBurn && typeKey != DFIPKeys::DUSDLoanBurn) { + return DeFiErrors::GovVarVariableUnsupportedDFIPType(typeKey); + } + } else if (typeId == ParamIDs::Feature) { + if (typeKey != DFIPKeys::GovUnset && typeKey != DFIPKeys::GovFoundation && + typeKey != DFIPKeys::MNSetRewardAddress && typeKey != DFIPKeys::MNSetOperatorAddress && + typeKey != DFIPKeys::MNSetOwnerAddress && typeKey != DFIPKeys::GovernanceEnabled && + typeKey != DFIPKeys::ConsortiumEnabled && typeKey != DFIPKeys::CFPPayout && + typeKey != DFIPKeys::EmissionUnusedFund && typeKey != DFIPKeys::MintTokens && + typeKey != DFIPKeys::EVMEnabled && typeKey != DFIPKeys::ICXEnabled && + typeKey != DFIPKeys::TransferDomain) { + return DeFiErrors::GovVarVariableUnsupportedFeatureType(typeKey); + } + } else if (typeId == ParamIDs::Foundation) { + if (typeKey != DFIPKeys::Members) { + return DeFiErrors::GovVarVariableUnsupportedFoundationType(typeKey); + } + } else { + return DeFiErrors::GovVarVariableUnsupportedParamType(); + } + } else if (type == AttributeTypes::EVMType) { + if (typeId == EVMIDs::Block) { + if (typeKey != EVMKeys::Finalized && typeKey != EVMKeys::GasLimit && typeKey != EVMKeys::GasTarget) { + return DeFiErrors::GovVarVariableUnsupportedEVMType(typeKey); + } + } else { + return DeFiErrors::GovVarVariableUnsupportedGovType(); + } + } else if (type == AttributeTypes::Governance) { + if (typeId == GovernanceIDs::Proposals) { + if (typeKey != GovernanceKeys::FeeRedistribution && typeKey != GovernanceKeys::FeeBurnPct && + typeKey != GovernanceKeys::CFPFee && typeKey != GovernanceKeys::CFPApprovalThreshold && + typeKey != GovernanceKeys::VOCFee && typeKey != GovernanceKeys::VOCApprovalThreshold && + typeKey != GovernanceKeys::VOCEmergencyPeriod && typeKey != GovernanceKeys::VOCEmergencyFee && + typeKey != GovernanceKeys::VOCEmergencyQuorum && typeKey != GovernanceKeys::Quorum && + typeKey != GovernanceKeys::VotingPeriod && typeKey != GovernanceKeys::CFPMaxCycles) { + return DeFiErrors::GovVarVariableUnsupportedProposalType(typeKey); + } + } else { + return DeFiErrors::GovVarVariableUnsupportedGovType(); + } + } else if (type == AttributeTypes::Transfer) { + if (typeId == TransferIDs::DVMToEVM) { + if (typeKey != TransferKeys::TransferEnabled && typeKey != TransferKeys::SrcFormats && + typeKey != TransferKeys::DestFormats && typeKey != TransferKeys::NativeEnabled && + typeKey != TransferKeys::DATEnabled && typeKey != TransferKeys::Disallowed) { + return DeFiErrors::GovVarVariableUnsupportedTransferType(typeKey); + } + } else if (typeId == TransferIDs::EVMToDVM) { + if (typeKey != TransferKeys::TransferEnabled && typeKey != TransferKeys::SrcFormats && + typeKey != TransferKeys::DestFormats && typeKey != TransferKeys::AuthFormats && + typeKey != TransferKeys::NativeEnabled && typeKey != TransferKeys::DATEnabled && + typeKey != TransferKeys::Disallowed) { + return DeFiErrors::GovVarVariableUnsupportedTransferType(typeKey); + } + } else { + return DeFiErrors::GovVarVariableUnsupportedGovType(); + } + } else if (type == AttributeTypes::Vaults) { + if (typeId == VaultIDs::DUSDVault) { + if (typeKey != VaultKeys::DUSDVaultEnabled) { + return DeFiErrors::GovVarVariableUnsupportedVaultsType(typeKey); + } + } else { + return DeFiErrors::GovVarVariableUnsupportedGovType(); + } + } else if (type == AttributeTypes::Rules) { + if (typeId == RulesIDs::TXRules) { + if (typeKey != RulesKeys::CoreOPReturn && typeKey != RulesKeys::DVMOPReturn && + typeKey != RulesKeys::EVMOPReturn) { + return DeFiErrors::GovVarVariableUnsupportedRulesType(typeKey); + } + } else { + return DeFiErrors::GovVarVariableUnsupportedGovType(); + } + } + + return Res::Ok(); +} + Res ATTRIBUTES::ProcessVariable(const std::string &key, const std::optional &value, std::function applyVariable) { @@ -1068,99 +1170,18 @@ Res ATTRIBUTES::ProcessVariable(const std::string &key, typeKey = itype->second; - if (type == AttributeTypes::Param) { - if (typeId == ParamIDs::DFIP2201) { - if (typeKey != DFIPKeys::Active && typeKey != DFIPKeys::Premium && typeKey != DFIPKeys::MinSwap) { - return Res::Err("Unsupported type for DFIP2201 {%d}", typeKey); - } - } else if (typeId == ParamIDs::DFIP2203 || typeId == ParamIDs::DFIP2206F) { - if (typeKey != DFIPKeys::Active && typeKey != DFIPKeys::RewardPct && typeKey != DFIPKeys::BlockPeriod && - typeKey != DFIPKeys::StartBlock) { - return Res::Err("Unsupported type for this DFIP {%d}", typeKey); - } + auto res = CheckValidAttrV0Key(type, typeId, typeKey); + if (!res) { + return res; + } - if (typeKey == DFIPKeys::BlockPeriod || typeKey == DFIPKeys::StartBlock) { - if (typeId == ParamIDs::DFIP2203) { - futureUpdated = true; - } else { - futureDUSDUpdated = true; - } - } - } else if (typeId == ParamIDs::DFIP2206A) { - if (typeKey != DFIPKeys::DUSDInterestBurn && typeKey != DFIPKeys::DUSDLoanBurn) { - return DeFiErrors::GovVarVariableUnsupportedDFIPType(typeKey); - } - } else if (typeId == ParamIDs::Feature) { - if (typeKey != DFIPKeys::GovUnset && typeKey != DFIPKeys::GovFoundation && - typeKey != DFIPKeys::MNSetRewardAddress && typeKey != DFIPKeys::MNSetOperatorAddress && - typeKey != DFIPKeys::MNSetOwnerAddress && typeKey != DFIPKeys::GovernanceEnabled && - typeKey != DFIPKeys::ConsortiumEnabled && typeKey != DFIPKeys::CFPPayout && - typeKey != DFIPKeys::EmissionUnusedFund && typeKey != DFIPKeys::MintTokens && - typeKey != DFIPKeys::EVMEnabled && typeKey != DFIPKeys::ICXEnabled && - typeKey != DFIPKeys::TransferDomain) { - return DeFiErrors::GovVarVariableUnsupportedFeatureType(typeKey); - } - } else if (typeId == ParamIDs::Foundation) { - if (typeKey != DFIPKeys::Members) { - return DeFiErrors::GovVarVariableUnsupportedFoundationType(typeKey); - } - } else { - return DeFiErrors::GovVarVariableUnsupportedParamType(); - } - } else if (type == AttributeTypes::EVMType) { - if (typeId == EVMIDs::Block) { - if (typeKey != EVMKeys::Finalized && typeKey != EVMKeys::GasLimit && typeKey != EVMKeys::GasTarget) { - return DeFiErrors::GovVarVariableUnsupportedEVMType(typeKey); - } - } else { - return DeFiErrors::GovVarVariableUnsupportedGovType(); - } - } else if (type == AttributeTypes::Governance) { - if (typeId == GovernanceIDs::Proposals) { - if (typeKey != GovernanceKeys::FeeRedistribution && typeKey != GovernanceKeys::FeeBurnPct && - typeKey != GovernanceKeys::CFPFee && typeKey != GovernanceKeys::CFPApprovalThreshold && - typeKey != GovernanceKeys::VOCFee && typeKey != GovernanceKeys::VOCApprovalThreshold && - typeKey != GovernanceKeys::VOCEmergencyPeriod && typeKey != GovernanceKeys::VOCEmergencyFee && - typeKey != GovernanceKeys::VOCEmergencyQuorum && typeKey != GovernanceKeys::Quorum && - typeKey != GovernanceKeys::VotingPeriod && typeKey != GovernanceKeys::CFPMaxCycles) { - return DeFiErrors::GovVarVariableUnsupportedProposalType(typeKey); - } - } else { - return DeFiErrors::GovVarVariableUnsupportedGovType(); - } - } else if (type == AttributeTypes::Transfer) { - if (typeId == TransferIDs::DVMToEVM) { - if (typeKey != TransferKeys::TransferEnabled && typeKey != TransferKeys::SrcFormats && - typeKey != TransferKeys::DestFormats && typeKey != TransferKeys::NativeEnabled && - typeKey != TransferKeys::DATEnabled && typeKey != TransferKeys::Disallowed) { - return DeFiErrors::GovVarVariableUnsupportedTransferType(typeKey); - } - } else if (typeId == TransferIDs::EVMToDVM) { - if (typeKey != TransferKeys::TransferEnabled && typeKey != TransferKeys::SrcFormats && - typeKey != TransferKeys::DestFormats && typeKey != TransferKeys::AuthFormats && - typeKey != TransferKeys::NativeEnabled && typeKey != TransferKeys::DATEnabled && - typeKey != TransferKeys::Disallowed) { - return DeFiErrors::GovVarVariableUnsupportedTransferType(typeKey); - } - } else { - return DeFiErrors::GovVarVariableUnsupportedGovType(); - } - } else if (type == AttributeTypes::Vaults) { - if (typeId == VaultIDs::DUSDVault) { - if (typeKey != VaultKeys::DUSDVaultEnabled) { - return DeFiErrors::GovVarVariableUnsupportedVaultsType(typeKey); - } - } else { - return DeFiErrors::GovVarVariableUnsupportedGovType(); - } - } else if (type == AttributeTypes::Rules) { - if (typeId == RulesIDs::TXRules) { - if (typeKey != RulesKeys::CoreOPReturn && typeKey != RulesKeys::DVMOPReturn && - typeKey != RulesKeys::EVMOPReturn) { - return DeFiErrors::GovVarVariableUnsupportedRulesType(typeKey); + if (type == AttributeTypes::Param && (typeId == ParamIDs::DFIP2203 || typeId == ParamIDs::DFIP2206F)) { + if (typeKey == DFIPKeys::BlockPeriod || typeKey == DFIPKeys::StartBlock) { + if (typeId == ParamIDs::DFIP2203) { + futureUpdated = true; + } else { + futureDUSDUpdated = true; } - } else { - return DeFiErrors::GovVarVariableUnsupportedGovType(); } } @@ -1496,6 +1517,65 @@ std::set attrsVersion27TokenHiddenSet = { TokenKeys::Epitaph, }; +Res ATTRIBUTES::CheckKeys() const { + for (const auto &attribute : attributes) { + const auto attrV0 = std::get_if(&attribute.first); + if (!attrV0) { + return DeFiErrors::GovVarUnsupportedVersion(); + } + + // Check type + if (!displayTypes().count(attrV0->type)) { + return DeFiErrors::GovVarVariableInvalidKey("type", displayTypes()); + } + + // Check typeId + if (attrV0->type == AttributeTypes::Param) { + if (!allowedExportParamsIDs().count(attrV0->typeId)) { + return DeFiErrors::GovVarVariableInvalidKey("param", allowedExportParamsIDs()); + } + } else if (attrV0->type == AttributeTypes::Locks) { + if (!displayLocksIDs().count(attrV0->typeId)) { + return DeFiErrors::GovVarVariableInvalidKey("locks", displayLocksIDs()); + } + } else if (attrV0->type == AttributeTypes::EVMType) { + if (!displayEVMIDs().count(attrV0->typeId)) { + return DeFiErrors::GovVarVariableInvalidKey("evm", displayEVMIDs()); + } + } else if (attrV0->type == AttributeTypes::Oracles) { + if (!displayOracleIDs().count(attrV0->typeId)) { + return DeFiErrors::GovVarVariableInvalidKey("oracles", displayOracleIDs()); + } + } else if (attrV0->type == AttributeTypes::Governance) { + if (!displayGovernanceIDs().count(attrV0->typeId)) { + return DeFiErrors::GovVarVariableInvalidKey("governance", displayGovernanceIDs()); + } + } else if (attrV0->type == AttributeTypes::Transfer) { + if (!displayTransferIDs().count(attrV0->typeId)) { + return DeFiErrors::GovVarVariableInvalidKey("transferdomain", displayTransferIDs()); + } + } else if (attrV0->type == AttributeTypes::Vaults) { + if (!displayVaultIDs().count(attrV0->typeId)) { + return DeFiErrors::GovVarVariableInvalidKey("vaults", displayVaultIDs()); + } + } else if (attrV0->type == AttributeTypes::Rules) { + if (!displayRulesIDs().count(attrV0->typeId)) { + return DeFiErrors::GovVarVariableInvalidKey("rules", displayRulesIDs()); + } + } + + // Check key - Locks and Oracles have height int keys so skip. + if (attrV0->type != AttributeTypes::Locks && attrV0->type != AttributeTypes::Oracles) { + auto res = CheckValidAttrV0Key(attrV0->type, attrV0->typeId, attrV0->key); + if (!res) { + return res; + } + } + } + + return Res::Ok(); +} + UniValue ATTRIBUTES::ExportFiltered(GovVarsFilter filter, const std::string &prefix) const { UniValue ret(UniValue::VOBJ); for (const auto &attribute : attributes) { diff --git a/src/dfi/govvariables/attributes.h b/src/dfi/govvariables/attributes.h index 75f36050fd..3b59bb510d 100644 --- a/src/dfi/govvariables/attributes.h +++ b/src/dfi/govvariables/attributes.h @@ -467,6 +467,7 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator &displayVersions(); static const std::map &displayTypes(); static const std::map &displayParamsIDs(); + static const std::map &allowedExportParamsIDs(); + static const std::map &displayLocksIDs(); static const std::map &displayOracleIDs(); - static const std::map &displayConsortiumIDs(); static const std::map &displayGovernanceIDs(); static const std::map &displayTransferIDs(); static const std::map &displayEVMIDs(); @@ -581,7 +583,6 @@ class ATTRIBUTES : public GovVariable, public AutoRegistrator &allowedParamIDs(); static const std::map &allowedLocksIDs(); static const std::map &allowedOracleIDs(); - static const std::map &allowedConsortiumIDs(); static const std::map &allowedGovernanceIDs(); static const std::map &allowedTransferIDs(); static const std::map &allowedEVMIDs();