2015-05-27 18:28:55 +02:00
|
|
|
// Copyright (c) 2014-2015 The Dash Developers
|
2015-04-22 16:33:44 +02:00
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
#include "db.h"
|
|
|
|
#include "init.h"
|
|
|
|
#include "activemasternode.h"
|
|
|
|
#include "masternodeman.h"
|
|
|
|
#include "masternode-payments.h"
|
|
|
|
#include "masternode-budget.h"
|
|
|
|
#include "masternodeconfig.h"
|
|
|
|
#include "rpcserver.h"
|
|
|
|
#include "utilmoneystr.h"
|
2016-01-28 20:33:10 +01:00
|
|
|
#include <boost/lexical_cast.hpp>
|
2015-04-22 16:33:44 +02:00
|
|
|
|
|
|
|
#include <fstream>
|
|
|
|
using namespace json_spirit;
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
Value mnbudget(const Array& params, bool fHelp)
|
|
|
|
{
|
|
|
|
string strCommand;
|
|
|
|
if (params.size() >= 1)
|
|
|
|
strCommand = params[0].get_str();
|
|
|
|
|
|
|
|
if (fHelp ||
|
2016-02-01 01:44:18 +01:00
|
|
|
(strCommand != "vote-many" && strCommand != "vote-alias" && strCommand != "prepare" && strCommand != "submit" &&
|
2015-09-15 18:56:08 +02:00
|
|
|
strCommand != "vote" && strCommand != "getvotes" && strCommand != "getproposal" && strCommand != "getproposalhash" &&
|
2016-01-28 20:33:10 +01:00
|
|
|
strCommand != "list" && strCommand != "projection" && strCommand != "check" && strCommand != "nextblock" && strCommand != "nextsuperblocksize"))
|
2015-04-22 16:33:44 +02:00
|
|
|
throw runtime_error(
|
2015-09-15 18:56:08 +02:00
|
|
|
"mnbudget \"command\"...\n"
|
|
|
|
"Manage proposals\n"
|
2015-04-22 16:33:44 +02:00
|
|
|
"\nAvailable commands:\n"
|
2015-09-15 18:56:08 +02:00
|
|
|
" check - Scan proposals and remove invalid from proposals list\n"
|
|
|
|
" prepare - Prepare proposal by signing and creating tx\n"
|
|
|
|
" submit - Submit proposal to network\n"
|
|
|
|
" getproposalhash - Get proposal hash(es) by proposal name\n"
|
|
|
|
" getproposal - Show proposal\n"
|
|
|
|
" getvotes - Show detailed votes list for proposal\n"
|
|
|
|
" list - List all proposals\n"
|
|
|
|
" nextblock - Get info about next superblock for budget system\n"
|
2016-01-28 20:33:10 +01:00
|
|
|
" nextsuperblocksize - Get superblock size for a given blockheight\n"
|
2015-07-03 19:54:10 +02:00
|
|
|
" projection - Show the projection of which proposals will be paid the next cycle\n"
|
2015-09-15 18:56:08 +02:00
|
|
|
" vote - Vote on a proposal by single masternode (using dash.conf setup)\n"
|
|
|
|
" vote-many - Vote on a proposal by all masternodes (using masternode.conf setup)\n"
|
2016-02-01 01:44:18 +01:00
|
|
|
" vote-alias - Vote on a proposal by alias\n"
|
2015-04-22 16:33:44 +02:00
|
|
|
);
|
|
|
|
|
2015-08-30 01:51:31 +02:00
|
|
|
if(strCommand == "nextblock")
|
|
|
|
{
|
|
|
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
|
|
|
if(!pindexPrev) return "unknown";
|
|
|
|
|
|
|
|
int nNext = pindexPrev->nHeight - pindexPrev->nHeight % GetBudgetPaymentCycleBlocks() + GetBudgetPaymentCycleBlocks();
|
|
|
|
return nNext;
|
|
|
|
}
|
|
|
|
|
2016-01-28 20:33:10 +01:00
|
|
|
if(strCommand == "nextsuperblocksize")
|
|
|
|
{
|
|
|
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
|
|
|
if(!pindexPrev) return "unknown";
|
|
|
|
|
|
|
|
int nHeight = pindexPrev->nHeight - pindexPrev->nHeight % GetBudgetPaymentCycleBlocks() + GetBudgetPaymentCycleBlocks();
|
|
|
|
|
|
|
|
CAmount nTotal = budget.GetTotalBudget(nHeight);
|
|
|
|
return nTotal;
|
|
|
|
}
|
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
if(strCommand == "prepare")
|
2015-04-22 16:33:44 +02:00
|
|
|
{
|
2015-09-15 18:56:08 +02:00
|
|
|
if (params.size() != 7)
|
|
|
|
throw runtime_error("Correct usage is 'mnbudget prepare <proposal-name> <url> <payment-count> <block-start> <dash-address> <monthly-payment-dash>'");
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
int nBlockMin = 0;
|
|
|
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
|
|
|
|
2015-05-04 11:31:31 +02:00
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
2015-04-22 16:33:44 +02:00
|
|
|
mnEntries = masternodeConfig.getEntries();
|
|
|
|
|
2015-09-04 05:44:02 +02:00
|
|
|
std::string strProposalName = SanitizeString(params[1].get_str());
|
|
|
|
std::string strURL = SanitizeString(params[2].get_str());
|
2015-05-04 17:04:09 +02:00
|
|
|
int nPaymentCount = params[3].get_int();
|
|
|
|
int nBlockStart = params[4].get_int();
|
2015-06-16 19:04:35 +02:00
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
//set block min
|
|
|
|
if(pindexPrev != NULL) nBlockMin = pindexPrev->nHeight;
|
2015-06-16 19:04:35 +02:00
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
if(nBlockStart < nBlockMin)
|
2015-07-23 04:11:39 +02:00
|
|
|
return "Invalid block start, must be more than current height.";
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
CBitcoinAddress address(params[5].get_str());
|
2015-04-22 16:33:44 +02:00
|
|
|
if (!address.IsValid())
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address");
|
|
|
|
|
2015-05-04 11:31:31 +02:00
|
|
|
// Parse Dash address
|
|
|
|
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
2015-05-04 17:04:09 +02:00
|
|
|
CAmount nAmount = AmountFromValue(params[6]);
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
//*************************************************************************
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-28 17:55:11 +02:00
|
|
|
// create transaction 15 minutes into the future, to allow for confirmation time
|
2015-07-30 03:26:21 +02:00
|
|
|
CBudgetProposalBroadcast budgetProposalBroadcast(strProposalName, strURL, nPaymentCount, scriptPubKey, nAmount, nBlockStart, 0);
|
2015-07-14 16:05:33 +02:00
|
|
|
|
|
|
|
std::string strError = "";
|
2015-07-16 00:56:40 +02:00
|
|
|
if(!budgetProposalBroadcast.IsValid(strError, false))
|
2015-07-14 16:05:33 +02:00
|
|
|
return "Proposal is not valid - " + budgetProposalBroadcast.GetHash().ToString() + " - " + strError;
|
|
|
|
|
2015-07-30 23:27:25 +02:00
|
|
|
bool useIX = false; //true;
|
|
|
|
// if (params.size() > 7) {
|
|
|
|
// if(params[7].get_str() != "false" && params[7].get_str() != "true")
|
|
|
|
// return "Invalid use_ix, must be true or false";
|
|
|
|
// useIX = params[7].get_str() == "true" ? true : false;
|
|
|
|
// }
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
CWalletTx wtx;
|
2015-08-04 18:31:05 +02:00
|
|
|
if(!pwalletMain->GetBudgetSystemCollateralTX(wtx, budgetProposalBroadcast.GetHash(), useIX)){
|
|
|
|
return "Error making collateral transaction for proposal. Please check your wallet balance and make sure your wallet is unlocked.";
|
|
|
|
}
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
// make our change address
|
|
|
|
CReserveKey reservekey(pwalletMain);
|
|
|
|
//send the tx to the network
|
2015-07-17 17:52:55 +02:00
|
|
|
pwalletMain->CommitTransaction(wtx, reservekey, useIX ? "ix" : "tx");
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-07-30 03:26:21 +02:00
|
|
|
return wtx.GetHash().ToString();
|
2015-04-22 16:33:44 +02:00
|
|
|
}
|
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
if(strCommand == "submit")
|
2015-04-22 16:33:44 +02:00
|
|
|
{
|
2015-09-15 18:56:08 +02:00
|
|
|
if (params.size() != 8)
|
|
|
|
throw runtime_error("Correct usage is 'mnbudget submit <proposal-name> <url> <payment-count> <block-start> <dash-address> <monthly-payment-dash> <fee-tx>'");
|
|
|
|
|
|
|
|
if(!masternodeSync.IsBlockchainSynced()){
|
|
|
|
return "Must wait for client to sync with masternode network. Try again in a minute or so.";
|
|
|
|
}
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
int nBlockMin = 0;
|
|
|
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
|
|
|
|
2015-05-04 11:31:31 +02:00
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
2015-04-22 16:33:44 +02:00
|
|
|
mnEntries = masternodeConfig.getEntries();
|
|
|
|
|
2015-09-04 05:44:02 +02:00
|
|
|
std::string strProposalName = SanitizeString(params[1].get_str());
|
|
|
|
std::string strURL = SanitizeString(params[2].get_str());
|
2015-05-04 17:04:09 +02:00
|
|
|
int nPaymentCount = params[3].get_int();
|
|
|
|
int nBlockStart = params[4].get_int();
|
2015-06-16 19:04:35 +02:00
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
//set block min
|
|
|
|
if(pindexPrev != NULL) nBlockMin = pindexPrev->nHeight;
|
2015-06-16 19:04:35 +02:00
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
if(nBlockStart < nBlockMin)
|
|
|
|
return "Invalid payment count, must be more than current height.";
|
|
|
|
|
|
|
|
CBitcoinAddress address(params[5].get_str());
|
2015-04-22 16:33:44 +02:00
|
|
|
if (!address.IsValid())
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid Dash address");
|
|
|
|
|
2015-05-04 11:31:31 +02:00
|
|
|
// Parse Dash address
|
|
|
|
CScript scriptPubKey = GetScriptForDestination(address.Get());
|
2015-05-04 17:04:09 +02:00
|
|
|
CAmount nAmount = AmountFromValue(params[6]);
|
2015-09-15 18:56:08 +02:00
|
|
|
uint256 hash = ParseHashV(params[7], "Proposal hash");
|
2015-07-10 00:08:26 +02:00
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
//create the proposal incase we're the first to make it
|
2015-07-30 03:26:21 +02:00
|
|
|
CBudgetProposalBroadcast budgetProposalBroadcast(strProposalName, strURL, nPaymentCount, scriptPubKey, nAmount, nBlockStart, hash);
|
2015-07-10 00:08:26 +02:00
|
|
|
|
|
|
|
std::string strError = "";
|
2015-09-15 18:56:08 +02:00
|
|
|
|
|
|
|
if(!budgetProposalBroadcast.IsValid(strError)){
|
|
|
|
return "Proposal is not valid - " + budgetProposalBroadcast.GetHash().ToString() + " - " + strError;
|
|
|
|
}
|
|
|
|
|
2015-08-06 20:12:35 +02:00
|
|
|
int nConf = 0;
|
|
|
|
if(!IsBudgetCollateralValid(hash, budgetProposalBroadcast.GetHash(), strError, budgetProposalBroadcast.nTime, nConf)){
|
2015-08-28 23:37:53 +02:00
|
|
|
return "Proposal FeeTX is not valid - " + hash.ToString() + " - " + strError;
|
2015-07-10 00:08:26 +02:00
|
|
|
}
|
|
|
|
|
2015-07-25 18:29:29 +02:00
|
|
|
budget.mapSeenMasternodeBudgetProposals.insert(make_pair(budgetProposalBroadcast.GetHash(), budgetProposalBroadcast));
|
2015-07-08 04:35:58 +02:00
|
|
|
budgetProposalBroadcast.Relay();
|
2015-07-12 19:34:21 +02:00
|
|
|
budget.AddProposal(budgetProposalBroadcast);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
return budgetProposalBroadcast.GetHash().ToString();
|
2015-07-10 00:08:26 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "vote-many")
|
|
|
|
{
|
2015-09-15 18:56:08 +02:00
|
|
|
if(params.size() != 3)
|
|
|
|
throw runtime_error("Correct usage is 'mnbudget vote-many <proposal-hash> <yes|no>'");
|
2015-07-10 00:08:26 +02:00
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
uint256 hash;
|
|
|
|
std::string strVote;
|
2015-07-10 00:08:26 +02:00
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
hash = ParseHashV(params[1], "Proposal hash");
|
|
|
|
strVote = params[2].get_str();
|
2015-07-10 00:08:26 +02:00
|
|
|
|
|
|
|
if(strVote != "yes" && strVote != "no") return "You can only vote 'yes' or 'no'";
|
|
|
|
int nVote = VOTE_ABSTAIN;
|
|
|
|
if(strVote == "yes") nVote = VOTE_YES;
|
|
|
|
if(strVote == "no") nVote = VOTE_NO;
|
|
|
|
|
|
|
|
int success = 0;
|
|
|
|
int failed = 0;
|
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
|
|
|
mnEntries = masternodeConfig.getEntries();
|
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
Object resultsObj;
|
2015-07-10 00:08:26 +02:00
|
|
|
|
|
|
|
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
|
|
|
std::string errorMessage;
|
|
|
|
std::vector<unsigned char> vchMasterNodeSignature;
|
|
|
|
std::string strMasterNodeSignMessage;
|
|
|
|
|
|
|
|
CPubKey pubKeyCollateralAddress;
|
|
|
|
CKey keyCollateralAddress;
|
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
Object statusObj;
|
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
if(!darkSendSigner.SetKey(mne.getPrivKey(), errorMessage, keyMasternode, pubKeyMasternode)){
|
|
|
|
failed++;
|
2015-07-17 17:52:55 +02:00
|
|
|
statusObj.push_back(Pair("result", "failed"));
|
|
|
|
statusObj.push_back(Pair("errorMessage", "Masternode signing error, could not set key correctly: " + errorMessage));
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
2016-02-01 01:44:18 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMasternode* pmn = mnodeman.Find(pubKeyMasternode);
|
|
|
|
if(pmn == NULL)
|
|
|
|
{
|
|
|
|
failed++;
|
|
|
|
statusObj.push_back(Pair("result", "failed"));
|
|
|
|
statusObj.push_back(Pair("errorMessage", "Can't find masternode by pubkey"));
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CBudgetVote vote(pmn->vin, hash, nVote);
|
|
|
|
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
|
|
|
failed++;
|
|
|
|
statusObj.push_back(Pair("result", "failed"));
|
|
|
|
statusObj.push_back(Pair("errorMessage", "Failure to sign."));
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string strError = "";
|
|
|
|
if(budget.UpdateProposal(vote, NULL, strError)) {
|
|
|
|
budget.mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
|
|
|
vote.Relay();
|
|
|
|
success++;
|
|
|
|
statusObj.push_back(Pair("result", "success"));
|
|
|
|
} else {
|
|
|
|
failed++;
|
|
|
|
statusObj.push_back(Pair("result", strError.c_str()));
|
|
|
|
}
|
|
|
|
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
|
|
|
}
|
|
|
|
|
|
|
|
Object returnObj;
|
|
|
|
returnObj.push_back(Pair("overall", strprintf("Voted successfully %d time(s) and failed %d time(s).", success, failed)));
|
|
|
|
returnObj.push_back(Pair("detail", resultsObj));
|
|
|
|
|
|
|
|
return returnObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "vote-alias")
|
|
|
|
{
|
|
|
|
if(params.size() != 4)
|
|
|
|
throw runtime_error("Correct usage is 'mnbudget vote-alias <proposal-hash> <yes|no> <alias-name>'");
|
|
|
|
|
|
|
|
uint256 hash;
|
|
|
|
std::string strVote;
|
|
|
|
|
|
|
|
hash = ParseHashV(params[1], "Proposal hash");
|
|
|
|
strVote = params[2].get_str();
|
|
|
|
std::string strAlias = params[3].get_str();
|
|
|
|
|
|
|
|
if(strVote != "yes" && strVote != "no") return "You can only vote 'yes' or 'no'";
|
|
|
|
int nVote = VOTE_ABSTAIN;
|
|
|
|
if(strVote == "yes") nVote = VOTE_YES;
|
|
|
|
if(strVote == "no") nVote = VOTE_NO;
|
|
|
|
|
|
|
|
int success = 0;
|
|
|
|
int failed = 0;
|
|
|
|
|
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
|
|
|
mnEntries = masternodeConfig.getEntries();
|
|
|
|
|
|
|
|
Object resultsObj;
|
|
|
|
|
|
|
|
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
|
|
|
|
|
|
|
if( strAlias != mne.getAlias()) continue;
|
|
|
|
|
|
|
|
std::string errorMessage;
|
|
|
|
std::vector<unsigned char> vchMasterNodeSignature;
|
|
|
|
std::string strMasterNodeSignMessage;
|
|
|
|
|
|
|
|
CPubKey pubKeyCollateralAddress;
|
|
|
|
CKey keyCollateralAddress;
|
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
|
|
|
|
Object statusObj;
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(mne.getPrivKey(), errorMessage, keyMasternode, pubKeyMasternode)){
|
|
|
|
failed++;
|
|
|
|
statusObj.push_back(Pair("result", "failed"));
|
|
|
|
statusObj.push_back(Pair("errorMessage", "Masternode signing error, could not set key correctly: " + errorMessage));
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
2015-07-10 00:08:26 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMasternode* pmn = mnodeman.Find(pubKeyMasternode);
|
|
|
|
if(pmn == NULL)
|
|
|
|
{
|
|
|
|
failed++;
|
2015-07-17 17:52:55 +02:00
|
|
|
statusObj.push_back(Pair("result", "failed"));
|
|
|
|
statusObj.push_back(Pair("errorMessage", "Can't find masternode by pubkey"));
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
2015-07-10 00:08:26 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CBudgetVote vote(pmn->vin, hash, nVote);
|
|
|
|
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
2015-07-17 17:52:55 +02:00
|
|
|
failed++;
|
|
|
|
statusObj.push_back(Pair("result", "failed"));
|
|
|
|
statusObj.push_back(Pair("errorMessage", "Failure to sign."));
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
|
|
|
continue;
|
2015-07-10 00:08:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-26 16:01:49 +02:00
|
|
|
std::string strError = "";
|
|
|
|
if(budget.UpdateProposal(vote, NULL, strError)) {
|
|
|
|
budget.mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
|
|
|
vote.Relay();
|
|
|
|
success++;
|
|
|
|
statusObj.push_back(Pair("result", "success"));
|
|
|
|
} else {
|
|
|
|
failed++;
|
|
|
|
statusObj.push_back(Pair("result", strError.c_str()));
|
|
|
|
}
|
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
2015-07-10 00:08:26 +02:00
|
|
|
}
|
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
Object returnObj;
|
|
|
|
returnObj.push_back(Pair("overall", strprintf("Voted successfully %d time(s) and failed %d time(s).", success, failed)));
|
|
|
|
returnObj.push_back(Pair("detail", resultsObj));
|
|
|
|
|
|
|
|
return returnObj;
|
2015-07-10 00:08:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "vote")
|
|
|
|
{
|
|
|
|
if (params.size() != 3)
|
2015-09-15 18:56:08 +02:00
|
|
|
throw runtime_error("Correct usage is 'mnbudget vote <proposal-hash> <yes|no>'");
|
2015-07-10 00:08:26 +02:00
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
uint256 hash = ParseHashV(params[1], "Proposal hash");
|
2015-07-17 17:52:55 +02:00
|
|
|
std::string strVote = params[2].get_str();
|
2015-07-10 00:08:26 +02:00
|
|
|
|
|
|
|
if(strVote != "yes" && strVote != "no") return "You can only vote 'yes' or 'no'";
|
|
|
|
int nVote = VOTE_ABSTAIN;
|
|
|
|
if(strVote == "yes") nVote = VOTE_YES;
|
|
|
|
if(strVote == "no") nVote = VOTE_NO;
|
|
|
|
|
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
std::string errorMessage;
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
2015-07-17 17:52:55 +02:00
|
|
|
return "Error upon calling SetKey";
|
2015-07-10 00:08:26 +02:00
|
|
|
|
2015-08-04 18:31:05 +02:00
|
|
|
CMasternode* pmn = mnodeman.Find(activeMasternode.vin);
|
|
|
|
if(pmn == NULL)
|
|
|
|
{
|
|
|
|
return "Failure to find masternode in list : " + activeMasternode.vin.ToString();
|
|
|
|
}
|
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
CBudgetVote vote(activeMasternode.vin, hash, nVote);
|
2015-04-22 16:33:44 +02:00
|
|
|
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
|
|
|
return "Failure to sign.";
|
|
|
|
}
|
|
|
|
|
2015-07-26 16:01:49 +02:00
|
|
|
std::string strError = "";
|
|
|
|
if(budget.UpdateProposal(vote, NULL, strError)){
|
|
|
|
budget.mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
|
|
|
vote.Relay();
|
|
|
|
return "Voted successfully";
|
|
|
|
} else {
|
|
|
|
return "Error voting : " + strError;
|
|
|
|
}
|
2015-04-22 16:33:44 +02:00
|
|
|
}
|
|
|
|
|
2015-07-03 19:54:10 +02:00
|
|
|
if(strCommand == "projection")
|
2015-04-22 16:33:44 +02:00
|
|
|
{
|
|
|
|
Object resultObj;
|
2015-07-17 17:52:55 +02:00
|
|
|
CAmount nTotalAllotted = 0;
|
2015-04-22 16:33:44 +02:00
|
|
|
|
|
|
|
std::vector<CBudgetProposal*> winningProps = budget.GetBudget();
|
2015-07-08 04:35:58 +02:00
|
|
|
BOOST_FOREACH(CBudgetProposal* pbudgetProposal, winningProps)
|
2015-04-22 16:33:44 +02:00
|
|
|
{
|
2015-07-08 04:35:58 +02:00
|
|
|
nTotalAllotted += pbudgetProposal->GetAllotted();
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-04-30 19:11:34 +02:00
|
|
|
CTxDestination address1;
|
2015-07-08 04:35:58 +02:00
|
|
|
ExtractDestination(pbudgetProposal->GetPayee(), address1);
|
2015-04-30 19:11:34 +02:00
|
|
|
CBitcoinAddress address2(address1);
|
|
|
|
|
2015-04-22 16:33:44 +02:00
|
|
|
Object bObj;
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("URL", pbudgetProposal->GetURL()));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("Hash", pbudgetProposal->GetHash().ToString()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("BlockStart", (int64_t)pbudgetProposal->GetBlockStart()));
|
|
|
|
bObj.push_back(Pair("BlockEnd", (int64_t)pbudgetProposal->GetBlockEnd()));
|
|
|
|
bObj.push_back(Pair("TotalPaymentCount", (int64_t)pbudgetProposal->GetTotalPaymentCount()));
|
|
|
|
bObj.push_back(Pair("RemainingPaymentCount", (int64_t)pbudgetProposal->GetRemainingPaymentCount()));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("PaymentAddress", address2.ToString()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("Ratio", pbudgetProposal->GetRatio()));
|
2016-01-29 21:41:04 +01:00
|
|
|
bObj.push_back(Pair("AbsoluteYesCount", (int64_t)pbudgetProposal->GetYesCount()-(int64_t)pbudgetProposal->GetNoCount()));
|
|
|
|
bObj.push_back(Pair("YesCount", (int64_t)pbudgetProposal->GetYesCount()));
|
|
|
|
bObj.push_back(Pair("NoCount", (int64_t)pbudgetProposal->GetNoCount()));
|
|
|
|
bObj.push_back(Pair("AbstainCount", (int64_t)pbudgetProposal->GetAbstainCount()));
|
2015-07-18 17:46:44 +02:00
|
|
|
bObj.push_back(Pair("TotalPayment", ValueFromAmount(pbudgetProposal->GetAmount()*pbudgetProposal->GetTotalPaymentCount())));
|
|
|
|
bObj.push_back(Pair("MonthlyPayment", ValueFromAmount(pbudgetProposal->GetAmount())));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("Alloted", ValueFromAmount(pbudgetProposal->GetAllotted())));
|
2015-07-04 16:49:49 +02:00
|
|
|
|
|
|
|
std::string strError = "";
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("IsValid", pbudgetProposal->IsValid(strError)));
|
2015-07-28 17:55:11 +02:00
|
|
|
bObj.push_back(Pair("IsValidReason", strError.c_str()));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("fValid", pbudgetProposal->fValid));
|
2015-07-04 16:49:49 +02:00
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
resultObj.push_back(Pair(pbudgetProposal->GetName(), bObj));
|
2015-04-22 16:33:44 +02:00
|
|
|
}
|
2015-09-15 18:56:08 +02:00
|
|
|
resultObj.push_back(Pair("TotalBudgetAlloted", ValueFromAmount(nTotalAllotted)));
|
2015-04-22 16:33:44 +02:00
|
|
|
|
|
|
|
return resultObj;
|
|
|
|
}
|
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
if(strCommand == "list")
|
2015-07-03 19:54:10 +02:00
|
|
|
{
|
2015-09-15 18:56:08 +02:00
|
|
|
if (params.size() > 2)
|
|
|
|
throw runtime_error("Correct usage is 'mnbudget list [valid]'");
|
|
|
|
|
2015-07-15 00:52:07 +02:00
|
|
|
std::string strShow = "valid";
|
2015-09-15 18:56:08 +02:00
|
|
|
if (params.size() == 2) strShow = params[1].get_str();
|
|
|
|
|
2015-07-03 19:54:10 +02:00
|
|
|
Object resultObj;
|
|
|
|
int64_t nTotalAllotted = 0;
|
|
|
|
|
|
|
|
std::vector<CBudgetProposal*> winningProps = budget.GetAllProposals();
|
2015-07-08 04:35:58 +02:00
|
|
|
BOOST_FOREACH(CBudgetProposal* pbudgetProposal, winningProps)
|
2015-07-03 19:54:10 +02:00
|
|
|
{
|
2015-07-15 00:52:07 +02:00
|
|
|
if(strShow == "valid" && !pbudgetProposal->fValid) continue;
|
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
nTotalAllotted += pbudgetProposal->GetAllotted();
|
2015-07-03 19:54:10 +02:00
|
|
|
|
|
|
|
CTxDestination address1;
|
2015-07-08 04:35:58 +02:00
|
|
|
ExtractDestination(pbudgetProposal->GetPayee(), address1);
|
2015-07-03 19:54:10 +02:00
|
|
|
CBitcoinAddress address2(address1);
|
|
|
|
|
|
|
|
Object bObj;
|
2015-08-29 08:01:12 +02:00
|
|
|
bObj.push_back(Pair("Name", pbudgetProposal->GetName()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("URL", pbudgetProposal->GetURL()));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("Hash", pbudgetProposal->GetHash().ToString()));
|
|
|
|
bObj.push_back(Pair("FeeHash", pbudgetProposal->nFeeTXHash.ToString()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("BlockStart", (int64_t)pbudgetProposal->GetBlockStart()));
|
|
|
|
bObj.push_back(Pair("BlockEnd", (int64_t)pbudgetProposal->GetBlockEnd()));
|
|
|
|
bObj.push_back(Pair("TotalPaymentCount", (int64_t)pbudgetProposal->GetTotalPaymentCount()));
|
|
|
|
bObj.push_back(Pair("RemainingPaymentCount", (int64_t)pbudgetProposal->GetRemainingPaymentCount()));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("PaymentAddress", address2.ToString()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("Ratio", pbudgetProposal->GetRatio()));
|
2016-01-29 21:41:04 +01:00
|
|
|
bObj.push_back(Pair("AbsoluteYesCount", (int64_t)pbudgetProposal->GetYesCount()-(int64_t)pbudgetProposal->GetNoCount()));
|
|
|
|
bObj.push_back(Pair("YesCount", (int64_t)pbudgetProposal->GetYesCount()));
|
|
|
|
bObj.push_back(Pair("NoCount", (int64_t)pbudgetProposal->GetNoCount()));
|
|
|
|
bObj.push_back(Pair("AbstainCount", (int64_t)pbudgetProposal->GetAbstainCount()));
|
2015-07-18 17:46:44 +02:00
|
|
|
bObj.push_back(Pair("TotalPayment", ValueFromAmount(pbudgetProposal->GetAmount()*pbudgetProposal->GetTotalPaymentCount())));
|
|
|
|
bObj.push_back(Pair("MonthlyPayment", ValueFromAmount(pbudgetProposal->GetAmount())));
|
2015-07-04 16:49:49 +02:00
|
|
|
|
2015-07-28 17:55:11 +02:00
|
|
|
bObj.push_back(Pair("IsEstablished", pbudgetProposal->IsEstablished()));
|
|
|
|
|
2015-07-04 16:49:49 +02:00
|
|
|
std::string strError = "";
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("IsValid", pbudgetProposal->IsValid(strError)));
|
2015-07-28 17:55:11 +02:00
|
|
|
bObj.push_back(Pair("IsValidReason", strError.c_str()));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("fValid", pbudgetProposal->fValid));
|
2015-07-04 16:49:49 +02:00
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
resultObj.push_back(Pair(pbudgetProposal->GetName(), bObj));
|
2015-07-03 19:54:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return resultObj;
|
|
|
|
}
|
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
if(strCommand == "getproposalhash")
|
2015-04-22 16:33:44 +02:00
|
|
|
{
|
|
|
|
if (params.size() != 2)
|
2015-09-15 18:56:08 +02:00
|
|
|
throw runtime_error("Correct usage is 'mnbudget getproposalhash <proposal-name>'");
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-09-12 17:17:03 +02:00
|
|
|
std::string strProposalName = SanitizeString(params[1].get_str());
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
CBudgetProposal* pbudgetProposal = budget.FindProposal(strProposalName);
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
if(pbudgetProposal == NULL) return "Unknown proposal";
|
|
|
|
|
|
|
|
Object resultObj;
|
|
|
|
|
|
|
|
std::vector<CBudgetProposal*> winningProps = budget.GetAllProposals();
|
|
|
|
BOOST_FOREACH(CBudgetProposal* pbudgetProposal, winningProps)
|
|
|
|
{
|
|
|
|
if(pbudgetProposal->GetName() != strProposalName) continue;
|
|
|
|
if(!pbudgetProposal->fValid) continue;
|
|
|
|
|
|
|
|
CTxDestination address1;
|
|
|
|
ExtractDestination(pbudgetProposal->GetPayee(), address1);
|
|
|
|
CBitcoinAddress address2(address1);
|
|
|
|
|
2016-01-29 21:41:04 +01:00
|
|
|
resultObj.push_back(Pair(pbudgetProposal->GetHash().ToString(), pbudgetProposal->GetHash().ToString()));
|
2015-09-15 18:56:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if(resultObj.size() > 1) return resultObj;
|
|
|
|
|
|
|
|
return pbudgetProposal->GetHash().ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "getproposal")
|
|
|
|
{
|
|
|
|
if (params.size() != 2)
|
|
|
|
throw runtime_error("Correct usage is 'mnbudget getproposal <proposal-hash>'");
|
|
|
|
|
|
|
|
uint256 hash = ParseHashV(params[1], "Proposal hash");
|
|
|
|
|
|
|
|
CBudgetProposal* pbudgetProposal = budget.FindProposal(hash);
|
|
|
|
|
|
|
|
if(pbudgetProposal == NULL) return "Unknown proposal";
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-04-30 19:11:34 +02:00
|
|
|
CTxDestination address1;
|
2015-07-08 04:35:58 +02:00
|
|
|
ExtractDestination(pbudgetProposal->GetPayee(), address1);
|
2015-04-30 19:11:34 +02:00
|
|
|
CBitcoinAddress address2(address1);
|
|
|
|
|
2015-04-22 16:33:44 +02:00
|
|
|
Object obj;
|
2015-07-17 17:52:55 +02:00
|
|
|
obj.push_back(Pair("Name", pbudgetProposal->GetName()));
|
|
|
|
obj.push_back(Pair("Hash", pbudgetProposal->GetHash().ToString()));
|
|
|
|
obj.push_back(Pair("FeeHash", pbudgetProposal->nFeeTXHash.ToString()));
|
|
|
|
obj.push_back(Pair("URL", pbudgetProposal->GetURL()));
|
2015-07-08 04:35:58 +02:00
|
|
|
obj.push_back(Pair("BlockStart", (int64_t)pbudgetProposal->GetBlockStart()));
|
|
|
|
obj.push_back(Pair("BlockEnd", (int64_t)pbudgetProposal->GetBlockEnd()));
|
|
|
|
obj.push_back(Pair("TotalPaymentCount", (int64_t)pbudgetProposal->GetTotalPaymentCount()));
|
|
|
|
obj.push_back(Pair("RemainingPaymentCount", (int64_t)pbudgetProposal->GetRemainingPaymentCount()));
|
2015-07-17 17:52:55 +02:00
|
|
|
obj.push_back(Pair("PaymentAddress", address2.ToString()));
|
2015-07-08 04:35:58 +02:00
|
|
|
obj.push_back(Pair("Ratio", pbudgetProposal->GetRatio()));
|
2016-01-29 21:41:04 +01:00
|
|
|
obj.push_back(Pair("AbsoluteYesCount", (int64_t)pbudgetProposal->GetYesCount()-(int64_t)pbudgetProposal->GetNoCount()));
|
|
|
|
obj.push_back(Pair("YesCount", (int64_t)pbudgetProposal->GetYesCount()));
|
|
|
|
obj.push_back(Pair("NoCount", (int64_t)pbudgetProposal->GetNoCount()));
|
|
|
|
obj.push_back(Pair("AbstainCount", (int64_t)pbudgetProposal->GetAbstainCount()));
|
2015-07-18 17:46:44 +02:00
|
|
|
obj.push_back(Pair("TotalPayment", ValueFromAmount(pbudgetProposal->GetAmount()*pbudgetProposal->GetTotalPaymentCount())));
|
|
|
|
obj.push_back(Pair("MonthlyPayment", ValueFromAmount(pbudgetProposal->GetAmount())));
|
|
|
|
|
2015-07-28 17:55:11 +02:00
|
|
|
obj.push_back(Pair("IsEstablished", pbudgetProposal->IsEstablished()));
|
|
|
|
|
2015-07-07 00:06:09 +02:00
|
|
|
std::string strError = "";
|
2015-07-08 04:35:58 +02:00
|
|
|
obj.push_back(Pair("IsValid", pbudgetProposal->IsValid(strError)));
|
2015-07-17 17:52:55 +02:00
|
|
|
obj.push_back(Pair("fValid", pbudgetProposal->fValid));
|
2015-07-07 00:06:09 +02:00
|
|
|
|
2015-04-22 16:33:44 +02:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "getvotes")
|
|
|
|
{
|
|
|
|
if (params.size() != 2)
|
2015-09-15 18:56:08 +02:00
|
|
|
throw runtime_error("Correct usage is 'mnbudget getvotes <proposal-hash>'");
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
uint256 hash = ParseHashV(params[1], "Proposal hash");
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
Object obj;
|
2015-07-06 22:23:09 +02:00
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
CBudgetProposal* pbudgetProposal = budget.FindProposal(hash);
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
if(pbudgetProposal == NULL) return "Unknown proposal";
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
std::map<uint256, CBudgetVote>::iterator it = pbudgetProposal->mapVotes.begin();
|
|
|
|
while(it != pbudgetProposal->mapVotes.end()){
|
2015-07-17 16:38:35 +02:00
|
|
|
|
|
|
|
Object bObj;
|
2015-08-08 19:36:01 +02:00
|
|
|
bObj.push_back(Pair("nHash", (*it).first.ToString().c_str()));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("Vote", (*it).second.GetVoteString()));
|
2015-07-17 16:38:35 +02:00
|
|
|
bObj.push_back(Pair("nTime", (int64_t)(*it).second.nTime));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("fValid", (*it).second.fValid));
|
2015-07-17 16:38:35 +02:00
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
obj.push_back(Pair((*it).second.vin.prevout.ToStringShort(), bObj));
|
2015-07-17 16:38:35 +02:00
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
it++;
|
|
|
|
}
|
2015-07-06 22:23:09 +02:00
|
|
|
|
2015-04-22 16:33:44 +02:00
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
2015-07-06 22:23:09 +02:00
|
|
|
if(strCommand == "check")
|
|
|
|
{
|
|
|
|
budget.CheckAndRemove();
|
|
|
|
|
|
|
|
return "Success";
|
|
|
|
}
|
|
|
|
|
2015-04-22 16:33:44 +02:00
|
|
|
return Value::null;
|
|
|
|
}
|
|
|
|
|
2015-09-23 02:15:23 +02:00
|
|
|
Value mnbudgetvoteraw(const Array& params, bool fHelp)
|
|
|
|
{
|
|
|
|
if (fHelp || params.size() != 6)
|
|
|
|
throw runtime_error(
|
|
|
|
"mnbudgetvoteraw <masternode-tx-hash> <masternode-tx-index> <proposal-hash> <yes|no> <time> <vote-sig>\n"
|
|
|
|
"Compile and relay a proposal vote with provided external signature instead of signing vote internally\n"
|
|
|
|
);
|
|
|
|
|
|
|
|
uint256 hashMnTx = ParseHashV(params[0], "mn tx hash");
|
|
|
|
int nMnTxIndex = params[1].get_int();
|
|
|
|
CTxIn vin = CTxIn(hashMnTx, nMnTxIndex);
|
|
|
|
|
|
|
|
uint256 hashProposal = ParseHashV(params[2], "Proposal hash");
|
|
|
|
std::string strVote = params[3].get_str();
|
|
|
|
|
|
|
|
if(strVote != "yes" && strVote != "no") return "You can only vote 'yes' or 'no'";
|
|
|
|
int nVote = VOTE_ABSTAIN;
|
|
|
|
if(strVote == "yes") nVote = VOTE_YES;
|
|
|
|
if(strVote == "no") nVote = VOTE_NO;
|
|
|
|
|
|
|
|
int64_t nTime = params[4].get_int64();
|
|
|
|
std::string strSig = params[5].get_str();
|
|
|
|
bool fInvalid = false;
|
|
|
|
vector<unsigned char> vchSig = DecodeBase64(strSig.c_str(), &fInvalid);
|
|
|
|
|
|
|
|
if (fInvalid)
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
|
|
|
|
|
|
|
|
CMasternode* pmn = mnodeman.Find(vin);
|
|
|
|
if(pmn == NULL)
|
|
|
|
{
|
|
|
|
return "Failure to find masternode in list : " + vin.ToString();
|
|
|
|
}
|
|
|
|
|
|
|
|
CBudgetVote vote(vin, hashProposal, nVote);
|
|
|
|
vote.nTime = nTime;
|
|
|
|
vote.vchSig = vchSig;
|
|
|
|
|
|
|
|
if(!vote.SignatureValid(true)){
|
|
|
|
return "Failure to verify signature.";
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string strError = "";
|
|
|
|
if(budget.UpdateProposal(vote, NULL, strError)){
|
|
|
|
budget.mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
|
|
|
vote.Relay();
|
|
|
|
return "Voted successfully";
|
|
|
|
} else {
|
|
|
|
return "Error voting : " + strError;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
Value mnfinalbudget(const Array& params, bool fHelp)
|
|
|
|
{
|
|
|
|
string strCommand;
|
|
|
|
if (params.size() >= 1)
|
|
|
|
strCommand = params[0].get_str();
|
|
|
|
|
|
|
|
if (fHelp ||
|
2015-09-15 18:56:08 +02:00
|
|
|
(strCommand != "vote-many" && strCommand != "vote" && strCommand != "list" && strCommand != "getvotes"))
|
2015-05-04 17:04:09 +02:00
|
|
|
throw runtime_error(
|
2015-09-15 18:56:08 +02:00
|
|
|
"mnfinalbudget \"command\"...\n"
|
|
|
|
"Manage current budgets\n"
|
2015-05-04 17:04:09 +02:00
|
|
|
"\nAvailable commands:\n"
|
2015-09-15 18:56:08 +02:00
|
|
|
" list - List existing finalized budgets\n"
|
|
|
|
" vote - Vote on a finalized budget by single masternode (using dash.conf setup)\n"
|
|
|
|
" vote-many - Vote on a finalized budget by all masternodes (using masternode.conf setup)\n"
|
|
|
|
" getvotes - Get vote information for each finalized budget\n"
|
2015-05-04 17:04:09 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
if(strCommand == "vote-many")
|
|
|
|
{
|
|
|
|
if (params.size() != 2)
|
2015-09-15 18:56:08 +02:00
|
|
|
throw runtime_error("Correct usage is 'mnfinalbudget vote-many <budget-hash>'");
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
std::string strHash = params[1].get_str();
|
|
|
|
uint256 hash(strHash);
|
|
|
|
|
|
|
|
int success = 0;
|
|
|
|
int failed = 0;
|
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
|
|
|
mnEntries = masternodeConfig.getEntries();
|
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
Object resultsObj;
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
|
|
|
|
std::string errorMessage;
|
|
|
|
std::vector<unsigned char> vchMasterNodeSignature;
|
|
|
|
std::string strMasterNodeSignMessage;
|
|
|
|
|
|
|
|
CPubKey pubKeyCollateralAddress;
|
|
|
|
CKey keyCollateralAddress;
|
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
Object statusObj;
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
if(!darkSendSigner.SetKey(mne.getPrivKey(), errorMessage, keyMasternode, pubKeyMasternode)){
|
|
|
|
failed++;
|
2015-07-17 17:52:55 +02:00
|
|
|
statusObj.push_back(Pair("result", "failed"));
|
|
|
|
statusObj.push_back(Pair("errorMessage", "Masternode signing error, could not set key correctly: " + errorMessage));
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
2015-05-04 17:04:09 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMasternode* pmn = mnodeman.Find(pubKeyMasternode);
|
|
|
|
if(pmn == NULL)
|
|
|
|
{
|
|
|
|
failed++;
|
2015-07-17 17:52:55 +02:00
|
|
|
statusObj.push_back(Pair("result", "failed"));
|
|
|
|
statusObj.push_back(Pair("errorMessage", "Can't find masternode by pubkey"));
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
2015-05-04 17:04:09 +02:00
|
|
|
continue;
|
2015-07-06 22:23:09 +02:00
|
|
|
}
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
|
|
|
|
CFinalizedBudgetVote vote(pmn->vin, hash);
|
|
|
|
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
|
|
|
failed++;
|
2015-07-17 17:52:55 +02:00
|
|
|
statusObj.push_back(Pair("result", "failed"));
|
|
|
|
statusObj.push_back(Pair("errorMessage", "Failure to sign."));
|
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
2015-05-04 17:04:09 +02:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-07-26 16:01:49 +02:00
|
|
|
std::string strError = "";
|
|
|
|
if(budget.UpdateFinalizedBudget(vote, NULL, strError)){
|
|
|
|
budget.mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
|
|
|
vote.Relay();
|
|
|
|
success++;
|
|
|
|
statusObj.push_back(Pair("result", "success"));
|
|
|
|
} else {
|
|
|
|
failed++;
|
|
|
|
statusObj.push_back(Pair("result", strError.c_str()));
|
|
|
|
}
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
resultsObj.push_back(Pair(mne.getAlias(), statusObj));
|
2015-05-04 17:04:09 +02:00
|
|
|
}
|
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
Object returnObj;
|
|
|
|
returnObj.push_back(Pair("overall", strprintf("Voted successfully %d time(s) and failed %d time(s).", success, failed)));
|
|
|
|
returnObj.push_back(Pair("detail", resultsObj));
|
|
|
|
|
|
|
|
return returnObj;
|
2015-05-04 17:04:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "vote")
|
|
|
|
{
|
|
|
|
if (params.size() != 2)
|
2015-09-15 18:56:08 +02:00
|
|
|
throw runtime_error("Correct usage is 'mnfinalbudget vote <budget-hash>'");
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
std::string strHash = params[1].get_str();
|
|
|
|
uint256 hash(strHash);
|
|
|
|
|
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
std::string errorMessage;
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
2015-07-17 17:52:55 +02:00
|
|
|
return "Error upon calling SetKey";
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-08-04 18:31:05 +02:00
|
|
|
CMasternode* pmn = mnodeman.Find(activeMasternode.vin);
|
|
|
|
if(pmn == NULL)
|
|
|
|
{
|
|
|
|
return "Failure to find masternode in list : " + activeMasternode.vin.ToString();
|
|
|
|
}
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
CFinalizedBudgetVote vote(activeMasternode.vin, hash);
|
|
|
|
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
|
|
|
return "Failure to sign.";
|
|
|
|
}
|
|
|
|
|
2015-07-26 16:01:49 +02:00
|
|
|
std::string strError = "";
|
|
|
|
if(budget.UpdateFinalizedBudget(vote, NULL, strError)){
|
|
|
|
budget.mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
|
|
|
vote.Relay();
|
|
|
|
return "success";
|
|
|
|
} else {
|
|
|
|
return "Error voting : " + strError;
|
|
|
|
}
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-09-15 18:56:08 +02:00
|
|
|
if(strCommand == "list")
|
2015-05-04 17:04:09 +02:00
|
|
|
{
|
|
|
|
Object resultObj;
|
|
|
|
|
|
|
|
std::vector<CFinalizedBudget*> winningFbs = budget.GetFinalizedBudgets();
|
2015-07-08 04:35:58 +02:00
|
|
|
BOOST_FOREACH(CFinalizedBudget* finalizedBudget, winningFbs)
|
2015-05-04 17:04:09 +02:00
|
|
|
{
|
|
|
|
Object bObj;
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("FeeTX", finalizedBudget->nFeeTXHash.ToString()));
|
|
|
|
bObj.push_back(Pair("Hash", finalizedBudget->GetHash().ToString()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("BlockStart", (int64_t)finalizedBudget->GetBlockStart()));
|
|
|
|
bObj.push_back(Pair("BlockEnd", (int64_t)finalizedBudget->GetBlockEnd()));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("Proposals", finalizedBudget->GetProposals()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("VoteCount", (int64_t)finalizedBudget->GetVoteCount()));
|
2015-07-17 17:52:55 +02:00
|
|
|
bObj.push_back(Pair("Status", finalizedBudget->GetStatus()));
|
2015-08-08 21:35:28 +02:00
|
|
|
|
|
|
|
std::string strError = "";
|
|
|
|
bObj.push_back(Pair("IsValid", finalizedBudget->IsValid(strError)));
|
|
|
|
bObj.push_back(Pair("IsValidReason", strError.c_str()));
|
2015-08-08 22:10:38 +02:00
|
|
|
|
2015-07-17 17:52:55 +02:00
|
|
|
resultObj.push_back(Pair(finalizedBudget->GetName(), bObj));
|
2015-05-04 17:04:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return resultObj;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-08-08 19:36:01 +02:00
|
|
|
if(strCommand == "getvotes")
|
|
|
|
{
|
|
|
|
if (params.size() != 2)
|
2015-09-15 18:56:08 +02:00
|
|
|
throw runtime_error("Correct usage is 'mnbudget getvotes <budget-hash>'");
|
2015-08-08 19:36:01 +02:00
|
|
|
|
|
|
|
std::string strHash = params[1].get_str();
|
|
|
|
uint256 hash(strHash);
|
|
|
|
|
|
|
|
Object obj;
|
|
|
|
|
|
|
|
CFinalizedBudget* pfinalBudget = budget.FindFinalizedBudget(hash);
|
|
|
|
|
|
|
|
if(pfinalBudget == NULL) return "Unknown budget hash";
|
|
|
|
|
|
|
|
std::map<uint256, CFinalizedBudgetVote>::iterator it = pfinalBudget->mapVotes.begin();
|
|
|
|
while(it != pfinalBudget->mapVotes.end()){
|
|
|
|
|
|
|
|
Object bObj;
|
|
|
|
bObj.push_back(Pair("nHash", (*it).first.ToString().c_str()));
|
|
|
|
bObj.push_back(Pair("nTime", (int64_t)(*it).second.nTime));
|
|
|
|
bObj.push_back(Pair("fValid", (*it).second.fValid));
|
|
|
|
|
|
|
|
obj.push_back(Pair((*it).second.vin.prevout.ToStringShort(), bObj));
|
|
|
|
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
return Value::null;
|
|
|
|
}
|