Dash Core  0.12.2.1
P2P Digital Currency
activemasternode.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2017 The Dash Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "activemasternode.h"
6 #include "masternode.h"
7 #include "masternode-sync.h"
8 #include "masternodeman.h"
9 #include "protocol.h"
10 
11 extern CWallet* pwalletMain;
12 
13 // Keep track of the active Masternode
15 
17 {
18  LogPrint("masternode", "CActiveMasternode::ManageState -- Start\n");
19  if(!fMasterNode) {
20  LogPrint("masternode", "CActiveMasternode::ManageState -- Not a masternode, returning\n");
21  return;
22  }
23 
24  if(Params().NetworkIDString() != CBaseChainParams::REGTEST && !masternodeSync.IsBlockchainSynced()) {
26  LogPrintf("CActiveMasternode::ManageState -- %s: %s\n", GetStateString(), GetStatus());
27  return;
28  }
29 
32  }
33 
34  LogPrint("masternode", "CActiveMasternode::ManageState -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
35 
36  if(eType == MASTERNODE_UNKNOWN) {
37  ManageStateInitial(connman);
38  }
39 
40  if(eType == MASTERNODE_REMOTE) {
42  } else if(eType == MASTERNODE_LOCAL) {
43  // Try Remote Start first so the started local masternode can be restarted without recreate masternode broadcast.
46  ManageStateLocal(connman);
47  }
48 
49  SendMasternodePing(connman);
50 }
51 
53 {
54  switch (nState) {
55  case ACTIVE_MASTERNODE_INITIAL: return "INITIAL";
56  case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "SYNC_IN_PROCESS";
57  case ACTIVE_MASTERNODE_INPUT_TOO_NEW: return "INPUT_TOO_NEW";
58  case ACTIVE_MASTERNODE_NOT_CAPABLE: return "NOT_CAPABLE";
59  case ACTIVE_MASTERNODE_STARTED: return "STARTED";
60  default: return "UNKNOWN";
61  }
62 }
63 
64 std::string CActiveMasternode::GetStatus() const
65 {
66  switch (nState) {
67  case ACTIVE_MASTERNODE_INITIAL: return "Node just started, not yet activated";
68  case ACTIVE_MASTERNODE_SYNC_IN_PROCESS: return "Sync in progress. Must wait until sync is complete to start Masternode";
69  case ACTIVE_MASTERNODE_INPUT_TOO_NEW: return strprintf("Masternode input must have at least %d confirmations", Params().GetConsensus().nMasternodeMinimumConfirmations);
70  case ACTIVE_MASTERNODE_NOT_CAPABLE: return "Not capable masternode: " + strNotCapableReason;
71  case ACTIVE_MASTERNODE_STARTED: return "Masternode successfully started";
72  default: return "Unknown";
73  }
74 }
75 
77 {
78  std::string strType;
79  switch(eType) {
80  case MASTERNODE_UNKNOWN:
81  strType = "UNKNOWN";
82  break;
83  case MASTERNODE_REMOTE:
84  strType = "REMOTE";
85  break;
86  case MASTERNODE_LOCAL:
87  strType = "LOCAL";
88  break;
89  default:
90  strType = "UNKNOWN";
91  break;
92  }
93  return strType;
94 }
95 
97 {
98  if(!fPingerEnabled) {
99  LogPrint("masternode", "CActiveMasternode::SendMasternodePing -- %s: masternode ping service is disabled, skipping...\n", GetStateString());
100  return false;
101  }
102 
103  if(!mnodeman.Has(outpoint)) {
104  strNotCapableReason = "Masternode not in masternode list";
106  LogPrintf("CActiveMasternode::SendMasternodePing -- %s: %s\n", GetStateString(), strNotCapableReason);
107  return false;
108  }
109 
112  mnp.fSentinelIsCurrent =
114  if(!mnp.Sign(keyMasternode, pubKeyMasternode)) {
115  LogPrintf("CActiveMasternode::SendMasternodePing -- ERROR: Couldn't sign Masternode Ping\n");
116  return false;
117  }
118 
119  // Update lastPing for our masternode in Masternode list
121  LogPrintf("CActiveMasternode::SendMasternodePing -- Too early to send Masternode Ping\n");
122  return false;
123  }
124 
126 
127  LogPrintf("CActiveMasternode::SendMasternodePing -- Relaying ping, collateral=%s\n", outpoint.ToStringShort());
128  mnp.Relay(connman);
129 
130  return true;
131 }
132 
134 {
137 
138  return true;
139 }
140 
142 {
143  LogPrint("masternode", "CActiveMasternode::ManageStateInitial -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
144 
145  // Check that our local network configuration is correct
146  if (!fListen) {
147  // listen option is probably overwritten by smth else, no good
149  strNotCapableReason = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter.";
150  LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
151  return;
152  }
153 
154  // First try to find whatever local address is specified by externalip option
155  bool fFoundLocal = GetLocal(service) && CMasternode::IsValidNetAddr(service);
156  if(!fFoundLocal) {
157  bool empty = true;
158  // If we have some peers, let's try to find our local address from one of them
159  connman.ForEachNodeContinueIf(CConnman::AllNodes, [&fFoundLocal, &empty, this](CNode* pnode) {
160  empty = false;
161  if (pnode->addr.IsIPv4())
162  fFoundLocal = GetLocal(service, &pnode->addr) && CMasternode::IsValidNetAddr(service);
163  return !fFoundLocal;
164  });
165  // nothing and no live connections, can't do anything for now
166  if (empty) {
168  strNotCapableReason = "Can't detect valid external address. Will retry when there are some connections available.";
169  LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
170  return;
171  }
172  }
173 
174  if(!fFoundLocal) {
176  strNotCapableReason = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
177  LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
178  return;
179  }
180 
181  int mainnetDefaultPort = Params(CBaseChainParams::MAIN).GetDefaultPort();
182  if(Params().NetworkIDString() == CBaseChainParams::MAIN) {
183  if(service.GetPort() != mainnetDefaultPort) {
185  strNotCapableReason = strprintf("Invalid port: %u - only %d is supported on mainnet.", service.GetPort(), mainnetDefaultPort);
186  LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
187  return;
188  }
189  } else if(service.GetPort() == mainnetDefaultPort) {
191  strNotCapableReason = strprintf("Invalid port: %u - %d is only supported on mainnet.", service.GetPort(), mainnetDefaultPort);
192  LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
193  return;
194  }
195 
196  LogPrintf("CActiveMasternode::ManageStateInitial -- Checking inbound connection to '%s'\n", service.ToString());
197 
198  if(!connman.ConnectNode(CAddress(service, NODE_NETWORK), NULL, true)) {
200  strNotCapableReason = "Could not connect to " + service.ToString();
201  LogPrintf("CActiveMasternode::ManageStateInitial -- %s: %s\n", GetStateString(), strNotCapableReason);
202  return;
203  }
204 
205  // Default to REMOTE
207 
208  // Check if wallet funds are available
209  if(!pwalletMain) {
210  LogPrintf("CActiveMasternode::ManageStateInitial -- %s: Wallet not available\n", GetStateString());
211  return;
212  }
213 
214  if(pwalletMain->IsLocked()) {
215  LogPrintf("CActiveMasternode::ManageStateInitial -- %s: Wallet is locked\n", GetStateString());
216  return;
217  }
218 
219  if(pwalletMain->GetBalance() < 1000*COIN) {
220  LogPrintf("CActiveMasternode::ManageStateInitial -- %s: Wallet balance is < 1000 DASH\n", GetStateString());
221  return;
222  }
223 
224  // Choose coins to use
225  CPubKey pubKeyCollateral;
226  CKey keyCollateral;
227 
228  // If collateral is found switch to LOCAL mode
229  if(pwalletMain->GetMasternodeOutpointAndKeys(outpoint, pubKeyCollateral, keyCollateral)) {
231  }
232 
233  LogPrint("masternode", "CActiveMasternode::ManageStateInitial -- End status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
234 }
235 
237 {
238  LogPrint("masternode", "CActiveMasternode::ManageStateRemote -- Start status = %s, type = %s, pinger enabled = %d, pubKeyMasternode.GetID() = %s\n",
240 
242  masternode_info_t infoMn;
244  if(infoMn.nProtocolVersion != PROTOCOL_VERSION) {
246  strNotCapableReason = "Invalid protocol version";
247  LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
248  return;
249  }
250  if(service != infoMn.addr) {
252  strNotCapableReason = "Broadcasted IP doesn't match our external address. Make sure you issued a new broadcast if IP of this masternode changed recently.";
253  LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
254  return;
255  }
258  strNotCapableReason = strprintf("Masternode in %s state", CMasternode::StateToString(infoMn.nActiveState));
259  LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
260  return;
261  }
263  LogPrintf("CActiveMasternode::ManageStateRemote -- STARTED!\n");
264  outpoint = infoMn.vin.prevout;
265  service = infoMn.addr;
266  fPingerEnabled = true;
268  }
269  }
270  else {
272  strNotCapableReason = "Masternode not in masternode list";
273  LogPrintf("CActiveMasternode::ManageStateRemote -- %s: %s\n", GetStateString(), strNotCapableReason);
274  }
275 }
276 
278 {
279  LogPrint("masternode", "CActiveMasternode::ManageStateLocal -- status = %s, type = %s, pinger enabled = %d\n", GetStatus(), GetTypeString(), fPingerEnabled);
281  return;
282  }
283 
284  // Choose coins to use
285  CPubKey pubKeyCollateral;
286  CKey keyCollateral;
287 
288  if(pwalletMain->GetMasternodeOutpointAndKeys(outpoint, pubKeyCollateral, keyCollateral)) {
289  int nPrevoutAge = GetUTXOConfirmations(outpoint);
290  if(nPrevoutAge < Params().GetConsensus().nMasternodeMinimumConfirmations){
292  strNotCapableReason = strprintf(_("%s - %d confirmations"), GetStatus(), nPrevoutAge);
293  LogPrintf("CActiveMasternode::ManageStateLocal -- %s: %s\n", GetStateString(), strNotCapableReason);
294  return;
295  }
296 
297  {
300  }
301 
303  std::string strError;
304  if(!CMasternodeBroadcast::Create(outpoint, service, keyCollateral, pubKeyCollateral, keyMasternode, pubKeyMasternode, strError, mnb)) {
306  strNotCapableReason = "Error creating mastenode broadcast: " + strError;
307  LogPrintf("CActiveMasternode::ManageStateLocal -- %s: %s\n", GetStateString(), strNotCapableReason);
308  return;
309  }
310 
311  {
312  LOCK(cs_main);
313  // remember the hash of the block where masternode collateral had minimum required confirmations
315  }
316 
317  fPingerEnabled = true;
319 
320  //update to masternode list
321  LogPrintf("CActiveMasternode::ManageStateLocal -- Update Masternode List\n");
322  mnodeman.UpdateMasternodeList(mnb, connman);
324 
325  //send to all peers
326  LogPrintf("CActiveMasternode::ManageStateLocal -- Relay broadcast, collateral=%s\n", outpoint.ToStringShort());
327  mnb.Relay(connman);
328  }
329 }
CNode * ConnectNode(CAddress addrConnect, const char *pszDest=NULL, bool fConnectToMasternode=false)
Definition: net.cpp:347
uint32_t nSentinelVersion
Definition: masternode.h:41
CMasternodeMan mnodeman
bool GetLocal(CService &addr, const CNetAddr *paddrPeer)
Definition: net.cpp:106
CMasternodeSync masternodeSync
CActiveMasternode activeMasternode
void Relay(CConnman &connman)
Definition: masternode.cpp:665
int GetUTXOHeight(const COutPoint &outpoint)
Definition: validation.cpp:454
std::string GetStatus() const
void ManageStateInitial(CConnman &connman)
std::string GetStateString() const
#define strprintf
Definition: tinyformat.h:1011
void CheckMasternode(const CPubKey &pubKeyMasternode, bool fForce)
CCriticalSection cs_wallet
Definition: wallet.h:672
bool IsMasternodePingedWithin(const COutPoint &outpoint, int nSeconds, int64_t nTimeToCheckAt=-1)
const Consensus::Params & GetConsensus() const
Definition: chainparams.h:55
static const CAmount COIN
Definition: amount.h:16
CCriticalSection cs_main
Definition: validation.cpp:62
void ManageStateLocal(CConnman &connman)
static const int ACTIVE_MASTERNODE_SYNC_IN_PROCESS
CAddress addr
Definition: net.h:688
Definition: net.h:108
CWallet * pwalletMain
std::string ToString(bool fUseGetnameinfo=true) const
Definition: netaddress.cpp:568
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Definition: pubkey.h:144
void SetMasternodeLastPing(const COutPoint &outpoint, const CMasternodePing &mnp)
int GetDefaultPort() const
Definition: chainparams.h:58
unsigned short GetPort() const
Definition: netaddress.cpp:495
static const int MASTERNODE_WATCHDOG_MAX_SECONDS
Definition: masternode.h:20
bool fMasterNode
Definition: util.cpp:108
CAmount GetBalance() const
Definition: wallet.cpp:2139
bool UpdateSentinelPing(int version)
int nMasternodeMinimumConfirmations
Definition: params.h:58
#define LogPrintf(...)
Definition: util.h:98
bool Sign(const CKey &keyMasternode, const CPubKey &pubKeyMasternode)
Definition: masternode.cpp:681
bool IsIPv4() const
Definition: netaddress.cpp:78
COutPoint prevout
Definition: transaction.h:61
Definition: net.h:661
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
#define LOCK(cs)
Definition: sync.h:168
static const int ACTIVE_MASTERNODE_INITIAL
bool GetMasternodeInfo(const COutPoint &outpoint, masternode_info_t &mnInfoRet)
static bool Create(const COutPoint &outpoint, const CService &service, const CKey &keyCollateralAddressNew, const CPubKey &pubKeyCollateralAddressNew, const CKey &keyMasternodeNew, const CPubKey &pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet)
Create Masternode broadcast, needs to be relayed manually after that.
Definition: masternode.cpp:397
bool IsLocked(bool fForMixing=false) const
Definition: crypter.h:166
CChain chainActive
Definition: validation.cpp:65
std::string ToString() const
Definition: uint256.cpp:65
std::string GetTypeString() const
static const int ACTIVE_MASTERNODE_STARTED
static const int MASTERNODE_MIN_MNP_SECONDS
Definition: masternode.h:18
version
Definition: setup.py:3
void ManageState(CConnman &connman)
Manage state of active Masternode.
int64_t sigTime
Definition: masternode.h:37
const CChainParams & Params()
bool fSentinelIsCurrent
Definition: masternode.h:39
int GetUTXOConfirmations(const COutPoint &outpoint)
Definition: validation.cpp:461
std::string strNotCapableReason
static const int PROTOCOL_VERSION
Definition: version.h:13
static std::string StateToString(int nStateIn)
Definition: masternode.cpp:294
bool IsValidNetAddr()
Definition: masternode.cpp:273
int64_t GetAdjustedTime()
Definition: timedata.cpp:33
bool IsBlockchainSynced()
static const int ACTIVE_MASTERNODE_INPUT_TOO_NEW
static bool IsValidStateForAutoStart(int nActiveStateIn)
Definition: masternode.h:233
bool fListen
Definition: net.cpp:77
masternode_type_enum_t eType
void NotifyMasternodeUpdates(CConnman &connman)
bool GetMasternodeOutpointAndKeys(COutPoint &outpointRet, CPubKey &pubKeyRet, CKey &keyRet, std::string strTxHash="", std::string strOutputIndex="")
Get 1000DASH output and keys which can be used for the Masternode.
Definition: wallet.cpp:2987
bool Has(const COutPoint &outpoint)
static const std::string MAIN
Definition: pubkey.h:37
bool ForEachNodeContinueIf(const Condition &cond, Callable &&func)
Definition: net.h:205
bool SendMasternodePing(CConnman &connman)
Ping Masternode.
void LockCoin(COutPoint &output)
Definition: wallet.cpp:4193
void Relay(CConnman &connman)
Definition: masternode.cpp:824
void UpdateMasternodeList(CMasternodeBroadcast mnb, CConnman &connman)
Update masternode list and maps using provided CMasternodeBroadcast.
static constexpr const CAllNodes AllNodes
Definition: net.h:160
Definition: key.h:35
std::string ToStringShort() const
Definition: transaction.cpp:17
static const int ACTIVE_MASTERNODE_NOT_CAPABLE
uint256 nCollateralMinConfBlockHash
Definition: masternode.h:159
std::string _(const char *psz)
Definition: util.h:84
static const std::string REGTEST