2016-08-17 09:08:25 +02:00
// Copyright (c) 2014-2016 The Dash Core developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
//#define ENABLE_DASH_DEBUG
# include "util.h"
# include "main.h"
# include "db.h"
# include "init.h"
# include "activemasternode.h"
# include "darksend.h"
# include "governance.h"
# include "darksend.h"
2016-10-17 20:54:28 +02:00
# include "masternode.h"
2016-08-17 09:08:25 +02:00
# include "masternode-payments.h"
# include "masternode-sync.h"
# include "masternodeconfig.h"
# include "masternodeman.h"
# include "rpcserver.h"
# include "utilmoneystr.h"
# include "governance-vote.h"
2016-08-28 21:15:48 +02:00
# include "governance-classes.h"
2016-08-17 09:08:25 +02:00
# include <boost/lexical_cast.hpp>
# include <fstream>
# include <iostream>
# include <sstream>
using namespace std ;
UniValue gobject ( const UniValue & params , bool fHelp )
{
2016-09-12 09:40:00 +02:00
std : : string strCommand ;
2016-08-17 09:08:25 +02:00
if ( params . size ( ) > = 1 )
strCommand = params [ 0 ] . get_str ( ) ;
if ( fHelp | |
2016-09-11 19:58:17 +02:00
( strCommand ! = " vote-many " & & strCommand ! = " vote-conf " & & strCommand ! = " vote-alias " & & strCommand ! = " prepare " & & strCommand ! = " submit " & &
2016-09-07 14:02:24 +02:00
strCommand ! = " vote " & & strCommand ! = " get " & & strCommand ! = " getvotes " & & strCommand ! = " list " & & strCommand ! = " diff " & & strCommand ! = " deserialize " ) )
2016-09-12 09:40:00 +02:00
throw std : : runtime_error (
2016-08-17 09:08:25 +02:00
" gobject \" command \" ... \n "
" Manage governance objects \n "
" \n Available commands: \n "
2016-09-12 09:40:00 +02:00
" prepare - Prepare governance object by signing and creating tx \n "
" submit - Submit governance object to network \n "
" get - Get governance object by hash \n "
" getvotes - Get votes for a governance object hash \n "
" list - List all governance objects \n "
2016-08-17 09:08:25 +02:00
" diff - List differences since last diff \n "
2016-09-12 09:40:00 +02:00
" vote-alias - Vote on a governance object by masternode alias (using masternode.conf setup) \n "
2016-08-17 09:08:25 +02:00
" vote-conf - Vote on a governance object by masternode configured in dash.conf \n "
2016-09-12 09:40:00 +02:00
" vote-many - Vote on a governance object by all masternodes (using masternode.conf setup) \n "
2016-08-17 09:08:25 +02:00
) ;
2016-09-12 09:40:00 +02:00
2016-08-17 09:08:25 +02:00
/*
2016-09-12 09:40:00 +02:00
- - - - - - Example Governance Item - - - - - -
2016-08-17 09:08:25 +02:00
gobject submit 6e622 bb41bad1fb18e7f23ae96770aeb33129e18bd9efe790522488e580a0a03 0 1 1464292854 " beer-reimbursement " 5 b5b22636f6e7472616374222c207b2270726f6a6563745f6e616d65223a20225c22626565722d7265696d62757273656d656e745c22222c20227061796d656e745f61646472657373223a20225c225879324c4b4a4a64655178657948726e34744744514238626a6876464564615576375c22222c2022656e645f64617465223a202231343936333030343030222c20226465736372697074696f6e5f75726c223a20225c227777772e646173687768616c652e6f72672f702f626565722d7265696d62757273656d656e745c22222c2022636f6e74726163745f75726c223a20225c22626565722d7265696d62757273656d656e742e636f6d2f3030312e7064665c22222c20227061796d656e745f616d6f756e74223a20223233342e323334323232222c2022676f7665726e616e63655f6f626a6563745f6964223a2037342c202273746172745f64617465223a202231343833323534303030227d5d5d1
*/
// DEBUG : TEST DESERIALIZATION OF GOVERNANCE META DATA
if ( strCommand = = " deserialize " )
{
std : : string strHex = params [ 1 ] . get_str ( ) ;
2016-09-12 09:40:00 +02:00
std : : vector < unsigned char > v = ParseHex ( strHex ) ;
std : : string s ( v . begin ( ) , v . end ( ) ) ;
2016-08-17 09:08:25 +02:00
UniValue u ( UniValue : : VOBJ ) ;
u . read ( s ) ;
return u . write ( ) . c_str ( ) ;
}
// PREPARE THE GOVERNANCE OBJECT BY CREATING A COLLATERAL TRANSACTION
if ( strCommand = = " prepare " )
{
2016-09-17 21:37:48 +02:00
if ( params . size ( ) ! = 5 ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Correct usage is 'gobject prepare <parent-hash> <revision> <time> <data-hex>' " ) ;
2016-09-15 08:49:24 +02:00
}
2016-08-17 09:08:25 +02:00
// ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
2016-10-22 18:52:36 +02:00
CBlockIndex * pindex = NULL ;
{
LOCK ( cs_main ) ;
2016-10-22 23:01:30 +02:00
pindex = chainActive . Tip ( ) ;
2016-10-22 18:52:36 +02:00
}
2016-08-17 09:08:25 +02:00
std : : vector < CMasternodeConfig : : CMasternodeEntry > mnEntries ;
mnEntries = masternodeConfig . getEntries ( ) ;
uint256 hashParent ;
// -- attach to root node (root node doesn't really exist, but has a hash of zero)
2016-09-12 09:40:00 +02:00
if ( params [ 1 ] . get_str ( ) = = " 0 " ) {
2016-08-17 09:08:25 +02:00
hashParent = uint256 ( ) ;
} else {
2016-09-12 09:40:00 +02:00
hashParent = ParseHashV ( params [ 1 ] , " fee-txid, parameter 1 " ) ;
2016-08-17 09:08:25 +02:00
}
std : : string strRevision = params [ 2 ] . get_str ( ) ;
std : : string strTime = params [ 3 ] . get_str ( ) ;
int nRevision = boost : : lexical_cast < int > ( strRevision ) ;
int nTime = boost : : lexical_cast < int > ( strTime ) ;
2016-09-17 21:37:48 +02:00
std : : string strData = params [ 4 ] . get_str ( ) ;
2016-09-12 09:40:00 +02:00
2016-08-17 09:08:25 +02:00
// CREATE A NEW COLLATERAL TRANSACTION FOR THIS SPECIFIC OBJECT
2016-09-17 21:37:48 +02:00
CGovernanceObject govobj ( hashParent , nRevision , nTime , uint256 ( ) , strData ) ;
2016-08-17 09:08:25 +02:00
2016-10-17 20:54:28 +02:00
if ( ( govobj . GetObjectType ( ) = = GOVERNANCE_OBJECT_TRIGGER ) | |
( govobj . GetObjectType ( ) = = GOVERNANCE_OBJECT_WATCHDOG ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Trigger and watchdog objects need not be prepared (however only masternodes can create them) " ) ;
2016-09-15 08:49:24 +02:00
}
2016-08-17 09:08:25 +02:00
std : : string strError = " " ;
if ( ! govobj . IsValidLocally ( pindex , strError , false ) )
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Governance object is not valid - " + govobj . GetHash ( ) . ToString ( ) + " - " + strError ) ;
CWalletTx wtx ;
2016-09-05 01:44:10 +02:00
if ( ! pwalletMain - > GetBudgetSystemCollateralTX ( wtx , govobj . GetHash ( ) , govobj . GetMinCollateralFee ( ) , false ) ) {
2016-09-12 09:40:00 +02:00
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Error making collateral transaction for governance object. Please check your wallet balance and make sure your wallet is unlocked. " ) ;
2016-08-17 09:08:25 +02:00
}
2016-09-12 09:40:00 +02:00
2016-08-17 09:08:25 +02:00
// -- make our change address
CReserveKey reservekey ( pwalletMain ) ;
// -- send the tx to the network
pwalletMain - > CommitTransaction ( wtx , reservekey , NetMsgType : : TX ) ;
2016-09-17 21:37:48 +02:00
DBG ( cout < < " gobject: prepare "
< < " strData = " < < govobj . GetDataAsString ( )
2016-08-17 09:08:25 +02:00
< < " , hash = " < < govobj . GetHash ( ) . GetHex ( )
2016-09-12 09:40:00 +02:00
< < " , txidFee = " < < wtx . GetHash ( ) . GetHex ( )
2016-08-17 09:08:25 +02:00
< < endl ; ) ;
return wtx . GetHash ( ) . ToString ( ) ;
}
// AFTER COLLATERAL TRANSACTION HAS MATURED USER CAN SUBMIT GOVERNANCE OBJECT TO PROPAGATE NETWORK
if ( strCommand = = " submit " )
{
2016-09-17 21:37:48 +02:00
if ( ( params . size ( ) < 5 ) | | ( params . size ( ) > 6 ) ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Correct usage is 'gobject submit <parent-hash> <revision> <time> <data-hex> <fee-txid>' " ) ;
2016-09-05 01:44:10 +02:00
}
2016-08-17 09:08:25 +02:00
if ( ! masternodeSync . IsBlockchainSynced ( ) ) {
throw JSONRPCError ( RPC_CLIENT_IN_INITIAL_DOWNLOAD , " Must wait for client to sync with masternode network. Try again in a minute or so. " ) ;
}
2016-09-05 01:44:10 +02:00
CMasternode mn ;
2016-09-15 08:49:24 +02:00
bool mnFound = mnodeman . Get ( activeMasternode . vin , mn ) ;
2016-09-05 01:44:10 +02:00
DBG ( cout < < " gobject: submit activeMasternode.pubKeyMasternode = " < < activeMasternode . pubKeyMasternode . GetHash ( ) . ToString ( )
2016-10-31 10:11:57 +01:00
< < " , vin = " < < activeMasternode . vin . prevout . ToStringShort ( )
2016-09-05 01:44:10 +02:00
< < " , params.size() = " < < params . size ( )
< < " , mnFound = " < < mnFound < < endl ; ) ;
2016-08-17 09:08:25 +02:00
// ASSEMBLE NEW GOVERNANCE OBJECT FROM USER PARAMETERS
2016-10-22 18:52:36 +02:00
CBlockIndex * pindex = NULL ;
{
LOCK ( cs_main ) ;
2016-10-22 23:01:30 +02:00
pindex = chainActive . Tip ( ) ;
2016-10-22 18:52:36 +02:00
}
2016-08-17 09:08:25 +02:00
2016-09-12 09:40:00 +02:00
uint256 txidFee ;
2016-08-17 09:08:25 +02:00
2016-09-17 21:37:48 +02:00
if ( params . size ( ) = = 6 ) {
txidFee = ParseHashV ( params [ 5 ] , " fee-txid, parameter 6 " ) ;
2016-09-05 01:44:10 +02:00
}
2016-08-17 09:08:25 +02:00
uint256 hashParent ;
2016-09-05 01:44:10 +02:00
if ( params [ 1 ] . get_str ( ) = = " 0 " ) { // attach to root node (root node doesn't really exist, but has a hash of zero)
2016-08-17 09:08:25 +02:00
hashParent = uint256 ( ) ;
} else {
2016-09-05 01:44:10 +02:00
hashParent = ParseHashV ( params [ 1 ] , " parent object hash, parameter 2 " ) ;
2016-08-17 09:08:25 +02:00
}
// GET THE PARAMETERS FROM USER
2016-09-05 01:44:10 +02:00
std : : string strRevision = params [ 2 ] . get_str ( ) ;
std : : string strTime = params [ 3 ] . get_str ( ) ;
2016-08-17 09:08:25 +02:00
int nRevision = boost : : lexical_cast < int > ( strRevision ) ;
int nTime = boost : : lexical_cast < int > ( strTime ) ;
2016-09-17 21:37:48 +02:00
std : : string strData = params [ 4 ] . get_str ( ) ;
2016-08-17 09:08:25 +02:00
2016-09-17 21:37:48 +02:00
CGovernanceObject govobj ( hashParent , nRevision , nTime , txidFee , strData ) ;
2016-08-17 09:08:25 +02:00
2016-09-17 21:37:48 +02:00
DBG ( cout < < " gobject: submit "
< < " strData = " < < govobj . GetDataAsString ( )
2016-08-17 09:08:25 +02:00
< < " , hash = " < < govobj . GetHash ( ) . GetHex ( )
2016-09-12 09:40:00 +02:00
< < " , txidFee = " < < txidFee . GetHex ( )
2016-08-17 09:08:25 +02:00
< < endl ; ) ;
2016-09-05 01:44:10 +02:00
// Attempt to sign triggers if we are a MN
2016-10-17 20:54:28 +02:00
if ( ( govobj . GetObjectType ( ) = = GOVERNANCE_OBJECT_TRIGGER ) | |
( govobj . GetObjectType ( ) = = GOVERNANCE_OBJECT_WATCHDOG ) ) {
2016-09-09 17:52:10 +02:00
if ( mnFound ) {
2016-09-15 08:49:24 +02:00
govobj . SetMasternodeInfo ( mn . vin ) ;
govobj . Sign ( activeMasternode . keyMasternode , activeMasternode . pubKeyMasternode ) ;
2016-09-09 17:52:10 +02:00
}
else {
2016-09-15 08:49:24 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Only valid masternodes can submit this type of object " ) ;
}
}
else {
2016-09-17 21:37:48 +02:00
if ( params . size ( ) ! = 6 ) {
2016-09-15 08:49:24 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " The fee-txid parameter must be included to submit this type of object " ) ;
2016-09-09 17:52:10 +02:00
}
2016-09-05 01:44:10 +02:00
}
2016-08-17 09:08:25 +02:00
std : : string strError = " " ;
2016-09-05 01:44:10 +02:00
if ( ! govobj . IsValidLocally ( pindex , strError , true ) ) {
2016-08-17 09:08:25 +02:00
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Governance object is not valid - " + govobj . GetHash ( ) . ToString ( ) + " - " + strError ) ;
}
// RELAY THIS OBJECT
governance . AddSeenGovernanceObject ( govobj . GetHash ( ) , SEEN_OBJECT_IS_VALID ) ;
govobj . Relay ( ) ;
governance . AddGovernanceObject ( govobj ) ;
return govobj . GetHash ( ) . ToString ( ) ;
}
if ( strCommand = = " vote-conf " )
{
if ( params . size ( ) ! = 4 )
2016-09-16 09:43:15 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Correct usage is 'gobject vote-conf <governance-hash> [funding|valid|delete] [yes|no|abstain]' " ) ;
2016-08-17 09:08:25 +02:00
uint256 hash ;
std : : string strVote ;
hash = ParseHashV ( params [ 1 ] , " Object hash " ) ;
2016-09-12 09:40:00 +02:00
std : : string strVoteSignal = params [ 2 ] . get_str ( ) ;
2016-08-17 09:08:25 +02:00
std : : string strVoteOutcome = params [ 3 ] . get_str ( ) ;
2016-09-12 09:40:00 +02:00
vote_signal_enum_t eVoteSignal = CGovernanceVoting : : ConvertVoteSignal ( strVoteSignal ) ;
2016-09-08 13:40:19 +02:00
if ( eVoteSignal = = VOTE_SIGNAL_NONE ) {
2016-09-12 09:40:00 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER ,
2016-09-08 13:40:19 +02:00
" Invalid vote signal. Please using one of the following: "
2016-09-12 09:40:00 +02:00
" (funding|valid|delete|endorsed) OR `custom sentinel code` " ) ;
2016-09-08 13:40:19 +02:00
}
2016-08-17 09:08:25 +02:00
2016-09-08 13:40:19 +02:00
vote_outcome_enum_t eVoteOutcome = CGovernanceVoting : : ConvertVoteOutcome ( strVoteOutcome ) ;
if ( eVoteOutcome = = VOTE_OUTCOME_NONE ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain' " ) ;
}
2016-08-17 09:08:25 +02:00
int success = 0 ;
int failed = 0 ;
UniValue resultsObj ( UniValue : : VOBJ ) ;
std : : vector < unsigned char > vchMasterNodeSignature ;
std : : string strMasterNodeSignMessage ;
UniValue statusObj ( UniValue : : VOBJ ) ;
2016-09-12 03:17:41 +02:00
UniValue returnObj ( UniValue : : VOBJ ) ;
2016-08-17 09:08:25 +02:00
2016-09-18 23:11:03 +02:00
CMasternode mn ;
bool mnFound = mnodeman . Get ( activeMasternode . vin , mn ) ;
if ( ! mnFound ) {
2016-08-17 09:08:25 +02:00
failed + + ;
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
2016-09-18 23:11:03 +02:00
statusObj . push_back ( Pair ( " errorMessage " , " Can't find masternode by collateral output " ) ) ;
2016-08-17 09:08:25 +02:00
resultsObj . push_back ( Pair ( " dash.conf " , statusObj ) ) ;
2016-09-12 03:17:41 +02:00
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 ;
2016-08-17 09:08:25 +02:00
}
2016-09-18 23:11:03 +02:00
CGovernanceVote vote ( mn . vin , hash , eVoteSignal , eVoteOutcome ) ;
if ( ! vote . Sign ( activeMasternode . keyMasternode , activeMasternode . pubKeyMasternode ) ) {
2016-08-17 09:08:25 +02:00
failed + + ;
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
statusObj . push_back ( Pair ( " errorMessage " , " Failure to sign. " ) ) ;
resultsObj . push_back ( Pair ( " dash.conf " , statusObj ) ) ;
2016-09-12 03:17:41 +02:00
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 ;
2016-08-17 09:08:25 +02:00
}
2016-11-13 18:52:34 +01:00
CGovernanceException exception ;
if ( governance . ProcessVote ( vote , exception ) ) {
2016-08-17 09:08:25 +02:00
success + + ;
statusObj . push_back ( Pair ( " result " , " success " ) ) ;
2016-11-13 18:52:34 +01:00
}
else {
2016-08-17 09:08:25 +02:00
failed + + ;
2016-09-12 03:17:41 +02:00
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
2016-11-13 18:52:34 +01:00
statusObj . push_back ( Pair ( " errorMessage " , exception . GetMessage ( ) ) ) ;
2016-08-17 09:08:25 +02:00
}
resultsObj . push_back ( Pair ( " dash.conf " , statusObj ) ) ;
returnObj . push_back ( Pair ( " overall " , strprintf ( " Voted successfully %d time(s) and failed %d time(s). " , success , failed ) ) ) ;
returnObj . push_back ( Pair ( " detail " , resultsObj ) ) ;
2016-09-11 19:58:17 +02:00
return returnObj ;
}
if ( strCommand = = " vote-many " )
{
if ( params . size ( ) ! = 4 )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Correct usage is 'gobject vote-many <governance-hash> [funding|valid|delete] [yes|no|abstain]' " ) ;
uint256 hash ;
std : : string strVote ;
hash = ParseHashV ( params [ 1 ] , " Object hash " ) ;
2016-09-12 09:40:00 +02:00
std : : string strVoteSignal = params [ 2 ] . get_str ( ) ;
2016-09-11 19:58:17 +02:00
std : : string strVoteOutcome = params [ 3 ] . get_str ( ) ;
2016-09-12 09:40:00 +02:00
vote_signal_enum_t eVoteSignal = CGovernanceVoting : : ConvertVoteSignal ( strVoteSignal ) ;
2016-09-11 19:58:17 +02:00
if ( eVoteSignal = = VOTE_SIGNAL_NONE ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER ,
" Invalid vote signal. Please using one of the following: "
" (funding|valid|delete|endorsed) OR `custom sentinel code` " ) ;
}
vote_outcome_enum_t eVoteOutcome = CGovernanceVoting : : ConvertVoteOutcome ( strVoteOutcome ) ;
if ( eVoteOutcome = = VOTE_OUTCOME_NONE ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain' " ) ;
}
int success = 0 ;
int failed = 0 ;
std : : vector < CMasternodeConfig : : CMasternodeEntry > mnEntries ;
mnEntries = masternodeConfig . getEntries ( ) ;
UniValue resultsObj ( UniValue : : VOBJ ) ;
BOOST_FOREACH ( CMasternodeConfig : : CMasternodeEntry mne , masternodeConfig . getEntries ( ) ) {
2016-09-12 09:40:00 +02:00
std : : string strError ;
2016-09-11 19:58:17 +02:00
std : : vector < unsigned char > vchMasterNodeSignature ;
std : : string strMasterNodeSignMessage ;
CPubKey pubKeyCollateralAddress ;
CKey keyCollateralAddress ;
CPubKey pubKeyMasternode ;
CKey keyMasternode ;
UniValue statusObj ( UniValue : : VOBJ ) ;
if ( ! darkSendSigner . GetKeysFromSecret ( mne . getPrivKey ( ) , keyMasternode , pubKeyMasternode ) ) {
failed + + ;
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
2016-09-12 09:40:00 +02:00
statusObj . push_back ( Pair ( " errorMessage " , " Masternode signing error, could not set key correctly " ) ) ;
2016-09-11 19:58:17 +02:00
resultsObj . push_back ( Pair ( mne . getAlias ( ) , statusObj ) ) ;
continue ;
}
2016-09-18 23:11:03 +02:00
uint256 nTxHash ;
nTxHash . SetHex ( mne . getTxHash ( ) ) ;
int nOutputIndex = 0 ;
if ( ! ParseInt32 ( mne . getOutputIndex ( ) , & nOutputIndex ) ) {
continue ;
}
CTxIn vin ( COutPoint ( nTxHash , nOutputIndex ) ) ;
CMasternode mn ;
bool mnFound = mnodeman . Get ( vin , mn ) ;
if ( ! mnFound ) {
2016-09-11 19:58:17 +02:00
failed + + ;
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
2016-09-18 23:11:03 +02:00
statusObj . push_back ( Pair ( " errorMessage " , " Can't find masternode by collateral output " ) ) ;
2016-09-11 19:58:17 +02:00
resultsObj . push_back ( Pair ( mne . getAlias ( ) , statusObj ) ) ;
continue ;
}
2016-09-18 23:11:03 +02:00
CGovernanceVote vote ( mn . vin , hash , eVoteSignal , eVoteOutcome ) ;
2016-09-11 19:58:17 +02:00
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 ;
}
2016-11-13 18:52:34 +01:00
CGovernanceException exception ;
if ( governance . ProcessVote ( vote , exception ) ) {
2016-09-11 19:58:17 +02:00
success + + ;
statusObj . push_back ( Pair ( " result " , " success " ) ) ;
2016-11-13 18:52:34 +01:00
}
else {
2016-09-11 19:58:17 +02:00
failed + + ;
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
2016-11-13 18:52:34 +01:00
statusObj . push_back ( Pair ( " errorMessage " , exception . GetMessage ( ) ) ) ;
2016-09-11 19:58:17 +02:00
}
resultsObj . push_back ( Pair ( mne . getAlias ( ) , statusObj ) ) ;
}
UniValue returnObj ( UniValue : : VOBJ ) ;
returnObj . push_back ( Pair ( " overall " , strprintf ( " Voted successfully %d time(s) and failed %d time(s). " , success , failed ) ) ) ;
returnObj . push_back ( Pair ( " detail " , resultsObj ) ) ;
2016-08-17 09:08:25 +02:00
return returnObj ;
}
// MASTERNODES CAN VOTE ON GOVERNANCE OBJECTS ON THE NETWORK FOR VARIOUS SIGNALS AND OUTCOMES
if ( strCommand = = " vote-alias " )
{
if ( params . size ( ) ! = 5 )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Correct usage is 'gobject vote-alias <governance-hash> [funding|valid|delete] [yes|no|abstain] <alias-name>' " ) ;
uint256 hash ;
std : : string strVote ;
// COLLECT NEEDED PARAMETRS FROM USER
hash = ParseHashV ( params [ 1 ] , " Object hash " ) ;
2016-09-12 09:40:00 +02:00
std : : string strVoteSignal = params [ 2 ] . get_str ( ) ;
2016-08-17 09:08:25 +02:00
std : : string strVoteOutcome = params [ 3 ] . get_str ( ) ;
std : : string strAlias = params [ 4 ] . get_str ( ) ;
2016-09-12 09:40:00 +02:00
2016-08-17 09:08:25 +02:00
// CONVERT NAMED SIGNAL/ACTION AND CONVERT
2016-09-12 09:40:00 +02:00
vote_signal_enum_t eVoteSignal = CGovernanceVoting : : ConvertVoteSignal ( strVoteSignal ) ;
2016-09-08 13:40:19 +02:00
if ( eVoteSignal = = VOTE_SIGNAL_NONE ) {
2016-09-12 09:40:00 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER ,
2016-09-08 13:40:19 +02:00
" Invalid vote signal. Please using one of the following: "
2016-09-12 09:40:00 +02:00
" (funding|valid|delete|endorsed) OR `custom sentinel code` " ) ;
2016-09-08 13:40:19 +02:00
}
2016-08-17 09:08:25 +02:00
2016-09-08 13:40:19 +02:00
vote_outcome_enum_t eVoteOutcome = CGovernanceVoting : : ConvertVoteOutcome ( strVoteOutcome ) ;
if ( eVoteOutcome = = VOTE_OUTCOME_NONE ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain' " ) ;
}
2016-08-17 09:08:25 +02:00
// EXECUTE VOTE FOR EACH MASTERNODE, COUNT SUCCESSES VS FAILURES
int success = 0 ;
int failed = 0 ;
std : : vector < CMasternodeConfig : : CMasternodeEntry > mnEntries ;
mnEntries = masternodeConfig . getEntries ( ) ;
UniValue resultsObj ( UniValue : : VOBJ ) ;
BOOST_FOREACH ( CMasternodeConfig : : CMasternodeEntry mne , masternodeConfig . getEntries ( ) )
{
// IF WE HAVE A SPECIFIC NODE REQUESTED TO VOTE, DO THAT
2016-09-18 23:11:03 +02:00
if ( strAlias ! = mne . getAlias ( ) ) continue ;
2016-08-17 09:08:25 +02:00
// INIT OUR NEEDED VARIABLES TO EXECUTE THE VOTE
2016-09-12 09:40:00 +02:00
std : : string strError ;
2016-08-17 09:08:25 +02:00
std : : vector < unsigned char > vchMasterNodeSignature ;
std : : string strMasterNodeSignMessage ;
CPubKey pubKeyCollateralAddress ;
CKey keyCollateralAddress ;
CPubKey pubKeyMasternode ;
CKey keyMasternode ;
// SETUP THE SIGNING KEY FROM MASTERNODE.CONF ENTRY
UniValue statusObj ( UniValue : : VOBJ ) ;
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . GetKeysFromSecret ( mne . getPrivKey ( ) , keyMasternode , pubKeyMasternode ) ) {
2016-08-17 09:08:25 +02:00
failed + + ;
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
2016-08-19 13:50:04 +02:00
statusObj . push_back ( Pair ( " errorMessage " , strprintf ( " Invalid masternode key %s. " , mne . getPrivKey ( ) ) ) ) ;
2016-08-17 09:08:25 +02:00
resultsObj . push_back ( Pair ( mne . getAlias ( ) , statusObj ) ) ;
continue ;
}
// SEARCH FOR THIS MASTERNODE ON THE NETWORK, THE NODE MUST BE ACTIVE TO VOTE
2016-09-18 23:11:03 +02:00
uint256 nTxHash ;
nTxHash . SetHex ( mne . getTxHash ( ) ) ;
int nOutputIndex = 0 ;
if ( ! ParseInt32 ( mne . getOutputIndex ( ) , & nOutputIndex ) ) {
continue ;
}
CTxIn vin ( COutPoint ( nTxHash , nOutputIndex ) ) ;
CMasternode mn ;
bool mnFound = mnodeman . Get ( vin , mn ) ;
if ( ! mnFound ) {
2016-08-17 09:08:25 +02:00
failed + + ;
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
statusObj . push_back ( Pair ( " errorMessage " , " Masternode must be publically available on network to vote. Masternode not found. " ) ) ;
resultsObj . push_back ( Pair ( mne . getAlias ( ) , statusObj ) ) ;
continue ;
}
// CREATE NEW GOVERNANCE OBJECT VOTE WITH OUTCOME/SIGNAL
2016-09-18 23:11:03 +02:00
CGovernanceVote vote ( vin , hash , eVoteSignal , eVoteOutcome ) ;
if ( ! vote . Sign ( keyMasternode , pubKeyMasternode ) ) {
2016-08-17 09:08:25 +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 ;
}
// UPDATE LOCAL DATABASE WITH NEW OBJECT SETTINGS
2016-11-13 18:52:34 +01:00
CGovernanceException exception ;
if ( governance . ProcessVote ( vote , exception ) ) {
2016-08-17 09:08:25 +02:00
success + + ;
statusObj . push_back ( Pair ( " result " , " success " ) ) ;
2016-11-13 18:52:34 +01:00
}
else {
2016-08-17 09:08:25 +02:00
failed + + ;
2016-09-12 03:17:41 +02:00
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
2016-11-13 18:52:34 +01:00
statusObj . push_back ( Pair ( " errorMessage " , exception . GetMessage ( ) ) ) ;
2016-08-17 09:08:25 +02:00
}
resultsObj . push_back ( Pair ( mne . getAlias ( ) , statusObj ) ) ;
}
// REPORT STATS TO THE USER
UniValue returnObj ( UniValue : : VOBJ ) ;
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 ;
}
// USERS CAN QUERY THE SYSTEM FOR A LIST OF VARIOUS GOVERNANCE ITEMS
if ( strCommand = = " list " | | strCommand = = " diff " )
{
if ( params . size ( ) > 2 )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Correct usage is 'gobject [list|diff] [valid]' " ) ;
// GET MAIN PARAMETER FOR THIS MODE, VALID OR ALL?
std : : string strShow = " valid " ;
if ( params . size ( ) = = 2 ) strShow = params [ 1 ] . get_str ( ) ;
if ( strShow ! = " valid " & & strShow ! = " all " ) return " Invalid mode, should be valid or all " ;
// GET STARTING TIME TO QUERY SYSTEM WITH
int nStartTime = 0 ; //list
if ( strCommand = = " diff " ) nStartTime = governance . GetLastDiffTime ( ) ;
// SETUP BLOCK INDEX VARIABLE / RESULTS VARIABLE
2016-10-22 18:52:36 +02:00
CBlockIndex * pindex = NULL ;
2016-08-17 09:08:25 +02:00
{
LOCK ( cs_main ) ;
pindex = chainActive . Tip ( ) ;
}
UniValue objResult ( UniValue : : VOBJ ) ;
// GET MATCHING GOVERNANCE OBJECTS
LOCK ( governance . cs ) ;
std : : vector < CGovernanceObject * > objs = governance . GetAllNewerThan ( nStartTime ) ;
governance . UpdateLastDiffTime ( GetTime ( ) ) ;
// CREATE RESULTS FOR USER
BOOST_FOREACH ( CGovernanceObject * pGovObj , objs )
{
// IF WE HAVE A SPECIFIC NODE REQUESTED TO VOTE, DO THAT
2016-11-13 18:52:34 +01:00
if ( strShow = = " valid " & & ! pGovObj - > IsSetCachedValid ( ) ) continue ;
2016-08-17 09:08:25 +02:00
UniValue bObj ( UniValue : : VOBJ ) ;
bObj . push_back ( Pair ( " DataHex " , pGovObj - > GetDataAsHex ( ) ) ) ;
bObj . push_back ( Pair ( " DataString " , pGovObj - > GetDataAsString ( ) ) ) ;
bObj . push_back ( Pair ( " Hash " , pGovObj - > GetHash ( ) . ToString ( ) ) ) ;
2016-11-13 18:52:34 +01:00
bObj . push_back ( Pair ( " CollateralHash " , pGovObj - > GetCollateralHash ( ) . ToString ( ) ) ) ;
2016-08-17 09:08:25 +02:00
// REPORT STATUS FOR FUNDING VOTES SPECIFICALLY
2016-09-30 03:48:18 +02:00
bObj . push_back ( Pair ( " AbsoluteYesCount " , pGovObj - > GetAbsoluteYesCount ( VOTE_SIGNAL_FUNDING ) ) ) ;
bObj . push_back ( Pair ( " YesCount " , pGovObj - > GetYesCount ( VOTE_SIGNAL_FUNDING ) ) ) ;
bObj . push_back ( Pair ( " NoCount " , pGovObj - > GetNoCount ( VOTE_SIGNAL_FUNDING ) ) ) ;
bObj . push_back ( Pair ( " AbstainCount " , pGovObj - > GetAbstainCount ( VOTE_SIGNAL_FUNDING ) ) ) ;
2016-08-17 09:08:25 +02:00
// REPORT VALIDITY AND CACHING FLAGS FOR VARIOUS SETTINGS
std : : string strError = " " ;
bObj . push_back ( Pair ( " fBlockchainValidity " , pGovObj - > IsValidLocally ( pindex , strError , false ) ) ) ;
bObj . push_back ( Pair ( " IsValidReason " , strError . c_str ( ) ) ) ;
2016-11-13 18:52:34 +01:00
bObj . push_back ( Pair ( " fCachedValid " , pGovObj - > IsSetCachedValid ( ) ) ) ;
bObj . push_back ( Pair ( " fCachedFunding " , pGovObj - > IsSetCachedFunding ( ) ) ) ;
bObj . push_back ( Pair ( " fCachedDelete " , pGovObj - > IsSetCachedDelete ( ) ) ) ;
bObj . push_back ( Pair ( " fCachedEndorsed " , pGovObj - > IsSetCachedEndorsed ( ) ) ) ;
2016-08-17 09:08:25 +02:00
2016-09-17 21:37:48 +02:00
objResult . push_back ( Pair ( pGovObj - > GetHash ( ) . ToString ( ) , bObj ) ) ;
2016-08-17 09:08:25 +02:00
}
return objResult ;
}
// GET SPECIFIC GOVERNANCE ENTRY
if ( strCommand = = " get " )
{
if ( params . size ( ) ! = 2 )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Correct usage is 'gobject get <governance-hash>' " ) ;
// COLLECT VARIABLES FROM OUR USER
uint256 hash = ParseHashV ( params [ 1 ] , " GovObj hash " ) ;
LOCK2 ( cs_main , governance . cs ) ;
// FIND THE GOVERNANCE OBJECT THE USER IS LOOKING FOR
CGovernanceObject * pGovObj = governance . FindGovernanceObject ( hash ) ;
if ( pGovObj = = NULL )
2016-09-12 09:40:00 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Unknown governance object " ) ;
2016-08-17 09:08:25 +02:00
// REPORT BASIC OBJECT STATS
UniValue objResult ( UniValue : : VOBJ ) ;
2016-09-30 03:48:18 +02:00
objResult . push_back ( Pair ( " DataHex " , pGovObj - > GetDataAsHex ( ) ) ) ;
objResult . push_back ( Pair ( " DataString " , pGovObj - > GetDataAsString ( ) ) ) ;
2016-08-17 09:08:25 +02:00
objResult . push_back ( Pair ( " Hash " , pGovObj - > GetHash ( ) . ToString ( ) ) ) ;
2016-11-13 18:52:34 +01:00
objResult . push_back ( Pair ( " CollateralHash " , pGovObj - > GetCollateralHash ( ) . ToString ( ) ) ) ;
2016-08-17 09:08:25 +02:00
// SHOW (MUCH MORE) INFORMATION ABOUT VOTES FOR GOVERNANCE OBJECT (THAN LIST/DIFF ABOVE)
// -- FUNDING VOTING RESULTS
UniValue objFundingResult ( UniValue : : VOBJ ) ;
2016-09-30 03:48:18 +02:00
objFundingResult . push_back ( Pair ( " AbsoluteYesCount " , pGovObj - > GetAbsoluteYesCount ( VOTE_SIGNAL_FUNDING ) ) ) ;
objFundingResult . push_back ( Pair ( " YesCount " , pGovObj - > GetYesCount ( VOTE_SIGNAL_FUNDING ) ) ) ;
objFundingResult . push_back ( Pair ( " NoCount " , pGovObj - > GetNoCount ( VOTE_SIGNAL_FUNDING ) ) ) ;
objFundingResult . push_back ( Pair ( " AbstainCount " , pGovObj - > GetAbstainCount ( VOTE_SIGNAL_FUNDING ) ) ) ;
2016-08-17 09:08:25 +02:00
objResult . push_back ( Pair ( " FundingResult " , objFundingResult ) ) ;
// -- VALIDITY VOTING RESULTS
UniValue objValid ( UniValue : : VOBJ ) ;
2016-09-30 03:48:18 +02:00
objValid . push_back ( Pair ( " AbsoluteYesCount " , pGovObj - > GetAbsoluteYesCount ( VOTE_SIGNAL_VALID ) ) ) ;
objValid . push_back ( Pair ( " YesCount " , pGovObj - > GetYesCount ( VOTE_SIGNAL_VALID ) ) ) ;
objValid . push_back ( Pair ( " NoCount " , pGovObj - > GetNoCount ( VOTE_SIGNAL_VALID ) ) ) ;
objValid . push_back ( Pair ( " AbstainCount " , pGovObj - > GetAbstainCount ( VOTE_SIGNAL_VALID ) ) ) ;
2016-08-17 09:08:25 +02:00
objResult . push_back ( Pair ( " ValidResult " , objValid ) ) ;
// -- DELETION CRITERION VOTING RESULTS
UniValue objDelete ( UniValue : : VOBJ ) ;
2016-09-30 03:48:18 +02:00
objDelete . push_back ( Pair ( " AbsoluteYesCount " , pGovObj - > GetAbsoluteYesCount ( VOTE_SIGNAL_DELETE ) ) ) ;
objDelete . push_back ( Pair ( " YesCount " , pGovObj - > GetYesCount ( VOTE_SIGNAL_DELETE ) ) ) ;
objDelete . push_back ( Pair ( " NoCount " , pGovObj - > GetNoCount ( VOTE_SIGNAL_DELETE ) ) ) ;
objDelete . push_back ( Pair ( " AbstainCount " , pGovObj - > GetAbstainCount ( VOTE_SIGNAL_DELETE ) ) ) ;
2016-08-17 09:08:25 +02:00
objResult . push_back ( Pair ( " DeleteResult " , objDelete ) ) ;
2016-09-12 09:40:00 +02:00
// -- ENDORSED VIA MASTERNODE-ELECTED BOARD
2016-08-17 09:08:25 +02:00
UniValue objEndorsed ( UniValue : : VOBJ ) ;
2016-09-30 03:48:18 +02:00
objEndorsed . push_back ( Pair ( " AbsoluteYesCount " , pGovObj - > GetAbsoluteYesCount ( VOTE_SIGNAL_ENDORSED ) ) ) ;
objEndorsed . push_back ( Pair ( " YesCount " , pGovObj - > GetYesCount ( VOTE_SIGNAL_ENDORSED ) ) ) ;
objEndorsed . push_back ( Pair ( " NoCount " , pGovObj - > GetNoCount ( VOTE_SIGNAL_ENDORSED ) ) ) ;
objEndorsed . push_back ( Pair ( " AbstainCount " , pGovObj - > GetAbstainCount ( VOTE_SIGNAL_ENDORSED ) ) ) ;
2016-08-17 09:08:25 +02:00
objResult . push_back ( Pair ( " EndorsedResult " , objEndorsed ) ) ;
2016-09-12 09:40:00 +02:00
// --
2016-08-17 09:08:25 +02:00
std : : string strError = " " ;
objResult . push_back ( Pair ( " fLocalValidity " , pGovObj - > IsValidLocally ( chainActive . Tip ( ) , strError , false ) ) ) ;
2016-09-30 03:48:18 +02:00
objResult . push_back ( Pair ( " IsValidReason " , strError . c_str ( ) ) ) ;
2016-11-13 18:52:34 +01:00
objResult . push_back ( Pair ( " fCachedValid " , pGovObj - > IsSetCachedValid ( ) ) ) ;
objResult . push_back ( Pair ( " fCachedFunding " , pGovObj - > IsSetCachedFunding ( ) ) ) ;
objResult . push_back ( Pair ( " fCachedDelete " , pGovObj - > IsSetCachedDelete ( ) ) ) ;
objResult . push_back ( Pair ( " fCachedEndorsed " , pGovObj - > IsSetCachedEndorsed ( ) ) ) ;
2016-08-17 09:08:25 +02:00
return objResult ;
}
// GETVOTES FOR SPECIFIC GOVERNANCE OBJECT
if ( strCommand = = " getvotes " )
{
2016-09-08 13:40:19 +02:00
if ( params . size ( ) ! = 2 )
2016-09-12 09:40:00 +02:00
throw std : : runtime_error (
2016-09-08 13:40:19 +02:00
" Correct usage is 'gobject getvotes <governance-hash>' "
2016-08-17 09:08:25 +02:00
) ;
// COLLECT PARAMETERS FROM USER
2016-09-12 09:40:00 +02:00
2016-08-17 09:08:25 +02:00
uint256 hash = ParseHashV ( params [ 1 ] , " Governance hash " ) ;
2016-09-12 09:40:00 +02:00
2016-08-17 09:08:25 +02:00
// FIND OBJECT USER IS LOOKING FOR
2016-09-12 09:40:00 +02:00
2016-08-17 09:08:25 +02:00
LOCK ( governance . cs ) ;
CGovernanceObject * pGovObj = governance . FindGovernanceObject ( hash ) ;
2016-09-08 13:40:19 +02:00
if ( pGovObj = = NULL ) {
2016-08-17 09:08:25 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Unknown governance-hash " ) ;
2016-09-08 13:40:19 +02:00
}
2016-08-17 09:08:25 +02:00
// REPORT RESULTS TO USER
UniValue bResult ( UniValue : : VOBJ ) ;
2016-09-12 09:40:00 +02:00
// GET MATCHING VOTES BY HASH, THEN SHOW USERS VOTE INFORMATION
2016-08-17 09:08:25 +02:00
2016-11-13 18:52:34 +01:00
std : : vector < CGovernanceVote > vecVotes = governance . GetMatchingVotes ( hash ) ;
BOOST_FOREACH ( CGovernanceVote vote , vecVotes ) {
bResult . push_back ( Pair ( vote . GetHash ( ) . ToString ( ) , vote . ToString ( ) ) ) ;
2016-09-08 13:40:19 +02:00
}
2016-08-17 09:08:25 +02:00
return bResult ;
}
return NullUniValue ;
}
UniValue voteraw ( const UniValue & params , bool fHelp )
{
if ( fHelp | | params . size ( ) ! = 6 )
2016-09-12 09:40:00 +02:00
throw std : : runtime_error (
2016-09-08 13:40:19 +02:00
" voteraw <masternode-tx-hash> <masternode-tx-index> <governance-hash> <vote-signal> [yes|no|abstain] <time> <vote-sig> \n "
2016-08-17 09:08:25 +02:00
" Compile and relay a governance 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 hashGovObj = ParseHashV ( params [ 2 ] , " Governance hash " ) ;
2016-09-08 13:40:19 +02:00
std : : string strVoteSignal = params [ 3 ] . get_str ( ) ;
std : : string strVoteOutcome = params [ 4 ] . get_str ( ) ;
vote_signal_enum_t eVoteSignal = CGovernanceVoting : : ConvertVoteSignal ( strVoteSignal ) ;
if ( eVoteSignal = = VOTE_SIGNAL_NONE ) {
2016-09-12 09:40:00 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER ,
2016-09-08 13:40:19 +02:00
" Invalid vote signal. Please using one of the following: "
2016-09-12 09:40:00 +02:00
" (funding|valid|delete|endorsed) OR `custom sentinel code` " ) ;
2016-09-08 13:40:19 +02:00
}
2016-08-17 09:08:25 +02:00
2016-09-08 13:40:19 +02:00
vote_outcome_enum_t eVoteOutcome = CGovernanceVoting : : ConvertVoteOutcome ( strVoteOutcome ) ;
if ( eVoteOutcome = = VOTE_OUTCOME_NONE ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Invalid vote outcome. Please use one of the following: 'yes', 'no' or 'abstain' " ) ;
}
2016-08-17 09:08:25 +02:00
2016-09-08 13:40:19 +02:00
int64_t nTime = params [ 5 ] . get_int64 ( ) ;
std : : string strSig = params [ 6 ] . get_str ( ) ;
2016-08-17 09:08:25 +02:00
bool fInvalid = false ;
2016-09-12 09:40:00 +02:00
std : : vector < unsigned char > vchSig = DecodeBase64 ( strSig . c_str ( ) , & fInvalid ) ;
2016-08-17 09:08:25 +02:00
2016-09-08 13:40:19 +02:00
if ( fInvalid ) {
2016-08-17 09:08:25 +02:00
throw JSONRPCError ( RPC_INVALID_ADDRESS_OR_KEY , " Malformed base64 encoding " ) ;
2016-09-08 13:40:19 +02:00
}
2016-08-17 09:08:25 +02:00
2016-09-18 23:11:03 +02:00
CMasternode mn ;
bool mnFound = mnodeman . Get ( vin , mn ) ;
if ( ! mnFound ) {
2016-08-17 09:08:25 +02:00
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Failure to find masternode in list : " + vin . ToString ( ) ) ;
}
2016-09-08 13:40:19 +02:00
CGovernanceVote vote ( vin , hashGovObj , eVoteSignal , eVoteOutcome ) ;
vote . SetTime ( nTime ) ;
vote . SetSignature ( vchSig ) ;
2016-08-17 09:08:25 +02:00
2016-09-18 23:11:03 +02:00
if ( ! vote . IsValid ( true ) ) {
2016-08-17 09:08:25 +02:00
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Failure to verify vote. " ) ;
}
2016-11-13 18:52:34 +01:00
CGovernanceException exception ;
if ( governance . ProcessVote ( vote , exception ) ) {
2016-08-17 09:08:25 +02:00
return " Voted successfully " ;
2016-11-13 18:52:34 +01:00
}
else {
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Error voting : " + exception . GetMessage ( ) ) ;
2016-08-17 09:08:25 +02:00
}
}
2016-08-28 21:15:48 +02:00
UniValue getgovernanceinfo ( const UniValue & params , bool fHelp )
{
if ( fHelp | | params . size ( ) ! = 0 ) {
2016-09-12 09:40:00 +02:00
throw std : : runtime_error (
2016-08-28 21:15:48 +02:00
" getgovernanceinfo \n "
" Returns an object containing governance parameters. \n "
" \n Result: \n "
" { \n "
2016-10-17 20:54:28 +02:00
" \" governanceminquorum \" : xxxxx, (numeric) the absolute minimum number of votes needed to trigger a governance action \n "
" \" masternodewatchdogmaxseconds \" : xxxxx, (numeric) sentinel watchdog expiration time in seconds \n "
" \" proposalfee \" : xxx.xx, (numeric) the collateral transaction fee which must be paid to create a proposal in " + CURRENCY_UNIT + " \n "
" \" superblockcycle \" : xxxxx, (numeric) the number of blocks between superblocks \n "
" \" lastsuperblock \" : xxxxx, (numeric) the block number of the last superblock \n "
" \" nextsuperblock \" : xxxxx, (numeric) the block number of the next superblock \n "
2016-08-28 21:15:48 +02:00
" } \n "
" \n Examples: \n "
+ HelpExampleCli ( " getgovernanceinfo " , " " )
+ HelpExampleRpc ( " getgovernanceinfo " , " " )
) ;
}
2016-09-08 13:33:25 +02:00
// Compute last/next superblock
int nLastSuperblock , nNextSuperblock ;
// Get current block height
2016-09-18 23:11:03 +02:00
int nBlockHeight = 0 ;
{
LOCK ( cs_main ) ;
nBlockHeight = ( int ) chainActive . Height ( ) ;
}
2016-09-08 13:33:25 +02:00
// Get chain parameters
int nSuperblockStartBlock = Params ( ) . GetConsensus ( ) . nSuperblockStartBlock ;
int nSuperblockCycle = Params ( ) . GetConsensus ( ) . nSuperblockCycle ;
// Get first superblock
int nFirstSuperblockOffset = ( nSuperblockCycle - nSuperblockStartBlock % nSuperblockCycle ) % nSuperblockCycle ;
int nFirstSuperblock = nSuperblockStartBlock + nFirstSuperblockOffset ;
if ( nBlockHeight < nFirstSuperblock ) {
nLastSuperblock = 0 ;
nNextSuperblock = nFirstSuperblock ;
} else {
nLastSuperblock = nBlockHeight - nBlockHeight % nSuperblockCycle ;
nNextSuperblock = nLastSuperblock + nSuperblockCycle ;
}
2016-08-28 21:15:48 +02:00
UniValue obj ( UniValue : : VOBJ ) ;
obj . push_back ( Pair ( " governanceminquorum " , Params ( ) . GetConsensus ( ) . nGovernanceMinQuorum ) ) ;
2016-10-17 20:54:28 +02:00
obj . push_back ( Pair ( " masternodewatchdogmaxseconds " , MASTERNODE_WATCHDOG_MAX_SECONDS ) ) ;
2016-09-05 01:44:10 +02:00
obj . push_back ( Pair ( " proposalfee " , ValueFromAmount ( GOVERNANCE_PROPOSAL_FEE_TX ) ) ) ;
2016-08-28 21:15:48 +02:00
obj . push_back ( Pair ( " superblockcycle " , Params ( ) . GetConsensus ( ) . nSuperblockCycle ) ) ;
2016-09-08 13:33:25 +02:00
obj . push_back ( Pair ( " lastsuperblock " , nLastSuperblock ) ) ;
obj . push_back ( Pair ( " nextsuperblock " , nNextSuperblock ) ) ;
2016-08-28 21:15:48 +02:00
return obj ;
}
UniValue getsuperblockbudget ( const UniValue & params , bool fHelp )
{
if ( fHelp | | params . size ( ) ! = 1 ) {
2016-09-12 09:40:00 +02:00
throw std : : runtime_error (
2016-08-28 21:15:48 +02:00
" getsuperblockbudget index \n "
" \n Returns the absolute minimum number of votes needed to trigger a governance action. \n "
" \n Arguments: \n "
" 1. index (numeric, required) The block index \n "
" \n Result: \n "
" n (numeric) The current minimum governance quorum \n "
" \n Examples: \n "
+ HelpExampleCli ( " getsuperblockbudget " , " 1000 " )
+ HelpExampleRpc ( " getsuperblockbudget " , " 1000 " )
) ;
}
int nBlockHeight = params [ 0 ] . get_int ( ) ;
if ( nBlockHeight < 0 ) {
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Block height out of range " ) ;
}
CAmount nBudget = CSuperblock : : GetPaymentsLimit ( nBlockHeight ) ;
std : : string strBudget = FormatMoney ( nBudget ) ;
return strBudget ;
}