Skip to content

Commit

Permalink
Wire up the rest of the sidestake contract machinery
Browse files Browse the repository at this point in the history
  • Loading branch information
jamescowens committed Oct 1, 2023
1 parent f9863ce commit 14fb263
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 8 deletions.
23 changes: 17 additions & 6 deletions src/gridcoin/contract/contract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,12 +677,13 @@ bool Contract::RequiresMasterKey() const
// beacons by signing them with the original private key:
return m_version == 1 && m_action == ContractAction::REMOVE;

case ContractType::POLL: return m_action == ContractAction::REMOVE;
case ContractType::PROJECT: return true;
case ContractType::PROTOCOL: return true;
case ContractType::SCRAPER: return true;
case ContractType::VOTE: return m_action == ContractAction::REMOVE;
default: return false;
case ContractType::POLL: return m_action == ContractAction::REMOVE;
case ContractType::PROJECT: return true;
case ContractType::PROTOCOL: return true;
case ContractType::SCRAPER: return true;
case ContractType::VOTE: return m_action == ContractAction::REMOVE;
case ContractType::SIDESTAKE: return true;
default: return false;
}
}

Expand Down Expand Up @@ -761,6 +762,7 @@ Contract::Type Contract::Type::Parse(std::string input)
if (input == "scraper") return ContractType::SCRAPER;
if (input == "protocol") return ContractType::PROTOCOL;
if (input == "message") return ContractType::MESSAGE;
if (input == "sidestake") return ContractType::SIDESTAKE;

return ContractType::UNKNOWN;
}
Expand All @@ -777,6 +779,7 @@ std::string Contract::Type::ToString() const
case ContractType::PROTOCOL: return "protocol";
case ContractType::SCRAPER: return "scraper";
case ContractType::VOTE: return "vote";
case ContractType::SIDESTAKE: return "sidestake";
default: return "";
}
}
Expand All @@ -793,6 +796,7 @@ std::string Contract::Type::ToString(ContractType contract_type)
case ContractType::PROTOCOL: return "protocol";
case ContractType::SCRAPER: return "scraper";
case ContractType::VOTE: return "vote";
case ContractType::SIDESTAKE: return "sidestake";
default: return "";
}
}
Expand All @@ -809,6 +813,7 @@ std::string Contract::Type::ToTranslatedString(ContractType contract_type)
case ContractType::PROTOCOL: return _("protocol");
case ContractType::SCRAPER: return _("scraper");
case ContractType::VOTE: return _("vote");
case ContractType::SIDESTAKE: return _("sidestake");
default: return "";
}
}
Expand Down Expand Up @@ -905,6 +910,9 @@ ContractPayload Contract::Body::ConvertFromLegacy(const ContractType type, uint3
case ContractType::VOTE:
return ContractPayload::Make<LegacyVote>(
LegacyVote::Parse(legacy.m_key, legacy.m_value));
case ContractType::SIDESTAKE:
// Sidestakes have no legacy representation as a contract.
assert(false && "Attempted to convert non-existent legacy sidestake contract.");
case ContractType::OUT_OF_BOUND:
assert(false);
}
Expand Down Expand Up @@ -961,6 +969,9 @@ void Contract::Body::ResetType(const ContractType type)
case ContractType::VOTE:
m_payload.Reset(new Vote());
break;
case ContractType::SIDESTAKE:
m_payload.Reset(new SideStakePayload());
break;
case ContractType::OUT_OF_BOUND:
assert(false);
}
Expand Down
2 changes: 2 additions & 0 deletions src/gridcoin/contract/registry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const std::vector<GRC::ContractType> RegistryBookmarks::CONTRACT_TYPES_WITH_REG_
ContractType::PROJECT,
ContractType::PROTOCOL,
ContractType::SCRAPER,
ContractType::SIDESTAKE
};

const std::vector<GRC::ContractType> RegistryBookmarks::CONTRACT_TYPES_SUPPORTING_REVERT = {
Expand All @@ -20,6 +21,7 @@ const std::vector<GRC::ContractType> RegistryBookmarks::CONTRACT_TYPES_SUPPORTIN
ContractType::PROTOCOL,
ContractType::SCRAPER,
ContractType::VOTE,
ContractType::SIDESTAKE
};

} // namespace GRC
3 changes: 3 additions & 0 deletions src/gridcoin/contract/registry.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "gridcoin/beacon.h"
#include "gridcoin/project.h"
#include "gridcoin/protocol.h"
#include "gridcoin/sidestake.h"
#include "gridcoin/scraper/scraper_registry.h"
#include "gridcoin/voting/registry.h"

