neobytes/src/rpcmasternode.cpp

615 lines
24 KiB
C++
Raw Normal View History

// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// 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 "masternode-budget.h"
#include "masternode-payments.h"
#include "masternode-sync.h"
#include "masternodeconfig.h"
#include "masternodeman.h"
#include "rpcserver.h"
2015-04-03 00:51:08 +02:00
#include "utilmoneystr.h"
#include <fstream>
#include <iomanip>
#include <univalue.h>
UniValue darksend(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 1)
throw runtime_error(
"darksend \"command\"\n"
"\nArguments:\n"
"1. \"command\" (string or set of strings, required) The command to execute\n"
"\nAvailable commands:\n"
" start - Start mixing\n"
" stop - Stop mixing\n"
" reset - Reset mixing\n"
" status - Print mixing status\n"
+ HelpRequiringPassphrase());
if(params[0].get_str() == "start"){
if (pwalletMain->IsLocked())
throw JSONRPCError(RPC_WALLET_UNLOCK_NEEDED, "Error: Please enter the wallet passphrase with walletpassphrase first.");
if(fMasterNode)
return "Mixing is not supported from masternodes";
fEnableDarksend = true;
bool result = darkSendPool.DoAutomaticDenominating();
// fEnableDarksend = result;
return "Mixing " + (result ? "started successfully" : ("start failed: " + darkSendPool.GetStatus() + ", will retry"));
}
if(params[0].get_str() == "stop"){
fEnableDarksend = false;
return "Mixing was stopped";
}
if(params[0].get_str() == "reset"){
darkSendPool.Reset();
return "Mixing was reset";
}
if(params[0].get_str() == "status"){
return "Mixing status: " + darkSendPool.GetStatus();
}
return "Unknown command, please see \"help darksend\"";
}
UniValue getpoolinfo(const UniValue& params, bool fHelp)
{
if (fHelp || params.size() != 0)
throw runtime_error(
"getpoolinfo\n"
"Returns an object containing anonymous pool-related information.");
UniValue obj(UniValue::VOBJ);
if (darkSendPool.pSubmittedToMasternode)
obj.push_back(Pair("masternode", darkSendPool.pSubmittedToMasternode->addr.ToString()));
obj.push_back(Pair("queue", (int64_t)vecDarksendQueue.size()));
obj.push_back(Pair("state", darkSendPool.GetState()));
obj.push_back(Pair("entries", darkSendPool.GetEntriesCount()));
obj.push_back(Pair("entries_accepted", darkSendPool.GetCountEntriesAccepted()));
return obj;
}
UniValue masternode(const UniValue& params, bool fHelp)
{
string strCommand;
if (params.size() >= 1)
strCommand = params[0].get_str();
if (fHelp ||
2015-08-26 22:15:37 +02:00
(strCommand != "start" && strCommand != "start-alias" && strCommand != "start-many" && strCommand != "start-all" && strCommand != "start-missing" &&
strCommand != "start-disabled" && strCommand != "list" && strCommand != "list-conf" && strCommand != "count" && strCommand != "enforce" &&
strCommand != "debug" && strCommand != "current" && strCommand != "winners" && strCommand != "genkey" && strCommand != "connect" &&
2015-07-24 17:21:02 +02:00
strCommand != "outputs" && strCommand != "status" && strCommand != "calcscore"))
throw runtime_error(
"masternode \"command\"... ( \"passphrase\" )\n"
"Set of commands to execute masternode related actions\n"
"\nArguments:\n"
"1. \"command\" (string or set of strings, required) The command to execute\n"
"2. \"passphrase\" (string, optional) The wallet passphrase\n"
"\nAvailable commands:\n"
" count - Print number of all known masternodes (optional: 'ds', 'enabled', 'all', 'qualify')\n"
" current - Print info on current masternode winner\n"
" debug - Print masternode status\n"
" genkey - Generate new masternodeprivkey\n"
" enforce - Enforce masternode payments\n"
" outputs - Print masternode compatible outputs\n"
" 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"
" list - Print list of all known masternodes (see masternodelist for more info)\n"
" list-conf - Print masternode.conf in JSON format\n"
" winners - Print list of masternode winners\n"
);
if (strCommand == "list")
{
UniValue newParams(UniValue::VARR);
// forward params but skip "list"
for (unsigned int i = 1; i < params.size(); i++)
newParams.push_back(params[i]);
return masternodelist(newParams, fHelp);
}
if (strCommand == "budget")
{
return "Show budgets";
}
2015-07-18 21:17:17 +02:00
if(strCommand == "connect")
{
std::string strAddress = "";
if (params.size() == 2){
strAddress = params[1].get_str();
} else {
2015-08-15 16:09:13 +02:00
throw runtime_error("Masternode address required\n");
2015-07-18 21:17:17 +02:00
}
CService addr = CService(strAddress);
CNode *pnode = ConnectNode((CAddress)addr, NULL, false);
if(pnode){
pnode->Release();
2015-07-18 21:17:17 +02:00
return "successfully connected";
} else {
2015-08-15 16:09:13 +02:00
throw runtime_error("error connecting\n");
2015-07-18 21:17:17 +02:00
}
}
if (strCommand == "count")
{
if (params.size() > 2){
2015-08-15 16:09:13 +02:00
throw runtime_error("too many parameters\n");
}
if (params.size() == 2)
{
int nCount = 0;
{
LOCK(cs_main);
if(chainActive.Tip())
mnodeman.GetNextMasternodeInQueueForPayment(chainActive.Tip()->nHeight, true, nCount);
}
if(params[1].get_str() == "ds") return mnodeman.CountEnabled(MIN_POOL_PEER_PROTO_VERSION);
if(params[1].get_str() == "enabled") return mnodeman.CountEnabled();
if(params[1].get_str() == "qualify") return nCount;
if(params[1].get_str() == "all") return strprintf("Total: %d (DS Compatible: %d / Enabled: %d / Qualify: %d)",
mnodeman.size(),
2015-07-19 01:20:48 +02:00
mnodeman.CountEnabled(MIN_POOL_PEER_PROTO_VERSION),
mnodeman.CountEnabled(),
nCount);
}
return mnodeman.size();
}
2015-07-18 21:17:17 +02:00
if (strCommand == "current")
{
int nCount = 0;
LOCK(cs_main);
CMasternode* winner = NULL;
if(chainActive.Tip())
winner = mnodeman.GetNextMasternodeInQueueForPayment(chainActive.Height() - 100, true, nCount);
2015-07-18 21:17:17 +02:00
if(winner) {
UniValue obj(UniValue::VOBJ);
2015-07-18 21:17:17 +02:00
obj.push_back(Pair("IP:port", winner->addr.ToString()));
obj.push_back(Pair("protocol", (int64_t)winner->protocolVersion));
obj.push_back(Pair("vin", winner->vin.prevout.ToStringShort()));
obj.push_back(Pair("pubkey", CBitcoinAddress(winner->pubkey.GetID()).ToString()));
2015-07-18 21:17:17 +02:00
obj.push_back(Pair("lastseen", (winner->lastPing == CMasternodePing()) ? winner->sigTime :
winner->lastPing.sigTime));
2015-07-18 21:17:17 +02:00
obj.push_back(Pair("activeseconds", (winner->lastPing == CMasternodePing()) ? 0 :
(winner->lastPing.sigTime - winner->sigTime)));
2015-07-18 21:17:17 +02:00
return obj;
}
return "unknown";
}
if (strCommand == "debug")
{
if(activeMasternode.status != ACTIVE_MASTERNODE_INITIAL || !masternodeSync.IsBlockchainSynced())
2015-07-23 04:11:39 +02:00
return activeMasternode.GetStatus();
2015-07-18 21:17:17 +02:00
CTxIn vin = CTxIn();
CPubKey pubkey = CPubKey();
2015-07-18 21:17:17 +02:00
CKey key;
bool found = activeMasternode.GetMasterNodeVin(vin, pubkey, key);
if(!found){
2015-08-15 16:09:13 +02:00
throw runtime_error("Missing masternode input, please look at the documentation for instructions on masternode creation\n");
2015-07-18 21:17:17 +02:00
} else {
2015-07-23 04:11:39 +02:00
return activeMasternode.GetStatus();
2015-07-18 21:17:17 +02:00
}
}
if(strCommand == "enforce")
{
return (uint64_t)enforceMasternodePaymentsTime;
}
if (strCommand == "start")
{
2015-08-15 16:09:13 +02:00
if(!fMasterNode) throw runtime_error("you must set masternode=1 in the configuration\n");
if(pwalletMain->IsLocked()) {
SecureString strWalletPass;
strWalletPass.reserve(100);
if (params.size() == 2){
strWalletPass = params[1].get_str().c_str();
} else {
2015-08-15 16:09:13 +02:00
throw runtime_error("Your wallet is locked, passphrase is required\n");
}
if(!pwalletMain->Unlock(strWalletPass)){
2015-08-15 16:09:13 +02:00
throw runtime_error("incorrect passphrase\n");
}
}
if(activeMasternode.status != ACTIVE_MASTERNODE_STARTED){
activeMasternode.status = ACTIVE_MASTERNODE_INITIAL; // TODO: consider better way
activeMasternode.ManageStatus();
pwalletMain->Lock();
}
return activeMasternode.GetStatus();
}
if (strCommand == "start-alias")
{
2015-07-18 03:23:52 +02:00
if (params.size() < 2){
2015-08-15 16:09:13 +02:00
throw runtime_error("command needs at least 2 parameters\n");
}
std::string alias = params[1].get_str();
2015-07-18 03:23:52 +02:00
if(pwalletMain->IsLocked()) {
SecureString strWalletPass;
strWalletPass.reserve(100);
if (params.size() == 3){
strWalletPass = params[2].get_str().c_str();
} else {
2015-08-15 16:09:13 +02:00
throw runtime_error("Your wallet is locked, passphrase is required\n");
2015-07-18 03:23:52 +02:00
}
if(!pwalletMain->Unlock(strWalletPass)){
2015-08-15 16:09:13 +02:00
throw runtime_error("incorrect passphrase\n");
2015-07-18 03:23:52 +02:00
}
}
2015-07-18 03:23:52 +02:00
bool found = false;
UniValue statusObj(UniValue::VOBJ);
2015-07-18 03:23:52 +02:00
statusObj.push_back(Pair("alias", alias));
2015-03-21 20:49:21 +01:00
2015-07-18 03:23:52 +02:00
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
if(mne.getAlias() == alias) {
found = true;
std::string errorMessage;
2015-07-18 03:23:52 +02:00
bool result = activeMasternode.Register(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), errorMessage);
2015-07-18 03:23:52 +02:00
statusObj.push_back(Pair("result", result ? "successful" : "failed"));
if(!result) {
statusObj.push_back(Pair("errorMessage", errorMessage));
}
break;
}
}
2015-07-18 03:23:52 +02:00
if(!found) {
statusObj.push_back(Pair("result", "failed"));
statusObj.push_back(Pair("errorMessage", "could not find alias in config. Verify with list-conf."));
}
pwalletMain->Lock();
return statusObj;
}
2015-08-26 22:15:37 +02:00
if (strCommand == "start-many" || strCommand == "start-all" || strCommand == "start-missing" || strCommand == "start-disabled")
{
2015-07-18 03:23:52 +02:00
if(pwalletMain->IsLocked()) {
SecureString strWalletPass;
strWalletPass.reserve(100);
2015-07-18 03:23:52 +02:00
if (params.size() == 2){
strWalletPass = params[1].get_str().c_str();
} else {
2015-08-15 16:09:13 +02:00
throw runtime_error("Your wallet is locked, passphrase is required\n");
2015-07-18 03:23:52 +02:00
}
2015-07-18 03:23:52 +02:00
if(!pwalletMain->Unlock(strWalletPass)){
2015-08-15 16:09:13 +02:00
throw runtime_error("incorrect passphrase\n");
2015-07-18 03:23:52 +02:00
}
}
if((strCommand == "start-missing" || strCommand == "start-disabled") &&
(masternodeSync.RequestedMasternodeAssets <= MASTERNODE_SYNC_LIST ||
masternodeSync.RequestedMasternodeAssets == MASTERNODE_SYNC_FAILED)) {
throw runtime_error("You can't use this command until masternode list is synced\n");
}
2015-07-18 03:23:52 +02:00
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
mnEntries = masternodeConfig.getEntries();
2015-07-18 03:23:52 +02:00
int successful = 0;
int failed = 0;
UniValue resultsObj(UniValue::VOBJ);
2015-07-18 03:23:52 +02:00
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
std::string errorMessage;
2015-03-21 20:49:21 +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);
if(strCommand == "start-missing" && pmn) continue;
if(strCommand == "start-disabled" && pmn && pmn->IsEnabled()) continue;
2015-07-18 03:23:52 +02:00
bool result = activeMasternode.Register(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), errorMessage);
UniValue statusObj(UniValue::VOBJ);
2015-07-18 03:23:52 +02:00
statusObj.push_back(Pair("alias", mne.getAlias()));
2015-02-17 11:27:47 +01:00
statusObj.push_back(Pair("result", result ? "successful" : "failed"));
2015-07-18 03:23:52 +02:00
if(result) {
successful++;
} else {
failed++;
2015-07-18 03:23:52 +02:00
statusObj.push_back(Pair("errorMessage", errorMessage));
}
2015-07-18 03:23:52 +02:00
resultsObj.push_back(Pair("status", statusObj));
}
pwalletMain->Lock();
UniValue returnObj(UniValue::VOBJ);
returnObj.push_back(Pair("overall", strprintf("Successfully started %d masternodes, failed to start %d, total %d", successful, failed, successful + failed)));
2015-07-18 03:23:52 +02:00
returnObj.push_back(Pair("detail", resultsObj));
2015-07-18 03:23:52 +02:00
return returnObj;
}
if (strCommand == "create")
{
2015-08-15 16:09:13 +02:00
throw runtime_error("Not implemented yet, please look at the documentation for instructions on masternode creation\n");
}
if (strCommand == "genkey")
{
CKey secret;
secret.MakeNewKey(false);
return CBitcoinSecret(secret).ToString();
}
if(strCommand == "list-conf")
{
2015-07-18 03:23:52 +02:00
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
mnEntries = masternodeConfig.getEntries();
UniValue resultObj(UniValue::VOBJ);
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
CTxIn vin = CTxIn(uint256S(mne.getTxHash()), uint32_t(atoi(mne.getOutputIndex().c_str())));
CMasternode *pmn = mnodeman.Find(vin);
std::string strStatus = pmn ? pmn->Status() : "MISSING";
UniValue mnObj(UniValue::VOBJ);
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()));
mnObj.push_back(Pair("status", strStatus));
resultObj.push_back(Pair("masternode", mnObj));
}
return resultObj;
}
if (strCommand == "outputs"){
// Find possible candidates
vector<COutput> possibleCoins = activeMasternode.SelectCoinsMasternode();
UniValue obj(UniValue::VOBJ);
BOOST_FOREACH(COutput& out, possibleCoins) {
obj.push_back(Pair(out.tx->GetHash().ToString(), strprintf("%d", out.i)));
}
return obj;
}
2015-06-24 18:41:03 +02:00
if(strCommand == "status")
{
2015-08-15 16:09:13 +02:00
if(!fMasterNode) throw runtime_error("This is not a masternode\n");
2015-06-24 18:41:03 +02:00
UniValue mnObj(UniValue::VOBJ);
CMasternode *pmn = mnodeman.Find(activeMasternode.vin);
mnObj.push_back(Pair("vin", activeMasternode.vin.ToString()));
mnObj.push_back(Pair("service", activeMasternode.service.ToString()));
if (pmn) mnObj.push_back(Pair("pubkey", CBitcoinAddress(pmn->pubkey.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")
{
int nHeight;
{
LOCK(cs_main);
CBlockIndex* pindex = chainActive.Tip();
if(!pindex) return NullUniValue;
nHeight = pindex->nHeight;
}
int nLast = 10;
std::string strFilter = "";
if (params.size() >= 2){
2015-07-22 00:14:54 +02:00
nLast = atoi(params[1].get_str());
}
if (params.size() == 3){
strFilter = params[2].get_str();
}
if (params.size() > 3)
throw runtime_error("Correct usage is 'masternode winners ( \"count\" \"filter\" )'");
UniValue obj(UniValue::VOBJ);
2015-07-18 21:17:17 +02:00
for(int i = nHeight - nLast; i < nHeight + 20; i++)
2015-07-18 21:17:17 +02:00
{
std::string strPayment = GetRequiredPaymentsString(i);
if(strFilter !="" && strPayment.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strprintf("%d", i), strPayment));
2015-07-18 21:17:17 +02:00
}
return obj;
}
2015-07-24 17:21:02 +02:00
/*
Shows which masternode wins by score each block
*/
if (strCommand == "calcscore")
{
int nHeight;
{
LOCK(cs_main);
CBlockIndex* pindex = chainActive.Tip();
if(!pindex) return NullUniValue;
nHeight = pindex->nHeight;
}
2015-07-24 17:21:02 +02:00
int nLast = 10;
if (params.size() >= 2){
nLast = atoi(params[1].get_str());
}
UniValue obj(UniValue::VOBJ);
2015-07-24 17:21:02 +02:00
std::vector<CMasternode> vMasternodes = mnodeman.GetFullMasternodeVector();
for(int i = nHeight - nLast; i < nHeight + 20; i++){
arith_uint256 nHigh = 0;
2015-07-24 17:21:02 +02:00
CMasternode *pBestMasternode = NULL;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
arith_uint256 n = UintToArith256(mn.CalculateScore(1, i - 100));
2015-07-24 17:21:02 +02:00
if(n > nHigh){
nHigh = n;
pBestMasternode = &mn;
}
}
if(pBestMasternode)
obj.push_back(Pair(strprintf("%d", i), pBestMasternode->vin.prevout.ToStringShort().c_str()));
2015-07-24 17:21:02 +02:00
}
return obj;
}
return NullUniValue;
}
UniValue masternodelist(const UniValue& params, bool fHelp)
{
std::string strMode = "status";
std::string strFilter = "";
if (params.size() >= 1) strMode = params[0].get_str();
if (params.size() == 2) strFilter = params[1].get_str();
if (fHelp ||
(strMode != "status" && strMode != "vin" && strMode != "pubkey" && strMode != "lastseen" && strMode != "activeseconds" && strMode != "rank" && strMode != "addr"
&& strMode != "protocol" && strMode != "full" && strMode != "lastpaid"))
{
throw runtime_error(
"masternodelist ( \"mode\" \"filter\" )\n"
"Get a list of masternodes in different modes\n"
"\nArguments:\n"
"1. \"mode\" (string, optional/required to use filter, defaults = status) The mode to run list in\n"
2015-04-05 23:59:25 +02:00
"2. \"filter\" (string, optional) Filter results. Partial match by IP by default in all modes,\n"
" additional matches in some modes are also available\n"
"\nAvailable modes:\n"
" activeseconds - Print number of seconds masternode recognized by the network as enabled\n"
" (since latest issued \"masternode start/start-many/start-alias\")\n"
" addr - Print ip address associated with a masternode (can be additionally filtered, partial match)\n"
2015-06-23 22:44:20 +02:00
" full - Print info in format 'status protocol pubkey IP lastseen activeseconds lastpaid'\n"
2015-04-05 23:59:25 +02:00
" (can be additionally filtered, partial match)\n"
" lastseen - Print timestamp of when a masternode was last seen on the network\n"
" lastpaid - The last time a node was paid on the network\n"
" protocol - Print protocol of a masternode (can be additionally filtered, exact match))\n"
2015-04-05 23:59:25 +02:00
" pubkey - Print public key associated with a masternode (can be additionally filtered,\n"
" partial match)\n"
" rank - Print rank of a masternode based on current block\n"
2015-04-05 23:59:25 +02:00
" status - Print masternode status: ENABLED / EXPIRED / VIN_SPENT / REMOVE / POS_ERROR\n"
" (can be additionally filtered, partial match)\n"
);
}
UniValue obj(UniValue::VOBJ);
if (strMode == "rank") {
std::vector<pair<int, CMasternode> > vMasternodeRanks = mnodeman.GetMasternodeRanks(chainActive.Tip()->nHeight);
BOOST_FOREACH(PAIRTYPE(int, CMasternode)& s, vMasternodeRanks) {
std::string strVin = s.second.vin.prevout.ToStringShort();
if(strFilter !="" && strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, s.first));
}
} else {
std::vector<CMasternode> vMasternodes = mnodeman.GetFullMasternodeVector();
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
std::string strVin = mn.vin.prevout.ToStringShort();
if (strMode == "activeseconds") {
if(strFilter !="" && strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, (int64_t)(mn.lastPing.sigTime - mn.sigTime)));
} else if (strMode == "addr") {
if(strFilter !="" && mn.vin.prevout.hash.ToString().find(strFilter) == string::npos &&
strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, mn.addr.ToString()));
} else if (strMode == "full") {
std::ostringstream addrStream;
addrStream << setw(21) << strVin;
std::ostringstream stringStream;
stringStream << setw(9) <<
mn.Status() << " " <<
mn.protocolVersion << " " <<
CBitcoinAddress(mn.pubkey.GetID()).ToString() << " " << setw(21) <<
mn.addr.ToString() << " " <<
2015-07-23 04:11:39 +02:00
(int64_t)mn.lastPing.sigTime << " " << setw(8) <<
(int64_t)(mn.lastPing.sigTime - mn.sigTime) << " " <<
(int64_t)mn.GetLastPaid();
std::string output = stringStream.str();
stringStream << " " << strVin;
if(strFilter !="" && stringStream.str().find(strFilter) == string::npos &&
strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(addrStream.str(), output));
} else if (strMode == "lastseen") {
if(strFilter !="" && strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, (int64_t)mn.lastPing.sigTime));
} else if (strMode == "lastpaid"){
if(strFilter !="" && mn.vin.prevout.hash.ToString().find(strFilter) == string::npos &&
strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, (int64_t)mn.GetLastPaid()));
} else if (strMode == "protocol") {
if(strFilter !="" && strFilter != strprintf("%d", mn.protocolVersion) &&
strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, (int64_t)mn.protocolVersion));
} else if (strMode == "pubkey") {
CBitcoinAddress address(mn.pubkey.GetID());
if(strFilter !="" && address.ToString().find(strFilter) == string::npos &&
strVin.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, address.ToString()));
} else if(strMode == "status") {
std::string strStatus = mn.Status();
if(strFilter !="" && strVin.find(strFilter) == string::npos && strStatus.find(strFilter) == string::npos) continue;
obj.push_back(Pair(strVin, strStatus));
}
}
}
return obj;
}