Improve support for start-many:

- refactored CActiveMasternode
- added masternodeconfig to handle remote masternode configuration
- read masternodeconfig upon init
- new masternode rpc commands: stop-many, start-alias, stop-alias, list-conf
- added notCapableReason field for better handling not capable issues
This commit is contained in:
Francis Reynders 2014-12-06 20:41:53 +01:00
parent b40755d88c
commit 2d3420c407
20 changed files with 777 additions and 306 deletions

View File

@ -168,6 +168,7 @@ HEADERS += src/qt/bitcoingui.h \
src/core.h \
src/masternode.h \
src/activemasternode.h \
src/masternodeconfig.h \
src/net.h \
src/key.h \
src/db.h \
@ -269,6 +270,7 @@ SOURCES += src/qt/bitcoin.cpp \
src/instantx.cpp \
src/masternode.cpp \
src/activemasternode.cpp \
src/masternodeconfig.cpp \
src/core.cpp \
src/init.cpp \
src/net.cpp \

View File

@ -2,289 +2,337 @@
#include "core.h"
#include "activemasternode.h"
using namespace std;
using namespace boost;
CActiveMasternode activeMasternode;
//
// Bootup the masternode, look for a 1000DRK input and register on the network
//
void CActiveMasternode::RegisterAsMasterNode(bool stop)
void CActiveMasternode::ManageStatus()
{
if(!fMasterNode) return;
std::string errorMessage;
LogPrintf("CActiveMasternode::ManageStatus() - Begin\n");
if(!fMasterNode) return;
//need correct adjusted time to send ping
bool fIsInitialDownload = IsInitialBlockDownload();
if(fIsInitialDownload) {
isCapableMasterNode = MASTERNODE_SYNC_IN_PROCESS;
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sync in progress. Must wait until sync is complete to start masternode.\n");
status = MASTERNODE_SYNC_IN_PROCESS;
LogPrintf("CActiveMasternode::ManageStatus() - Sync in progress. Must wait until sync is complete to start masternode.\n");
return;
}
std::string errorMessage;
CKey key2;
CPubKey pubkey2;
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, key2, pubkey2))
{
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Invalid masternodeprivkey: '%s'\n", errorMessage.c_str());
exit(0);
if(status == MASTERNODE_INPUT_TOO_NEW || status == MASTERNODE_NOT_CAPABLE || status == MASTERNODE_SYNC_IN_PROCESS){
status = MASTERNODE_NOT_PROCESSED;
}
if(isCapableMasterNode == MASTERNODE_INPUT_TOO_NEW || isCapableMasterNode == MASTERNODE_NOT_CAPABLE || isCapableMasterNode == MASTERNODE_SYNC_IN_PROCESS){
isCapableMasterNode = MASTERNODE_NOT_PROCESSED;
}
if(isCapableMasterNode == MASTERNODE_NOT_PROCESSED) {
if(status == MASTERNODE_NOT_PROCESSED) {
if(strMasterNodeAddr.empty()) {
if(!GetLocal(masterNodeSignAddr)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Can't detect external address. Please use the masternodeaddr configuration option.\n");
isCapableMasterNode = MASTERNODE_NOT_CAPABLE;
if(!GetLocal(service)) {
notCapableReason = "Can't detect external address. Please use the masternodeaddr configuration option.";
status = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str());
return;
}
} else {
masterNodeSignAddr = CService(strMasterNodeAddr);
service = CService(strMasterNodeAddr);
}
if((fTestNet && masterNodeSignAddr.GetPort() != 19999) || (!fTestNet && masterNodeSignAddr.GetPort() != 9999)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Invalid port\n");
isCapableMasterNode = MASTERNODE_NOT_CAPABLE;
if((fTestNet && service.GetPort() != 19999) || (!fTestNet && service.GetPort() != 9999)) {
notCapableReason = "Invalid port: " + boost::lexical_cast<string>(service.GetPort()) + " -only 9999 or 19999 are supported.";
status = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str());
return;
}
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Checking inbound connection to '%s'\n", masterNodeSignAddr.ToString().c_str());
LogPrintf("CActiveMasternode::ManageStatus() - Checking inbound connection to '%s'\n", service.ToString().c_str());
if(ConnectNode((CAddress)masterNodeSignAddr, masterNodeSignAddr.ToString().c_str())){
masternodePortOpen = MASTERNODE_PORT_OPEN;
} else {
masternodePortOpen = MASTERNODE_PORT_NOT_OPEN;
isCapableMasterNode = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Port not open.\n");
if(!ConnectNode((CAddress)service, service.ToString().c_str())){
notCapableReason = "Could not connect to " + service.ToString();
status = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str());
return;
}
if(pwalletMain->IsLocked()){
isCapableMasterNode = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Not capable.\n");
notCapableReason = "Wallet is locked.";
status = MASTERNODE_NOT_CAPABLE;
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason.c_str());
return;
}
isCapableMasterNode = MASTERNODE_NOT_CAPABLE;
// Set defaults
status = MASTERNODE_NOT_CAPABLE;
notCapableReason = "Unknown.";
CKey SecretKey;
// Choose coins to use
if(GetMasterNodeVin(vinMasternode, pubkeyMasterNode, SecretKey)) {
CPubKey pubKeyCollateralAddress;
CKey keyCollateralAddress;
if(GetInputAge(vinMasternode) < MASTERNODE_MIN_CONFIRMATIONS){
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Input must have least %d confirmations - %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS, GetInputAge(vinMasternode));
isCapableMasterNode = MASTERNODE_INPUT_TOO_NEW;
if(GetMasterNodeVin(vin, pubKeyCollateralAddress, keyCollateralAddress)) {
if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){
LogPrintf("CActiveMasternode::ManageStatus() - Input must have least %d confirmations - %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS, GetInputAge(vin));
status = MASTERNODE_INPUT_TOO_NEW;
return;
}
int protocolVersion = PROTOCOL_VERSION;
masterNodeSignatureTime = GetAdjustedTime();
LogPrintf("CActiveMasternode::ManageStatus() - Is capable master node!\n");
std::string vchPubKey(pubkeyMasterNode.begin(), pubkeyMasterNode.end());
std::string vchPubKey2(pubkey2.begin(), pubkey2.end());
std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(protocolVersion);
status = MASTERNODE_IS_CAPABLE;
notCapableReason = "";
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, SecretKey)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sign message failed\n");
return;
}
pwalletMain->LockCoin(vin.prevout);
if(!darkSendSigner.VerifyMessage(pubkeyMasterNode, vchMasterNodeSignature, strMessage, errorMessage)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Verify message failed\n");
return;
}
// send to all nodes
CPubKey pubKeyMasternode;
CKey keyMasternode;
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Is capable master node!\n");
isCapableMasterNode = MASTERNODE_IS_CAPABLE;
pwalletMain->LockCoin(vinMasternode.prevout);
bool found = false;
BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes)
if(mn.vin == vinMasternode)
found = true;
if(!found) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Adding myself to masternode list %s - %s\n", masterNodeSignAddr.ToString().c_str(), vinMasternode.ToString().c_str());
CMasterNode mn(masterNodeSignAddr, vinMasternode, pubkeyMasterNode, vchMasterNodeSignature, masterNodeSignatureTime, pubkey2, PROTOCOL_VERSION);
mn.UpdateLastSeen(masterNodeSignatureTime);
darkSendMasterNodes.push_back(mn);
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Masternode input = %s\n", vinMasternode.ToString().c_str());
}
//relay to all
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
{
pnode->PushMessage("dsee", vinMasternode, masterNodeSignAddr, vchMasterNodeSignature, masterNodeSignatureTime, pubkeyMasterNode, pubkey2, -1, -1, masterNodeSignatureTime, protocolVersion);
LogPrintf("Register::ManageStatus() - Error upon calling SetKey: %s\n", errorMessage.c_str());
return;
}
if(!Register(vin, service, keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage)) {
LogPrintf("CActiveMasternode::ManageStatus() - Error on Register: %s", errorMessage.c_str());
}
return;
} else {
LogPrintf("CActiveMasternode::ManageStatus() - Could not find suitable coins!\n");
}
}
if(isCapableMasterNode != MASTERNODE_IS_CAPABLE && isCapableMasterNode != MASTERNODE_REMOTELY_ENABLED) return;
//send to all peers
if(!Dseep(errorMessage)) {
LogPrintf("CActiveMasternode::ManageStatus() - Error on Ping: %s", errorMessage.c_str());
}
}
masterNodeSignatureTime = GetAdjustedTime();
// Send stop dseep to network for remote masternode
bool CActiveMasternode::StopMasterNode(std::string strService, std::string strKeyMasternode, std::string& errorMessage) {
CTxIn vin;
CKey keyMasternode;
CPubKey pubKeyMasternode;
std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + boost::lexical_cast<std::string>(stop);
if(!darkSendSigner.SetKey(strKeyMasternode, errorMessage, keyMasternode, pubKeyMasternode)) {
LogPrintf("CActiveMasternode::StopMasterNode() - Error: %s\n", errorMessage.c_str());
return false;
}
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, key2)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Sign message failed\n");
return;
return StopMasterNode(vin, CService(strService), keyMasternode, pubKeyMasternode, errorMessage);
}
// Send stop dseep to network for main masternode
bool CActiveMasternode::StopMasterNode(std::string& errorMessage) {
if(status != MASTERNODE_IS_CAPABLE && status != MASTERNODE_REMOTELY_ENABLED) {
errorMessage = "masternode is not in a running status";
LogPrintf("CActiveMasternode::StopMasterNode() - Error: %s\n", errorMessage.c_str());
return false;
}
status = MASTERNODE_STOPPED;
CPubKey pubKeyMasternode;
CKey keyMasternode;
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
{
LogPrintf("Register::ManageStatus() - Error upon calling SetKey: %s\n", errorMessage.c_str());
return false;
}
if(!darkSendSigner.VerifyMessage(pubkey2, vchMasterNodeSignature, strMessage, errorMessage)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Verify message failed\n");
return;
return StopMasterNode(vin, service, keyMasternode, pubKeyMasternode, errorMessage);
}
// Send stop dseep to network for any masternode
bool CActiveMasternode::StopMasterNode(CTxIn vin, CService service, CKey keyMasternode, CPubKey pubKeyMasternode, std::string& errorMessage) {
pwalletMain->UnlockCoin(vin.prevout);
return Dseep(vin, service, keyMasternode, pubKeyMasternode, errorMessage, true);
}
bool CActiveMasternode::Dseep(std::string& errorMessage) {
if(status != MASTERNODE_IS_CAPABLE && status != MASTERNODE_REMOTELY_ENABLED) {
errorMessage = "masternode is not in a running status";
LogPrintf("CActiveMasternode::Dseep() - Error: %s\n", errorMessage.c_str());
return false;
}
CPubKey pubKeyMasternode;
CKey keyMasternode;
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode))
{
LogPrintf("Register::ManageStatus() - Error upon calling SetKey: %s\n", errorMessage.c_str());
return false;
}
return Dseep(vin, service, keyMasternode, pubKeyMasternode, errorMessage, false);
}
bool CActiveMasternode::Dseep(CTxIn vin, CService service, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage, bool stop) {
std::string errorMessage;
std::vector<unsigned char> vchMasterNodeSignature;
std::string strMasterNodeSignMessage;
int64 masterNodeSignatureTime = GetAdjustedTime();
std::string strMessage = service.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + boost::lexical_cast<std::string>(stop);
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, keyMasternode)) {
retErrorMessage = "sign message failed: " + errorMessage;
LogPrintf("CActiveMasternode::Dseep() - Error: %s\n", retErrorMessage.c_str());
return false;
}
if(!darkSendSigner.VerifyMessage(pubKeyMasternode, vchMasterNodeSignature, strMessage, errorMessage)) {
retErrorMessage = "Verify message failed: " + errorMessage;
LogPrintf("CActiveMasternode::Dseep() - Error: %s\n", retErrorMessage.c_str());
return false;
}
// Update Last Seen timestamp in masternode list
bool found = false;
BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes) {
//LogPrintf(" -- %s\n", mn.vin.ToString().c_str());
if(mn.vin == vinMasternode) {
if(mn.vin == vin) {
found = true;
mn.UpdateLastSeen();
}
}
if(!found){
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Darksend Masternode List doesn't include our masternode, Shutting down masternode pinging service! %s\n", vinMasternode.ToString().c_str());
isCapableMasterNode = MASTERNODE_STOPPED;
return;
// Seems like we are trying to send a ping while the masternode is not registered in the network
retErrorMessage = "Darksend Masternode List doesn't include our masternode, Shutting down masternode pinging service! " + vin.ToString();
LogPrintf("CActiveMasternode::Dseep() - Error: %s\n", retErrorMessage.c_str());
status = MASTERNODE_NOT_CAPABLE;
notCapableReason = retErrorMessage;
return false;
}
LogPrintf("CActiveMasternode::RegisterAsMasterNode() - Masternode input = %s\n", vinMasternode.ToString().c_str());
//send to all peers
LogPrintf("CActiveMasternode::Dseep() - SendDarkSendElectionEntryPing vin = %s\n", vin.ToString().c_str());
SendDarkSendElectionEntryPing(vin, vchMasterNodeSignature, masterNodeSignatureTime, stop);
if (stop) isCapableMasterNode = MASTERNODE_STOPPED;
//relay to all peers
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
pnode->PushMessage("dseep", vinMasternode, vchMasterNodeSignature, masterNodeSignatureTime, stop);
}
return true;
}
//
// Bootup the masternode, look for a 1000DRK input and register on the network
// Takes 2 parameters to start a remote masternode
//
bool CActiveMasternode::RegisterAsMasterNodeRemoteOnly(std::string strMasterNodeAddr, std::string strMasterNodePrivKey)
{
if(!fMasterNode) return false;
bool CActiveMasternode::Register(std::string strService, std::string strKeyMasternode, std::string txHash, std::string strOutputIndex, std::string& errorMessage) {
CTxIn vin;
CPubKey pubKeyCollateralAddress;
CKey keyCollateralAddress;
CPubKey pubKeyMasternode;
CKey keyMasternode;
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Address %s MasterNodePrivKey %s\n", strMasterNodeAddr.c_str(), strMasterNodePrivKey.c_str());
if(!darkSendSigner.SetKey(strKeyMasternode, errorMessage, keyMasternode, pubKeyMasternode))
{
LogPrintf("Register::Register() - Error upon calling SetKey: %s\n", errorMessage.c_str());
return false;
}
if(!GetMasterNodeVin(vin, pubKeyCollateralAddress, keyCollateralAddress, txHash, strOutputIndex)) {
errorMessage = "could not allocate vin";
LogPrintf("Register::Register() - Error: %s\n", errorMessage.c_str());
return false;
}
return Register(vin, CService(strService), keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage);
}
bool CActiveMasternode::Register(CTxIn vin, CService service, CKey keyCollateralAddress, CPubKey pubKeyCollateralAddress, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage) {
std::string errorMessage;
std::vector<unsigned char> vchMasterNodeSignature;
std::string strMasterNodeSignMessage;
int64 masterNodeSignatureTime = GetAdjustedTime();
CKey key2;
CPubKey pubkey2;
std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end());
std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end());
std::string strMessage = service.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(PROTOCOL_VERSION);
if(!darkSendSigner.SetKey(strMasterNodePrivKey, errorMessage, key2, pubkey2))
{
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Invalid masternodeprivkey: '%s'\n", errorMessage.c_str());
return false;
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, keyCollateralAddress)) {
retErrorMessage = "sign message failed: " + errorMessage;
LogPrintf("CActiveMasternode::Register() - Error: %s\n", retErrorMessage.c_str());
return false;
}
CService masterNodeSignAddr = CService(strMasterNodeAddr);
BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes){
if(mn.addr == masterNodeSignAddr){
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Address in use\n");
return false;
}
if(!darkSendSigner.VerifyMessage(pubKeyCollateralAddress, vchMasterNodeSignature, strMessage, errorMessage)) {
retErrorMessage = "Verify message failed: " + errorMessage;
LogPrintf("CActiveMasternode::Register() - Error: %s\n", retErrorMessage.c_str());
return false;
}
bool found = false;
BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes)
if(mn.vin == vin)
found = true;
if(!found) {
LogPrintf("CActiveMasternode::Register() - Adding to masternode list service: %s - vin: %s\n", service.ToString().c_str(), vin.ToString().c_str());
CMasterNode mn(service, vin, pubKeyCollateralAddress, vchMasterNodeSignature, masterNodeSignatureTime, pubKeyMasternode, PROTOCOL_VERSION);
mn.UpdateLastSeen(masterNodeSignatureTime);
darkSendMasterNodes.push_back(mn);
}
if((fTestNet && masterNodeSignAddr.GetPort() != 19999) || (!fTestNet && masterNodeSignAddr.GetPort() != 9999)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Invalid port\n");
return false;
}
//send to all peers
LogPrintf("CActiveMasternode::Register() - SendDarkSendElectionEntry vin = %s\n", vin.ToString().c_str());
SendDarkSendElectionEntry(vin, service, vchMasterNodeSignature, masterNodeSignatureTime, pubKeyCollateralAddress, pubKeyMasternode, -1, -1, masterNodeSignatureTime, PROTOCOL_VERSION);
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Checking inbound connection to '%s'\n", masterNodeSignAddr.ToString().c_str());
if(!ConnectNode((CAddress)masterNodeSignAddr, masterNodeSignAddr.ToString().c_str())){
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Error connecting to port\n");
return false;
}
if(pwalletMain->IsLocked()){
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Wallet is locked\n");
return false;
}
CKey SecretKey;
CTxIn vinMasternode;
CPubKey pubkeyMasterNode;
int masterNodeSignatureTime = 0;
// Choose coins to use
while (GetMasterNodeVin(vinMasternode, pubkeyMasterNode, SecretKey)) {
// don't use a vin that's registered
BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes)
if(mn.vin == vinMasternode)
continue;
if(GetInputAge(vinMasternode) < MASTERNODE_MIN_CONFIRMATIONS)
continue;
masterNodeSignatureTime = GetAdjustedTime();
std::string vchPubKey(pubkeyMasterNode.begin(), pubkeyMasterNode.end());
std::string vchPubKey2(pubkey2.begin(), pubkey2.end());
std::string strMessage = masterNodeSignAddr.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(PROTOCOL_VERSION);
if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, SecretKey)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Sign message failed\n");
return false;
}
if(!darkSendSigner.VerifyMessage(pubkeyMasterNode, vchMasterNodeSignature, strMessage, errorMessage)) {
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Verify message failed\n");
return false;
}
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - Is capable master node!\n");
pwalletMain->LockCoin(vinMasternode.prevout);
int protocolVersion = PROTOCOL_VERSION;
//relay to all
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
pnode->PushMessage("dsee", vinMasternode, masterNodeSignAddr, vchMasterNodeSignature, masterNodeSignatureTime, pubkeyMasterNode, pubkey2, -1, -1, masterNodeSignatureTime, protocolVersion);
}
return true;
}
LogPrintf("CActiveMasternode::RegisterAsMasterNodeRemoteOnly() - No sutable vin found\n");
return false;
return true;
}
bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey) {
return GetMasterNodeVin(vin, pubkey, secretKey, "", "");
}
bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey)
{
int64 nValueIn = 0;
bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex) {
CScript pubScript;
// try once before we try to denominate
if (!pwalletMain->SelectCoinsMasternode(vin, nValueIn, pubScript))
{
if(fDebug) LogPrintf("CActiveMasternode::GetMasterNodeVin - I'm not a capable masternode\n");
return false;
// Find possible candidates
vector<COutput> possibleCoins = SelectCoinsMasternode();
COutput *selectedOutput;
// Find the vin
if(!strTxHash.empty()) {
// Let's find it
uint256 txHash(strTxHash);
int outputIndex = boost::lexical_cast<int>(outputIndex);
bool found = false;
BOOST_FOREACH(COutput& out, possibleCoins) {
if(true) {
selectedOutput = &out;
found = true;
break;
}
}
if(!found) {
LogPrintf("CActiveMasternode::GetMasterNodeVin - Could not locate valid vin\n");
return false;
}
} else {
// No output specified, Select the first one
if(possibleCoins.size() > 0) {
selectedOutput = &possibleCoins[0];
} else {
LogPrintf("CActiveMasternode::GetMasterNodeVin - Could not locate specified vin from possible list\n");
return false;
}
}
CTxDestination address1;
// At this point we have a selected output, retrieve the associated info
return GetVinFromOutput(*selectedOutput, vin, pubkey, secretKey);
}
// Extract masternode vin information from output
bool CActiveMasternode::GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey) {
CScript pubScript;
vin = CTxIn(out.tx->GetHash(),out.i);
pubScript = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
CTxDestination address1;
ExtractDestination(pubScript, address1);
CBitcoinAddress address2(address1);
@ -303,16 +351,62 @@ bool CActiveMasternode::GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secr
return true;
}
// get all possible outputs for running masternode
vector<COutput> CActiveMasternode::SelectCoinsMasternode()
{
CCoinControl *coinControl=NULL;
vector<COutput> vCoins;
vector<COutput> filteredCoins;
// Retrieve all possible outputs
pwalletMain->AvailableCoins(vCoins, true, coinControl, ALL_COINS);
// Filter
BOOST_FOREACH(const COutput& out, vCoins)
{
if(out.tx->vout[out.i].nValue == 1000*COIN) { //exactly
filteredCoins.push_back(out);
}
}
return filteredCoins;
}
/* select coins with specified transaction hash and output index */
/*
bool CActiveMasternode::SelectCoinsMasternode(CTxIn& vin, int64& nValueIn, CScript& pubScript, std::string strTxHash, std::string strOutputIndex)
{
CWalletTx ctx;
// Convert configuration strings
uint256 txHash;
int outputIndex;
txHash.SetHex(strTxHash);
std::istringstream(strOutputIndex) >> outputIndex;
if(pwalletMain->GetTransaction(txHash, ctx)) {
if(ctx.vout[outputIndex].nValue == 1000*COIN) { //exactly
vin = CTxIn(ctx.GetHash(), outputIndex);
pubScript = ctx.vout[outputIndex].scriptPubKey; // the inputs PubKey
nValueIn = ctx.vout[outputIndex].nValue;
return true;
}
}
return false;
}
*/
// when starting a masternode, this can enable to run as a hot wallet with no funds
bool CActiveMasternode::EnableHotColdMasterNode(CTxIn& vin, int64 sigTime, CService& addr)
bool CActiveMasternode::EnableHotColdMasterNode(CTxIn& newVin, CService& newService)
{
if(!fMasterNode) return false;
isCapableMasterNode = MASTERNODE_REMOTELY_ENABLED;
status = MASTERNODE_REMOTELY_ENABLED;
vinMasternode = vin;
masterNodeSignatureTime = sigTime;
masterNodeSignAddr = addr;
//The values below are needed for signing dseep messages going forward
this->vin = newVin;
this->service = newService;
LogPrintf("CActiveMasternode::EnableHotColdMasterNode() - Enabled! You may shut down the cold daemon.\n");

View File

@ -1,4 +1,3 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
@ -21,36 +20,45 @@ extern CActiveMasternode activeMasternode;
class CActiveMasternode
{
public:
CTxIn vinMasternode;
CPubKey pubkeyMasterNode;
CPubKey pubkeyMasterNode2;
// Initialized by init.cpp
// Keys for the main masternode
CPubKey pubKeyMasternode;
std::string strMasterNodeSignMessage;
std::vector<unsigned char> vchMasterNodeSignature;
// Initialized while registering masternode
CTxIn vin;
CService service;
std::string masterNodeAddr;
CService masterNodeSignAddr;
int isCapableMasterNode;
int64 masterNodeSignatureTime;
int masternodePortOpen;
int status;
std::string notCapableReason;
CActiveMasternode()
{
isCapableMasterNode = MASTERNODE_NOT_PROCESSED;
masternodePortOpen = 0;
status = MASTERNODE_NOT_PROCESSED;
}
void ManageStatus(); // manage status of main masternode
bool Dseep(std::string& errorMessage); // ping for main masternode
bool Dseep(CTxIn vin, CService service, CKey key, CPubKey pubKey, std::string &retErrorMessage, bool stop); // ping for any masternode
bool StopMasterNode(std::string& errorMessage); // stop main masternode
bool StopMasterNode(std::string strService, std::string strKeyMasternode, std::string& errorMessage); // stop remote masternode
bool StopMasterNode(CTxIn vin, CService service, CKey key, CPubKey pubKey, std::string& errorMessage); // stop any masternode
bool Register(std::string strService, std::string strKey, std::string txHash, std::string strOutputIndex, std::string& errorMessage); // register remote masternode
bool Register(CTxIn vin, CService service, CKey key, CPubKey pubKey, CKey keyMasternode, CPubKey pubKeyMasternode, std::string &retErrorMessage); // register any masternode
// get 1000DRK input that can be used for the masternode
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey);
bool GetMasterNodeVin(CTxIn& vin, CPubKey& pubkey, CKey& secretKey, std::string strTxHash, std::string strOutputIndex);
vector<COutput> SelectCoinsMasternode();
bool GetVinFromOutput(COutput out, CTxIn& vin, CPubKey& pubkey, CKey& secretKey);
// start the masternode and register with the network
void RegisterAsMasterNode(bool stop);
// start a remote masternode
bool RegisterAsMasterNodeRemoteOnly(std::string strMasterNodeAddr, std::string strMasterNodePrivKey);
//bool SelectCoinsMasternode(CTxIn& vin, int64& nValueIn, CScript& pubScript, std::string strTxHash, std::string strOutputIndex);
// enable hot wallet mode (run a masternode with no funds)
bool EnableHotColdMasterNode(CTxIn& vin, int64 sigTime, CService& addr);
bool EnableHotColdMasterNode(CTxIn& vin, CService& addr);
};
#endif
#endif

