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

Consortium implementation #1541

Merged
merged 19 commits into from
Nov 12, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
165 changes: 161 additions & 4 deletions src/masternodes/govvariables/attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ const std::map<std::string, uint8_t>& ATTRIBUTES::allowedTypes() {
{"params", AttributeTypes::Param},
{"poolpairs", AttributeTypes::Poolpairs},
{"token", AttributeTypes::Token},
{"consortium", AttributeTypes::Consortium},
};
return types;
}
Expand All @@ -70,6 +71,7 @@ const std::map<uint8_t, std::string>& ATTRIBUTES::displayTypes() {
{AttributeTypes::Param, "params"},
{AttributeTypes::Poolpairs, "poolpairs"},
{AttributeTypes::Token, "token"},
{AttributeTypes::Consortium,"consortium"}
};
return types;
}
Expand Down Expand Up @@ -142,6 +144,13 @@ const std::map<uint8_t, std::map<std::string, uint8_t>>& ATTRIBUTES::allowedKeys
{"loan_minting_interest", TokenKeys::LoanMintingInterest},
}
},
{
AttributeTypes::Consortium, {
{"members", ConsortiumKeys::Members},
{"mint_limit", ConsortiumKeys::MintLimit},
{"daily_mint_limit", ConsortiumKeys::DailyMintLimit},
}
},
{
AttributeTypes::Poolpairs, {
{"token_a_fee_pct", PoolKeys::TokenAFeePCT},
Expand All @@ -165,6 +174,7 @@ const std::map<uint8_t, std::map<std::string, uint8_t>>& ATTRIBUTES::allowedKeys
{"mn-setrewardaddress", DFIPKeys::MNSetRewardAddress},
{"mn-setoperatoraddress", DFIPKeys::MNSetOperatorAddress},
{"mn-setowneraddress", DFIPKeys::MNSetOwnerAddress},
{"consortium_enabled", DFIPKeys::ConsortiumEnabled},
}
},
};
Expand Down Expand Up @@ -193,6 +203,13 @@ const std::map<uint8_t, std::map<uint8_t, std::string>>& ATTRIBUTES::displayKeys
{TokenKeys::Epitaph, "epitaph"},
}
},
{
AttributeTypes::Consortium, {
{ConsortiumKeys::Members, "members"},
{ConsortiumKeys::MintLimit, "mint_limit"},
{ConsortiumKeys::DailyMintLimit,"daily_mint_limit"},
}
},
{
AttributeTypes::Poolpairs, {
{PoolKeys::TokenAFeePCT, "token_a_fee_pct"},
Expand All @@ -216,6 +233,7 @@ const std::map<uint8_t, std::map<uint8_t, std::string>>& ATTRIBUTES::displayKeys
{DFIPKeys::MNSetRewardAddress, "mn-setrewardaddress"},
{DFIPKeys::MNSetOperatorAddress, "mn-setoperatoraddress"},
{DFIPKeys::MNSetOwnerAddress, "mn-setowneraddress"},
{DFIPKeys::ConsortiumEnabled, "consortium_enabled"},
}
},
{
Expand All @@ -230,6 +248,8 @@ const std::map<uint8_t, std::map<uint8_t, std::string>>& ATTRIBUTES::displayKeys
{EconomyKeys::DFIP2206FMinted, "dfip2206f_minted"},
{EconomyKeys::NegativeInt, "negative_interest"},
{EconomyKeys::NegativeIntCurrent, "negative_interest_current"},
{EconomyKeys::ConsortiumMinted, "consortium"},
{EconomyKeys::ConsortiumMembersMinted, "consortium_members"},
}
},
};
Expand Down Expand Up @@ -344,6 +364,60 @@ static bool VerifyToken(const CCustomCSView& view, const uint32_t id) {
return view.GetToken(DCT_ID{id}).has_value();
}

