Dash Core Source Documentation (0.16.0.1)

Find detailed information regarding the Dash Core source code.

activemasternode.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2020 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 
6 #include <evo/deterministicmns.h>
7 #include <init.h>
9 #include <netbase.h>
10 #include <protocol.h>
11 #include <validation.h>
12 #include <warnings.h>
13 
14 // Keep track of the active Masternode
17 
19 {
20  switch (state) {
22  return "WAITING_FOR_PROTX";
24  return "POSE_BANNED";
25  case MASTERNODE_REMOVED:
26  return "REMOVED";
28  return "OPERATOR_KEY_CHANGED";
30  return "PROTX_IP_CHANGED";
31  case MASTERNODE_READY:
32  return "READY";
33  case MASTERNODE_ERROR:
34  return "ERROR";
35  default:
36  return "UNKNOWN";
37  }
38 }
39 
41 {
42  switch (state) {
44  return "Waiting for ProTx to appear on-chain";
46  return "Masternode was PoSe banned";
47  case MASTERNODE_REMOVED:
48  return "Masternode removed from list";
50  return "Operator key changed or revoked";
52  return "IP address specified in ProTx changed";
53  case MASTERNODE_READY:
54  return "Ready";
55  case MASTERNODE_ERROR:
56  return "Error. " + strError;
57  default:
58  return "Unknown";
59  }
60 }
61 
63 {
64  LOCK(cs_main);
65 
66  if (!fMasternodeMode) return;
67 
68  if (!deterministicMNManager->IsDIP3Enforced(pindex->nHeight)) return;
69 
70  // Check that our local network configuration is correct
72  // listen option is probably overwritten by something else, no good
74  strError = "Masternode must accept connections from outside. Make sure listen configuration option is not overwritten by some another parameter.";
75  LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError);
76  return;
77  }
78 
81  return;
82  }
83 
84  CDeterministicMNList mnList = deterministicMNManager->GetListForBlock(pindex);
85 
87  if (!dmn) {
88  // MN not appeared on the chain yet
89  return;
90  }
91 
92  if (!mnList.IsMNValid(dmn->proTxHash)) {
93  if (mnList.IsMNPoSeBanned(dmn->proTxHash)) {
95  } else {
97  }
98  return;
99  }
100 
101  LogPrintf("CActiveMasternodeManager::Init -- proTxHash=%s, proTx=%s\n", dmn->proTxHash.ToString(), dmn->ToString());
102 
103  if (activeMasternodeInfo.service != dmn->pdmnState->addr) {
105  strError = "Local address does not match the address from ProTx";
106  LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError);
107  return;
108  }
109 
110  // Check socket connectivity
111  LogPrintf("CActiveMasternodeManager::Init -- Checking inbound connection to '%s'\n", activeMasternodeInfo.service.ToString());
113  if (hSocket == INVALID_SOCKET) {
115  strError = "Could not create socket to connect to " + activeMasternodeInfo.service.ToString();
116  LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError);
117  return;
118  }
120  CloseSocket(hSocket);
121 
122  if (!fConnected && Params().RequireRoutableExternalIP()) {
124  strError = "Could not connect to " + activeMasternodeInfo.service.ToString();
125  LogPrintf("CActiveMasternodeManager::Init -- ERROR: %s\n", strError);
126  return;
127  }
128 
129  activeMasternodeInfo.proTxHash = dmn->proTxHash;
130  activeMasternodeInfo.outpoint = dmn->collateralOutpoint;
132 }
133 
134 void CActiveMasternodeManager::UpdatedBlockTip(const CBlockIndex* pindexNew, const CBlockIndex* pindexFork, bool fInitialDownload)
135 {
136  LOCK(cs_main);
137 
138  if (!fMasternodeMode) return;
139 
140  if (!deterministicMNManager->IsDIP3Enforced(pindexNew->nHeight)) return;
141 
142  if (state == MASTERNODE_READY) {
143  auto oldMNList = deterministicMNManager->GetListForBlock(pindexNew->pprev);
144  auto newMNList = deterministicMNManager->GetListForBlock(pindexNew);
145  if (!newMNList.IsMNValid(activeMasternodeInfo.proTxHash)) {
146  // MN disappeared from MN list
150  // MN might have reappeared in same block with a new ProTx
151  Init(pindexNew);
152  return;
153  }
154 
155  auto oldDmn = oldMNList.GetMN(activeMasternodeInfo.proTxHash);
156  auto newDmn = newMNList.GetMN(activeMasternodeInfo.proTxHash);
157  if (newDmn->pdmnState->pubKeyOperator != oldDmn->pdmnState->pubKeyOperator) {
158  // MN operator key changed or revoked
162  // MN might have reappeared in same block with a new ProTx
163  Init(pindexNew);
164  return;
165  }
166 
167  if (newDmn->pdmnState->addr != oldDmn->pdmnState->addr) {
168  // MN IP changed
172  Init(pindexNew);
173  return;
174  }
175  } else {
176  // MN might have (re)appeared with a new ProTx or we've found some peers
177  // and figured out our local address
178  Init(pindexNew);
179  }
180 }
181 
183 {
184  // First try to find whatever our own local address is known internally.
185  // Addresses could be specified via externalip or bind option, discovered via UPnP
186  // or added by TorController. Use some random dummy IPv4 peer to prefer the one
187  // reachable via IPv4.
188  CNetAddr addrDummyPeer;
189  bool fFoundLocal{false};
190  if (LookupHost("8.8.8.8", addrDummyPeer, false)) {
191  fFoundLocal = GetLocal(addrRet, &addrDummyPeer) && IsValidNetAddr(addrRet);
192  }
193  if (!fFoundLocal && !Params().RequireRoutableExternalIP()) {
194  if (Lookup("127.0.0.1", addrRet, GetListenPort(), false)) {
195  fFoundLocal = true;
196  }
197  }
198  if (!fFoundLocal) {
199  bool empty = true;
200  // If we have some peers, let's try to find our local address from one of them
201  g_connman->ForEachNodeContinueIf(CConnman::AllNodes, [&fFoundLocal, &empty](CNode* pnode) {
202  empty = false;
203  if (pnode->addr.IsIPv4())
205  return !fFoundLocal;
206  });
207  // nothing and no live connections, can't do anything for now
208  if (empty) {
209  strError = "Can't detect valid external address. Please consider using the externalip configuration option if problem persists. Make sure to use IPv4 address only.";
210  LogPrintf("CActiveMasternodeManager::GetLocalAddress -- ERROR: %s\n", strError);
211  return false;
212  }
213  }
214  return true;
215 }
216 
218 {
219  // TODO: regtest is fine with any addresses for now,
220  // should probably be a bit smarter if one day we start to implement tests for this
221  return !Params().RequireRoutableExternalIP() ||
222  (addrIn.IsIPv4() && IsReachable(addrIn) && addrIn.IsRoutable());
223 }
static constexpr const CAllNodes AllNodes
Definition: net.h:225
bool GetLocal(CService &addr, const CNetAddr *paddrPeer)
Definition: net.cpp:132
std::string ToString(bool fUseGetnameinfo=true) const
Definition: netaddress.cpp:581
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: chain.h:177
static bool IsSelectableSocket(const SOCKET &s)
Definition: compat.h:117
CCriticalSection cs_main
Definition: validation.cpp:213
bool IsMNValid(const uint256 &proTxHash) const
std::shared_ptr< const CDeterministicMN > CDeterministicMNCPtr
unsigned short GetListenPort()
Definition: net.cpp:126
#define INVALID_SOCKET
Definition: compat.h:73
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
const impl< T, B, MP > empty
bool IsIPv4() const
Definition: netaddress.cpp:89
bool fMasternodeMode
Definition: util.cpp:93
#define LogPrintf(...)
Definition: util.h:203
CActiveMasternodeInfo activeMasternodeInfo
bool ConnectSocketDirectly(const CService &addrConnect, const SOCKET &hSocket, int nTimeout)
Definition: netbase.cpp:482
#define LOCK(cs)
Definition: sync.h:178
masternode_state_t state
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:143
bool RequireRoutableExternalIP() const
Require addresses specified with "-externalip" parameter to be routable.
Definition: chainparams.h:65
bool CloseSocket(SOCKET &hSocket)
Close socket and set hSocket to INVALID_SOCKET.
Definition: netbase.cpp:690
int nConnectTimeout
Definition: netbase.cpp:35
bool GetLocalAddress(CService &addrRet)
bool IsRoutable() const
Definition: netaddress.cpp:230
void SetNull()
Definition: transaction.h:43
bool IsMNPoSeBanned(const uint256 &proTxHash) const
unsigned int SOCKET
Definition: compat.h:62
const CAddress addr
Definition: net.h:834
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:33
virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
Notifies listeners of updated block chain tip.
256-bit opaque blob.
Definition: uint256.h:123
bool IsReachable(enum Network net)
check whether a given network is one we can probably connect to
Definition: net.cpp:316
CDeterministicMNCPtr GetMNByOperatorKey(const CBLSPublicKey &pubKey)
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: chain.h:170
const CChainParams & Params()
Return the currently selected parameters.
bool Lookup(const char *pszName, std::vector< CService > &vAddr, int portDefault, bool fAllowLookup, unsigned int nMaxSolutions)
Definition: netbase.cpp:140
SOCKET CreateSocket(const CService &addrConnect)
Definition: netbase.cpp:446
bool fListen
Definition: net.cpp:113
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:97
std::string GetStateString() const
static bool IsValidNetAddr(CService addrIn)
std::string GetStatus() const
std::unique_ptr< CBLSPublicKey > blsPubKeyOperator
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:183
Information about a peer.
Definition: net.h:800
bool LookupHost(const char *pszName, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:117
void Init(const CBlockIndex *pindex)
CActiveMasternodeManager * activeMasternodeManager
Released under the MIT license