diff --git a/src/gridcoin/sidestake.cpp b/src/gridcoin/sidestake.cpp index c310c625c9..5378af713b 100644 --- a/src/gridcoin/sidestake.cpp +++ b/src/gridcoin/sidestake.cpp @@ -49,15 +49,17 @@ CBitcoinAddressForStorage::CBitcoinAddressForStorage(CBitcoinAddress address) SideStake::SideStake() : m_key() , m_allocation() + , m_description() , m_timestamp(0) , m_hash() , m_previous_hash() , m_status(SideStakeStatus::UNKNOWN) {} -SideStake::SideStake(CBitcoinAddressForStorage address, double allocation) +SideStake::SideStake(CBitcoinAddressForStorage address, double allocation, std::string description) : m_key(address) , m_allocation(allocation) + , m_description(description) , m_timestamp(0) , m_hash() , m_previous_hash() @@ -66,11 +68,13 @@ SideStake::SideStake(CBitcoinAddressForStorage address, double allocation) SideStake::SideStake(CBitcoinAddressForStorage address, double allocation, + std::string description, int64_t timestamp, uint256 hash, SideStakeStatus status) : m_key(address) , m_allocation(allocation) + , m_description(description) , m_timestamp(timestamp) , m_hash(hash) , m_previous_hash() @@ -163,10 +167,11 @@ SideStakePayload::SideStakePayload(uint32_t version) SideStakePayload::SideStakePayload(const uint32_t version, CBitcoinAddressForStorage key, double value, + std::string description, SideStakeStatus status) : IContractPayload() , m_version(version) - , m_entry(SideStake(key, value, 0, uint256{}, status)) + , m_entry(SideStake(key, value, description, 0, uint256{}, status)) { } @@ -603,6 +608,7 @@ void SideStakeRegistry::LoadLocalSideStakesFromConfig() SideStake sidestake(static_cast(address), dAllocation, + std::string {}, 0, uint256{}, SideStakeStatus::ACTIVE); diff --git a/src/gridcoin/sidestake.h b/src/gridcoin/sidestake.h index 25d5de8574..afebd8faed 100644 --- a/src/gridcoin/sidestake.h +++ b/src/gridcoin/sidestake.h @@ -69,6 +69,8 @@ class SideStake double m_allocation; //!< The allocation is a double precision floating point between 0.0 and 1.0 inclusive + std::string m_description; //!< The description of the sidestake (optional) + int64_t m_timestamp; //!< Time of the sidestake contract transaction. uint256 m_hash; //!< The hash of the transaction that contains a mandatory sidestake. @@ -88,17 +90,19 @@ class SideStake //! //! \param address //! \param allocation + //! \param description (optional) //! - SideStake(CBitcoinAddressForStorage address, double allocation); + SideStake(CBitcoinAddressForStorage address, double allocation, std::string description); //! //! \brief Initialize a sidestake instance with the provided parameters. //! //! \param address //! \param allocation + //! \param description (optional) //! \param status //! - SideStake(CBitcoinAddressForStorage address, double allocation, SideStakeStatus status); + SideStake(CBitcoinAddressForStorage address, double allocation, std::string description, SideStakeStatus status); //! //! \brief Initialize a sidestake instance with the provided parameters. This form is normally used to construct a @@ -106,11 +110,12 @@ class SideStake //! //! \param address //! \param allocation + //! \param description (optional) //! \param timestamp //! \param hash //! \param status //! - SideStake(CBitcoinAddressForStorage address, double allocation, int64_t timestamp, uint256 hash, SideStakeStatus status); + SideStake(CBitcoinAddressForStorage address, double allocation, std::string description, int64_t timestamp, uint256 hash, SideStakeStatus status); //! //! \brief Determine whether a sidestake contains each of the required elements. @@ -176,6 +181,7 @@ class SideStake { READWRITE(m_key); READWRITE(m_allocation); + READWRITE(m_description); READWRITE(m_timestamp); READWRITE(m_hash); READWRITE(m_previous_hash); @@ -242,7 +248,8 @@ class SideStakePayload : public IContractPayload //! \param value. Value string for the sidestake entry //! \param status. Status of the sidestake entry //! - SideStakePayload(const uint32_t version, CBitcoinAddressForStorage key, double value, SideStakeStatus status); + SideStakePayload(const uint32_t version, CBitcoinAddressForStorage key, double value, + std::string description, SideStakeStatus status); //! //! \brief Initialize a sidestake entry payload from the given sidestake entry diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index ee6581ef46..44bf74fcd4 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -2269,6 +2269,17 @@ UniValue addkey(const UniValue& params, bool fHelp) } } + // For add a mandatory sidestake, the 4th parameter is the allocation and the description (5th parameter) is optional. + if (type == GRC::ContractType::SIDESTAKE) { + if (action == GRC::ContractAction::ADD) { + required_param_count = 4; + param_count_max = 5; + } else { + required_param_count = 3; + param_count_max = 3; + } + } + if (fHelp || params.size() < required_param_count || params.size() > param_count_max) { std::string error_string; @@ -2320,22 +2331,45 @@ UniValue addkey(const UniValue& params, bool fHelp) case GRC::ContractType::PROJECT: { if (action == GRC::ContractAction::ADD) { + bool gdpr_export_control = false; + if (block_v13_enabled) { + // We must do our own conversion to boolean here, because the 5th parameter can either be + // a boolean for project or a string for sidestake, which means the client.cpp entry cannot contain a + // unicode type specifier for the 5th parameter. + if (ToLower(params[4].get_str()) == "true") { + gdpr_export_control = true; + } else if (ToLower(params[4].get_str()) != "false") { + // Neither true or false - throw an exception. + throw JSONRPCError(RPC_INVALID_PARAMETER, "GDPR export parameter invalid. Must be true or false."); + } + contract = GRC::MakeContract( contract_version, action, uint32_t{3}, // Contract payload version number, 3 params[2].get_str(), // Name params[3].get_str(), // URL - params[4].getBool()); // GDPR stats export protection enforced boolean + gdpr_export_control); // GDPR stats export protection enforced boolean + } else if (project_v2_enabled) { + // We must do our own conversion to boolean here, because the 5th parameter can either be + // a boolean for project or a string for sidestake, which means the client.cpp entry cannot contain a + // unicode type specifier for the 5th parameter. + if (ToLower(params[4].get_str()) == "true") { + gdpr_export_control = true; + } else if (ToLower(params[4].get_str()) != "false") { + // Neither true or false - throw an exception. + throw JSONRPCError(RPC_INVALID_PARAMETER, "GDPR export parameter invalid. Must be true or false."); + } + contract = GRC::MakeContract( contract_version, action, uint32_t{2}, // Contract payload version number, 2 params[2].get_str(), // Name params[3].get_str(), // URL - params[4].getBool()); // GDPR stats export protection enforced boolean + gdpr_export_control); // GDPR stats export protection enforced boolean } else { contract = GRC::MakeContract( @@ -2443,6 +2477,13 @@ UniValue addkey(const UniValue& params, bool fHelp) throw JSONRPCError(RPC_INVALID_PARAMETER, "Address specified for the sidestake is invalid."); } + std::string description; + if (params.size() > 4) { + description = params[4].get_str(); + } + + // We have to do our own conversion here because the 4th parameter type specifier cannot be set other + // than string in the client.cpp file. double allocation = 0.0; if (!ParseDouble(params[3].get_str(), &allocation)) { throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid allocation specified."); @@ -2460,6 +2501,7 @@ UniValue addkey(const UniValue& params, bool fHelp) uint32_t {1}, // Contract payload version number sidestake_address, // Sidestake address allocation, // Sidestake allocation + description, // Sidestake description GRC::SideStakeStatus::MANDATORY // sidestake status ); } else { diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 8bc4bbca8d..b1a76da8f8 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -201,7 +201,6 @@ static const CRPCConvertParam vRPCConvertParams[] = { "superblocks" , 1 }, // Developer - { "addkey" , 4 }, { "auditsnapshotaccrual" , 1 }, { "auditsnapshotaccruals" , 0 }, { "beaconaudit" , 0 },