Ensure wallet is available and unlocked for some governance and evo RPCs (#2874)

* Ensure wallet is available and unlocked for specific governance rpc commands

* Ensure wallet is available and unlocked for specific protx rpc commands

Do this in actual rpc command handlers, not in the top protx rpc

* Fix few pwalletMain occurrences in rpc
This commit is contained in:
UdjinM6 2019-04-25 18:37:08 +03:00 committed by GitHub
parent 0c2fdf4da8
commit ed30db713c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 47 deletions

View File

@ -116,11 +116,12 @@ UniValue gobject_check(const JSONRPCRequest& request)
}
#ifdef ENABLE_WALLET
void gobject_prepare_help()
void gobject_prepare_help(CWallet* const pwallet)
{
throw std::runtime_error(
"gobject prepare <parent-hash> <revision> <time> <data-hex>\n"
"Prepare governance object by signing and creating tx\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
"1. parent-hash (string, required) hash of the parent object, \"0\" is root\n"
"2. revision (numeric, required) object revision in the system\n"
@ -136,11 +137,13 @@ UniValue gobject_prepare(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6 && request.params.size() != 8))
gobject_prepare_help();
gobject_prepare_help(pwallet);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
EnsureWalletIsUnlocked(pwallet);
// ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
uint256 hashParent;
@ -190,8 +193,6 @@ UniValue gobject_prepare(const JSONRPCRequest& request)
if (!govobj.IsValidLocally(strError, false))
throw JSONRPCError(RPC_INTERNAL_ERROR, "Governance object is not valid - " + govobj.GetHash().ToString() + " - " + strError);
EnsureWalletIsUnlocked(pwallet);
// If specified, spend this outpoint as the proposal fee
COutPoint outpoint;
outpoint.SetNull();
@ -505,11 +506,12 @@ UniValue VoteWithMasternodes(const std::map<uint256, CKey>& keys,
}
#ifdef ENABLE_WALLET
void gobject_vote_many_help()
void gobject_vote_many_help(CWallet* const pwallet)
{
throw std::runtime_error(
"gobject vote-many <governance-hash> <vote> <vote-outcome>\n"
"Vote on a governance object by all masternodes for which the voting key is present in the local wallet\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
"1. governance-hash (string, required) hash of the governance object\n"
"2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n"
@ -521,7 +523,10 @@ UniValue gobject_vote_many(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || request.params.size() != 4)
gobject_vote_many_help();
gobject_vote_many_help(pwallet);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
uint256 hash = ParseHashV(request.params[1], "Object hash");
std::string strVoteSignal = request.params[2].get_str();
@ -539,9 +544,7 @@ UniValue gobject_vote_many(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
}
if (!pwallet) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-many not supported when wallet is disabled.");
}
EnsureWalletIsUnlocked(pwallet);
std::map<uint256, CKey> votingKeys;
@ -556,11 +559,12 @@ UniValue gobject_vote_many(const JSONRPCRequest& request)
return VoteWithMasternodes(votingKeys, hash, eVoteSignal, eVoteOutcome);
}
void gobject_vote_alias_help()
void gobject_vote_alias_help(CWallet* const pwallet)
{
throw std::runtime_error(
"gobject vote-alias <governance-hash> <vote> <vote-outcome> <alias-name>\n"
"Vote on a governance object by masternode's voting key (if present in local wallet)\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
"1. governance-hash (string, required) hash of the governance object\n"
"2. vote (string, required) vote, possible values: [funding|valid|delete|endorsed]\n"
@ -573,7 +577,10 @@ UniValue gobject_vote_alias(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || request.params.size() != 5)
gobject_vote_alias_help();
gobject_vote_alias_help(pwallet);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
uint256 hash = ParseHashV(request.params[1], "Object hash");
std::string strVoteSignal = request.params[2].get_str();
@ -591,9 +598,7 @@ UniValue gobject_vote_alias(const JSONRPCRequest& request)
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain'");
}
if (!pwallet) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "vote-alias not supported when wallet is disabled");
}
EnsureWalletIsUnlocked(pwallet);
uint256 proTxHash = ParseHashV(request.params[4], "protx-hash");
auto dmn = deterministicMNManager->GetListAtChainTip().GetValidMN(proTxHash);
@ -602,7 +607,7 @@ UniValue gobject_vote_alias(const JSONRPCRequest& request)
}
CKey votingKey;
if (!pwalletMain->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
if (!pwallet->GetKey(dmn->pdmnState->keyIDVoting, votingKey)) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Private key for voting address %s not known by wallet", CBitcoinAddress(dmn->pdmnState->keyIDVoting).ToString()));
}
@ -881,9 +886,13 @@ UniValue gobject_getcurrentvotes(const JSONRPCRequest& request)
" getcurrentvotes - Get only current (tallying) votes for a governance object hash (does not include old votes)\n"
" list - List governance objects (can be filtered by signal and/or object type)\n"
" diff - List differences since last diff\n"
#ifdef ENABLE_WALLET
" vote-alias - Vote on a governance object by masternode alias/proTxHash\n"
#endif // ENABLE_WALLET
" vote-conf - Vote on a governance object by masternode configured in dash.conf\n"
#ifdef ENABLE_WALLET
" vote-many - Vote on a governance object by all masternodes for which the voting key is in the wallet\n"
#endif // ENABLE_WALLET
);
}