View File

@ -109,7 +109,7 @@ void ProcessMessageDarksend(CNode* pfrom, std::string& strCommand, CDataStream&
vRecv >> nDenom >> txCollateral;
std::string error = "";
int mn = GetMasternodeByVin(activeMasternode.vinMasternode);
int mn = GetMasternodeByVin(activeMasternode.vin);
if(mn == -1){
std::string strError = "Not in the masternode list";
pfrom->PushMessage("dssu", darkSendPool.sessionID, darkSendPool.GetState(), darkSendPool.GetEntriesCount(), MASTERNODE_REJECTED, strError);
@ -591,7 +591,7 @@ void CDarkSendPool::Check()
if(!mapDarksendBroadcastTxes.count(txNew.GetHash())){
CDarksendBroadcastTx dstx;
dstx.tx = txNew;
dstx.vin = activeMasternode.vinMasternode;
dstx.vin = activeMasternode.vin;
dstx.vchSig = vchSig;
dstx.sigTime = sigTime;
@ -799,7 +799,7 @@ void CDarkSendPool::CheckTimeout(){
if(state == POOL_STATUS_QUEUE && sessionUsers == GetMaxPoolTransactions()) {
CDarksendQueue dsq;
dsq.nDenom = sessionDenom;
dsq.vin = activeMasternode.vinMasternode;
dsq.vin = activeMasternode.vin;
dsq.time = GetTime();
dsq.ready = true;
dsq.Sign();
@ -1852,7 +1852,7 @@ bool CDarkSendPool::IsCompatibleWithSession(int64 nDenom, CTransaction txCollate
//broadcast that I'm accepting entries, only if it's the first entry though
CDarksendQueue dsq;
dsq.nDenom = nDenom;
dsq.vin = activeMasternode.vinMasternode;
dsq.vin = activeMasternode.vin;
dsq.time = GetTime();
dsq.Sign();
dsq.Relay();
@ -2104,6 +2104,8 @@ void ThreadCheckDarkSendPool()
RenameThread("bitcoin-darksend");
unsigned int c = 0;
std::string errorMessage;
while (true)
{
c++;
@ -2152,16 +2154,14 @@ void ThreadCheckDarkSendPool()
}
}
if(c % MASTERNODE_PING_SECONDS == 0){
activeMasternode.RegisterAsMasterNode(false);
activeMasternode.ManageStatus();
}
if(c % 60 == 0){
//if we've used 1/5 of the masternode list, then clear the list.
if((int)vecMasternodesUsed.size() > (int)darkSendMasterNodes.size() / 5)
vecMasternodesUsed.clear();
}
//auto denom every 2.5 minutes (liquidity provides try less often)

View File

@ -12,6 +12,7 @@
#include "ui_interface.h"
#include "checkpointsync.h"
#include "activemasternode.h"
#include "masternodeconfig.h"
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
@ -198,6 +199,10 @@ bool AppInit(int argc, char* argv[])
return false;
}
// Process masternode config
masternodeConfig.read(GetMasternodeConfigFile());
// Command-line RPC
for (int i = 1; i < argc; i++)
if (!IsSwitchChar(argv[i][0]) && !boost::algorithm::istarts_with(argv[i], "darkcoin:"))
@ -384,7 +389,8 @@ std::string HelpMessage()
"\n" + _("Masternode options:") + "\n" +
" -masternode=<n> " + _("Enable the client to act as a masternode (0-1, default: 0)") + "\n" +
" -masternodeprivkey=<n> " + _("Set the masternode private key") + "\n" +
" -mnconf=<file> " + _("Specify masternode configuration file (default: masternode.conf)") + "\n" +
" -masternodeprivkey=<n> " + _("Set the masternode private key") + "\n" +
" -masternodeaddr=<n> " + _("Set external address:port to get to this masternode (example: address:port)") + "\n" +
" -masternodeminprotocol=<n> " + _("Ignore masternodes less than version (example: 70050; default : 0)") + "\n" +
@ -1232,7 +1238,7 @@ bool AppInit2(boost::thread_group& threadGroup)
return InitError(_("Invalid masternodeprivkey. Please see documenation."));
}
activeMasternode.pubkeyMasterNode2 = pubkey;
activeMasternode.pubKeyMasternode = pubkey;
} else {
return InitError(_("You must specify a masternodeprivkey in the configuration. Please see documentation for help."));

View File

@ -207,7 +207,7 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64 nBlockHeight)
}
int winner = GetCurrentMasterNode(1, nBlockHeight);
int n = GetMasternodeRank(activeMasternode.vinMasternode, nBlockHeight, MIN_INSTANTX_PROTO_VERSION);
int n = GetMasternodeRank(activeMasternode.vin, nBlockHeight, MIN_INSTANTX_PROTO_VERSION);
if(n == -1 || winner == -1)
{
@ -225,7 +225,7 @@ void DoConsensusVote(CTransaction& tx, bool approved, int64 nBlockHeight)
}
CConsensusVote ctx;
ctx.vinMasternode = activeMasternode.vinMasternode;
ctx.vinMasternode = activeMasternode.vin;
ctx.approved = approved;
ctx.txHash = tx.GetHash();
ctx.nBlockHeight = nBlockHeight;
@ -274,7 +274,7 @@ void ProcessConsensusVote(CConsensusVote& ctx)
}
//We're not the winning masternode
if(darkSendMasterNodes[winner].vin != activeMasternode.vinMasternode) {
if(darkSendMasterNodes[winner].vin != activeMasternode.vin) {
LogPrintf("InstantX::ProcessConsensusVote - I'm not the winning masternode\n");
return;
}
@ -453,4 +453,4 @@ void CTransactionLock::AddSignature(CConsensusVote cv)
int CTransactionLock::CountSignatures()
{
return vecConsensusVotes.size();
}
}

