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

gui, researcher: Add GDPR protection display #2527

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
2 changes: 2 additions & 0 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class CMainParams : public CChainParams {
consensus.BlockV11Height = 2053000;
consensus.BlockV12Height = std::numeric_limits<int>::max();
consensus.PollV3Height = std::numeric_limits<int>::max();
consensus.ProjectV2Height = std::numeric_limits<int>::max();
// Immediately post zero payment interval fees 40% for mainnet
consensus.InitialMRCFeeFractionPostZeroInterval = Fraction(2, 5);
// Zero day interval is 14 days on mainnet
Expand Down Expand Up @@ -162,6 +163,7 @@ class CTestNetParams : public CChainParams {
consensus.BlockV11Height = 1301500;
consensus.BlockV12Height = 1871830;
consensus.PollV3Height = 1944820;
consensus.ProjectV2Height = 1944820;
// Immediately post zero payment interval fees 40% for testnet, the same as mainnet
consensus.InitialMRCFeeFractionPostZeroInterval = Fraction(2, 5);
// Zero day interval is 10 minutes on testnet. The very short interval facilitates testing.
Expand Down
8 changes: 8 additions & 0 deletions src/chainparams.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ inline bool IsPollV3Enabled(int nHeight)
return nHeight >= PollV3Height;
}

inline bool IsProjectV2Enabled(int nHeight)
{
// Temporary override for testing. Cf. Corresponding code in init.cpp
int ProjectV2Height = gArgs.GetArg("-projectv2height", Params().GetConsensus().ProjectV2Height);

return nHeight >= ProjectV2Height;
}

inline int GetSuperblockAgeSpacing(int nHeight)
{
return (fTestNet ? 86400 : (nHeight > 364500) ? 86400 : 43200);
Expand Down
2 changes: 2 additions & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ struct Params {
int BlockV12Height;
/** Block height at which poll v3 contract payloads are valid */
int PollV3Height;
/** Block height at which project v2 contracts are allowed */
int ProjectV2Height;
/** The fraction of rewards taken as fees in an MRC after the zero payment interval. Only consesnus critical
* at BlockV12Height or above.
*/
Expand Down
28 changes: 22 additions & 6 deletions src/gridcoin/project.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// file COPYING or https://opensource.org/licenses/mit-license.php.

#include "main.h"
#include "gridcoin/contract/contract.h"
#include "gridcoin/project.h"

#include <algorithm>
Expand All @@ -27,17 +26,23 @@ Whitelist& GRC::GetWhitelist()

constexpr uint32_t Project::CURRENT_VERSION; // For clang

Project::Project() : m_timestamp(0)
Project::Project()
: m_timestamp(0)
, m_gdpr_controls(false)
{
}

Project::Project(std::string name, std::string url)
: Project(std::move(name), std::move(url), 0)
Project::Project(std::string name, std::string url, int64_t timestamp)
: Project(std::move(name), std::move(url), timestamp, CURRENT_VERSION, false)
{
}

Project::Project(std::string name, std::string url, int64_t timestamp)
: m_name(std::move(name)), m_url(std::move(url)), m_timestamp(timestamp)
Project::Project(std::string name, std::string url, int64_t timestamp, uint32_t version, bool gdpr_controls)
: m_version(version)
, m_name(std::move(name))
, m_url(std::move(url))
, m_timestamp(timestamp)
, m_gdpr_controls(gdpr_controls)
{
}

Expand Down Expand Up @@ -76,6 +81,17 @@ std::string Project::StatsUrl(const std::string& type) const
return BaseUrl() + "stats/" + type + ".gz";
}

std::optional<bool> Project::HasGDPRControls() const
{
std::optional<bool> has_gdpr_controls;

if (m_version >= 2) {
has_gdpr_controls = m_gdpr_controls;
}

return has_gdpr_controls;
}

// -----------------------------------------------------------------------------
// Class: WhitelistSnapshot
// -----------------------------------------------------------------------------
Expand Down
47 changes: 36 additions & 11 deletions src/gridcoin/project.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define GRIDCOIN_PROJECT_H

#include "amount.h"
#include "contract/contract.h"
#include "gridcoin/contract/handler.h"
#include "gridcoin/contract/payload.h"
#include "serialize.h"
Expand All @@ -29,7 +30,7 @@ class Project : public IContractPayload
//! ensure that the serialization/deserialization routines also handle all
//! of the previous versions.
//!
static constexpr uint32_t CURRENT_VERSION = 1;
static constexpr uint32_t CURRENT_VERSION = 2;

//!
//! \brief The maximum number of characters allowed for a serialized project
Expand All @@ -53,9 +54,10 @@ class Project : public IContractPayload
//!
uint32_t m_version = CURRENT_VERSION;

std::string m_name; //!< As it exists in the contract key field.
std::string m_url; //!< As it exists in the contract value field.
int64_t m_timestamp; //!< Timestamp of the contract.
std::string m_name; //!< As it exists in the contract key field.
std::string m_url; //!< As it exists in the contract value field.
int64_t m_timestamp; //!< Timestamp of the contract.
bool m_gdpr_controls; //!< Boolean to indicate whether project has GDPR stats export controls.

//!
//! \brief Initialize an empty, invalid project object.
Expand All @@ -67,17 +69,19 @@ class Project : public IContractPayload
//!
//! \param name Project name from contract message key.
//! \param url Project URL from contract message value.
//! \param timestamp Contract timestamp.
//!
Project(std::string name, std::string url);
Project(std::string name, std::string url, int64_t timestamp = 0);

//!
//! \brief Initialize a \c Project using data from the contract.
//!
//! \param name Project name from contract message key.
//! \param url Project URL from contract message value.
//! \param timestamp Contract timestamp.
//! \param name Project name from contract message key.
//! \param url Project URL from contract message value.
//! \param timestamp Contract timestamp.
//! \param gdpr_controls Boolean to indicate gdpr stats export controls enforced
//!
Project(std::string name, std::string url, int64_t timestamp);
Project(std::string name, std::string url, int64_t timestamp, uint32_t version, bool gdpr_controls = false);

//!
//! \brief Get the type of contract that this payload contains data for.
Expand All @@ -97,8 +101,20 @@ class Project : public IContractPayload
//!
bool WellFormed(const ContractAction action) const override
{
return !m_name.empty()
&& (action == ContractAction::REMOVE || !m_url.empty());
if (m_name.empty()) {
return false;
}

if (action != ContractAction::REMOVE && m_url.empty()) {
return false;
}

// m_gdpr_controls is not serialized unless the contract version is v2+
if (m_version < 2 && m_gdpr_controls) {
return false;
}

return true;
}

//!
Expand Down Expand Up @@ -150,6 +166,11 @@ class Project : public IContractPayload
//!
std::string StatsUrl(const std::string& type = "") const;

//!
//! \brief Returns true if project has project stats GDPR export controls
//!
std::optional<bool> HasGDPRControls() const;

ADD_CONTRACT_PAYLOAD_SERIALIZE_METHODS;

template <typename Stream, typename Operation>
Expand All @@ -163,6 +184,10 @@ class Project : public IContractPayload

if (contract_action != ContractAction::REMOVE) {
READWRITE(LIMITED_STRING(m_url, MAX_URL_SIZE));

if (m_version >= 2) {
READWRITE(m_gdpr_controls);
}
}
}
};
Expand Down
3 changes: 3 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,9 @@ void SetupServerArgs()
// Temporary for poll v3 testing
hidden_args.emplace_back("-pollv3height");

