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"
|
|
|
|
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#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 ||
|
2015-07-10 00:08:26 +02:00
|
|
|
(strCommand != "vote-many" && strCommand != "prepare" && strCommand != "submit" && strCommand != "vote" && strCommand != "getvotes" && strCommand != "getinfo" && strCommand != "show" && strCommand != "projection" && strCommand != "check"))
|
2015-04-22 16:33:44 +02:00
|
|
|
throw runtime_error(
|
|
|
|
"mnbudget \"command\"... ( \"passphrase\" )\n"
|
|
|
|
"Vote or show current budgets\n"
|
|
|
|
"\nAvailable commands:\n"
|
2015-07-10 00:08:26 +02:00
|
|
|
" prepare - Prepare proposal for network by signing and creating tx\n"
|
|
|
|
" submit - Submit proposal for network\n"
|
2015-05-04 17:04:09 +02:00
|
|
|
" vote-many - Vote on a Dash initiative\n"
|
|
|
|
" vote-alias - Vote on a Dash initiative\n"
|
|
|
|
" vote - Vote on a Dash initiative/budget\n"
|
|
|
|
" getvotes - Show current masternode budgets\n"
|
|
|
|
" getinfo - Show current masternode budgets\n"
|
|
|
|
" show - Show all budgets\n"
|
2015-07-03 19:54:10 +02:00
|
|
|
" projection - Show the projection of which proposals will be paid the next cycle\n"
|
2015-07-06 22:23:09 +02:00
|
|
|
" check - Scan proposals and remove invalid\n"
|
2015-04-22 16:33:44 +02:00
|
|
|
);
|
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
if(strCommand == "prepare")
|
2015-04-22 16:33:44 +02:00
|
|
|
{
|
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-07-12 16:45:58 +02:00
|
|
|
if (params.size() != 8 && params.size() != 9)
|
|
|
|
throw runtime_error("Correct usage of vote-many is 'mnbudget prepare PROPOSAL-NAME URL PAYMENT_COUNT BLOCK_START DASH_ADDRESS DASH_AMOUNT YES|NO|ABSTAIN [USE_IX(TRUE|FALSE)]'");
|
2015-04-22 16:33:44 +02:00
|
|
|
|
|
|
|
std::string strProposalName = params[1].get_str();
|
|
|
|
if(strProposalName.size() > 20)
|
|
|
|
return "Invalid proposal name, limit of 20 characters.";
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
std::string strURL = params[2].get_str();
|
|
|
|
if(strURL.size() > 64)
|
|
|
|
return "Invalid url, limit of 64 characters.";
|
|
|
|
|
|
|
|
int nPaymentCount = params[3].get_int();
|
|
|
|
if(nPaymentCount < 1)
|
|
|
|
return "Invalid payment count, must be more than zero.";
|
|
|
|
|
|
|
|
//set block min
|
2015-05-26 16:56:51 +02:00
|
|
|
if(pindexPrev != NULL) nBlockMin = pindexPrev->nHeight - GetBudgetPaymentCycleBlocks()*(nPaymentCount+1);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
int nBlockStart = params[4].get_int();
|
2015-06-16 19:04:35 +02:00
|
|
|
if(nBlockStart % GetBudgetPaymentCycleBlocks() != 0){
|
|
|
|
int nNext = pindexPrev->nHeight-(pindexPrev->nHeight % GetBudgetPaymentCycleBlocks())+GetBudgetPaymentCycleBlocks();
|
2015-07-10 00:08:26 +02:00
|
|
|
return "Invalid block start - must be a budget cycle block. Next valid block: " + boost::lexical_cast<std::string>(nNext);
|
2015-06-16 19:04:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int nBlockEnd = nBlockStart + (GetBudgetPaymentCycleBlocks()*nPaymentCount);
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
if(nBlockStart < nBlockMin)
|
|
|
|
return "Invalid payment count, must be more than current height.";
|
|
|
|
|
2015-06-16 19:04:35 +02:00
|
|
|
if(nBlockEnd < pindexPrev->nHeight)
|
|
|
|
return "Invalid ending block, starting block + (payment_cycle*payments) 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-07-12 16:45:58 +02:00
|
|
|
std::string strVote = params[7].get_str().c_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;
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
std::string errorMessage;
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
|
|
|
return(" Error upon calling SetKey");
|
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-10 00:08:26 +02:00
|
|
|
CBudgetProposalBroadcast budgetProposalBroadcast(strProposalName, strURL, nPaymentCount, scriptPubKey, nAmount, nBlockStart, 0);
|
2015-07-12 16:45:58 +02:00
|
|
|
std::string strCommand = "tx";
|
2015-07-12 08:09:51 +02:00
|
|
|
bool useIX = true;
|
2015-07-12 16:45:58 +02:00
|
|
|
if (params.size() > 8)
|
|
|
|
useIX = (params[8].get_str() == "true" ? true : false);
|
|
|
|
|
|
|
|
if(useIX)
|
|
|
|
{
|
|
|
|
strCommand = "ix";
|
|
|
|
}
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
CWalletTx wtx;
|
2015-07-12 16:45:58 +02:00
|
|
|
pwalletMain->GetBudgetSystemCollateralTX(wtx, budgetProposalBroadcast.GetHash(), useIX);
|
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
|
|
|
|
pwalletMain->CommitTransaction(wtx, reservekey, strCommand);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
return wtx.GetHash().ToString().c_str();
|
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-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-07-12 16:45:58 +02:00
|
|
|
if (params.size() != 9)
|
|
|
|
throw runtime_error("Correct usage of vote-many is 'mnbudget submit PROPOSAL-NAME URL PAYMENT_COUNT BLOCK_START DASH_ADDRESS DASH_AMOUNT YES|NO|ABSTAIN FEE_TX'");
|
2015-07-10 00:08:26 +02:00
|
|
|
|
|
|
|
// Check these inputs the same way we check the vote commands:
|
|
|
|
// **********************************************************
|
2015-04-22 16:33:44 +02:00
|
|
|
|
|
|
|
std::string strProposalName = params[1].get_str();
|
|
|
|
if(strProposalName.size() > 20)
|
|
|
|
return "Invalid proposal name, limit of 20 characters.";
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
std::string strURL = params[2].get_str();
|
|
|
|
if(strURL.size() > 64)
|
|
|
|
return "Invalid url, limit of 64 characters.";
|
|
|
|
|
|
|
|
int nPaymentCount = params[3].get_int();
|
|
|
|
if(nPaymentCount < 1)
|
|
|
|
return "Invalid payment count, must be more than zero.";
|
|
|
|
|
|
|
|
//set block min
|
2015-05-26 16:56:51 +02:00
|
|
|
if(pindexPrev != NULL) nBlockMin = pindexPrev->nHeight - GetBudgetPaymentCycleBlocks()*(nPaymentCount+1);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
int nBlockStart = params[4].get_int();
|
2015-06-16 19:04:35 +02:00
|
|
|
if(nBlockStart % GetBudgetPaymentCycleBlocks() != 0){
|
|
|
|
int nNext = pindexPrev->nHeight-(pindexPrev->nHeight % GetBudgetPaymentCycleBlocks())+GetBudgetPaymentCycleBlocks();
|
|
|
|
return "Invalid block start - must be a budget cycle block. Next valid block: " + boost::lexical_cast<std::string>(nNext);
|
|
|
|
}
|
|
|
|
|
|
|
|
int nBlockEnd = nBlockStart + (GetBudgetPaymentCycleBlocks()*nPaymentCount);
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
if(nBlockStart < nBlockMin)
|
|
|
|
return "Invalid payment count, must be more than current height.";
|
|
|
|
|
2015-06-16 19:04:35 +02:00
|
|
|
if(nBlockEnd < pindexPrev->nHeight)
|
|
|
|
return "Invalid ending block, starting block + (payment_cycle*payments) 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-07-12 16:45:58 +02:00
|
|
|
std::string strVote = params[7].get_str().c_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;
|
2015-04-22 16:33:44 +02:00
|
|
|
|
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
std::string errorMessage;
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
|
|
|
return(" Error upon calling SetKey");
|
|
|
|
|
2015-07-12 16:45:58 +02:00
|
|
|
uint256 hash = ParseHashV(params[8], "parameter 1");
|
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-10 00:08:26 +02:00
|
|
|
CBudgetProposalBroadcast budgetProposalBroadcast(strProposalName, strURL, nPaymentCount, scriptPubKey, nAmount, nBlockStart, hash);
|
|
|
|
|
|
|
|
std::string strError = "";
|
|
|
|
if(!IsBudgetCollateralValid(hash ,strError)){
|
|
|
|
return "Proposal FeeTX is not valid - " + hash.ToString() + " - " + strError;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!budgetProposalBroadcast.IsValid(strError)){
|
|
|
|
return "Proposal is not valid - " + budgetProposalBroadcast.GetHash().ToString() + " - " + strError;
|
2015-05-04 17:04:09 +02:00
|
|
|
}
|
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
mapSeenMasternodeBudgetProposals.insert(make_pair(budgetProposalBroadcast.GetHash(), budgetProposalBroadcast));
|
|
|
|
budgetProposalBroadcast.Relay();
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-07-12 16:45:58 +02:00
|
|
|
return budgetProposalBroadcast.GetHash().ToString().c_str();
|
2015-07-10 00:08:26 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "vote-many")
|
|
|
|
{
|
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
|
|
|
mnEntries = masternodeConfig.getEntries();
|
|
|
|
|
|
|
|
if (params.size() != 3)
|
2015-07-12 16:45:58 +02:00
|
|
|
throw runtime_error("Correct usage of vote-many is 'mnbudget vote-many PROPOSAL-HASH YES|NO|ABSTAIN'");
|
2015-07-10 00:08:26 +02:00
|
|
|
|
|
|
|
uint256 hash = ParseHashV(params[1], "parameter 1");
|
|
|
|
std::string strVote = params[2].get_str().c_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;
|
|
|
|
|
|
|
|
Object resultObj;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(mne.getPrivKey(), errorMessage, keyMasternode, pubKeyMasternode)){
|
|
|
|
printf(" Error upon calling SetKey for %s\n", mne.getAlias().c_str());
|
|
|
|
failed++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMasternode* pmn = mnodeman.Find(pubKeyMasternode);
|
|
|
|
if(pmn == NULL)
|
|
|
|
{
|
|
|
|
printf("Can't find masternode by pubkey for %s\n", mne.getAlias().c_str());
|
|
|
|
failed++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CBudgetVote vote(pmn->vin, hash, nVote);
|
|
|
|
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
|
|
|
return "Failure to sign.";
|
|
|
|
}
|
|
|
|
|
|
|
|
mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
|
|
|
vote.Relay();
|
|
|
|
|
|
|
|
success++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return("Voted successfully " + boost::lexical_cast<std::string>(success) + " time(s) and failed " + boost::lexical_cast<std::string>(failed) + " time(s).");
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "vote")
|
|
|
|
{
|
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
|
|
|
mnEntries = masternodeConfig.getEntries();
|
|
|
|
|
|
|
|
if (params.size() != 3)
|
2015-07-12 16:45:58 +02:00
|
|
|
throw runtime_error("Correct usage of vote is 'mnbudget vote PROPOSAL-HASH YES|NO|ABSTAIN'");
|
2015-07-10 00:08:26 +02:00
|
|
|
|
|
|
|
uint256 hash = ParseHashV(params[1], "parameter 1");
|
|
|
|
std::string strVote = params[2].get_str().c_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;
|
|
|
|
|
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
std::string errorMessage;
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
|
|
|
return(" Error upon calling SetKey");
|
|
|
|
|
|
|
|
CBudgetVote vote(activeMasternode.vin, hash, nVote);
|
2015-04-22 16:33:44 +02:00
|
|
|
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
|
|
|
return "Failure to sign.";
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:28:55 +02:00
|
|
|
mapSeenMasternodeBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
2015-05-04 11:31:31 +02:00
|
|
|
vote.Relay();
|
2015-07-02 18:41:33 +02:00
|
|
|
budget.UpdateProposal(vote, NULL);
|
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-04-30 21:54:34 +02:00
|
|
|
int64_t 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()));
|
|
|
|
bObj.push_back(Pair("Hash", pbudgetProposal->GetHash().ToString().c_str()));
|
|
|
|
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-05-04 17:04:09 +02:00
|
|
|
bObj.push_back(Pair("PaymentAddress", address2.ToString().c_str()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("Ratio", pbudgetProposal->GetRatio()));
|
|
|
|
bObj.push_back(Pair("Yeas", (int64_t)pbudgetProposal->GetYeas()));
|
|
|
|
bObj.push_back(Pair("Nays", (int64_t)pbudgetProposal->GetNays()));
|
|
|
|
bObj.push_back(Pair("Abstains", (int64_t)pbudgetProposal->GetAbstains()));
|
|
|
|
bObj.push_back(Pair("Alloted", (int64_t)pbudgetProposal->GetAllotted()));
|
2015-04-30 21:54:34 +02:00
|
|
|
bObj.push_back(Pair("TotalBudgetAlloted", nTotalAllotted));
|
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-04 16:49:49 +02:00
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
resultObj.push_back(Pair(pbudgetProposal->GetName().c_str(), bObj));
|
2015-04-22 16:33:44 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return resultObj;
|
|
|
|
}
|
|
|
|
|
2015-07-03 19:54:10 +02:00
|
|
|
if(strCommand == "show")
|
|
|
|
{
|
|
|
|
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-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-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("URL", pbudgetProposal->GetURL()));
|
|
|
|
bObj.push_back(Pair("Hash", pbudgetProposal->GetHash().ToString().c_str()));
|
|
|
|
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-03 19:54:10 +02:00
|
|
|
bObj.push_back(Pair("PaymentAddress", address2.ToString().c_str()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("Ratio", pbudgetProposal->GetRatio()));
|
|
|
|
bObj.push_back(Pair("Yeas", (int64_t)pbudgetProposal->GetYeas()));
|
|
|
|
bObj.push_back(Pair("Nays", (int64_t)pbudgetProposal->GetNays()));
|
|
|
|
bObj.push_back(Pair("Abstains", (int64_t)pbudgetProposal->GetAbstains()));
|
|
|
|
bObj.push_back(Pair("Amount", (int64_t)pbudgetProposal->GetAmount()));
|
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-04 16:49:49 +02:00
|
|
|
|
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
resultObj.push_back(Pair(pbudgetProposal->GetName().c_str(), bObj));
|
2015-07-03 19:54:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return resultObj;
|
|
|
|
}
|
|
|
|
|
2015-04-22 16:33:44 +02:00
|
|
|
if(strCommand == "getinfo")
|
|
|
|
{
|
|
|
|
if (params.size() != 2)
|
|
|
|
throw runtime_error("Correct usage of getinfo is 'mnbudget getinfo profilename'");
|
|
|
|
|
|
|
|
std::string strProposalName = params[1].get_str();
|
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
CBudgetProposal* pbudgetProposal = budget.FindProposal(strProposalName);
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
if(pbudgetProposal == NULL) return "Unknown proposal name";
|
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-08 04:35:58 +02:00
|
|
|
obj.push_back(Pair("Name", pbudgetProposal->GetName().c_str()));
|
|
|
|
obj.push_back(Pair("Hash", pbudgetProposal->GetHash().ToString().c_str()));
|
|
|
|
obj.push_back(Pair("URL", pbudgetProposal->GetURL().c_str()));
|
|
|
|
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-04-30 19:11:34 +02:00
|
|
|
obj.push_back(Pair("PaymentAddress", address2.ToString().c_str()));
|
2015-07-08 04:35:58 +02:00
|
|
|
obj.push_back(Pair("Ratio", pbudgetProposal->GetRatio()));
|
|
|
|
obj.push_back(Pair("Yeas", (int64_t)pbudgetProposal->GetYeas()));
|
|
|
|
obj.push_back(Pair("Nays", (int64_t)pbudgetProposal->GetNays()));
|
|
|
|
obj.push_back(Pair("Abstains", (int64_t)pbudgetProposal->GetAbstains()));
|
|
|
|
obj.push_back(Pair("Alloted", (int64_t)pbudgetProposal->GetAllotted()));
|
2015-04-22 16:33:44 +02:00
|
|
|
|
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-07 00:06:09 +02:00
|
|
|
|
2015-04-22 16:33:44 +02:00
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "getvotes")
|
|
|
|
{
|
|
|
|
if (params.size() != 2)
|
|
|
|
throw runtime_error("Correct usage of getvotes is 'mnbudget getinfo profilename'");
|
|
|
|
|
|
|
|
std::string strProposalName = params[1].get_str();
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
Object obj;
|
2015-07-06 22:23:09 +02:00
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
CBudgetProposal* pbudgetProposal = budget.FindProposal(strProposalName);
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
if(pbudgetProposal == NULL) return "Unknown proposal name";
|
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-05-04 17:04:09 +02:00
|
|
|
obj.push_back(Pair((*it).second.vin.prevout.ToStringShort().c_str(), (*it).second.GetVoteString().c_str()));
|
|
|
|
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-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 ||
|
|
|
|
(strCommand != "suggest" && strCommand != "vote-many" && strCommand != "vote" && strCommand != "show"))
|
|
|
|
throw runtime_error(
|
|
|
|
"mnbudget \"command\"... ( \"passphrase\" )\n"
|
|
|
|
"Vote or show current budgets\n"
|
|
|
|
"\nAvailable commands:\n"
|
|
|
|
" suggest - Suggest a budget to be paid\n"
|
|
|
|
" vote-many - Vote on a finalized budget\n"
|
|
|
|
" vote - Vote on a finalized budget\n"
|
|
|
|
" show - Show existing finalized budgets\n"
|
|
|
|
);
|
|
|
|
|
|
|
|
if(strCommand == "suggest")
|
|
|
|
{
|
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
|
|
|
mnEntries = masternodeConfig.getEntries();
|
2015-07-06 22:23:09 +02:00
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
|
|
|
if(!pindexPrev)
|
|
|
|
return "Must be synced to suggest";
|
|
|
|
|
|
|
|
if (params.size() < 3)
|
2015-05-26 16:56:51 +02:00
|
|
|
throw runtime_error("Correct usage of suggest is 'mnfinalbudget suggest BUDGET_NAME PROPNAME [PROP2 PROP3 PROP4]'");
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
std::string strBudgetName = params[1].get_str();
|
|
|
|
if(strBudgetName.size() > 20)
|
|
|
|
return "Invalid budget name, limit of 20 characters.";
|
|
|
|
|
2015-05-26 16:56:51 +02:00
|
|
|
int nBlockStart = pindexPrev->nHeight-(pindexPrev->nHeight % GetBudgetPaymentCycleBlocks())+GetBudgetPaymentCycleBlocks();
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-05-30 22:12:12 +02:00
|
|
|
std::vector<CTxBudgetPayment> vecPayments;
|
2015-05-26 16:56:51 +02:00
|
|
|
for(int i = 2; i < (int)params.size(); i++)
|
2015-05-04 17:04:09 +02:00
|
|
|
{
|
2015-05-26 16:56:51 +02:00
|
|
|
std::string strHash = params[i].get_str();
|
2015-05-04 17:04:09 +02:00
|
|
|
uint256 hash(strHash);
|
2015-07-08 04:35:58 +02:00
|
|
|
CBudgetProposal* pbudgetProposal = budget.FindProposal(hash);
|
|
|
|
if(!pbudgetProposal){
|
2015-05-30 22:12:12 +02:00
|
|
|
return "Invalid proposal " + strHash + ". Please check the proposal hash";
|
|
|
|
} else {
|
|
|
|
CTxBudgetPayment out;
|
|
|
|
out.nProposalHash = hash;
|
2015-07-08 04:35:58 +02:00
|
|
|
out.payee = pbudgetProposal->GetPayee();
|
|
|
|
out.nAmount = pbudgetProposal->GetAmount();
|
2015-05-30 22:12:12 +02:00
|
|
|
vecPayments.push_back(out);
|
|
|
|
}
|
2015-05-04 17:04:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
std::string errorMessage;
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
|
|
|
return(" Error upon calling SetKey");
|
|
|
|
|
2015-07-10 00:08:26 +02:00
|
|
|
//create transaction
|
|
|
|
uint256 hash = 0;
|
|
|
|
|
2015-05-04 17:04:09 +02:00
|
|
|
//create the proposal incase we're the first to make it
|
2015-07-10 00:08:26 +02:00
|
|
|
CFinalizedBudgetBroadcast finalizedBudgetBroadcast(strBudgetName, nBlockStart, vecPayments, hash);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
if(!finalizedBudgetBroadcast.IsValid())
|
|
|
|
return "Invalid finalized budget broadcast (are all the hashes correct?)";
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
mapSeenFinalizedBudgets.insert(make_pair(finalizedBudgetBroadcast.GetHash(), finalizedBudgetBroadcast));
|
|
|
|
finalizedBudgetBroadcast.Relay();
|
|
|
|
budget.AddFinalizedBudget(finalizedBudgetBroadcast);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-07-08 04:35:58 +02:00
|
|
|
CFinalizedBudgetVote vote(activeMasternode.vin, finalizedBudgetBroadcast.GetHash());
|
2015-05-04 17:04:09 +02:00
|
|
|
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
|
|
|
return "Failure to sign.";
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:28:55 +02:00
|
|
|
mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
2015-05-04 17:04:09 +02:00
|
|
|
vote.Relay();
|
2015-07-02 18:41:33 +02:00
|
|
|
budget.UpdateFinalizedBudget(vote, NULL);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
return "success";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "vote-many")
|
|
|
|
{
|
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
|
|
|
mnEntries = masternodeConfig.getEntries();
|
|
|
|
|
|
|
|
if (params.size() != 2)
|
|
|
|
throw runtime_error("Correct usage of vote-many is 'mnfinalbudget vote-many BUDGET_HASH'");
|
|
|
|
|
|
|
|
std::string strHash = params[1].get_str();
|
|
|
|
uint256 hash(strHash);
|
|
|
|
|
|
|
|
int success = 0;
|
|
|
|
int failed = 0;
|
|
|
|
|
|
|
|
Object resultObj;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(mne.getPrivKey(), errorMessage, keyMasternode, pubKeyMasternode)){
|
|
|
|
printf(" Error upon calling SetKey for %s\n", mne.getAlias().c_str());
|
|
|
|
failed++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
CMasternode* pmn = mnodeman.Find(pubKeyMasternode);
|
|
|
|
if(pmn == NULL)
|
|
|
|
{
|
|
|
|
printf("Can't find masternode by pubkey for %s\n", mne.getAlias().c_str());
|
|
|
|
failed++;
|
|
|
|
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++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:28:55 +02:00
|
|
|
mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
2015-05-04 17:04:09 +02:00
|
|
|
vote.Relay();
|
2015-07-02 18:41:33 +02:00
|
|
|
budget.UpdateFinalizedBudget(vote, NULL);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
success++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return("Voted successfully " + boost::lexical_cast<std::string>(success) + " time(s) and failed " + boost::lexical_cast<std::string>(failed) + " time(s).");
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "vote")
|
|
|
|
{
|
|
|
|
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
|
|
|
|
mnEntries = masternodeConfig.getEntries();
|
|
|
|
|
|
|
|
if (params.size() != 2)
|
|
|
|
throw runtime_error("Correct usage of vote is 'mnfinalbudget vote BUDGET_HASH'");
|
|
|
|
|
|
|
|
std::string strHash = params[1].get_str();
|
|
|
|
uint256 hash(strHash);
|
|
|
|
|
|
|
|
CPubKey pubKeyMasternode;
|
|
|
|
CKey keyMasternode;
|
|
|
|
std::string errorMessage;
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
|
|
|
|
return(" Error upon calling SetKey");
|
|
|
|
|
|
|
|
CFinalizedBudgetVote vote(activeMasternode.vin, hash);
|
|
|
|
if(!vote.Sign(keyMasternode, pubKeyMasternode)){
|
|
|
|
return "Failure to sign.";
|
|
|
|
}
|
|
|
|
|
2015-05-27 18:28:55 +02:00
|
|
|
mapSeenFinalizedBudgetVotes.insert(make_pair(vote.GetHash(), vote));
|
2015-05-04 17:04:09 +02:00
|
|
|
vote.Relay();
|
2015-07-02 18:41:33 +02:00
|
|
|
budget.UpdateFinalizedBudget(vote, NULL);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
|
|
|
return "success";
|
|
|
|
}
|
|
|
|
|
|
|
|
if(strCommand == "show")
|
|
|
|
{
|
|
|
|
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-10 00:08:26 +02:00
|
|
|
bObj.push_back(Pair("FeeTX", finalizedBudget->nFeeTXHash.ToString().c_str()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("Hash", finalizedBudget->GetHash().ToString().c_str()));
|
|
|
|
bObj.push_back(Pair("BlockStart", (int64_t)finalizedBudget->GetBlockStart()));
|
|
|
|
bObj.push_back(Pair("BlockEnd", (int64_t)finalizedBudget->GetBlockEnd()));
|
2015-07-10 00:08:26 +02:00
|
|
|
bObj.push_back(Pair("Proposals", finalizedBudget->GetProposals().c_str()));
|
2015-07-08 04:35:58 +02:00
|
|
|
bObj.push_back(Pair("VoteCount", (int64_t)finalizedBudget->GetVoteCount()));
|
|
|
|
bObj.push_back(Pair("Status", finalizedBudget->GetStatus().c_str()));
|
|
|
|
resultObj.push_back(Pair(finalizedBudget->GetName().c_str(), bObj));
|
2015-05-04 17:04:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return resultObj;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return Value::null;
|
|
|
|
}
|