View File

@ -73,6 +73,7 @@ OBJS= \
obj/core.o \
obj/masternode.o \
obj/activemasternode.o \
obj/masternodeconfig.o \
obj/instantx.o \
obj/keystore.o \
obj/darksend.o \

View File

@ -85,6 +85,7 @@ OBJS= \
obj/core.o \
obj/masternode.o \
obj/activemasternode.o \
obj/masternodeconfig.o \
obj/instantx.o \
obj/keystore.o \
obj/main.o \

View File

@ -90,6 +90,7 @@ OBJS= \
obj/core.o \
obj/masternode.o \
obj/activemasternode.o \
obj/masternodeconfig.o \
obj/instantx.o \
obj/keystore.o \
obj/main.o \

View File

@ -127,6 +127,7 @@ OBJS= \
obj/init.o \
obj/core.o \
obj/masternode.o \
obj/masternodeconfig.o \
obj/activemasternode.o \
obj/instantx.o \
obj/keystore.o \

View File

@ -1,11 +1,8 @@
#include "masternode.h"
#include "activemasternode.h"
#include "darksend.h"
#include "core.h"
/** The list of active masternodes */
std::vector<CMasterNode> darkSendMasterNodes;
/** Object for who's going to get paid on which blocks */
@ -163,8 +160,8 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream
darkSendMasterNodes.push_back(mn);
// if it matches our masternodeprivkey, then we've been remotely activated
if(pubkey2 == activeMasternode.pubkeyMasterNode2 && protocolVersion == PROTOCOL_VERSION){
activeMasternode.EnableHotColdMasterNode(vin, sigTime, addr);
if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){
activeMasternode.EnableHotColdMasterNode(vin, addr);
}
if(count == -1 && !isLocal)
@ -194,6 +191,8 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream
bool stop;
vRecv >> vin >> vchSig >> sigTime >> stop;
//LogPrintf("dseep - Received: vin: %s sigTime: %lld stop: %s\n", vin.ToString().c_str(), sigTime, stop ? "true" : "false");
if (sigTime > GetAdjustedTime() + 60 * 60) {
LogPrintf("dseep - Signature rejected, too far into the future %s\n", vin.ToString().c_str());
return;
@ -208,7 +207,8 @@ void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream
BOOST_FOREACH(CMasterNode& mn, darkSendMasterNodes) {
if(mn.vin.prevout == vin.prevout) {
// take this only if it's newer
// LogPrintf("dseep - Found corresponding mn for vin: %s\n", vin.ToString().c_str());
// take this only if it's newer
if(mn.lastDseep < sigTime){
std::string strMessage = mn.addr.ToString() + boost::lexical_cast<std::string>(sigTime) + boost::lexical_cast<std::string>(stop);

31
src/masternodeconfig.cpp Normal file
View File

@ -0,0 +1,31 @@
#include "masternodeconfig.h"
#include "util.h"
CMasternodeConfig masternodeConfig;
void CMasternodeConfig::add(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex) {
CMasternodeEntry cme(alias, ip, privKey, txHash, outputIndex);
entries.push_back(cme);
}
void CMasternodeConfig::read(boost::filesystem::path path) {
boost::filesystem::ifstream streamConfig(GetMasternodeConfigFile());
if (!streamConfig.good()) {
return; // No masternode.conf file is OK
}
for(std::string line; std::getline(streamConfig, line); )
{
if(line.empty()) {
continue;
}
std::istringstream iss(line);
std::string alias, ip, privKey, txHash, outputIndex;
if (!(iss >> alias >> ip >> privKey >> txHash >> outputIndex)) {
LogPrintf("CMasternodeConfig::read - Could not parse masternode.conf. Line: %s\n", line.c_str());
}
add(alias, ip, privKey, txHash, outputIndex);
}
streamConfig.close();
}

102
src/masternodeconfig.h Normal file
View File

@ -0,0 +1,102 @@
// Copyright (c) 2009-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.
#ifndef SRC_MASTERNODECONFIG_H_
#define SRC_MASTERNODECONFIG_H_
#include <string>
#include <vector>
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
class CMasternodeConfig;
extern CMasternodeConfig masternodeConfig;
class CMasternodeConfig
{
public:
class CMasternodeEntry {
private:
std::string alias;
std::string ip;
std::string privKey;
std::string txHash;
std::string outputIndex;
public:
CMasternodeEntry(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex) {
this->alias = alias;
this->ip = ip;
this->privKey = privKey;
this->txHash = txHash;
this->outputIndex = outputIndex;
}
const std::string& getAlias() const {
return alias;
}
void setAlias(const std::string& alias) {
this->alias = alias;
}
const std::string& getOutputIndex() const {
return outputIndex;
}
void setOutputIndex(const std::string& outputIndex) {
this->outputIndex = outputIndex;
}
const std::string& getPrivKey() const {
return privKey;
}
void setPrivKey(const std::string& privKey) {
this->privKey = privKey;
}
const std::string& getTxHash() const {
return txHash;
}
void setTxHash(const std::string& txHash) {
this->txHash = txHash;
}
const std::string& getIp() const {
return ip;
}
void setIp(const std::string& ip) {
this->ip = ip;
}
};
CMasternodeConfig() {
entries = std::vector<CMasternodeEntry>();
}
void clear();
void read(boost::filesystem::path path);
void add(std::string alias, std::string ip, std::string privKey, std::string txHash, std::string outputIndex);
std::vector<CMasternodeEntry>& getEntries() {
return entries;
}
private:
std::vector<CMasternodeEntry> entries;
};
#endif /* SRC_MASTERNODECONFIG_H_ */

View File

@ -1970,6 +1970,15 @@ void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std:
}
}
void SendDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector<unsigned char> vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated, const int protocolVersion)
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
pnode->PushMessage("dsee", vin, addr, vchSig, nNow, pubkey, pubkey2, count, current, lastUpdated, protocolVersion);
}
}
void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned char> vchSig, const int64 nNow, const bool stop)
{
LOCK(cs_vNodes);
@ -1981,6 +1990,15 @@ void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned
}
}
void SendDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned char> vchSig, const int64 nNow, const bool stop)
{
LOCK(cs_vNodes);
BOOST_FOREACH(CNode* pnode, vNodes)
{
pnode->PushMessage("dseep", vin, vchSig, nNow, stop);
}
}
void RelayDarkSendCompletedTransaction(const int sessionID, const bool error, const std::string errorMessage)
{
LOCK(cs_vNodes);
@ -1988,4 +2006,4 @@ void RelayDarkSendCompletedTransaction(const int sessionID, const bool error, co
{
pnode->PushMessage("dsc", sessionID, error, errorMessage);
}
}
}

