neobytes/src/activemasternode.cpp

213 lines
8.2 KiB
C++
Raw Normal View History

// Copyright (c) 2014-2016 The Dash Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2015-08-12 14:27:58 +02:00
#include "addrman.h"
#include "protocol.h"
#include "activemasternode.h"
#include "masternode.h"
#include "masternode-sync.h"
#include "masternodeman.h"
#include "spork.h"
//
2015-03-05 09:10:15 +01:00
// Bootup the Masternode, look for a 1000DRK input and register on the network
//
void CActiveMasternode::ManageStatus()
2015-07-26 04:27:40 +02:00
{
std::string errorMessage;
2014-12-23 02:23:04 +01:00
if(!fMasterNode) return;
2014-12-23 02:23:04 +01:00
if (fDebug) LogPrintf("CActiveMasternode::ManageStatus() - Begin\n");
//need correct blocks to send ping
if(Params().NetworkIDString() != CBaseChainParams::REGTEST && !masternodeSync.IsBlockchainSynced()) {
status = ACTIVE_MASTERNODE_SYNC_IN_PROCESS;
2015-07-23 04:19:37 +02:00
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", GetStatus());
return;
}
2015-07-23 04:19:37 +02:00
if(status == ACTIVE_MASTERNODE_SYNC_IN_PROCESS) status = ACTIVE_MASTERNODE_INITIAL;
if(status == ACTIVE_MASTERNODE_INITIAL) {
CMasternode *pmn;
pmn = mnodeman.Find(pubKeyMasternode);
if(pmn != NULL) {
pmn->Check();
if((pmn->IsEnabled() || pmn->IsPreEnabled()) && pmn->protocolVersion == PROTOCOL_VERSION)
EnableHotColdMasterNode(pmn->vin, pmn->addr);
}
}
if(status != ACTIVE_MASTERNODE_STARTED) {
// Set defaults
status = ACTIVE_MASTERNODE_NOT_CAPABLE;
notCapableReason = "";
if(pwalletMain->IsLocked()){
notCapableReason = "Wallet is locked.";
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
return;
}
if(pwalletMain->GetBalance() == 0){
notCapableReason = "Hot node, waiting for remote activation.";
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
return;
}
if(strMasterNodeAddr.empty()) {
if(!GetLocal(service)) {
2015-08-05 05:02:54 +02:00
notCapableReason = "Can't detect external address. Please use the masternodeaddr configuration option.";
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
return;
}
} else {
2015-03-22 00:58:18 +01:00
service = CService(strMasterNodeAddr);
}
int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
if(service.GetPort() != mainnetDefaultPort) {
notCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", service.GetPort(), mainnetDefaultPort);
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
2015-02-06 20:41:39 +01:00
return;
}
} else if(service.GetPort() == mainnetDefaultPort) {
notCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", service.GetPort(), mainnetDefaultPort);
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
2015-03-11 20:26:39 +01:00
return;
2015-02-06 20:41:39 +01:00
}
LogPrintf("CActiveMasternode::ManageStatus() - Checking inbound connection to '%s'\n", service.ToString());
if(!ConnectNode((CAddress)service, NULL, true)){
notCapableReason = "Could not connect to " + service.ToString();
LogPrintf("CActiveMasternode::ManageStatus() - not capable: %s\n", notCapableReason);
return;
}
// Choose coins to use
CPubKey pubKeyCollateralAddress;
CKey keyCollateralAddress;
if(pwalletMain->GetMasternodeVinAndKeys(vin, pubKeyCollateralAddress, keyCollateralAddress)) {
if(GetInputAge(vin) < Params().GetConsensus().nMasternodeMinimumConfirmations){
status = ACTIVE_MASTERNODE_INPUT_TOO_NEW;
2015-07-23 04:19:37 +02:00
notCapableReason = strprintf("%s - %d confirmations", GetStatus(), GetInputAge(vin));
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason);
return;
}
2015-07-30 15:44:18 +02:00
LOCK(pwalletMain->cs_wallet);
pwalletMain->LockCoin(vin.prevout);
// send to all nodes
CMasternodeBroadcast mnb;
if(!CMasternodeBroadcast::Create(vin, service, keyCollateralAddress, pubKeyCollateralAddress, keyMasternode, pubKeyMasternode, errorMessage, mnb)) {
notCapableReason = "Error on CreateBroadcast: " + errorMessage;
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason);
return;
}
//update to masternode list
LogPrintf("CActiveMasternode::ManageStatus() - Update Masternode List\n");
mnodeman.UpdateMasternodeList(mnb);
//send to all peers
LogPrintf("CActiveMasternode::ManageStatus() - Relay broadcast vin = %s\n", vin.ToString());
mnb.Relay();
LogPrintf("CActiveMasternode::ManageStatus() - Is capable master node!\n");
status = ACTIVE_MASTERNODE_STARTED;
return;
} else {
notCapableReason = "Could not find suitable coins!";
LogPrintf("CActiveMasternode::ManageStatus() - %s\n", notCapableReason);
return;
}
}
//send to all peers
if(!SendMasternodePing(errorMessage)) {
LogPrintf("CActiveMasternode::ManageStatus() - Error on Ping: %s\n", errorMessage);
}
}
std::string CActiveMasternode::GetStatus() {
switch (status) {
2015-07-23 04:19:37 +02:00
case ACTIVE_MASTERNODE_INITIAL: return "Node just started, not yet activated";
case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "Sync in progress. Must wait until sync is complete to start Masternode";
case ACTIVE_MASTERNODE_INPUT_TOO_NEW: return strprintf("Masternode input must have at least %d confirmations", Params().GetConsensus().nMasternodeMinimumConfirmations);
2015-07-23 04:19:37 +02:00
case ACTIVE_MASTERNODE_NOT_CAPABLE: return "Not capable masternode: " + notCapableReason;
case ACTIVE_MASTERNODE_STARTED: return "Masternode successfully started";
default: return "unknown";
}
}
bool CActiveMasternode::SendMasternodePing(std::string& errorMessage) {
if(status != ACTIVE_MASTERNODE_STARTED) {
2015-03-22 00:58:18 +01:00
errorMessage = "Masternode is not in a running status";
return false;
}
LogPrintf("CActiveMasternode::SendMasternodePing() - Relay Masternode Ping vin = %s\n", vin.ToString());
CMasternodePing mnp(vin);
if(!mnp.Sign(keyMasternode, pubKeyMasternode))
{
errorMessage = "Couldn't sign Masternode Ping";
return false;
}
// Update lastPing for our masternode in Masternode list
2015-02-25 12:54:03 +01:00
CMasternode* pmn = mnodeman.Find(vin);
if(pmn != NULL)
{
if(pmn->IsPingedWithin(MASTERNODE_PING_SECONDS, mnp.sigTime)){
errorMessage = "Too early to send Masternode Ping";
return false;
}
pmn->lastPing = mnp;
mnodeman.mapSeenMasternodePing.insert(make_pair(mnp.GetHash(), mnp));
//mnodeman.mapSeenMasternodeBroadcast.lastPing is probably outdated, so we'll update it
CMasternodeBroadcast mnb(*pmn);
uint256 hash = mnb.GetHash();
if(mnodeman.mapSeenMasternodeBroadcast.count(hash)) mnodeman.mapSeenMasternodeBroadcast[hash].lastPing = mnp;
mnp.Relay();
return true;
}
else
{
2015-03-22 00:58:18 +01:00
// Seems like we are trying to send a ping while the Masternode is not registered in the network
errorMessage = "PrivateSend Masternode List doesn't include our Masternode, shutting down Masternode pinging service! " + vin.ToString();
status = ACTIVE_MASTERNODE_NOT_CAPABLE;
notCapableReason = errorMessage;
return false;
}
}
2015-03-05 09:10:15 +01:00
// when starting a Masternode, this can enable to run as a hot wallet with no funds
bool CActiveMasternode::EnableHotColdMasterNode(CTxIn& newVin, CService& newService)
{
if(!fMasterNode) return false;
status = ACTIVE_MASTERNODE_STARTED;
//The values below are needed for signing mnping messages going forward
vin = newVin;
service = newService;
LogPrintf("CActiveMasternode::EnableHotColdMasterNode() - Enabled! You may shut down the cold daemon.\n");
return true;
}