View File

@ -110,6 +110,7 @@ static CKey ParsePrivKey(CWallet* pwallet, const std::string &strKeyOrAddress, b
if (!pwallet) {
throw std::runtime_error("addresses not supported when wallet is disabled");
}
EnsureWalletIsUnlocked(pwallet);
CKeyID keyId;
CKey key;
if (!address.GetKeyID(keyId) || !pwallet->GetKey(keyId, key))
@ -210,7 +211,7 @@ static void FundSpecialTx(CWallet* pwallet, CMutableTransaction& tx, const Speci
}
CWalletTx wtx;
CReserveKey reservekey(pwalletMain);
CReserveKey reservekey(pwallet);
CAmount nFee;
int nChangePos = -1;
std::string strFailReason;
@ -293,7 +294,7 @@ static std::string SignAndSendSpecialTx(const CMutableTransaction& tx)
return sendrawtransaction(sendRequest).get_str();
}
void protx_register_fund_help()
void protx_register_fund_help(CWallet* const pwallet)
{
throw std::runtime_error(
"protx register_fund \"collateralAddress\" \"ipAndPort\" \"ownerAddress\" \"operatorPubKey\" \"votingAddress\" operatorReward \"payoutAddress\" ( \"fundAddress\" )\n"
@ -302,6 +303,7 @@ void protx_register_fund_help()
"masternode.\n"
"A few of the limitations you see in the arguments are temporary and might be lifted after DIP3\n"
"is fully deployed.\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
+ GetHelpString(1, "collateralAddress")
+ GetHelpString(2, "ipAndPort")
@ -318,13 +320,14 @@ void protx_register_fund_help()
);
}
void protx_register_help()
void protx_register_help(CWallet* const pwallet)
{
throw std::runtime_error(
"protx register \"collateralHash\" collateralIndex \"ipAndPort\" \"ownerAddress\" \"operatorPubKey\" \"votingAddress\" operatorReward \"payoutAddress\" ( \"feeSourceAddress\" )\n"
"\nSame as \"protx register_fund\", but with an externally referenced collateral.\n"
"The collateral is specified through \"collateralHash\" and \"collateralIndex\" and must be an unspent\n"
"transaction output spendable by this wallet. It must also not be used by any other masternode.\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
+ GetHelpString(1, "collateralHash")
+ GetHelpString(2, "collateralIndex")
@ -371,12 +374,13 @@ void protx_register_prepare_help()
);
}
void protx_register_submit_help()
void protx_register_submit_help(CWallet* const pwallet)
{
throw std::runtime_error(
"protx register_submit \"tx\" \"sig\"\n"
"\nSubmits the specified ProTx to the network. This command will also sign the inputs of the transaction\n"
"which were previously added by \"protx register_prepare\" to cover transaction fees\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
"1. \"tx\" (string, required) The serialized transaction previously returned by \"protx register_prepare\"\n"
"2. \"sig\" (string, required) The signature signed with the collateral key. Must be in base64 format.\n"
@ -396,13 +400,20 @@ UniValue protx_register(const JSONRPCRequest& request)
bool isPrepareRegister = request.params[0].get_str() == "register_prepare";
if (isFundRegister && (request.fHelp || (request.params.size() != 8 && request.params.size() != 9))) {
protx_register_fund_help();
protx_register_fund_help(pwallet);
} else if (isExternalRegister && (request.fHelp || (request.params.size() != 9 && request.params.size() != 10))) {
protx_register_help();
protx_register_help(pwallet);
} else if (isPrepareRegister && (request.fHelp || (request.params.size() != 9 && request.params.size() != 10))) {
protx_register_prepare_help();
}
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
if (isExternalRegister || isFundRegister) {
EnsureWalletIsUnlocked(pwallet);
}
size_t paramIdx = 1;
CAmount collateralAmount = 1000 * COIN;
@ -538,10 +549,16 @@ UniValue protx_register(const JSONRPCRequest& request)
UniValue protx_register_submit(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || request.params.size() != 3) {
protx_register_submit_help();
protx_register_submit_help(pwallet);
}
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
EnsureWalletIsUnlocked(pwallet);
CMutableTransaction tx;
if (!DecodeHexTx(tx, request.params[1].get_str())) {
throw JSONRPCError(RPC_INVALID_PARAMETER, "transaction not deserializable");
@ -563,13 +580,14 @@ UniValue protx_register_submit(const JSONRPCRequest& request)
return SignAndSendSpecialTx(tx);
}
void protx_update_service_help()
void protx_update_service_help(CWallet* const pwallet)
{
throw std::runtime_error(
"protx update_service \"proTxHash\" \"ipAndPort\" \"operatorKey\" (\"operatorPayoutAddress\" \"feeSourceAddress\" )\n"
"\nCreates and sends a ProUpServTx to the network. This will update the IP address\n"
"of a masternode.\n"
"If this is done for a masternode that got PoSe-banned, the ProUpServTx will also revive this masternode.\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
+ GetHelpString(1, "proTxHash")
+ GetHelpString(2, "ipAndPort")
@ -587,7 +605,12 @@ UniValue protx_update_service(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || (request.params.size() < 4 || request.params.size() > 6))
protx_update_service_help();
protx_update_service_help(pwallet);
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
EnsureWalletIsUnlocked(pwallet);
CProUpServTx ptx;
ptx.nVersion = CProRegTx::CURRENT_VERSION;
@ -653,13 +676,14 @@ UniValue protx_update_service(const JSONRPCRequest& request)
return SignAndSendSpecialTx(tx);
}
void protx_update_registrar_help()
void protx_update_registrar_help(CWallet* const pwallet)
{
throw std::runtime_error(
"protx update_registrar \"proTxHash\" \"operatorPubKey\" \"votingAddress\" \"payoutAddress\" ( \"feeSourceAddress\" )\n"
"\nCreates and sends a ProUpRegTx to the network. This will update the operator key, voting key and payout\n"
"address of the masternode specified by \"proTxHash\".\n"
"The owner key of the masternode must be known to your wallet.\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
+ GetHelpString(1, "proTxHash")
+ GetHelpString(2, "operatorPubKey")
@ -677,9 +701,14 @@ UniValue protx_update_registrar(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || (request.params.size() != 5 && request.params.size() != 6)) {
protx_update_registrar_help();
protx_update_registrar_help(pwallet);
}
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
EnsureWalletIsUnlocked(pwallet);
CProUpRegTx ptx;
ptx.nVersion = CProRegTx::CURRENT_VERSION;
ptx.proTxHash = ParseHashV(request.params[1], "proTxHash");
@ -706,7 +735,7 @@ UniValue protx_update_registrar(const JSONRPCRequest& request)
ptx.scriptPayout = GetScriptForDestination(payoutAddress.Get());
CKey keyOwner;
if (!pwalletMain->GetKey(dmn->pdmnState->keyIDOwner, keyOwner)) {
if (!pwallet->GetKey(dmn->pdmnState->keyIDOwner, keyOwner)) {
throw std::runtime_error(strprintf("Private key for owner address %s not found in your wallet", CBitcoinAddress(dmn->pdmnState->keyIDOwner).ToString()));
}
@ -731,7 +760,7 @@ UniValue protx_update_registrar(const JSONRPCRequest& request)
return SignAndSendSpecialTx(tx);
}
void protx_revoke_help()
void protx_revoke_help(CWallet* const pwallet)
{
throw std::runtime_error(
"protx revoke \"proTxHash\" \"operatorKey\" ( reason \"feeSourceAddress\")\n"
@ -739,6 +768,7 @@ void protx_revoke_help()
"put it into the PoSe-banned state. It will also set the service field of the masternode\n"
"to zero. Use this in case your operator key got compromised or you want to stop providing your service\n"
"to the masternode owner.\n"
+ HelpRequiringPassphrase(pwallet) + "\n"
"\nArguments:\n"
+ GetHelpString(1, "proTxHash")
+ GetHelpString(2, "operatorKey")
@ -755,9 +785,14 @@ UniValue protx_revoke(const JSONRPCRequest& request)
{
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
if (request.fHelp || (request.params.size() < 3 || request.params.size() > 5)) {
protx_revoke_help();
protx_revoke_help(pwallet);
}
if (!EnsureWalletIsAvailable(pwallet, request.fHelp))
return NullUniValue;
EnsureWalletIsUnlocked(pwallet);
CProUpRevTx ptx;
ptx.nVersion = CProRegTx::CURRENT_VERSION;
ptx.proTxHash = ParseHashV(request.params[1], "proTxHash");
@ -1097,33 +1132,16 @@ UniValue protx(const JSONRPCRequest& request)
command = request.params[0].get_str();
}
#ifdef ENABLE_WALLET
CWallet* const pwallet = GetWalletForJSONRPCRequest(request);
#else
CWallet* const pwallet = nullptr;
#endif
auto checkWallet = [&](const std::string& command) {
if (!pwallet) {
throw std::runtime_error(strprintf("%s not supported when wallet is disabled", command));
}
};
#ifdef ENABLE_WALLET
if (command == "register" || command == "register_fund" || command == "register_prepare") {
checkWallet(command);
return protx_register(request);
} if (command == "register_submit") {
checkWallet(command);
} else if (command == "register_submit") {
return protx_register_submit(request);
} else if (command == "update_service") {
checkWallet(command);
return protx_update_service(request);
} else if (command == "update_registrar") {
checkWallet(command);
return protx_update_registrar(request);
} else if (command == "revoke") {
checkWallet(command);
return protx_revoke(request);
} else
#endif