From b86cff2d26c2d878a1fe33fde0db059b7024119e Mon Sep 17 00:00:00 2001 From: Prasanna Loganathar Date: Fri, 17 Mar 2023 15:46:22 +0800 Subject: [PATCH] Add sleep in batchvote rpc (#1810) * Add sleep in batchvote rpc * Reduce time and minor refactor * Update rpc_proposals.cpp * Add sleep time parameter for voteGovBatch * Add description for sleep-time parameter --------- Co-authored-by: cedric ogire --- src/init.cpp | 1 + src/masternodes/rpc_proposals.cpp | 36 +++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 217cb38702..eb4f345edc 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -637,6 +637,7 @@ void SetupServerArgs() gArgs.AddArg("-dftxworkers=", 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=", 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=", 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=", "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); diff --git a/src/masternodes/rpc_proposals.cpp b/src/masternodes/rpc_proposals.cpp index dce091328b..ffc0aecdfc 100644 --- a/src/masternodes/rpc_proposals.cpp +++ b/src/masternodes/rpc_proposals.cpp @@ -4,6 +4,7 @@ #include const bool DEFAULT_RPC_GOV_NEUTRAL = false; +const int SLEEP_TIME_MILLIS = 500; struct VotingInfo { int32_t votesPossible = 0; @@ -610,18 +611,19 @@ 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 mnMultiVotes; + std::vector voteList; { CCustomCSView view(*pcustomcsview); @@ -629,18 +631,23 @@ UniValue votegovbatch(const JSONRPCRequest &request) { 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; @@ -652,7 +659,7 @@ 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) { @@ -660,7 +667,8 @@ UniValue votegovbatch(const JSONRPCRequest &request) { } else if (dest.index() == WitV0KeyHashType) { ckeyId = CKeyID(std::get(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(); @@ -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; @@ -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 }); } @@ -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; @@ -734,6 +743,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;