View File

@ -691,7 +691,9 @@ void RelayDarkSendFinalTransaction(const int sessionID, const CTransaction& txNe
void RelayDarkSendIn(const std::vector<CTxIn>& in, const int64& nAmount, const CTransaction& txCollateral, const std::vector<CTxOut>& out);
void RelayDarkSendStatus(const int sessionID, const int newState, const int newEntriesCount, const int newAccepted, const std::string error="");
void RelayDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector<unsigned char> vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated, const int protocolVersion);
void SendDarkSendElectionEntry(const CTxIn vin, const CService addr, const std::vector<unsigned char> vchSig, const int64 nNow, const CPubKey pubkey, const CPubKey pubkey2, const int count, const int current, const int64 lastUpdated, const int protocolVersion);
void RelayDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned char> vchSig, const int64 nNow, const bool stop);
void SendDarkSendElectionEntryPing(const CTxIn vin, const std::vector<unsigned char> vchSig, const int64 nNow, const bool stop);
void RelayDarkSendCompletedTransaction(const int sessionID, const bool error, const std::string errorMessage);
void RelayDarkSendMasterNodeContestant();

View File

@ -15,6 +15,7 @@
#include "ui_interface.h"
#include "paymentserver.h"
#include "splashscreen.h"
#include "masternodeconfig.h"
#include <QMessageBox>
#if QT_VERSION < 0x050000
@ -154,6 +155,9 @@ int main(int argc, char *argv[])
}
ReadConfigFile(mapArgs, mapMultiArgs);
// Process masternode config
masternodeConfig.read(GetMasternodeConfigFile());
// Application identification (must be set before OptionsModel is initialized,
// as it is used to locate QSettings)
QApplication::setOrganizationName("DarkCoin");