static ResVal<CAttributeValue> VerifyConsortiumMember(const std::string& str) {
UniValue values(UniValue::VOBJ);
CConsortiumMembers members;

if (!values.read(str))
return Res::Err("Not a valid consortium member object!");

for (const auto &key : values.getKeys())
{
UniValue value(values[key].get_obj());
CConsortiumMember member;

member.status = 0;

member.name = trim_all_ws(value["name"].getValStr()).substr(0, CConsortiumMember::MAX_CONSORTIUM_MEMBERS_STRING_LENGTH);
Mixa84 marked this conversation as resolved.
Show resolved Hide resolved
if (!value["ownerAddress"].isNull()) {
const auto dest = DecodeDestination(value["ownerAddress"].getValStr());
if (!IsValidDestination(dest)) {
return Res::Err("Invalid ownerAddress in consortium member data");
}
member.ownerAddress = GetScriptForDestination(dest);
} else {
return Res::Err("Empty ownerAddress in consortium member data!");
}

member.backingId = trim_all_ws(value["backingId"].getValStr()).substr(0, CConsortiumMember::MAX_CONSORTIUM_MEMBERS_STRING_LENGTH);
if (!AmountFromValue(value["mintLimit"], member.mintLimit) || !member.mintLimit) {
return Res::Err("Mint limit is an invalid amount");
}

if (!AmountFromValue(value["dailyMintLimit"], member.dailyMintLimit) || !member.dailyMintLimit) {
return Res::Err("Daily mint limit is an invalid amount");
}

if (!value["status"].isNull())
{
uint32_t tmp;

if (ParseUInt32(value["status"].getValStr(), &tmp)) {
if (tmp > 1) {
return Res::Err("Status can be either 0 or 1");
}
member.status = static_cast<uint8_t>(tmp);
} else {
return Res::Err("Status must be a positive number!");
}
}

members[key] = member;
}

return {members, Res::Ok()};
}