Expand Down Expand Up @@ -50,6 +51,7 @@ class RegistryBookmarks
case ContractType::PROJECT: return GetWhitelist();
case ContractType::PROTOCOL: return GetProtocolRegistry();
case ContractType::SCRAPER: return GetScraperRegistry();
case ContractType::SIDESTAKE: return GetSideStakeRegistry();
case ContractType::UNKNOWN:
[[fallthrough]];
case ContractType::CLAIM:
Expand Down Expand Up @@ -78,6 +80,7 @@ class RegistryBookmarks
case ContractType::PROTOCOL: return GetProtocolRegistry();
case ContractType::SCRAPER: return GetScraperRegistry();
case ContractType::VOTE: return GetPollRegistry();
case ContractType::SIDESTAKE: return GetSideStakeRegistry();
[[fallthrough]];
case ContractType::UNKNOWN:
[[fallthrough]];
Expand Down
24 changes: 23 additions & 1 deletion src/gridcoin/sidestake.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,16 +182,30 @@ const SideStakeRegistry::SideStakeMap& SideStakeRegistry::SideStakeEntries() con
const std::vector<SideStake_ptr> SideStakeRegistry::ActiveSideStakeEntries()
{
std::vector<SideStake_ptr> sidestakes;
double allocation_sum = 0.0;

// For right now refresh sidestakes from config file. This is about the same overhead as the original
// function in the miner. Perhaps replace with a signal to only refresh when r-w config file is
// actually changed.
LoadLocalSideStakesFromConfig();

// The loops below prevent sidestakes from being added that cause a total allocation above 1.0 (100%).

// Do mandatory sidestakes first.
for (const auto& entry : m_sidestake_entries)
{
if (entry.second->m_status == SideStakeStatus::ACTIVE || entry.second->m_status == SideStakeStatus::MANDATORY) {
if (entry.second->m_status == SideStakeStatus::MANDATORY && allocation_sum + entry.second->m_allocation <= 1.0) {
sidestakes.push_back(entry.second);
allocation_sum += entry.second->m_allocation;
}
}

// Followed by local active sidestakes
for (const auto& entry : m_sidestake_entries)
{
if (entry.second->m_status == SideStakeStatus::ACTIVE && allocation_sum + entry.second->m_allocation <= 1.0) {
sidestakes.push_back(entry.second);
allocation_sum += entry.second->m_allocation;
}
}

Expand Down Expand Up @@ -519,9 +533,17 @@ void SideStakeRegistry::LoadLocalSideStakesFromConfig()
}
}

// First, determine allocation already taken by mandatory sidestakes, because they must be allocated first.
for (const auto& entry : SideStakeEntries()) {
if (entry.second->m_status == SideStakeStatus::MANDATORY) {
dSumAllocation += entry.second->m_allocation;
}
}

for (const auto& entry : raw_vSideStakeAlloc)
{
std::string sAddress;

double dAllocation = 0.0;

sAddress = entry.first;
Expand Down
2 changes: 2 additions & 0 deletions src/gridcoin/sidestake.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ class SideStakeRegistry : public IContractHandler
//! \brief Get the collection of active sidestake entries. This is presented as a vector of
//! smart pointers to the relevant sidestake entries in the database. The entries included have
//! the status of active (for local sidestakes) and/or mandatory (for contract sidestakes).
//! Mandatory sidestakes come before local ones, and the method ensures that the sidestakes
//! returned do not total an allocation greater than 1.0.
//!
//! \return A vector of smart pointers to sidestake entries.
//!
Expand Down
32 changes: 31 additions & 1 deletion src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "blockchain.h"
#include "gridcoin/protocol.h"
#include "gridcoin/scraper/scraper_registry.h"
#include "gridcoin/sidestake.h"
#include "node/blockstorage.h"
#include <util/string.h>
#include "gridcoin/mrc.h"
Expand Down Expand Up @@ -2304,7 +2305,8 @@ UniValue addkey(const UniValue& params, bool fHelp)

if (!(type == GRC::ContractType::PROJECT
|| type == GRC::ContractType::SCRAPER
|| type == GRC::ContractType::PROTOCOL)) {
|| type == GRC::ContractType::PROTOCOL
|| type == GRC::ContractType::SIDESTAKE)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid contract type for addkey.");
}

Expand Down Expand Up @@ -2433,6 +2435,34 @@ UniValue addkey(const UniValue& params, bool fHelp)
params[2].get_str(), // key
params[3].get_str()); // value
break;
case GRC::ContractType::SIDESTAKE:
{
CBitcoinAddress sidestake_address;
if (!sidestake_address.SetString(params[2].get_str())) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Address specified for the sidestake is invalid.");
}

double allocation = 0.0;
if (!ParseDouble(params[3].get_str(), &allocation)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid allocation specified.");
}

allocation /= 100.0;

if (allocation > 1.0) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Allocation specified is greater than 100.0%.");
}

contract = GRC::MakeContract<GRC::SideStakePayload>(
contract_version,
action,
uint32_t {1}, // Contract payload version number
sidestake_address, // Sidestake address
allocation, // Sidestake allocation
GRC::SideStakeStatus::ACTIVE
);
break;
}
case GRC::ContractType::BEACON:
[[fallthrough]];
case GRC::ContractType::CLAIM:
Expand Down

0 comments on commit 14fb263

Please sign in to comment.