Line data Source code
1 : // Copyright (c) 2014-2015 The Dash developers
2 : // Copyright (c) 2015-2022 The PIVX Core developers
3 : // Distributed under the MIT/X11 software license, see the accompanying
4 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 :
6 : #include "masternode.h"
7 :
8 : #include "addrman.h"
9 : #include "masternodeman.h"
10 : #include "netbase.h"
11 : #include "sync.h"
12 : #include "tiertwo/tiertwo_sync_state.h"
13 : #include "wallet/wallet.h"
14 :
15 : #define MASTERNODE_MIN_MNP_SECONDS_REGTEST 90
16 : #define MASTERNODE_MIN_MNB_SECONDS_REGTEST 25
17 : #define MASTERNODE_PING_SECONDS_REGTEST 25
18 : #define MASTERNODE_EXPIRATION_SECONDS_REGTEST 12 * 60
19 : #define MASTERNODE_REMOVAL_SECONDS_REGTEST 13 * 60
20 :
21 : #define MASTERNODE_MIN_MNP_SECONDS (10 * 60)
22 : #define MASTERNODE_MIN_MNB_SECONDS (5 * 60)
23 : #define MASTERNODE_PING_SECONDS (5 * 60)
24 : #define MASTERNODE_EXPIRATION_SECONDS (120 * 60)
25 : #define MASTERNODE_REMOVAL_SECONDS (130 * 60)
26 : #define MASTERNODE_CHECK_SECONDS 5
27 :
28 122294 : int MasternodeMinPingSeconds()
29 : {
30 122294 : return Params().IsRegTestNet() ? MASTERNODE_MIN_MNP_SECONDS_REGTEST : MASTERNODE_MIN_MNP_SECONDS;
31 : }
32 :
33 10 : int MasternodeBroadcastSeconds()
34 : {
35 10 : return Params().IsRegTestNet() ? MASTERNODE_MIN_MNB_SECONDS_REGTEST : MASTERNODE_MIN_MNB_SECONDS;
36 : }
37 :
38 34121 : int MasternodePingSeconds()
39 : {
40 34121 : return Params().IsRegTestNet() ? MASTERNODE_PING_SECONDS_REGTEST : MASTERNODE_PING_SECONDS;
41 : }
42 :
43 120245 : int MasternodeExpirationSeconds()
44 : {
45 120245 : return Params().IsRegTestNet() ? MASTERNODE_EXPIRATION_SECONDS_REGTEST : MASTERNODE_EXPIRATION_SECONDS;
46 : }
47 :
48 140066 : int MasternodeRemovalSeconds()
49 : {
50 140066 : return Params().IsRegTestNet() ? MASTERNODE_REMOVAL_SECONDS_REGTEST : MASTERNODE_REMOVAL_SECONDS;
51 : }
52 :
53 : // Used for sigTime < maxTimeWindow
54 52337 : int64_t GetMaxTimeWindow()
55 : {
56 52337 : return GetAdjustedTime() + 60 * 2;
57 : }
58 :
59 :
60 136 : CMasternode::CMasternode() :
61 136 : CSignedMessage()
62 : {
63 136 : LOCK(cs);
64 136 : vin = CTxIn();
65 136 : addr = CService();
66 136 : pubKeyCollateralAddress = CPubKey();
67 136 : pubKeyMasternode = CPubKey();
68 136 : sigTime = 0;
69 136 : lastPing = CMasternodePing();
70 136 : protocolVersion = PROTOCOL_VERSION;
71 136 : nScanningErrorCount = 0;
72 136 : nLastScanningErrorBlockHeight = 0;
73 136 : mnPayeeScript.clear();
74 136 : }
75 :
76 7725 : CMasternode::CMasternode(const CMasternode& other) :
77 7725 : CSignedMessage(other)
78 : {
79 7725 : LOCK(cs);
80 7725 : vin = other.vin;
81 7725 : addr = other.addr;
82 7725 : pubKeyCollateralAddress = other.pubKeyCollateralAddress;
83 7725 : pubKeyMasternode = other.pubKeyMasternode;
84 7725 : sigTime = other.sigTime;
85 7725 : lastPing = other.lastPing;
86 7725 : protocolVersion = other.protocolVersion;
87 7725 : nScanningErrorCount = other.nScanningErrorCount;
88 7725 : nLastScanningErrorBlockHeight = other.nLastScanningErrorBlockHeight;
89 7725 : mnPayeeScript = other.mnPayeeScript;
90 7725 : }
91 :
92 3830 : CMasternode::CMasternode(const CDeterministicMNCPtr& dmn, int64_t registeredTime, const uint256& registeredHash) :
93 3830 : CSignedMessage()
94 : {
95 3830 : LOCK(cs);
96 3830 : vin = CTxIn(dmn->collateralOutpoint);
97 3830 : addr = dmn->pdmnState->addr;
98 3830 : pubKeyCollateralAddress = CPubKey();
99 3830 : pubKeyMasternode = CPubKey();
100 3830 : sigTime = registeredTime;
101 3830 : lastPing = CMasternodePing(vin, registeredHash, registeredTime);
102 3830 : protocolVersion = PROTOCOL_VERSION;
103 3830 : nScanningErrorCount = 0;
104 3830 : nLastScanningErrorBlockHeight = 0;
105 3830 : mnPayeeScript = dmn->pdmnState->scriptPayout;
106 3830 : }
107 :
108 82 : uint256 CMasternode::GetSignatureHash() const
109 : {
110 82 : int version = !addr.IsAddrV1Compatible() ? PROTOCOL_VERSION | ADDRV2_FORMAT : PROTOCOL_VERSION;
111 82 : CHashWriter ss(SER_GETHASH, version);
112 82 : ss << nMessVersion;
113 82 : ss << addr;
114 82 : ss << sigTime;
115 82 : ss << pubKeyCollateralAddress;
116 82 : ss << pubKeyMasternode;
117 82 : ss << protocolVersion;
118 82 : return ss.GetHash();
119 : }
120 :
121 0 : std::string CMasternode::GetStrMessage() const
122 : {
123 0 : return (addr.ToString() +
124 0 : std::to_string(sigTime) +
125 0 : pubKeyCollateralAddress.GetID().ToString() +
126 0 : pubKeyMasternode.GetID().ToString() +
127 0 : std::to_string(protocolVersion)
128 0 : );
129 : }
130 :
131 : //
132 : // When a new masternode broadcast is sent, update our information
133 : //
134 12 : bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb)
135 : {
136 12 : if (mnb.sigTime > sigTime) {
137 : // TODO: lock cs. Need to be careful as mnb.lastPing.CheckAndUpdate locks cs_main internally.
138 12 : nMessVersion = mnb.nMessVersion;
139 12 : pubKeyMasternode = mnb.pubKeyMasternode;
140 12 : pubKeyCollateralAddress = mnb.pubKeyCollateralAddress;
141 12 : sigTime = mnb.sigTime;
142 12 : vchSig = mnb.vchSig;
143 12 : protocolVersion = mnb.protocolVersion;
144 12 : addr = mnb.addr;
145 12 : int nDoS = 0;
146 12 : if (mnb.lastPing.IsNull() || (!mnb.lastPing.IsNull() && mnb.lastPing.CheckAndUpdate(nDoS, false))) {
147 0 : lastPing = mnb.lastPing;
148 0 : mnodeman.mapSeenMasternodePing.emplace(lastPing.GetHash(), lastPing);
149 : }
150 12 : return true;
151 : }
152 : return false;
153 : }
154 :
155 : //
156 : // Deterministically calculate a given "score" for a Masternode depending on how close it's hash is to
157 : // the proof of work for that block. The further away they are the better, the furthest will win the election
158 : // and get paid this block
159 : //
160 43641 : arith_uint256 CMasternode::CalculateScore(const uint256& hash) const
161 : {
162 43641 : CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
163 43641 : ss << hash;
164 87282 : const arith_uint256& hash2 = UintToArith256(ss.GetHash());
165 :
166 43641 : CHashWriter ss2(SER_GETHASH, PROTOCOL_VERSION);
167 43641 : ss2 << hash;
168 130923 : const arith_uint256& aux = UintToArith256(vin.prevout.hash) + vin.prevout.n;
169 43641 : ss2 << aux;
170 87282 : const arith_uint256& hash3 = UintToArith256(ss2.GetHash());
171 :
172 43641 : return (hash3 > hash2 ? hash3 - hash2 : hash2 - hash3);
173 : }
174 :
175 122938 : CMasternode::state CMasternode::GetActiveState() const
176 : {
177 245876 : LOCK(cs);
178 122938 : if (fCollateralSpent) {
179 : return MASTERNODE_VIN_SPENT;
180 : }
181 120334 : if (!IsPingedWithin(MasternodeRemovalSeconds())) {
182 : return MASTERNODE_REMOVE;
183 : }
184 120245 : if (!IsPingedWithin(MasternodeExpirationSeconds())) {
185 : return MASTERNODE_EXPIRED;
186 : }
187 120165 : if(lastPing.sigTime - sigTime < MasternodeMinPingSeconds()){
188 3891 : return MASTERNODE_PRE_ENABLED;
189 : }
190 : return MASTERNODE_ENABLED;
191 : }
192 :
193 14 : bool CMasternode::IsValidNetAddr() const
194 : {
195 : // TODO: regtest is fine with any addresses for now,
196 : // should probably be a bit smarter if one day we start to implement tests for this
197 14 : return Params().IsRegTestNet() ||
198 0 : (IsReachable(addr) && addr.IsRoutable());
199 : }
200 :
201 82 : CMasternodeBroadcast::CMasternodeBroadcast() :
202 82 : CMasternode()
203 82 : { }
204 :
205 14 : CMasternodeBroadcast::CMasternodeBroadcast(CService newAddr, CTxIn newVin, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int protocolVersionIn, const CMasternodePing& _lastPing) :
206 14 : CMasternode()
207 : {
208 14 : vin = newVin;
209 14 : addr = newAddr;
210 14 : pubKeyCollateralAddress = pubKeyCollateralAddressNew;
211 14 : pubKeyMasternode = pubKeyMasternodeNew;
212 14 : protocolVersion = protocolVersionIn;
213 14 : lastPing = _lastPing;
214 14 : sigTime = lastPing.sigTime;
215 14 : }
216 :
217 2617 : CMasternodeBroadcast::CMasternodeBroadcast(const CMasternode& mn) :
218 2617 : CMasternode(mn)
219 2617 : { }
220 :
221 14 : bool CMasternodeBroadcast::Create(const std::string& strService,
222 : const std::string& strKeyMasternode,
223 : const std::string& strTxHash,
224 : const std::string& strOutputIndex,
225 : std::string& strErrorRet,
226 : CMasternodeBroadcast& mnbRet,
227 : bool fOffline,
228 : int chainHeight)
229 : {
230 14 : CPubKey pubKeyCollateralAddressNew;
231 28 : CKey keyCollateralAddressNew;
232 14 : CPubKey pubKeyMasternodeNew;
233 28 : CKey keyMasternodeNew;
234 :
235 : //need correct blocks to send ping
236 14 : if (!fOffline && !g_tiertwo_sync_state.IsBlockchainSynced()) {
237 0 : strErrorRet = "Sync in progress. Must wait until sync is complete to start Masternode";
238 0 : LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
239 0 : return false;
240 : }
241 :
242 28 : std::string strError;
243 14 : if (strTxHash.empty() || strOutputIndex.empty()) {
244 0 : strError = "Invalid masternode collateral hash or output index";
245 0 : return error("%s: %s", __func__, strError);
246 : }
247 :
248 14 : const uint256 collateralHash = uint256S(strTxHash);
249 14 : int collateralOutputIndex;
250 14 : try {
251 28 : collateralOutputIndex = std::stoi(strOutputIndex.c_str());
252 0 : } catch (const std::exception& e) {
253 0 : strError = "Invalid masternode output index";
254 0 : return error("%s: %s on strOutputIndex", __func__, e.what());
255 : }
256 :
257 14 : if (!CMessageSigner::GetKeysFromSecret(strKeyMasternode, keyMasternodeNew, pubKeyMasternodeNew)) {
258 0 : strErrorRet = strprintf("Invalid masternode key %s", strKeyMasternode);
259 0 : LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
260 0 : return false;
261 : }
262 :
263 : // Use wallet-0 here. Legacy mnb creation can be removed after transition to DMN
264 14 : COutPoint collateralOut(collateralHash, collateralOutputIndex);
265 14 : if (vpwallets.empty() || !vpwallets[0]->GetMasternodeVinAndKeys(pubKeyCollateralAddressNew,
266 : keyCollateralAddressNew,
267 : collateralOut,
268 : true, // fValidateCollateral
269 : strError)) {
270 0 : strErrorRet = strError; // GetMasternodeVinAndKeys logs this error. Only returned for GUI error notification.
271 0 : LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strprintf("Could not allocate txin %s:%s for masternode %s", strTxHash, strOutputIndex, strService));
272 0 : return false;
273 : }
274 :
275 14 : int nPort = 0;
276 14 : int nDefaultPort = Params().GetDefaultPort();
277 28 : std::string strHost;
278 28 : SplitHostPort(strService, nPort, strHost);
279 14 : if (nPort == 0) nPort = nDefaultPort;
280 28 : CService _service(LookupNumeric(strHost.c_str(), nPort));
281 :
282 : // The service needs the correct default port to work properly
283 42 : if (!CheckDefaultPort(_service, strErrorRet, "CMasternodeBroadcast::Create"))
284 : return false;
285 :
286 28 : CTxIn txin(collateralOut.hash, collateralOut.n);
287 14 : return Create(txin, _service, keyCollateralAddressNew, pubKeyCollateralAddressNew, keyMasternodeNew, pubKeyMasternodeNew, strErrorRet, mnbRet);
288 : }
289 :
290 14 : bool CMasternodeBroadcast::Create(const CTxIn& txin,
291 : const CService& service,
292 : const CKey& keyCollateralAddressNew,
293 : const CPubKey& pubKeyCollateralAddressNew,
294 : const CKey& keyMasternodeNew,
295 : const CPubKey& pubKeyMasternodeNew,
296 : std::string& strErrorRet,
297 : CMasternodeBroadcast& mnbRet)
298 : {
299 : // wait for reindex and/or import to finish
300 14 : if (fImporting || fReindex) return false;
301 :
302 42 : LogPrint(BCLog::MASTERNODE, "CMasternodeBroadcast::Create -- pubKeyCollateralAddressNew = %s, pubKeyMasternodeNew.GetID() = %s\n",
303 : EncodeDestination(pubKeyCollateralAddressNew.GetID()),
304 : pubKeyMasternodeNew.GetID().ToString());
305 :
306 : // Get block hash to ping (TODO: move outside of this function)
307 14 : const uint256& nBlockHashToPing = mnodeman.GetBlockHashToPing();
308 28 : CMasternodePing mnp(txin, nBlockHashToPing, GetAdjustedTime());
309 14 : if (!mnp.Sign(keyMasternodeNew, pubKeyMasternodeNew.GetID())) {
310 0 : strErrorRet = strprintf("Failed to sign ping, masternode=%s", txin.prevout.hash.ToString());
311 0 : LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
312 0 : mnbRet = CMasternodeBroadcast();
313 0 : return false;
314 : }
315 :
316 28 : mnbRet = CMasternodeBroadcast(service, txin, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION, mnp);
317 :
318 14 : if (!mnbRet.IsValidNetAddr()) {
319 0 : strErrorRet = strprintf("Invalid IP address %s, masternode=%s", mnbRet.addr.ToStringIP (), txin.prevout.hash.ToString());
320 0 : LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
321 0 : mnbRet = CMasternodeBroadcast();
322 0 : return false;
323 : }
324 :
325 14 : if (!mnbRet.Sign(keyCollateralAddressNew, pubKeyCollateralAddressNew)) {
326 0 : strErrorRet = strprintf("Failed to sign broadcast, masternode=%s", txin.prevout.hash.ToString());
327 0 : LogPrint(BCLog::MASTERNODE,"CMasternodeBroadcast::Create -- %s\n", strErrorRet);
328 0 : mnbRet = CMasternodeBroadcast();
329 0 : return false;
330 : }
331 :
332 : return true;
333 : }
334 :
335 14 : bool CMasternodeBroadcast::Sign(const CKey& key, const CPubKey& pubKey)
336 : {
337 28 : std::string strError = "";
338 14 : nMessVersion = MessageVersion::MESS_VER_HASH;
339 28 : const std::string strMessage = GetSignatureHash().GetHex();
340 :
341 14 : if (!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
342 0 : return error("%s : SignMessage() (nMessVersion=%d) failed", __func__, nMessVersion);
343 : }
344 :
345 14 : if (!CMessageSigner::VerifyMessage(pubKey, vchSig, strMessage, strError)) {
346 0 : return error("%s : VerifyMessage() (nMessVersion=%d) failed, error: %s\n",
347 0 : __func__, nMessVersion, strError);
348 : }
349 :
350 : return true;
351 : }
352 :
353 68 : bool CMasternodeBroadcast::CheckSignature() const
354 : {
355 136 : std::string strError = "";
356 68 : std::string strMessage = (
357 68 : nMessVersion == MessageVersion::MESS_VER_HASH ?
358 68 : GetSignatureHash().GetHex() :
359 0 : GetStrMessage()
360 204 : );
361 :
362 68 : if(!CMessageSigner::VerifyMessage(pubKeyCollateralAddress, vchSig, strMessage, strError))
363 0 : return error("%s : VerifyMessage (nMessVersion=%d) failed: %s", __func__, nMessVersion, strError);
364 :
365 : return true;
366 : }
367 :
368 14 : bool CMasternodeBroadcast::CheckDefaultPort(CService service, std::string& strErrorRet, const std::string& strContext)
369 : {
370 14 : int nDefaultPort = Params().GetDefaultPort();
371 :
372 14 : if (service.GetPort() != nDefaultPort && !Params().IsRegTestNet()) {
373 0 : strErrorRet = strprintf("Invalid port %u for masternode %s, only %d is supported on %s-net.",
374 0 : service.GetPort(), service.ToString(), nDefaultPort, Params().NetworkIDString());
375 0 : LogPrintf("%s - %s\n", strContext, strErrorRet);
376 0 : return false;
377 : }
378 :
379 : return true;
380 : }
381 :
382 68 : bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
383 : {
384 : // make sure signature isn't in the future (past is OK)
385 68 : if (sigTime > GetMaxTimeWindow()) {
386 0 : LogPrint(BCLog::MASTERNODE,"mnb - Signature rejected, too far into the future %s\n", vin.prevout.hash.ToString());
387 0 : nDos = 1;
388 0 : return false;
389 : }
390 :
391 : // reject old signature version
392 68 : if (nMessVersion != MessageVersion::MESS_VER_HASH) {
393 0 : LogPrint(BCLog::MASTERNODE, "mnb - rejecting old message version for mn %s\n", vin.prevout.hash.ToString());
394 0 : nDos = 30;
395 0 : return false;
396 : }
397 :
398 68 : if (protocolVersion < ActiveProtocol()) {
399 0 : LogPrint(BCLog::MASTERNODE,"mnb - ignoring outdated Masternode %s protocol version %d\n", vin.prevout.hash.ToString(), protocolVersion);
400 0 : return false;
401 : }
402 :
403 136 : CScript pubkeyScript;
404 68 : pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID());
405 :
406 68 : if (pubkeyScript.size() != 25) {
407 0 : LogPrint(BCLog::MASTERNODE,"mnb - pubkey the wrong size\n");
408 0 : nDos = 100;
409 0 : return false;
410 : }
411 :
412 136 : CScript pubkeyScript2;
413 68 : pubkeyScript2 = GetScriptForDestination(pubKeyMasternode.GetID());
414 :
415 68 : if (pubkeyScript2.size() != 25) {
416 0 : LogPrint(BCLog::MASTERNODE,"mnb - pubkey2 the wrong size\n");
417 0 : nDos = 100;
418 0 : return false;
419 : }
420 :
421 68 : if (!vin.scriptSig.empty()) {
422 0 : LogPrint(BCLog::MASTERNODE,"mnb - Ignore Not Empty ScriptSig %s\n", vin.prevout.hash.ToString());
423 0 : return false;
424 : }
425 :
426 136 : std::string strError = "";
427 68 : if (!CheckSignature()) {
428 : // For now (till v6.0), let's be "naive" and not fully ban nodes when the node is syncing
429 : // This could be a bad parsed BIP155 address that got stored on db on an old software version.
430 0 : nDos = g_tiertwo_sync_state.IsSynced() ? 100 : 5;
431 0 : return error("%s : Got bad Masternode address signature", __func__);
432 : }
433 :
434 136 : if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
435 0 : if (addr.GetPort() != 51472) return false;
436 68 : } else if (addr.GetPort() == 51472)
437 : return false;
438 :
439 : // incorrect ping or its sigTime
440 68 : if(lastPing.IsNull() || !lastPing.CheckAndUpdate(nDos, false, true)) {
441 0 : return false;
442 : }
443 :
444 : //search existing Masternode list, this is where we update existing Masternodes with new mnb broadcasts
445 68 : CMasternode* pmn = mnodeman.Find(vin.prevout);
446 :
447 : // no such masternode, nothing to update
448 68 : if (pmn == nullptr) return true;
449 :
450 : // this broadcast is older or equal than the one that we already have - it's bad and should never happen
451 : // unless someone is doing something fishy
452 : // (mapSeenMasternodeBroadcast in CMasternodeMan::ProcessMessage should filter legit duplicates)
453 10 : if(pmn->sigTime >= sigTime) {
454 0 : return error("%s : Bad sigTime %d for Masternode %20s %105s (existing broadcast is at %d)",
455 0 : __func__, sigTime, addr.ToString(), vin.ToString(), pmn->sigTime);
456 : }
457 :
458 : // masternode is not enabled yet/already, nothing to update
459 10 : if (!pmn->IsEnabled()) return true;
460 :
461 : // mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below,
462 : // after that they just need to match
463 10 : if (pmn->pubKeyCollateralAddress == pubKeyCollateralAddress && !pmn->IsBroadcastedWithin(MasternodeBroadcastSeconds())) {
464 : //take the newest entry
465 20 : LogPrint(BCLog::MASTERNODE,"mnb - Got updated entry for %s\n", vin.prevout.hash.ToString());
466 10 : if (pmn->UpdateFromNewBroadcast((*this))) {
467 10 : if (pmn->IsEnabled()) Relay();
468 : }
469 10 : g_tiertwo_sync_state.AddedMasternodeList(GetHash());
470 : }
471 :
472 : return true;
473 : }
474 :
475 78 : void CMasternodeBroadcast::Relay()
476 : {
477 78 : CInv inv(MSG_MASTERNODE_ANNOUNCE, GetHash());
478 78 : g_connman->RelayInv(inv);
479 78 : }
480 :
481 2872 : uint256 CMasternodeBroadcast::GetHash() const
482 : {
483 2872 : CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
484 2872 : ss << sigTime;
485 2872 : ss << pubKeyCollateralAddress;
486 2872 : return ss.GetHash();
487 : }
488 :
489 63948 : CMasternodePing::CMasternodePing() :
490 : CSignedMessage(),
491 : vin(),
492 : blockHash(),
493 63948 : sigTime(0)
494 63948 : { }
495 :
496 4455 : CMasternodePing::CMasternodePing(const CTxIn& newVin, const uint256& nBlockHash, uint64_t _sigTime) :
497 : CSignedMessage(),
498 : vin(newVin),
499 : blockHash(nBlockHash),
500 4455 : sigTime(_sigTime)
501 4455 : { }
502 :
503 164288 : uint256 CMasternodePing::GetHash() const
504 : {
505 164288 : CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
506 164288 : ss << vin;
507 164288 : if (nMessVersion == MessageVersion::MESS_VER_HASH) ss << blockHash;
508 164288 : ss << sigTime;
509 164288 : return ss.GetHash();
510 : }
511 :
512 0 : std::string CMasternodePing::GetStrMessage() const
513 : {
514 0 : return vin.ToString() + blockHash.ToString() + std::to_string(sigTime);
515 : }
516 :
517 52269 : bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireAvailable, bool fCheckSigTimeOnly)
518 : {
519 52269 : if (sigTime > GetMaxTimeWindow()) {
520 0 : LogPrint(BCLog::MNPING,"%s: Signature rejected, too far into the future %s\n", __func__, vin.prevout.hash.ToString());
521 0 : nDos = 30;
522 0 : return false;
523 : }
524 :
525 52269 : if (sigTime <= GetAdjustedTime() - 60 * 60) {
526 0 : LogPrint(BCLog::MNPING,"%s: Signature rejected, too far into the past %s - %d %d \n", __func__, vin.prevout.hash.ToString(), sigTime, GetAdjustedTime());
527 0 : nDos = 30;
528 0 : return false;
529 : }
530 :
531 : // reject old signature version
532 52269 : if (nMessVersion != MessageVersion::MESS_VER_HASH) {
533 0 : LogPrint(BCLog::MNPING, "mnp - rejecting old message version for mn %s\n", vin.prevout.hash.ToString());
534 0 : nDos = 30;
535 0 : return false;
536 : }
537 :
538 : // Check if the ping block hash exists and it's within 24 blocks from the tip
539 52269 : if (!mnodeman.IsWithinDepth(blockHash, 2 * MNPING_DEPTH)) {
540 3 : LogPrint(BCLog::MNPING,"%s: Masternode %s block hash %s is too old or has an invalid block hash\n",
541 : __func__, vin.prevout.hash.ToString(), blockHash.ToString());
542 : // don't ban peers relaying stale data before the active protocol enforcement
543 1 : nDos = 33;
544 1 : return false;
545 : }
546 :
547 : // see if we have this Masternode
548 52268 : CMasternode* pmn = mnodeman.Find(vin.prevout);
549 52268 : const bool isMasternodeFound = (pmn != nullptr);
550 52268 : const bool isSignatureValid = (isMasternodeFound && CheckSignature(pmn->pubKeyMasternode.GetID()));
551 :
552 52268 : if(fCheckSigTimeOnly) {
553 136 : if (isMasternodeFound && !isSignatureValid) {
554 0 : nDos = 33;
555 0 : return false;
556 : }
557 : return true;
558 : }
559 :
560 156396 : LogPrint(BCLog::MNPING, "%s: New Ping - %s - %s - %lli\n", __func__, GetHash().ToString(), blockHash.ToString(), sigTime);
561 :
562 52132 : if (isMasternodeFound && pmn->protocolVersion >= ActiveProtocol()) {
563 :
564 : // Update ping only if the masternode is in available state (pre-enabled or enabled)
565 4252 : if (fRequireAvailable && !pmn->IsAvailableState()) {
566 5 : nDos = 20;
567 5 : return false;
568 : }
569 :
570 : // update only if there is no known ping for this masternode or
571 : // last ping was more then MASTERNODE_MIN_MNP_SECONDS-60 ago comparing to this one
572 2127 : if (!pmn->IsPingedWithin(MasternodeMinPingSeconds() - 60, sigTime)) {
573 2115 : if (!isSignatureValid) {
574 0 : nDos = 33;
575 0 : return false;
576 : }
577 :
578 : // ping have passed the basic checks, can be updated now
579 2115 : mnodeman.mapSeenMasternodePing.emplace(GetHash(), *this);
580 :
581 : // SetLastPing locks masternode cs. Be careful with the lock ordering.
582 2115 : pmn->SetLastPing(*this);
583 :
584 : //mnodeman.mapSeenMasternodeBroadcast.lastPing is probably outdated, so we'll update it
585 4230 : CMasternodeBroadcast mnb(*pmn);
586 2115 : const uint256& hash = mnb.GetHash();
587 2115 : if (mnodeman.mapSeenMasternodeBroadcast.count(hash)) {
588 2115 : mnodeman.mapSeenMasternodeBroadcast[hash].lastPing = *this;
589 : }
590 :
591 2115 : if (!pmn->IsEnabled()) return false;
592 :
593 4168 : LogPrint(BCLog::MNPING, "%s: Masternode ping accepted, vin: %s\n", __func__, vin.prevout.hash.ToString());
594 :
595 2084 : Relay();
596 : return true;
597 : }
598 24 : LogPrint(BCLog::MNPING, "%s: Masternode ping arrived too early, vin: %s\n", __func__, vin.prevout.hash.ToString());
599 : //nDos = 1; //disable, this is happening frequently and causing banned peers
600 12 : return false;
601 : }
602 100000 : LogPrint(BCLog::MNPING, "%s: Couldn't find compatible Masternode entry, vin: %s\n", __func__, vin.prevout.hash.ToString());
603 :
604 : return false;
605 : }
606 :
607 2566 : void CMasternodePing::Relay()
608 : {
609 2566 : CInv inv(MSG_MASTERNODE_PING, GetHash());
610 2566 : g_connman->RelayInv(inv);
611 2566 : }
612 :
613 3830 : MasternodeRef MakeMasternodeRefForDMN(const CDeterministicMNCPtr& dmn)
614 : {
615 : // create legacy masternode for DMN
616 3830 : int refHeight = std::max(dmn->pdmnState->nRegisteredHeight, dmn->pdmnState->nPoSeRevivedHeight);
617 15320 : const CBlockIndex* pindex = WITH_LOCK(cs_main, return mapBlockIndex.at(chainActive[refHeight]->GetBlockHash()); );
618 3830 : return std::make_shared<CMasternode>(CMasternode(dmn, pindex->GetBlockTime(), pindex->GetBlockHash()));
619 : }
|