// Temporary for project v2 testing
hidden_args.emplace_back("-projectv2height");

// -boinckey should now be removed entirely. It is put here to prevent the executable erroring out on
// an invalid parameter for old clients that may have left the argument in.
hidden_args.emplace_back("-boinckey");
Expand Down
23 changes: 23 additions & 0 deletions src/qt/researcher/projecttablemodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ class CompareRowLessThan
return pLeft->m_error < pRight->m_error;
case ProjectTableModel::Whitelisted:
return pLeft->m_whitelisted < pRight->m_whitelisted;
case ProjectTableModel::GDPRControls:
if (pLeft->m_gdpr_controls && pRight->m_gdpr_controls) {
return *pLeft->m_gdpr_controls < *pRight->m_gdpr_controls;
} else if (!pLeft->m_gdpr_controls && pRight->m_gdpr_controls) {
return true;
} else if (!pRight->m_gdpr_controls) {
return false;
}
case ProjectTableModel::Magnitude:
return pLeft->m_magnitude < pRight->m_magnitude;
case ProjectTableModel::RecentAverageCredit:
Expand Down Expand Up @@ -123,6 +131,7 @@ ProjectTableModel::ProjectTableModel(ResearcherModel *model, const bool extended
<< tr("Name")
<< tr("Eligible")
<< tr("Whitelist")
<< tr("Has GDPR Controls")
<< tr("Magnitude")
<< tr("Avg. Credit")
<< tr("CPID");
Expand Down Expand Up @@ -167,6 +176,11 @@ QVariant ProjectTableModel::data(const QModelIndex &index, int role) const
return row->m_error;
}
break;
case GDPRControls:
if (row->m_gdpr_controls) {
return *row->m_gdpr_controls;
}
break;
case Cpid:
return row->m_cpid;
case Magnitude:
Expand All @@ -188,6 +202,15 @@ QVariant ProjectTableModel::data(const QModelIndex &index, int role) const
return QIcon(":/icons/round_green_check");
}
break;
case GDPRControls:
if (row->m_gdpr_controls && *row->m_gdpr_controls && row->m_error.isEmpty()) {
if (row->m_rac <= 0) {
return QIcon(":/icons/warning");
} else {
return QIcon(":/icons/round_green_check");
}
}
break;
}
break;

Expand Down
1 change: 1 addition & 0 deletions src/qt/researcher/projecttablemodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class ProjectTableModel : public QAbstractTableModel
Name,
Eligible,
Whitelisted,
GDPRControls,
Magnitude,
RecentAverageCredit,
Cpid,
Expand Down
3 changes: 3 additions & 0 deletions src/qt/researcher/researchermodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@ std::vector<ProjectRow> ResearcherModel::buildProjectTable(bool extended) const
}
}

row.m_gdpr_controls = whitelist_project->HasGDPRControls();

rows.emplace(whitelist_project->m_name, std::move(row));
} else {
row.m_whitelisted = false;
Expand All @@ -503,6 +505,7 @@ std::vector<ProjectRow> ResearcherModel::buildProjectTable(bool extended) const
}

ProjectRow row;
row.m_gdpr_controls = project.HasGDPRControls();
row.m_whitelisted = true;
row.m_name = QString::fromStdString(project.DisplayName()).toLower();
row.m_magnitude = 0.0;
Expand Down
2 changes: 2 additions & 0 deletions src/qt/researcher/researchermodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <memory>
#include "amount.h"
#include <QObject>
#include <optional>

QT_BEGIN_NAMESPACE
class QIcon;
Expand Down Expand Up @@ -59,6 +60,7 @@ class ProjectRow
{
public:
bool m_whitelisted;
std::optional<bool> m_gdpr_controls;
QString m_name;
QString m_cpid;
double m_magnitude = 0.0;
Expand Down
Loading