2016-12-20 14:26:45 +01:00
// Copyright (c) 2014-2017 The Dash Core developers
2014-12-09 02:17:57 +01:00
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# include "activemasternode.h"
2016-12-20 14:27:59 +01:00
# include "init.h"
# include "main.h"
2016-01-24 20:05:31 +01:00
# include "masternode-payments.h"
# include "masternode-sync.h"
2014-12-06 20:41:53 +01:00
# include "masternodeconfig.h"
2016-01-24 20:05:31 +01:00
# include "masternodeman.h"
2017-05-05 13:26:27 +02:00
# include "privatesend-client.h"
# include "privatesend-server.h"
2014-12-09 02:17:57 +01:00
# include "rpcserver.h"
2016-12-20 14:27:59 +01:00
# include "util.h"
2015-04-03 00:51:08 +02:00
# include "utilmoneystr.h"
2014-12-09 02:17:57 +01:00
# include <fstream>
2016-02-02 16:28:56 +01:00
# include <iomanip>
# include <univalue.h>
2014-12-09 02:17:57 +01:00
2016-09-12 19:38:52 +02:00
void EnsureWalletIsUnlocked ( ) ;
2016-05-25 07:25:16 +02:00
UniValue privatesend ( const UniValue & params , bool fHelp )
2014-12-09 02:17:57 +01:00
{
2016-02-01 18:22:00 +01:00
if ( fHelp | | params . size ( ) ! = 1 )
2016-09-16 17:22:57 +02:00
throw std : : runtime_error (
2016-05-25 07:25:16 +02:00
" privatesend \" command \" \n "
2016-02-01 18:22:00 +01:00
" \n Arguments: \n "
" 1. \" command \" (string or set of strings, required) The command to execute \n "
" \n Available commands: \n "
" start - Start mixing \n "
" stop - Stop mixing \n "
" reset - Reset mixing \n "
2017-02-10 01:51:47 +01:00
) ;
2014-12-09 02:17:57 +01:00
2016-09-11 11:02:54 +02:00
if ( params [ 0 ] . get_str ( ) = = " start " ) {
2017-02-10 01:51:47 +01:00
{
LOCK ( pwalletMain - > cs_wallet ) ;
EnsureWalletIsUnlocked ( ) ;
}
2014-12-09 02:17:57 +01:00
2014-12-30 01:09:34 +01:00
if ( fMasterNode )
2016-02-01 18:22:00 +01:00
return " Mixing is not supported from masternodes " ;
2014-12-30 01:09:34 +01:00
2017-05-05 13:26:27 +02:00
privateSendClient . fEnablePrivateSend = true ;
bool result = privateSendClient . DoAutomaticDenominating ( ) ;
return " Mixing " + ( result ? " started successfully " : ( " start failed: " + privateSendClient . GetStatus ( ) + " , will retry " ) ) ;
2016-02-01 18:22:00 +01:00
}
2016-09-16 17:22:57 +02:00
if ( params [ 0 ] . get_str ( ) = = " stop " ) {
2017-05-05 13:26:27 +02:00
privateSendClient . fEnablePrivateSend = false ;
2016-02-01 18:22:00 +01:00
return " Mixing was stopped " ;
2014-12-09 02:17:57 +01:00
}
2016-09-16 17:22:57 +02:00
if ( params [ 0 ] . get_str ( ) = = " reset " ) {
2017-05-05 13:26:27 +02:00
privateSendClient . ResetPool ( ) ;
2016-02-01 18:22:00 +01:00
return " Mixing was reset " ;
2014-12-09 02:17:57 +01:00
}
2016-05-25 07:25:16 +02:00
return " Unknown command, please see \" help privatesend \" " ;
2014-12-09 02:17:57 +01:00
}
2016-02-02 16:28:56 +01:00
UniValue getpoolinfo ( const UniValue & params , bool fHelp )
2014-12-09 02:17:57 +01:00
{
if ( fHelp | | params . size ( ) ! = 0 )
2016-09-16 17:22:57 +02:00
throw std : : runtime_error (
2014-12-09 02:17:57 +01:00
" getpoolinfo \n "
2016-11-21 21:40:56 +01:00
" Returns an object containing mixing pool related information. \n " ) ;
2014-12-09 02:17:57 +01:00
2017-05-05 13:26:27 +02:00
CPrivateSend privateSend = fMasterNode ? ( CPrivateSend ) privateSendServer : ( CPrivateSend ) privateSendClient ;
2016-02-02 16:28:56 +01:00
UniValue obj ( UniValue : : VOBJ ) ;
2017-05-05 13:26:27 +02:00
obj . push_back ( Pair ( " state " , privateSend . GetStateString ( ) ) ) ;
obj . push_back ( Pair ( " mixing_mode " , ( ! fMasterNode & & privateSendClient . fPrivateSendMultiSession ) ? " multi-session " : " normal " ) ) ;
obj . push_back ( Pair ( " queue " , privateSend . GetQueueSize ( ) ) ) ;
obj . push_back ( Pair ( " entries " , privateSend . GetEntriesCount ( ) ) ) ;
obj . push_back ( Pair ( " status " , privateSendClient . GetStatus ( ) ) ) ;
if ( privateSendClient . infoMixingMasternode . fInfoValid ) {
obj . push_back ( Pair ( " outpoint " , privateSendClient . infoMixingMasternode . vin . prevout . ToStringShort ( ) ) ) ;
obj . push_back ( Pair ( " addr " , privateSendClient . infoMixingMasternode . addr . ToString ( ) ) ) ;
2016-11-21 21:40:56 +01:00
}
if ( pwalletMain ) {
obj . push_back ( Pair ( " keys_left " , pwalletMain - > nKeysLeftSinceAutoBackup ) ) ;
obj . push_back ( Pair ( " warnings " , pwalletMain - > nKeysLeftSinceAutoBackup < PRIVATESEND_KEYS_THRESHOLD_WARNING
? " WARNING: keypool is almost depleted! " : " " ) ) ;
}
2014-12-09 02:17:57 +01:00
return obj ;
}
2014-12-06 20:41:53 +01:00
2016-02-02 16:28:56 +01:00
UniValue masternode ( const UniValue & params , bool fHelp )
2014-12-09 02:17:57 +01:00
{
2016-09-16 17:22:57 +02:00
std : : string strCommand ;
if ( params . size ( ) > = 1 ) {
2014-12-09 02:17:57 +01:00
strCommand = params [ 0 ] . get_str ( ) ;
2016-09-16 17:22:57 +02:00
}
if ( strCommand = = " start-many " )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " DEPRECATED, please use start-all instead " ) ;
2014-12-09 02:17:57 +01:00
if ( fHelp | |
2016-09-16 17:22:57 +02:00
( strCommand ! = " start " & & strCommand ! = " start-alias " & & strCommand ! = " start-all " & & strCommand ! = " start-missing " & &
strCommand ! = " start-disabled " & & strCommand ! = " list " & & strCommand ! = " list-conf " & & strCommand ! = " count " & &
2016-09-15 08:50:41 +02:00
strCommand ! = " debug " & & strCommand ! = " current " & & strCommand ! = " winner " & & strCommand ! = " winners " & & strCommand ! = " genkey " & &
strCommand ! = " connect " & & strCommand ! = " outputs " & & strCommand ! = " status " ) )
throw std : : runtime_error (
2017-02-10 01:51:47 +01:00
" masternode \" command \" ... \n "
2015-02-26 02:35:33 +01:00
" Set of commands to execute masternode related actions \n "
" \n Arguments: \n "
" 1. \" command \" (string or set of strings, required) The command to execute \n "
" \n Available commands: \n "
2016-05-27 08:25:00 +02:00
" count - Print number of all known masternodes (optional: 'ps', 'enabled', 'all', 'qualify') \n "
2016-09-15 08:50:41 +02:00
" current - Print info on current masternode winner to be paid the next block (calculated locally) \n "
2015-02-26 02:35:33 +01:00
" debug - Print masternode status \n "
" genkey - Generate new masternodeprivkey \n "
" outputs - Print masternode compatible outputs \n "
2015-09-09 05:38:45 +02:00
" start - Start local Hot masternode configured in dash.conf \n "
" start-alias - Start single remote masternode by assigned alias configured in masternode.conf \n "
" start-<mode> - Start remote masternodes configured in masternode.conf (<mode>: 'all', 'missing', 'disabled') \n "
2015-07-18 21:17:17 +02:00
" status - Print masternode status information \n "
2015-02-26 02:35:33 +01:00
" list - Print list of all known masternodes (see masternodelist for more info) \n "
" list-conf - Print masternode.conf in JSON format \n "
2016-09-15 08:50:41 +02:00
" winner - Print info on next masternode winner to vote for \n "
2015-02-26 02:35:33 +01:00
" winners - Print list of masternode winners \n "
) ;
2014-12-09 02:17:57 +01:00
if ( strCommand = = " list " )
{
2016-02-02 16:28:56 +01:00
UniValue newParams ( UniValue : : VARR ) ;
// forward params but skip "list"
2016-09-16 17:22:57 +02:00
for ( unsigned int i = 1 ; i < params . size ( ) ; i + + ) {
2016-02-02 16:28:56 +01:00
newParams . push_back ( params [ i ] ) ;
2016-09-16 17:22:57 +02:00
}
2015-02-23 21:26:23 +01:00
return masternodelist ( newParams , fHelp ) ;
}
2014-12-09 02:17:57 +01:00
2015-07-18 21:17:17 +02:00
if ( strCommand = = " connect " )
{
2016-09-16 17:22:57 +02:00
if ( params . size ( ) < 2 )
2016-03-15 01:52:49 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Masternode address required " ) ;
2016-09-16 17:22:57 +02:00
std : : string strAddress = params [ 1 ] . get_str ( ) ;
2015-07-18 21:17:17 +02:00
CService addr = CService ( strAddress ) ;
2016-07-30 13:05:41 +02:00
CNode * pnode = ConnectNode ( ( CAddress ) addr , NULL ) ;
2016-09-16 17:22:57 +02:00
if ( ! pnode )
throw JSONRPCError ( RPC_INTERNAL_ERROR , strprintf ( " Couldn't connect to masternode %s " , strAddress ) ) ;
return " successfully connected " ;
2015-07-18 21:17:17 +02:00
}
2015-02-23 21:26:23 +01:00
if ( strCommand = = " count " )
{
2016-09-16 17:22:57 +02:00
if ( params . size ( ) > 2 )
2016-03-15 01:52:49 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Too many parameters " ) ;
2015-08-20 17:36:44 +02:00
2016-09-16 17:22:57 +02:00
if ( params . size ( ) = = 1 )
return mnodeman . size ( ) ;
2015-08-20 17:36:44 +02:00
2016-09-16 17:22:57 +02:00
std : : string strMode = params [ 1 ] . get_str ( ) ;
if ( strMode = = " ps " )
return mnodeman . CountEnabled ( MIN_PRIVATESEND_PEER_PROTO_VERSION ) ;
if ( strMode = = " enabled " )
return mnodeman . CountEnabled ( ) ;
int nCount ;
2016-11-28 15:21:50 +01:00
mnodeman . GetNextMasternodeInQueueForPayment ( true , nCount ) ;
2016-09-16 17:22:57 +02:00
if ( strMode = = " qualify " )
return nCount ;
if ( strMode = = " all " )
return strprintf ( " Total: %d (PS Compatible: %d / Enabled: %d / Qualify: %d) " ,
mnodeman . size ( ) , mnodeman . CountEnabled ( MIN_PRIVATESEND_PEER_PROTO_VERSION ) ,
mnodeman . CountEnabled ( ) , nCount ) ;
2014-12-09 02:17:57 +01:00
}
2016-09-15 08:50:41 +02:00
if ( strCommand = = " current " | | strCommand = = " winner " )
2015-07-18 21:17:17 +02:00
{
2016-09-15 08:50:41 +02:00
int nCount ;
int nHeight ;
2016-03-02 21:57:24 +01:00
CMasternode * winner = NULL ;
2016-09-15 08:50:41 +02:00
{
LOCK ( cs_main ) ;
nHeight = chainActive . Height ( ) + ( strCommand = = " current " ? 1 : 10 ) ;
2015-07-18 21:17:17 +02:00
}
2016-11-28 15:21:50 +01:00
mnodeman . UpdateLastPaid ( ) ;
2016-09-15 08:50:41 +02:00
winner = mnodeman . GetNextMasternodeInQueueForPayment ( nHeight , true , nCount ) ;
if ( ! winner ) return " unknown " ;
2015-07-18 21:17:17 +02:00
2016-09-15 08:50:41 +02:00
UniValue obj ( UniValue : : VOBJ ) ;
obj . push_back ( Pair ( " height " , nHeight ) ) ;
obj . push_back ( Pair ( " IP:port " , winner - > addr . ToString ( ) ) ) ;
2016-09-16 00:00:06 +02:00
obj . push_back ( Pair ( " protocol " , ( int64_t ) winner - > nProtocolVersion ) ) ;
2016-09-15 08:50:41 +02:00
obj . push_back ( Pair ( " vin " , winner - > vin . prevout . ToStringShort ( ) ) ) ;
2016-09-16 00:00:06 +02:00
obj . push_back ( Pair ( " payee " , CBitcoinAddress ( winner - > pubKeyCollateralAddress . GetID ( ) ) . ToString ( ) ) ) ;
2016-09-15 08:50:41 +02:00
obj . push_back ( Pair ( " lastseen " , ( winner - > lastPing = = CMasternodePing ( ) ) ? winner - > sigTime :
winner - > lastPing . sigTime ) ) ;
obj . push_back ( Pair ( " activeseconds " , ( winner - > lastPing = = CMasternodePing ( ) ) ? 0 :
( winner - > lastPing . sigTime - winner - > sigTime ) ) ) ;
return obj ;
2015-07-18 21:17:17 +02:00
}
if ( strCommand = = " debug " )
{
2016-08-05 21:49:45 +02:00
if ( activeMasternode . nState ! = ACTIVE_MASTERNODE_INITIAL | | ! masternodeSync . IsBlockchainSynced ( ) )
2015-07-23 04:11:39 +02:00
return activeMasternode . GetStatus ( ) ;
2015-07-18 21:17:17 +02:00
2016-09-16 17:22:57 +02:00
CTxIn vin ;
CPubKey pubkey ;
2015-07-18 21:17:17 +02:00
CKey key ;
2016-09-16 17:22:57 +02:00
2016-07-15 08:33:16 +02:00
if ( ! pwalletMain | | ! pwalletMain - > GetMasternodeVinAndKeys ( vin , pubkey , key ) )
2016-03-15 01:52:49 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Missing masternode input, please look at the documentation for instructions on masternode creation " ) ;
2016-07-15 08:33:16 +02:00
return activeMasternode . GetStatus ( ) ;
2015-07-18 21:17:17 +02:00
}
2014-12-09 02:17:57 +01:00
if ( strCommand = = " start " )
{
2016-03-15 01:52:49 +01:00
if ( ! fMasterNode )
throw JSONRPCError ( RPC_INTERNAL_ERROR , " You must set masternode=1 in the configuration " ) ;
2014-12-09 02:17:57 +01:00
2016-10-24 01:14:54 +02:00
{
LOCK ( pwalletMain - > cs_wallet ) ;
EnsureWalletIsUnlocked ( ) ;
}
2014-12-09 02:17:57 +01:00
2016-08-05 21:49:45 +02:00
if ( activeMasternode . nState ! = ACTIVE_MASTERNODE_STARTED ) {
activeMasternode . nState = ACTIVE_MASTERNODE_INITIAL ; // TODO: consider better way
activeMasternode . ManageState ( ) ;
2015-01-21 22:57:02 +01:00
}
2014-12-26 21:00:56 +01:00
2015-07-14 07:25:07 +02:00
return activeMasternode . GetStatus ( ) ;
2014-12-09 02:17:57 +01:00
}
2014-12-06 20:41:53 +01:00
if ( strCommand = = " start-alias " )
2014-12-09 02:17:57 +01:00
{
2016-09-16 17:22:57 +02:00
if ( params . size ( ) < 2 )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Please specify an alias " ) ;
2015-07-18 03:23:52 +02:00
2016-10-24 01:14:54 +02:00
{
LOCK ( pwalletMain - > cs_wallet ) ;
EnsureWalletIsUnlocked ( ) ;
}
2015-07-18 03:23:52 +02:00
2016-09-16 17:22:57 +02:00
std : : string strAlias = params [ 1 ] . get_str ( ) ;
2014-12-06 20:41:53 +01:00
2016-09-16 17:22:57 +02:00
bool fFound = false ;
2014-12-06 20:41:53 +01:00
2016-02-02 16:28:56 +01:00
UniValue statusObj ( UniValue : : VOBJ ) ;
2016-09-16 17:22:57 +02:00
statusObj . push_back ( Pair ( " alias " , strAlias ) ) ;
2015-03-21 20:49:21 +01:00
2015-07-18 03:23:52 +02:00
BOOST_FOREACH ( CMasternodeConfig : : CMasternodeEntry mne , masternodeConfig . getEntries ( ) ) {
2016-09-16 17:22:57 +02:00
if ( mne . getAlias ( ) = = strAlias ) {
fFound = true ;
std : : string strError ;
2016-03-16 16:30:22 +01:00
CMasternodeBroadcast mnb ;
2014-12-06 20:41:53 +01:00
2016-09-16 17:22:57 +02:00
bool fResult = CMasternodeBroadcast : : Create ( mne . getIp ( ) , mne . getPrivKey ( ) , mne . getTxHash ( ) , mne . getOutputIndex ( ) , strError , mnb ) ;
2014-12-06 20:41:53 +01:00
2016-09-16 17:22:57 +02:00
statusObj . push_back ( Pair ( " result " , fResult ? " successful " : " failed " ) ) ;
if ( fResult ) {
2016-03-16 16:30:22 +01:00
mnodeman . UpdateMasternodeList ( mnb ) ;
mnb . Relay ( ) ;
} else {
2016-09-16 17:22:57 +02:00
statusObj . push_back ( Pair ( " errorMessage " , strError ) ) ;
2015-07-18 03:23:52 +02:00
}
2016-11-13 18:52:34 +01:00
mnodeman . NotifyMasternodeUpdates ( ) ;
2015-07-18 03:23:52 +02:00
break ;
}
}
2014-12-06 20:41:53 +01:00
2016-09-16 17:22:57 +02:00
if ( ! fFound ) {
2015-07-18 03:23:52 +02:00
statusObj . push_back ( Pair ( " result " , " failed " ) ) ;
2016-03-15 01:52:49 +01:00
statusObj . push_back ( Pair ( " errorMessage " , " Could not find alias in config. Verify with list-conf. " ) ) ;
2015-07-18 03:23:52 +02:00
}
return statusObj ;
2014-12-09 02:17:57 +01:00
}
2014-12-26 21:00:56 +01:00
2016-09-16 17:22:57 +02:00
if ( strCommand = = " start-all " | | strCommand = = " start-missing " | | strCommand = = " start-disabled " )
2014-12-26 21:00:56 +01:00
{
2016-10-24 01:14:54 +02:00
{
LOCK ( pwalletMain - > cs_wallet ) ;
EnsureWalletIsUnlocked ( ) ;
}
2014-12-06 20:41:53 +01:00
2016-08-29 21:11:34 +02:00
if ( ( strCommand = = " start-missing " | | strCommand = = " start-disabled " ) & & ! masternodeSync . IsMasternodeListSynced ( ) ) {
throw JSONRPCError ( RPC_CLIENT_IN_INITIAL_DOWNLOAD , " You can't use this command until masternode list is synced " ) ;
2015-08-31 06:20:38 +02:00
}
2016-09-16 17:22:57 +02:00
int nSuccessful = 0 ;
int nFailed = 0 ;
2014-12-06 20:41:53 +01:00
2016-02-02 16:28:56 +01:00
UniValue resultsObj ( UniValue : : VOBJ ) ;
2014-12-06 20:41:53 +01:00
2015-07-18 03:23:52 +02:00
BOOST_FOREACH ( CMasternodeConfig : : CMasternodeEntry mne , masternodeConfig . getEntries ( ) ) {
2016-09-16 17:22:57 +02:00
std : : string strError ;
2015-03-21 20:49:21 +01:00
2016-02-02 16:28:56 +01:00
CTxIn vin = CTxIn ( uint256S ( mne . getTxHash ( ) ) , uint32_t ( atoi ( mne . getOutputIndex ( ) . c_str ( ) ) ) ) ;
2015-08-26 22:15:37 +02:00
CMasternode * pmn = mnodeman . Find ( vin ) ;
2016-03-16 16:30:22 +01:00
CMasternodeBroadcast mnb ;
2015-08-26 22:15:37 +02:00
if ( strCommand = = " start-missing " & & pmn ) continue ;
if ( strCommand = = " start-disabled " & & pmn & & pmn - > IsEnabled ( ) ) continue ;
2016-09-16 17:22:57 +02:00
bool fResult = CMasternodeBroadcast : : Create ( mne . getIp ( ) , mne . getPrivKey ( ) , mne . getTxHash ( ) , mne . getOutputIndex ( ) , strError , mnb ) ;
2014-12-06 20:41:53 +01:00
2016-02-02 16:28:56 +01:00
UniValue statusObj ( UniValue : : VOBJ ) ;
2015-07-18 03:23:52 +02:00
statusObj . push_back ( Pair ( " alias " , mne . getAlias ( ) ) ) ;
2016-09-16 17:22:57 +02:00
statusObj . push_back ( Pair ( " result " , fResult ? " successful " : " failed " ) ) ;
2014-12-06 20:41:53 +01:00
2016-09-16 17:22:57 +02:00
if ( fResult ) {
nSuccessful + + ;
2016-03-16 16:30:22 +01:00
mnodeman . UpdateMasternodeList ( mnb ) ;
mnb . Relay ( ) ;
2015-07-18 03:23:52 +02:00
} else {
2016-09-16 17:22:57 +02:00
nFailed + + ;
statusObj . push_back ( Pair ( " errorMessage " , strError ) ) ;
2015-07-18 03:23:52 +02:00
}
2014-12-06 20:41:53 +01:00
2015-07-18 03:23:52 +02:00
resultsObj . push_back ( Pair ( " status " , statusObj ) ) ;
}
2016-11-13 18:52:34 +01:00
mnodeman . NotifyMasternodeUpdates ( ) ;
2014-12-06 20:41:53 +01:00
2016-02-02 16:28:56 +01:00
UniValue returnObj ( UniValue : : VOBJ ) ;
2016-09-16 17:22:57 +02:00
returnObj . push_back ( Pair ( " overall " , strprintf ( " Successfully started %d masternodes, failed to start %d, total %d " , nSuccessful , nFailed , nSuccessful + nFailed ) ) ) ;
2015-07-18 03:23:52 +02:00
returnObj . push_back ( Pair ( " detail " , resultsObj ) ) ;
2014-12-06 20:41:53 +01:00
2015-07-18 03:23:52 +02:00
return returnObj ;
2014-12-06 20:41:53 +01:00
}
2014-12-09 02:17:57 +01:00
if ( strCommand = = " genkey " )
{
CKey secret ;
secret . MakeNewKey ( false ) ;
return CBitcoinSecret ( secret ) . ToString ( ) ;
}
2016-09-16 17:22:57 +02:00
if ( strCommand = = " list-conf " )
2014-12-06 20:41:53 +01:00
{
2016-02-02 16:28:56 +01:00
UniValue resultObj ( UniValue : : VOBJ ) ;
2014-12-06 20:41:53 +01:00
BOOST_FOREACH ( CMasternodeConfig : : CMasternodeEntry mne , masternodeConfig . getEntries ( ) ) {
2016-02-02 16:28:56 +01:00
CTxIn vin = CTxIn ( uint256S ( mne . getTxHash ( ) ) , uint32_t ( atoi ( mne . getOutputIndex ( ) . c_str ( ) ) ) ) ;
2015-08-31 06:20:38 +02:00
CMasternode * pmn = mnodeman . Find ( vin ) ;
2016-09-16 00:00:06 +02:00
std : : string strStatus = pmn ? pmn - > GetStatus ( ) : " MISSING " ;
2015-08-31 06:20:38 +02:00
2016-02-02 16:28:56 +01:00
UniValue mnObj ( UniValue : : VOBJ ) ;
2015-03-16 20:44:16 +01:00
mnObj . push_back ( Pair ( " alias " , mne . getAlias ( ) ) ) ;
mnObj . push_back ( Pair ( " address " , mne . getIp ( ) ) ) ;
mnObj . push_back ( Pair ( " privateKey " , mne . getPrivKey ( ) ) ) ;
mnObj . push_back ( Pair ( " txHash " , mne . getTxHash ( ) ) ) ;
mnObj . push_back ( Pair ( " outputIndex " , mne . getOutputIndex ( ) ) ) ;
2015-08-31 06:20:38 +02:00
mnObj . push_back ( Pair ( " status " , strStatus ) ) ;
2015-03-16 20:44:16 +01:00
resultObj . push_back ( Pair ( " masternode " , mnObj ) ) ;
}
2014-12-06 20:41:53 +01:00
2015-03-16 20:44:16 +01:00
return resultObj ;
2014-12-06 20:41:53 +01:00
}
2016-09-16 17:22:57 +02:00
if ( strCommand = = " outputs " ) {
2014-12-26 21:00:56 +01:00
// Find possible candidates
2016-07-15 08:33:16 +02:00
std : : vector < COutput > vPossibleCoins ;
pwalletMain - > AvailableCoins ( vPossibleCoins , true , NULL , false , ONLY_1000 ) ;
2014-12-26 21:00:56 +01:00
2016-02-02 16:28:56 +01:00
UniValue obj ( UniValue : : VOBJ ) ;
2016-09-16 17:22:57 +02:00
BOOST_FOREACH ( COutput & out , vPossibleCoins ) {
2015-07-18 19:31:28 +02:00
obj . push_back ( Pair ( out . tx - > GetHash ( ) . ToString ( ) , strprintf ( " %d " , out . i ) ) ) ;
2016-09-16 17:22:57 +02:00
}
2014-12-26 21:00:56 +01:00
return obj ;
}
2016-09-16 17:22:57 +02:00
if ( strCommand = = " status " )
2015-06-24 18:41:03 +02:00
{
2016-09-16 17:22:57 +02:00
if ( ! fMasterNode )
2016-03-15 01:52:49 +01:00
throw JSONRPCError ( RPC_INTERNAL_ERROR , " This is not a masternode " ) ;
2015-06-24 18:41:03 +02:00
2016-02-02 16:28:56 +01:00
UniValue mnObj ( UniValue : : VOBJ ) ;
2015-08-28 22:18:55 +02:00
2015-07-18 19:31:28 +02:00
mnObj . push_back ( Pair ( " vin " , activeMasternode . vin . ToString ( ) ) ) ;
mnObj . push_back ( Pair ( " service " , activeMasternode . service . ToString ( ) ) ) ;
2016-09-18 23:13:23 +02:00
CMasternode mn ;
if ( mnodeman . Get ( activeMasternode . vin , mn ) ) {
mnObj . push_back ( Pair ( " payee " , CBitcoinAddress ( mn . pubKeyCollateralAddress . GetID ( ) ) . ToString ( ) ) ) ;
}
2015-08-15 16:09:13 +02:00
mnObj . push_back ( Pair ( " status " , activeMasternode . GetStatus ( ) ) ) ;
2015-06-24 18:41:03 +02:00
return mnObj ;
}
2015-07-18 21:17:17 +02:00
if ( strCommand = = " winners " )
{
2016-03-02 21:57:24 +01:00
int nHeight ;
{
LOCK ( cs_main ) ;
CBlockIndex * pindex = chainActive . Tip ( ) ;
if ( ! pindex ) return NullUniValue ;
nHeight = pindex - > nHeight ;
}
2015-07-21 00:09:42 +02:00
int nLast = 10 ;
2016-03-06 17:44:21 +01:00
std : : string strFilter = " " ;
2015-07-21 00:09:42 +02:00
2016-09-16 17:22:57 +02:00
if ( params . size ( ) > = 2 ) {
2015-07-22 00:14:54 +02:00
nLast = atoi ( params [ 1 ] . get_str ( ) ) ;
2015-07-21 00:09:42 +02:00
}
2016-09-16 17:22:57 +02:00
if ( params . size ( ) = = 3 ) {
2016-03-06 17:44:21 +01:00
strFilter = params [ 2 ] . get_str ( ) ;
}
if ( params . size ( ) > 3 )
2016-03-15 01:52:49 +01:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Correct usage is 'masternode winners ( \" count \" \" filter \" ) ' " ) ;
2016-03-06 17:44:21 +01:00
2016-02-02 16:28:56 +01:00
UniValue obj ( UniValue : : VOBJ ) ;
2015-07-18 21:17:17 +02:00
2016-09-16 17:22:57 +02:00
for ( int i = nHeight - nLast ; i < nHeight + 20 ; i + + ) {
2016-03-06 17:44:21 +01:00
std : : string strPayment = GetRequiredPaymentsString ( i ) ;
2016-09-16 17:22:57 +02:00
if ( strFilter ! = " " & & strPayment . find ( strFilter ) = = std : : string : : npos ) continue ;
2016-03-06 17:44:21 +01:00
obj . push_back ( Pair ( strprintf ( " %d " , i ) , strPayment ) ) ;
2015-07-18 21:17:17 +02:00
}
return obj ;
}
2016-02-02 16:28:56 +01:00
return NullUniValue ;
2014-12-09 02:17:57 +01:00
}
2016-02-02 16:28:56 +01:00
UniValue masternodelist ( const UniValue & params , bool fHelp )
2015-02-23 21:26:23 +01:00
{
2015-03-31 03:14:44 +02:00
std : : string strMode = " status " ;
2015-02-23 21:26:23 +01:00
std : : string strFilter = " " ;
if ( params . size ( ) > = 1 ) strMode = params [ 0 ] . get_str ( ) ;
if ( params . size ( ) = = 2 ) strFilter = params [ 1 ] . get_str ( ) ;
2016-09-11 22:22:37 +02:00
if ( fHelp | | (
strMode ! = " activeseconds " & & strMode ! = " addr " & & strMode ! = " full " & &
strMode ! = " lastseen " & & strMode ! = " lastpaidtime " & & strMode ! = " lastpaidblock " & &
2016-09-16 17:22:57 +02:00
strMode ! = " protocol " & & strMode ! = " payee " & & strMode ! = " rank " & & strMode ! = " status " ) )
2015-02-23 21:26:23 +01:00
{
2016-09-16 17:22:57 +02:00
throw std : : runtime_error (
2015-02-23 21:26:23 +01:00
" masternodelist ( \" mode \" \" filter \" ) \n "
" Get a list of masternodes in different modes \n "
" \n Arguments: \n "
2015-03-31 03:14:44 +02:00
" 1. \" mode \" (string, optional/required to use filter, defaults = status) The mode to run list in \n "
2016-09-16 17:22:57 +02:00
" 2. \" filter \" (string, optional) Filter results. Partial match by outpoint by default in all modes, \n "
2015-04-05 23:59:25 +02:00
" additional matches in some modes are also available \n "
2015-02-26 02:35:33 +01:00
" \n Available modes: \n "
2015-02-23 21:26:23 +01:00
" activeseconds - Print number of seconds masternode recognized by the network as enabled \n "
2015-07-14 07:25:07 +02:00
" (since latest issued \" masternode start/start-many/start-alias \" ) \n "
2015-07-18 19:31:28 +02:00
" addr - Print ip address associated with a masternode (can be additionally filtered, partial match) \n "
2016-09-16 17:22:57 +02:00
" full - Print info in format 'status protocol payee lastseen activeseconds lastpaidtime lastpaidblock IP' \n "
2015-04-05 23:59:25 +02:00
" (can be additionally filtered, partial match) \n "
2016-09-11 22:22:37 +02:00
" lastpaidblock - Print the last block height a node was paid on the network \n "
" lastpaidtime - Print the last time a node was paid on the network \n "
2016-09-16 17:22:57 +02:00
" lastseen - Print timestamp of when a masternode was last seen on the network \n "
" payee - Print Dash address associated with a masternode (can be additionally filtered, \n "
2015-04-05 23:59:25 +02:00
" partial match) \n "
2016-09-16 17:22:57 +02:00
" protocol - Print protocol of a masternode (can be additionally filtered, exact match)) \n "
2015-02-23 21:26:23 +01:00
" rank - Print rank of a masternode based on current block \n "
2017-01-19 20:06:56 +01:00
" status - Print masternode status: PRE_ENABLED / ENABLED / EXPIRED / WATCHDOG_EXPIRED / NEW_START_REQUIRED / \n "
" UPDATE_REQUIRED / POSE_BAN / OUTPOINT_SPENT (can be additionally filtered, partial match) \n "
2015-02-23 21:26:23 +01:00
) ;
}
2016-09-11 22:22:37 +02:00
if ( strMode = = " full " | | strMode = = " lastpaidtime " | | strMode = = " lastpaidblock " ) {
2016-11-28 15:21:50 +01:00
mnodeman . UpdateLastPaid ( ) ;
2016-09-11 22:22:37 +02:00
}
2016-02-02 16:28:56 +01:00
UniValue obj ( UniValue : : VOBJ ) ;
2015-03-14 19:34:51 +01:00
if ( strMode = = " rank " ) {
2016-11-28 15:21:50 +01:00
std : : vector < std : : pair < int , CMasternode > > vMasternodeRanks = mnodeman . GetMasternodeRanks ( ) ;
2015-03-14 19:34:51 +01:00
BOOST_FOREACH ( PAIRTYPE ( int , CMasternode ) & s , vMasternodeRanks ) {
2016-09-16 17:22:57 +02:00
std : : string strOutpoint = s . second . vin . prevout . ToStringShort ( ) ;
if ( strFilter ! = " " & & strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , s . first ) ) ;
2015-03-14 19:34:51 +01:00
}
} else {
std : : vector < CMasternode > vMasternodes = mnodeman . GetFullMasternodeVector ( ) ;
BOOST_FOREACH ( CMasternode & mn , vMasternodes ) {
2016-09-16 17:22:57 +02:00
std : : string strOutpoint = mn . vin . prevout . ToStringShort ( ) ;
2015-03-31 03:14:44 +02:00
if ( strMode = = " activeseconds " ) {
2016-09-16 17:22:57 +02:00
if ( strFilter ! = " " & & strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , ( int64_t ) ( mn . lastPing . sigTime - mn . sigTime ) ) ) ;
2015-07-18 19:31:28 +02:00
} else if ( strMode = = " addr " ) {
2016-09-16 17:22:57 +02:00
std : : string strAddress = mn . addr . ToString ( ) ;
if ( strFilter ! = " " & & strAddress . find ( strFilter ) = = std : : string : : npos & &
strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , strAddress ) ) ;
2015-03-14 19:34:51 +01:00
} else if ( strMode = = " full " ) {
2016-09-16 17:22:57 +02:00
std : : ostringstream streamFull ;
2017-01-25 12:37:45 +01:00
streamFull < < std : : setw ( 18 ) < <
2016-09-16 00:00:06 +02:00
mn . GetStatus ( ) < < " " < <
mn . nProtocolVersion < < " " < <
2016-09-16 17:22:57 +02:00
CBitcoinAddress ( mn . pubKeyCollateralAddress . GetID ( ) ) . ToString ( ) < < " " < <
( int64_t ) mn . lastPing . sigTime < < " " < < std : : setw ( 8 ) < <
( int64_t ) ( mn . lastPing . sigTime - mn . sigTime ) < < " " < < std : : setw ( 10 ) < <
mn . GetLastPaidTime ( ) < < " " < < std : : setw ( 6 ) < <
mn . GetLastPaidBlock ( ) < < " " < <
mn . addr . ToString ( ) ;
std : : string strFull = streamFull . str ( ) ;
if ( strFilter ! = " " & & strFull . find ( strFilter ) = = std : : string : : npos & &
strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , strFull ) ) ;
2016-09-11 22:22:37 +02:00
} else if ( strMode = = " lastpaidblock " ) {
2016-09-16 17:22:57 +02:00
if ( strFilter ! = " " & & strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , mn . GetLastPaidBlock ( ) ) ) ;
2016-09-11 22:22:37 +02:00
} else if ( strMode = = " lastpaidtime " ) {
2016-09-16 17:22:57 +02:00
if ( strFilter ! = " " & & strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , mn . GetLastPaidTime ( ) ) ) ;
} else if ( strMode = = " lastseen " ) {
if ( strFilter ! = " " & & strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , ( int64_t ) mn . lastPing . sigTime ) ) ;
} else if ( strMode = = " payee " ) {
2016-09-16 00:00:06 +02:00
CBitcoinAddress address ( mn . pubKeyCollateralAddress . GetID ( ) ) ;
2016-09-16 17:22:57 +02:00
std : : string strPayee = address . ToString ( ) ;
if ( strFilter ! = " " & & strPayee . find ( strFilter ) = = std : : string : : npos & &
strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , strPayee ) ) ;
} else if ( strMode = = " protocol " ) {
if ( strFilter ! = " " & & strFilter ! = strprintf ( " %d " , mn . nProtocolVersion ) & &
strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , ( int64_t ) mn . nProtocolVersion ) ) ;
} else if ( strMode = = " status " ) {
2016-09-16 00:00:06 +02:00
std : : string strStatus = mn . GetStatus ( ) ;
2016-09-16 17:22:57 +02:00
if ( strFilter ! = " " & & strStatus . find ( strFilter ) = = std : : string : : npos & &
strOutpoint . find ( strFilter ) = = std : : string : : npos ) continue ;
obj . push_back ( Pair ( strOutpoint , strStatus ) ) ;
2015-03-14 19:34:51 +01:00
}
2015-02-24 00:48:11 +01:00
}
}
return obj ;
2016-03-16 16:30:22 +01:00
}
2016-03-17 18:39:17 +01:00
bool DecodeHexVecMnb ( std : : vector < CMasternodeBroadcast > & vecMnb , std : : string strHexMnb ) {
2016-03-16 16:30:22 +01:00
if ( ! IsHex ( strHexMnb ) )
return false ;
2016-09-16 17:22:57 +02:00
std : : vector < unsigned char > mnbData ( ParseHex ( strHexMnb ) ) ;
2016-03-16 16:30:22 +01:00
CDataStream ssData ( mnbData , SER_NETWORK , PROTOCOL_VERSION ) ;
try {
2016-03-17 18:39:17 +01:00
ssData > > vecMnb ;
2016-03-16 16:30:22 +01:00
}
catch ( const std : : exception & ) {
return false ;
}
return true ;
}
UniValue masternodebroadcast ( const UniValue & params , bool fHelp )
{
2016-09-16 17:22:57 +02:00
std : : string strCommand ;
2016-03-16 16:30:22 +01:00
if ( params . size ( ) > = 1 )
strCommand = params [ 0 ] . get_str ( ) ;
if ( fHelp | |
( strCommand ! = " create-alias " & & strCommand ! = " create-all " & & strCommand ! = " decode " & & strCommand ! = " relay " ) )
2016-09-16 17:22:57 +02:00
throw std : : runtime_error (
2017-02-10 01:51:47 +01:00
" masternodebroadcast \" command \" ... \n "
2016-03-16 16:30:22 +01:00
" Set of commands to create and relay masternode broadcast messages \n "
" \n Arguments: \n "
" 1. \" command \" (string or set of strings, required) The command to execute \n "
" \n Available commands: \n "
" create-alias - Create single remote masternode broadcast message by assigned alias configured in masternode.conf \n "
" create-all - Create remote masternode broadcast messages for all masternodes configured in masternode.conf \n "
" decode - Decode masternode broadcast message \n "
" relay - Relay masternode broadcast message to the network \n "
2017-02-10 01:51:47 +01:00
) ;
2016-03-16 16:30:22 +01:00
if ( strCommand = = " create-alias " )
{
// wait for reindex and/or import to finish
if ( fImporting | | fReindex )
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Wait for reindex and/or import to finish " ) ;
if ( params . size ( ) < 2 )
2016-09-16 17:22:57 +02:00
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Please specify an alias " ) ;
2016-03-16 16:30:22 +01:00
2016-10-24 01:14:54 +02:00
{
LOCK ( pwalletMain - > cs_wallet ) ;
EnsureWalletIsUnlocked ( ) ;
}
2016-03-16 16:30:22 +01:00
2016-09-16 17:22:57 +02:00
bool fFound = false ;
std : : string strAlias = params [ 1 ] . get_str ( ) ;
2016-03-16 16:30:22 +01:00
UniValue statusObj ( UniValue : : VOBJ ) ;
2016-03-17 18:39:17 +01:00
std : : vector < CMasternodeBroadcast > vecMnb ;
2016-09-16 17:22:57 +02:00
statusObj . push_back ( Pair ( " alias " , strAlias ) ) ;
2016-03-16 16:30:22 +01:00
BOOST_FOREACH ( CMasternodeConfig : : CMasternodeEntry mne , masternodeConfig . getEntries ( ) ) {
2016-09-16 17:22:57 +02:00
if ( mne . getAlias ( ) = = strAlias ) {
fFound = true ;
std : : string strError ;
2016-03-16 16:30:22 +01:00
CMasternodeBroadcast mnb ;
2016-09-16 17:22:57 +02:00
bool fResult = CMasternodeBroadcast : : Create ( mne . getIp ( ) , mne . getPrivKey ( ) , mne . getTxHash ( ) , mne . getOutputIndex ( ) , strError , mnb , true ) ;
2016-03-16 16:30:22 +01:00
2016-09-16 17:22:57 +02:00
statusObj . push_back ( Pair ( " result " , fResult ? " successful " : " failed " ) ) ;
if ( fResult ) {
2016-03-17 18:39:17 +01:00
vecMnb . push_back ( mnb ) ;
CDataStream ssVecMnb ( SER_NETWORK , PROTOCOL_VERSION ) ;
ssVecMnb < < vecMnb ;
statusObj . push_back ( Pair ( " hex " , HexStr ( ssVecMnb . begin ( ) , ssVecMnb . end ( ) ) ) ) ;
2016-03-16 16:30:22 +01:00
} else {
2016-09-16 17:22:57 +02:00
statusObj . push_back ( Pair ( " errorMessage " , strError ) ) ;
2016-03-16 16:30:22 +01:00
}
break ;
}
}
2016-09-16 17:22:57 +02:00
if ( ! fFound ) {
2016-03-17 18:39:17 +01:00
statusObj . push_back ( Pair ( " result " , " not found " ) ) ;
2016-03-16 16:30:22 +01:00
statusObj . push_back ( Pair ( " errorMessage " , " Could not find alias in config. Verify with list-conf. " ) ) ;
}
return statusObj ;
}
if ( strCommand = = " create-all " )
{
// wait for reindex and/or import to finish
if ( fImporting | | fReindex )
throw JSONRPCError ( RPC_INTERNAL_ERROR , " Wait for reindex and/or import to finish " ) ;
2016-10-24 01:14:54 +02:00
{
LOCK ( pwalletMain - > cs_wallet ) ;
EnsureWalletIsUnlocked ( ) ;
}
2016-03-16 16:30:22 +01:00
std : : vector < CMasternodeConfig : : CMasternodeEntry > mnEntries ;
mnEntries = masternodeConfig . getEntries ( ) ;
2016-09-16 17:22:57 +02:00
int nSuccessful = 0 ;
int nFailed = 0 ;
2016-03-16 16:30:22 +01:00
UniValue resultsObj ( UniValue : : VOBJ ) ;
2016-03-17 18:39:17 +01:00
std : : vector < CMasternodeBroadcast > vecMnb ;
2016-03-16 16:30:22 +01:00
BOOST_FOREACH ( CMasternodeConfig : : CMasternodeEntry mne , masternodeConfig . getEntries ( ) ) {
2016-09-16 17:22:57 +02:00
std : : string strError ;
2016-03-16 16:30:22 +01:00
CMasternodeBroadcast mnb ;
2016-09-16 17:22:57 +02:00
bool fResult = CMasternodeBroadcast : : Create ( mne . getIp ( ) , mne . getPrivKey ( ) , mne . getTxHash ( ) , mne . getOutputIndex ( ) , strError , mnb , true ) ;
2016-03-16 16:30:22 +01:00
UniValue statusObj ( UniValue : : VOBJ ) ;
statusObj . push_back ( Pair ( " alias " , mne . getAlias ( ) ) ) ;
2016-09-16 17:22:57 +02:00
statusObj . push_back ( Pair ( " result " , fResult ? " successful " : " failed " ) ) ;
2016-03-16 16:30:22 +01:00
2016-09-16 17:22:57 +02:00
if ( fResult ) {
nSuccessful + + ;
2016-03-17 18:39:17 +01:00
vecMnb . push_back ( mnb ) ;
2016-03-16 16:30:22 +01:00
} else {
2016-09-16 17:22:57 +02:00
nFailed + + ;
statusObj . push_back ( Pair ( " errorMessage " , strError ) ) ;
2016-03-16 16:30:22 +01:00
}
resultsObj . push_back ( Pair ( " status " , statusObj ) ) ;
}
2016-03-17 18:39:17 +01:00
CDataStream ssVecMnb ( SER_NETWORK , PROTOCOL_VERSION ) ;
ssVecMnb < < vecMnb ;
2016-03-16 16:30:22 +01:00
UniValue returnObj ( UniValue : : VOBJ ) ;
2016-09-16 17:22:57 +02:00
returnObj . push_back ( Pair ( " overall " , strprintf ( " Successfully created broadcast messages for %d masternodes, failed to create %d, total %d " , nSuccessful , nFailed , nSuccessful + nFailed ) ) ) ;
2016-03-16 16:30:22 +01:00
returnObj . push_back ( Pair ( " detail " , resultsObj ) ) ;
2016-03-17 18:39:17 +01:00
returnObj . push_back ( Pair ( " hex " , HexStr ( ssVecMnb . begin ( ) , ssVecMnb . end ( ) ) ) ) ;
2016-03-16 16:30:22 +01:00
return returnObj ;
}
if ( strCommand = = " decode " )
{
if ( params . size ( ) ! = 2 )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " Correct usage is 'masternodebroadcast decode \" hexstring \" ' " ) ;
2016-03-17 18:39:17 +01:00
std : : vector < CMasternodeBroadcast > vecMnb ;
2016-03-16 16:30:22 +01:00
2016-03-17 18:39:17 +01:00
if ( ! DecodeHexVecMnb ( vecMnb , params [ 1 ] . get_str ( ) ) )
2016-03-16 16:30:22 +01:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " Masternode broadcast message decode failed " ) ;
2016-09-16 17:22:57 +02:00
int nSuccessful = 0 ;
int nFailed = 0 ;
int nDos = 0 ;
UniValue returnObj ( UniValue : : VOBJ ) ;
2016-03-17 18:39:17 +01:00
BOOST_FOREACH ( CMasternodeBroadcast & mnb , vecMnb ) {
UniValue resultObj ( UniValue : : VOBJ ) ;
2016-03-16 16:30:22 +01:00
2016-09-16 00:00:06 +02:00
if ( mnb . CheckSignature ( nDos ) ) {
2016-09-16 17:22:57 +02:00
nSuccessful + + ;
2016-03-17 18:39:17 +01:00
resultObj . push_back ( Pair ( " vin " , mnb . vin . ToString ( ) ) ) ;
resultObj . push_back ( Pair ( " addr " , mnb . addr . ToString ( ) ) ) ;
2016-09-16 00:00:06 +02:00
resultObj . push_back ( Pair ( " pubKeyCollateralAddress " , CBitcoinAddress ( mnb . pubKeyCollateralAddress . GetID ( ) ) . ToString ( ) ) ) ;
resultObj . push_back ( Pair ( " pubKeyMasternode " , CBitcoinAddress ( mnb . pubKeyMasternode . GetID ( ) ) . ToString ( ) ) ) ;
2016-03-17 18:39:17 +01:00
resultObj . push_back ( Pair ( " vchSig " , EncodeBase64 ( & mnb . vchSig [ 0 ] , mnb . vchSig . size ( ) ) ) ) ;
resultObj . push_back ( Pair ( " sigTime " , mnb . sigTime ) ) ;
2016-09-16 00:00:06 +02:00
resultObj . push_back ( Pair ( " protocolVersion " , mnb . nProtocolVersion ) ) ;
2016-03-17 18:39:17 +01:00
resultObj . push_back ( Pair ( " nLastDsq " , mnb . nLastDsq ) ) ;
UniValue lastPingObj ( UniValue : : VOBJ ) ;
lastPingObj . push_back ( Pair ( " vin " , mnb . lastPing . vin . ToString ( ) ) ) ;
lastPingObj . push_back ( Pair ( " blockHash " , mnb . lastPing . blockHash . ToString ( ) ) ) ;
lastPingObj . push_back ( Pair ( " sigTime " , mnb . lastPing . sigTime ) ) ;
lastPingObj . push_back ( Pair ( " vchSig " , EncodeBase64 ( & mnb . lastPing . vchSig [ 0 ] , mnb . lastPing . vchSig . size ( ) ) ) ) ;
resultObj . push_back ( Pair ( " lastPing " , lastPingObj ) ) ;
} else {
2016-09-16 17:22:57 +02:00
nFailed + + ;
2016-03-17 18:39:17 +01:00
resultObj . push_back ( Pair ( " errorMessage " , " Masternode broadcast signature verification failed " ) ) ;
}
2016-03-16 16:30:22 +01:00
2016-03-17 18:39:17 +01:00
returnObj . push_back ( Pair ( mnb . GetHash ( ) . ToString ( ) , resultObj ) ) ;
}
2016-03-16 16:30:22 +01:00
2016-09-16 17:22:57 +02:00
returnObj . push_back ( Pair ( " overall " , strprintf ( " Successfully decoded broadcast messages for %d masternodes, failed to decode %d, total %d " , nSuccessful , nFailed , nSuccessful + nFailed ) ) ) ;
2016-03-16 16:30:22 +01:00
2016-03-17 18:39:17 +01:00
return returnObj ;
2016-03-16 16:30:22 +01:00
}
if ( strCommand = = " relay " )
{
2016-03-18 00:37:48 +01:00
if ( params . size ( ) < 2 | | params . size ( ) > 3 )
throw JSONRPCError ( RPC_INVALID_PARAMETER , " masternodebroadcast relay \" hexstring \" ( fast ) \n "
" \n Arguments: \n "
" 1. \" hex \" (string, required) Broadcast messages hex string \n "
" 2. fast (string, optional) If none, using safe method \n " ) ;
2016-03-16 16:30:22 +01:00
2016-03-17 18:39:17 +01:00
std : : vector < CMasternodeBroadcast > vecMnb ;
2016-03-16 16:30:22 +01:00
2016-03-17 18:39:17 +01:00
if ( ! DecodeHexVecMnb ( vecMnb , params [ 1 ] . get_str ( ) ) )
2016-03-16 16:30:22 +01:00
throw JSONRPCError ( RPC_DESERIALIZATION_ERROR , " Masternode broadcast message decode failed " ) ;
2016-09-16 17:22:57 +02:00
int nSuccessful = 0 ;
int nFailed = 0 ;
bool fSafe = params . size ( ) = = 2 ;
UniValue returnObj ( UniValue : : VOBJ ) ;
2016-03-17 18:39:17 +01:00
// verify all signatures first, bailout if any of them broken
BOOST_FOREACH ( CMasternodeBroadcast & mnb , vecMnb ) {
UniValue resultObj ( UniValue : : VOBJ ) ;
2016-03-16 16:30:22 +01:00
2016-03-17 18:39:17 +01:00
resultObj . push_back ( Pair ( " vin " , mnb . vin . ToString ( ) ) ) ;
resultObj . push_back ( Pair ( " addr " , mnb . addr . ToString ( ) ) ) ;
2016-03-16 16:30:22 +01:00
2016-03-18 00:37:48 +01:00
int nDos = 0 ;
bool fResult ;
2016-09-16 00:00:06 +02:00
if ( mnb . CheckSignature ( nDos ) ) {
2016-03-18 00:37:48 +01:00
if ( fSafe ) {
2017-01-01 18:48:53 +01:00
fResult = mnodeman . CheckMnbAndUpdateMasternodeList ( NULL , mnb , nDos ) ;
2016-03-18 00:37:48 +01:00
} else {
mnodeman . UpdateMasternodeList ( mnb ) ;
mnb . Relay ( ) ;
fResult = true ;
}
2016-11-13 18:52:34 +01:00
mnodeman . NotifyMasternodeUpdates ( ) ;
2016-03-18 00:37:48 +01:00
} else fResult = false ;
if ( fResult ) {
2016-09-16 17:22:57 +02:00
nSuccessful + + ;
2016-03-17 18:39:17 +01:00
resultObj . push_back ( Pair ( mnb . GetHash ( ) . ToString ( ) , " successful " ) ) ;
} else {
2016-09-16 17:22:57 +02:00
nFailed + + ;
2016-03-17 18:39:17 +01:00
resultObj . push_back ( Pair ( " errorMessage " , " Masternode broadcast signature verification failed " ) ) ;
}
returnObj . push_back ( Pair ( mnb . GetHash ( ) . ToString ( ) , resultObj ) ) ;
}
2016-09-16 17:22:57 +02:00
returnObj . push_back ( Pair ( " overall " , strprintf ( " Successfully relayed broadcast messages for %d masternodes, failed to relay %d, total %d " , nSuccessful , nFailed , nSuccessful + nFailed ) ) ) ;
2016-03-17 18:39:17 +01:00
return returnObj ;
2016-03-16 16:30:22 +01:00
}
return NullUniValue ;
2015-02-23 21:26:23 +01:00
}