static inline void rtrim(std::string& s, unsigned char remove) {
s.erase(std::find_if(s.rbegin(), s.rend(), [&remove](unsigned char ch) {
return ch != remove;
Expand Down Expand Up @@ -372,6 +446,13 @@ const std::map<uint8_t, std::map<uint8_t,
{TokenKeys::DFIP2203Enabled, VerifyBool},
}
},
{
AttributeTypes::Consortium, {
{ConsortiumKeys::Members, VerifyConsortiumMember},
{ConsortiumKeys::MintLimit, VerifyPositiveFloat},
{ConsortiumKeys::DailyMintLimit, VerifyPositiveFloat},
}
},
{
AttributeTypes::Poolpairs, {
{PoolKeys::TokenAFeePCT, VerifyPct},
Expand All @@ -395,6 +476,7 @@ const std::map<uint8_t, std::map<uint8_t,
{DFIPKeys::MNSetRewardAddress, VerifyBool},
{DFIPKeys::MNSetOperatorAddress, VerifyBool},
{DFIPKeys::MNSetOwnerAddress, VerifyBool},
{DFIPKeys::ConsortiumEnabled, VerifyBool},
}
},
{
Expand Down Expand Up @@ -568,10 +650,11 @@ Res ATTRIBUTES::ProcessVariable(const std::string& key, const std::string& value
typeKey != DFIPKeys::GovFoundation &&
typeKey != DFIPKeys::MNSetRewardAddress &&
typeKey != DFIPKeys::MNSetOperatorAddress &&
typeKey != DFIPKeys::MNSetOwnerAddress) {
typeKey != DFIPKeys::MNSetOwnerAddress &&
typeKey != DFIPKeys::ConsortiumEnabled) {
return Res::Err("Unsupported type for Feature {%d}", typeKey);
}
} else {
} else {
return Res::Err("Unsupported Param ID");
}
}
Expand Down Expand Up @@ -773,6 +856,23 @@ Res ATTRIBUTES::Import(const UniValue & val) {
}
SetValue(newAttr, value);
return Res::Ok();
} else if (attrV0->type == AttributeTypes::Consortium && attrV0->key == ConsortiumKeys::Members) {
if (auto attrValue = std::get_if<CConsortiumMembers>(&value)) {
auto members = GetValue(*attrV0, CConsortiumMembers{});

for (auto const & member : *attrValue)
{
for (auto const & tmp : members)
if (tmp.first != member.first && tmp.second.ownerAddress == member.second.ownerAddress)
return Res::Err("Cannot add a member with an owner address of a existing consortium member!");

members[member.first] = member.second;
}
SetValue(*attrV0, members);

return Res::Ok();
} else
return Res::Err("Invalid member data");
}
}
SetValue(attribute, value);
Expand Down Expand Up @@ -846,8 +946,8 @@ UniValue ATTRIBUTES::ExportFiltered(GovVarsFilter filter, const std::string &pre
ret.pushKV(key, *bool_val ? "true" : "false");
} else if (const auto amount = std::get_if<CAmount>(&attribute.second)) {
if (attrV0->type == AttributeTypes::Param &&
(attrV0->typeId == ParamIDs::DFIP2203 || attrV0->typeId == ParamIDs::DFIP2206F) &&
(attrV0->key == DFIPKeys::BlockPeriod || attrV0->key == DFIPKeys::StartBlock)) {
(attrV0->typeId == DFIP2203 || attrV0->typeId == DFIP2206F) &&
(attrV0->key == DFIPKeys::BlockPeriod || attrV0->key == DFIPKeys::StartBlock)) {
ret.pushKV(key, KeyBuilder(*amount));
} else {
auto decimalStr = GetDecimaleString(*amount);
Expand Down Expand Up @@ -885,6 +985,47 @@ UniValue ATTRIBUTES::ExportFiltered(GovVarsFilter filter, const std::string &pre
ret.pushKV(KeyBuilder(poolkey, "total_swap_a"), ValueFromUint(dexTokenA.swaps));
ret.pushKV(KeyBuilder(poolkey, "total_swap_b"), ValueFromUint(dexTokenB.swaps));
}
} else if (auto members = std::get_if<CConsortiumMembers>(&attribute.second)) {
UniValue result(UniValue::VOBJ);
for (const auto& [id, member] : *members)
{
UniValue elem(UniValue::VOBJ);
elem.pushKV("name", member.name);
elem.pushKV("ownerAddress", ScriptToString(member.ownerAddress));
elem.pushKV("backingId", member.backingId);
elem.pushKV("mintLimit", ValueFromAmount(member.mintLimit));
elem.pushKV("dailyMintLimit", ValueFromAmount(member.dailyMintLimit));
elem.pushKV("status", member.status);
result.pushKV(id, elem);
}
ret.pushKV(key, result.write());
} else if (auto consortiumMinted = std::get_if<CConsortiumGlobalMinted>(&attribute.second)) {
for (const auto& token : *consortiumMinted)
{
auto& minted = token.second.minted;
auto& burnt = token.second.burnt;

auto tokenKey = KeyBuilder(key, token.first.v);
ret.pushKV(KeyBuilder(tokenKey, "minted"), ValueFromAmount(minted));
ret.pushKV(KeyBuilder(tokenKey, "burnt"), ValueFromAmount(burnt));
ret.pushKV(KeyBuilder(tokenKey, "supply"), ValueFromAmount(minted - burnt));
}
} else if (auto membersMinted = std::get_if<CConsortiumMembersMinted>(&attribute.second)) {
for (const auto& token : *membersMinted)
{
for (const auto& member : token.second)
{
auto& minted = member.second.minted;
auto& burnt = member.second.burnt;

auto tokenKey = KeyBuilder(key, token.first.v);
auto memberKey = KeyBuilder(tokenKey, member.first);
ret.pushKV(KeyBuilder(memberKey, "minted"), ValueFromAmount(minted));
ret.pushKV(KeyBuilder(memberKey, "daily_minted"), KeyBuilder(member.second.dailyMinted.first, ValueFromAmount(member.second.dailyMinted.second).getValStr()));
ret.pushKV(KeyBuilder(memberKey, "burnt"), ValueFromAmount(burnt));
ret.pushKV(KeyBuilder(memberKey, "supply"), ValueFromAmount(minted - burnt));
}
}
} else if (const auto splitValues = std::get_if<OracleSplits>(&attribute.second)) {
std::string keyValue;
for (auto it{splitValues->begin()}; it != splitValues->end(); ++it) {
Expand Down Expand Up @@ -1022,6 +1163,22 @@ Res ATTRIBUTES::Validate(const CCustomCSView & view) const
}
break;

case AttributeTypes::Consortium:
switch (attrV0->key) {
case ConsortiumKeys::Members:
case ConsortiumKeys::MintLimit:
case ConsortiumKeys::DailyMintLimit:
if (view.GetLastHeight() < Params().GetConsensus().GrandCentralHeight)
return Res::Err("Cannot be set before GrandCentral");

if (!view.GetToken(DCT_ID{attrV0->typeId}))
return Res::Err("No such token (%d)", attrV0->typeId);
break;
default:
return Res::Err("Unsupported key");
}
break;

case AttributeTypes::Oracles:
if (view.GetLastHeight() < Params().GetConsensus().FortCanningCrunchHeight) {
return Res::Err("Cannot be set before FortCanningCrunch");
Expand Down
Loading