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

Add sleep in batchvote rpc #1810

Merged
merged 7 commits into from
Mar 17, 2023
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
1 change: 1 addition & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,7 @@ void SetupServerArgs()
gArgs.AddArg("-dftxworkers=<n>", strprintf("No. of parallel workers associated with the DfTx related work pool. Stock splits, parallel processing of the chain where appropriate, etc use this worker pool (default: %d)", DEFAULT_DFTX_WORKERS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
gArgs.AddArg("-maxaddrratepersecond=<n>", strprintf("Sets MAX_ADDR_RATE_PER_SECOND limit for ADDR messages(default: %f)", MAX_ADDR_RATE_PER_SECOND), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
gArgs.AddArg("-maxaddrprocessingtokenbucket=<n>", strprintf("Sets MAX_ADDR_PROCESSING_TOKEN_BUCKET limit for ADDR messages(default: %d)", MAX_ADDR_PROCESSING_TOKEN_BUCKET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
gArgs.AddArg("-sleep-time=<n>", "Sets sleeping time for voteGovBatch, by default the value is set to 500ms", ArgsManager::ALLOW_ANY, OptionsCategory::HIDDEN);

#if HAVE_DECL_DAEMON
gArgs.AddArg("-daemon", "Run in the background as a daemon and accept commands", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
Expand Down
36 changes: 25 additions & 11 deletions src/masternodes/rpc_proposals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <functional>

const bool DEFAULT_RPC_GOV_NEUTRAL = false;
const int SLEEP_TIME_MILLIS = 500;

struct VotingInfo {
int32_t votesPossible = 0;
Expand Down Expand Up @@ -610,37 +611,43 @@ UniValue votegovbatch(const JSONRPCRequest &request) {
RPCTypeCheck(request.params, {UniValue::VARR}, false);

const auto &keys = request.params[0].get_array();
auto sleepTime = gArgs.GetBoolArg("-sleep-time", SLEEP_TIME_MILLIS);
auto neutralVotesAllowed = gArgs.GetBoolArg("-rpc-governance-accept-neutral", DEFAULT_RPC_GOV_NEUTRAL);

int targetHeight;

struct MasternodeMultiVote {
struct VotingState {
uint256 propId;
uint256 mnId;
CTxDestination dest;
CProposalVoteType type;
};

std::vector<MasternodeMultiVote> mnMultiVotes;
std::vector<VotingState> voteList;
{
CCustomCSView view(*pcustomcsview);

for (size_t i{}; i < keys.size(); ++i) {

const auto &votes{keys[i].get_array()};
if (votes.size() != 3) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Incorrect number of items, three expected, proposal ID, masternode ID and vote expected. %d entries provided.", votes.size()));
throw JSONRPCError(RPC_INVALID_PARAMETER,
strprintf("Incorrect number of items, three expected, proposal ID, masternode ID and vote expected. %d entries provided.",
votes.size()));
}

const auto propId = ParseHashV(votes[0].get_str(), "proposalId");
const auto prop = view.GetProposal(propId);
if (!prop) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Proposal <%s> does not exist", propId.GetHex()));
throw JSONRPCError(RPC_INVALID_PARAMETER,
strprintf("Proposal <%s> does not exist",
propId.GetHex()));
}

if (prop->status != CProposalStatusType::Voting) {
throw JSONRPCError(RPC_INVALID_PARAMETER,
strprintf("Proposal <%s> is not in voting period", propId.GetHex()));
strprintf("Proposal <%s> is not in voting period",
propId.GetHex()));
}

uint256 mnId;
Expand All @@ -652,15 +659,16 @@ UniValue votegovbatch(const JSONRPCRequest &request) {
const CTxDestination dest = DecodeDestination(id);
if (!IsValidDestination(dest)) {
throw JSONRPCError(RPC_INVALID_PARAMETER,
strprintf("The masternode id or address is not valid: %s", id));
strprintf("The masternode id or address is not valid: %s", id));
}
CKeyID ckeyId;
if (dest.index() == PKHashType) {
ckeyId = CKeyID(std::get<PKHash>(dest));
} else if (dest.index() == WitV0KeyHashType) {
ckeyId = CKeyID(std::get<WitnessV0KeyHash>(dest));
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("%s does not refer to a P2PKH or P2WPKH address", id));
throw JSONRPCError(RPC_INVALID_PARAMETER,
strprintf("%s does not refer to a P2PKH or P2WPKH address", id));
}
if (auto masterNodeIdByOwner = view.GetMasternodeIdByOwner(ckeyId)) {
mnId = masterNodeIdByOwner.value();
Expand All @@ -672,7 +680,7 @@ UniValue votegovbatch(const JSONRPCRequest &request) {
const auto node = view.GetMasternode(mnId);
if (!node) {
throw JSONRPCError(RPC_INVALID_PARAMETER,
strprintf("The masternode does not exist or the address doesn't own a masternode: %s", id));
strprintf("The masternode does not exist or the address doesn't own a masternode: %s", id));
}

auto vote = CProposalVoteType::VoteNeutral;
Expand All @@ -688,10 +696,11 @@ UniValue votegovbatch(const JSONRPCRequest &request) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "Decision supports yes or no. Neutral is currently disabled because of issue https://github.com/DeFiCh/ain/issues/1704");
}

mnMultiVotes.push_back({
voteList.push_back({
propId,
mnId,
node->ownerType == 1 ? CTxDestination(PKHash(node->ownerAuthAddress)) : CTxDestination(WitnessV0KeyHash(node->ownerAuthAddress)),
node->ownerType == 1 ? CTxDestination(PKHash(node->ownerAuthAddress)) :
CTxDestination(WitnessV0KeyHash(node->ownerAuthAddress)),
vote
});
}
Expand All @@ -701,7 +710,7 @@ UniValue votegovbatch(const JSONRPCRequest &request) {

UniValue ret(UniValue::VARR);

for (const auto& [propId, mnId, ownerDest, vote] : mnMultiVotes) {
for (const auto& [propId, mnId, ownerDest, vote] : voteList) {

CProposalVoteMessage msg;
msg.propId = propId;
Expand Down Expand Up @@ -739,6 +748,11 @@ UniValue votegovbatch(const JSONRPCRequest &request) {
execTestTx(CTransaction(rawTx), targetHeight, optAuthTx);

ret.push_back(signsend(rawTx, pwallet, optAuthTx)->GetHash().GetHex());
// Sleep the RPC worker thread a bit, so that the node can
// relay the TXs as it works through. Otherwise, the main
// chain can be locked for too long that prevent broadcasting of
// TXs
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
}

return ret;
Expand Down