View File

@ -9,12 +9,10 @@
#include "init.h"
#include "masternode.h"
#include "activemasternode.h"
#include "masternodeconfig.h"
#include "bitcoinrpc.h"
#include <fstream>
using namespace json_spirit;
using namespace std;
Value darksend(const Array& params, bool fHelp)
@ -75,7 +73,7 @@ Value getpoolinfo(const Array& params, bool fHelp)
"Returns an object containing anonymous pool-related information.");
Object obj;
obj.push_back(Pair("connected_to_masternode", activeMasternode.masterNodeAddr));
obj.push_back(Pair("connected_to_masternode", activeMasternode.service.ToString()));
obj.push_back(Pair("current_masternode", GetCurrentMasterNode()));
obj.push_back(Pair("state", darkSendPool.GetState()));
obj.push_back(Pair("entries", darkSendPool.GetEntriesCount()));
@ -90,10 +88,10 @@ Value masternode(const Array& params, bool fHelp)
strCommand = params[0].get_str();
if (fHelp ||
(strCommand != "start" && strCommand != "start-many" && strCommand != "stop" && strCommand != "list" && strCommand != "count" && strCommand != "enforce"
(strCommand != "start" && strCommand != "start-alias" && strCommand != "start-many" && strCommand != "stop" && strCommand != "stop-alias" && strCommand != "stop-many" && strCommand != "list" && strCommand != "list-conf" && strCommand != "count" && strCommand != "enforce"
&& strCommand != "debug" && strCommand != "current" && strCommand != "winners" && strCommand != "genkey" && strCommand != "connect"))
throw runtime_error(
"masternode <start|start-many|stop|list|count|debug|current|winners|genkey|enforce> passphrase\n");
"masternode <start|start-alias|start-many|stop|stop-alias|stop-many|list|list-conf|count|debug|current|winners|genkey|enforce> passphrase\n");
if (strCommand == "stop")
{
@ -115,15 +113,126 @@ Value masternode(const Array& params, bool fHelp)
}
}
activeMasternode.RegisterAsMasterNode(true);
std::string errorMessage;
if(!activeMasternode.StopMasterNode(errorMessage)) {
return "stop failed: " + errorMessage;
}
pwalletMain->Lock();
if(activeMasternode.isCapableMasterNode == MASTERNODE_STOPPED) return "successfully stopped masternode";
if(activeMasternode.isCapableMasterNode == MASTERNODE_NOT_CAPABLE) return "not capable masternode";
if(activeMasternode.status == MASTERNODE_STOPPED) return "successfully stopped masternode";
if(activeMasternode.status == MASTERNODE_NOT_CAPABLE) return "not capable masternode";
return "unknown";
}
if (strCommand == "stop-alias")
{
if (params.size() < 2){
throw runtime_error(
"command needs at least 2 parameters\n");
}
std::string alias = params[1].get_str().c_str();
if(pwalletMain->IsLocked()) {
SecureString strWalletPass;
strWalletPass.reserve(100);
if (params.size() == 3){
strWalletPass = params[2].get_str().c_str();
} else {
throw runtime_error(
"Your wallet is locked, passphrase is required\n");
}
if(!pwalletMain->Unlock(strWalletPass)){
return "incorrect passphrase";
}
}
bool found = false;
Object statusObj;
statusObj.push_back(Pair("alias", alias));
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
if(mne.getAlias() == alias) {
found = true;
std::string errorMessage;
bool result = activeMasternode.StopMasterNode(mne.getIp(), mne.getPrivKey(), errorMessage);
statusObj.push_back(Pair("result", result ? "successful" : "failed"));
if(!result) {
statusObj.push_back(Pair("errorMessage", errorMessage));
}
break;
}
}
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;
}
if (strCommand == "stop-many")
{
if(pwalletMain->IsLocked()) {
SecureString strWalletPass;
strWalletPass.reserve(100);
if (params.size() == 2){
strWalletPass = params[1].get_str().c_str();
} else {
throw runtime_error(
"Your wallet is locked, passphrase is required\n");
}
if(!pwalletMain->Unlock(strWalletPass)){
return "incorrect passphrase";
}
}
int total = 0;
int successful = 0;
int fail = 0;
Object resultsObj;
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
total++;
std::string errorMessage;
bool result = activeMasternode.StopMasterNode(mne.getIp(), mne.getPrivKey(), errorMessage);
Object statusObj;
statusObj.push_back(Pair("alias", mne.getAlias()));
statusObj.push_back(Pair("result", result ? "successful" : "failed"));
if(result) {
successful++;
} else {
fail++;
statusObj.push_back(Pair("errorMessage", errorMessage));
}
resultsObj.push_back(Pair("status", statusObj));
}
pwalletMain->Lock();
Object returnObj;
returnObj.push_back(Pair("overall", "Successfully stopped " + boost::lexical_cast<std::string>(successful) + " masternodes, failed to stop " +
boost::lexical_cast<std::string>(fail) + ", total " + boost::lexical_cast<std::string>(total)));
returnObj.push_back(Pair("detail", resultsObj));
return returnObj;
}
if (strCommand == "list")
{
std::string strCommand = "active";
@ -187,57 +296,140 @@ Value masternode(const Array& params, bool fHelp)
}
}
activeMasternode.RegisterAsMasterNode(false);
activeMasternode.status = MASTERNODE_NOT_PROCESSED; // TODO: consider better way
std::string errorMessage;
activeMasternode.ManageStatus();
pwalletMain->Lock();
if(activeMasternode.isCapableMasterNode == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely";
if(activeMasternode.isCapableMasterNode == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations";
if(activeMasternode.isCapableMasterNode == MASTERNODE_STOPPED) return "masternode is stopped";
if(activeMasternode.isCapableMasterNode == MASTERNODE_IS_CAPABLE) return "successfully started masternode";
if(activeMasternode.masternodePortOpen == MASTERNODE_PORT_NOT_OPEN) return "inbound port is not open. Please open it and try again. (19999 for testnet and 9999 for mainnet)";
if(activeMasternode.isCapableMasterNode == MASTERNODE_NOT_CAPABLE) return "not capable masternode";
if(activeMasternode.isCapableMasterNode == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start.";
if(activeMasternode.status == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely";
if(activeMasternode.status == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations";
if(activeMasternode.status == MASTERNODE_STOPPED) return "masternode is stopped";
if(activeMasternode.status == MASTERNODE_IS_CAPABLE) return "successfully started masternode";
if(activeMasternode.status == MASTERNODE_NOT_CAPABLE) return "not capable masternode: " + activeMasternode.notCapableReason;
if(activeMasternode.status == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start.";
return "unknown";
}
if (strCommand == "start-alias")
{
if (params.size() < 2){
throw runtime_error(
"command needs at least 2 parameters\n");
}
std::string alias = params[1].get_str().c_str();
if(pwalletMain->IsLocked()) {
SecureString strWalletPass;
strWalletPass.reserve(100);
if (params.size() == 3){
strWalletPass = params[2].get_str().c_str();
} else {
throw runtime_error(
"Your wallet is locked, passphrase is required\n");
}
if(!pwalletMain->Unlock(strWalletPass)){
return "incorrect passphrase";
}
}
bool found = false;
Object statusObj;
statusObj.push_back(Pair("alias", alias));
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
if(mne.getAlias() == alias) {
found = true;
std::string errorMessage;
bool result = activeMasternode.Register(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), errorMessage);
statusObj.push_back(Pair("result", result ? "successful" : "failed"));
if(!result) {
statusObj.push_back(Pair("errorMessage", errorMessage));
}
break;
}
}
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;
}
if (strCommand == "start-many")
{
boost::filesystem::path pathDebug = GetDataDir() / "masternode.conf";
std::ifstream infile(pathDebug.string().c_str());
if(pwalletMain->IsLocked()) {
SecureString strWalletPass;
strWalletPass.reserve(100);
std::string line;
int total = 0;
int successful = 0;
int fail = 0;
while (std::getline(infile, line))
{
std::istringstream iss(line);
std::string a, b;
if (!(iss >> a >> b)) { break; } // error
if (params.size() == 2){
strWalletPass = params[1].get_str().c_str();
} else {
throw runtime_error(
"Your wallet is locked, passphrase is required\n");
}
total++;
if(activeMasternode.RegisterAsMasterNodeRemoteOnly(a, b)){
successful++;
} else {
fail++;
}
}
printf(" Successfully started %d masternodes, failed to start %d, total %d\n", successful, fail, total);
return "";
if(!pwalletMain->Unlock(strWalletPass)){
return "incorrect passphrase";
}
}
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
mnEntries = masternodeConfig.getEntries();
int total = 0;
int successful = 0;
int fail = 0;
Object resultsObj;
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
total++;
std::string errorMessage;
bool result = activeMasternode.Register(mne.getIp(), mne.getPrivKey(), mne.getTxHash(), mne.getOutputIndex(), errorMessage);
Object statusObj;
statusObj.push_back(Pair("alias", mne.getAlias()));
statusObj.push_back(Pair("result", result ? "succesful" : "failed"));
if(result) {
successful++;
} else {
fail++;
statusObj.push_back(Pair("errorMessage", errorMessage));
}
resultsObj.push_back(Pair("status", statusObj));
}
pwalletMain->Lock();
Object returnObj;
returnObj.push_back(Pair("overall", "Successfully started " + boost::lexical_cast<std::string>(successful) + " masternodes, failed to start " +
boost::lexical_cast<std::string>(fail) + ", total " + boost::lexical_cast<std::string>(total)));
returnObj.push_back(Pair("detail", resultsObj));
return returnObj;
}
if (strCommand == "debug")
{
if(activeMasternode.isCapableMasterNode == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely";
if(activeMasternode.isCapableMasterNode == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations";
if(activeMasternode.isCapableMasterNode == MASTERNODE_IS_CAPABLE) return "successfully started masternode";
if(activeMasternode.isCapableMasterNode == MASTERNODE_STOPPED) return "masternode is stopped";
if(activeMasternode.masternodePortOpen == MASTERNODE_PORT_NOT_OPEN) return "inbound port is not open. Please open it and try again. (19999 for testnet and 9999 for mainnet)";
if(activeMasternode.isCapableMasterNode == MASTERNODE_NOT_CAPABLE) return "not capable masternode";
if(activeMasternode.isCapableMasterNode == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start.";
if(activeMasternode.status == MASTERNODE_REMOTELY_ENABLED) return "masternode started remotely";
if(activeMasternode.status == MASTERNODE_INPUT_TOO_NEW) return "masternode input must have at least 15 confirmations";
if(activeMasternode.status == MASTERNODE_IS_CAPABLE) return "successfully started masternode";
if(activeMasternode.status == MASTERNODE_STOPPED) return "masternode is stopped";
if(activeMasternode.status == MASTERNODE_NOT_CAPABLE) return "not capable masternode: " + activeMasternode.notCapableReason;
if(activeMasternode.status == MASTERNODE_SYNC_IN_PROCESS) return "sync in process. Must wait until client is synced to start.";
CTxIn vin = CTxIn();
CPubKey pubkey = CScript();
@ -318,6 +510,26 @@ Value masternode(const Array& params, bool fHelp)
}
}
if(strCommand == "list-conf")
{
std::vector<CMasternodeConfig::CMasternodeEntry> mnEntries;
mnEntries = masternodeConfig.getEntries();
Object resultObj;
BOOST_FOREACH(CMasternodeConfig::CMasternodeEntry mne, masternodeConfig.getEntries()) {
Object mnObj;
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()));
resultObj.push_back(Pair("masternode", mnObj));
}
return resultObj;
}
return Value::null;
}

View File

@ -1127,6 +1127,13 @@ boost::filesystem::path GetConfigFile()
return pathConfigFile;
}
boost::filesystem::path GetMasternodeConfigFile()
{
boost::filesystem::path pathConfigFile(GetArg("-mnconf", "masternode.conf"));
if (!pathConfigFile.is_complete()) pathConfigFile = GetDataDir(false) / pathConfigFile;
return pathConfigFile;
}
void ReadConfigFile(map<string, string>& mapSettingsRet,
map<string, vector<string> >& mapMultiSettingsRet)
{

View File

@ -210,6 +210,7 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest);
boost::filesystem::path GetDefaultDataDir();
const boost::filesystem::path &GetDataDir(bool fNetSpecific = true);
boost::filesystem::path GetConfigFile();
boost::filesystem::path GetMasternodeConfigFile();
boost::filesystem::path GetPidFile();
#ifndef WIN32
void CreatePidFile(const boost::filesystem::path &path, pid_t pid);

View File

@ -1201,26 +1201,6 @@ static void ApproximateBestSubset(vector<pair<int64, pair<const CWalletTx*,unsig
}
}
/* select coins with 1 unspent output */
bool CWallet::SelectCoinsMasternode(CTxIn& vin, int64& nValueRet, CScript& pubScript) const
{
CCoinControl *coinControl=NULL;
vector<COutput> vCoins;
AvailableCoins(vCoins, true, coinControl, ALL_COINS);
BOOST_FOREACH(const COutput& out, vCoins)
{
if(out.tx->vout[out.i].nValue == 1000*COIN){ //exactly
vin = CTxIn(out.tx->GetHash(),out.i);
pubScript = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
nValueRet = out.tx->vout[out.i].nValue;
return true;
}
}
return false;
}
bool CWallet::SelectCoinsMinConf(int64 nTargetValue, int nConfMine, int nConfTheirs, vector<COutput> vCoins,
set<pair<const CWalletTx*,unsigned int> >& setCoinsRet, int64& nValueRet) const
{