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 104538 : int MasternodeMinPingSeconds()
29 : {
30 104538 : return Params().IsRegTestNet() ? MASTERNODE_MIN_MNP_SECONDS_REGTEST : MASTERNODE_MIN_MNP_SECONDS;
31 : }
32 :
33 2 : int MasternodeBroadcastSeconds()
34 : {
35 2 : return Params().IsRegTestNet() ? MASTERNODE_MIN_MNB_SECONDS_REGTEST : MASTERNODE_MIN_MNB_SECONDS;
36 : }
37 :
38 16666 : int MasternodePingSeconds()
39 : {
40 16666 : return Params().IsRegTestNet() ? MASTERNODE_PING_SECONDS_REGTEST : MASTERNODE_PING_SECONDS;
41 : }
42 :
43 104226 : int MasternodeExpirationSeconds()
44 : {
45 104226 : return Params().IsRegTestNet() ? MASTERNODE_EXPIRATION_SECONDS_REGTEST : MASTERNODE_EXPIRATION_SECONDS;
46 : }
47 :
48 108277 : int MasternodeRemovalSeconds()
49 : {
50 108277 : return Params().IsRegTestNet() ? MASTERNODE_REMOVAL_SECONDS_REGTEST : MASTERNODE_REMOVAL_SECONDS;
51 : }
52 :
53 : // Used for sigTime < maxTimeWindow
54 50510 : int64_t GetMaxTimeWindow()
55 : {
56 50510 : return GetAdjustedTime() + 60 * 2;
57 : }
58 :
59 :
60 93 : CMasternode::CMasternode() :
61 93 : CSignedMessage()
62 : {
63 93 : LOCK(cs);
64 93 : vin = CTxIn();
65 93 : addr = CService();
66 93 : pubKeyCollateralAddress = CPubKey();
67 93 : pubKeyMasternode = CPubKey();
68 93 : sigTime = 0;
69 93 : lastPing = CMasternodePing();
70 93 : protocolVersion = PROTOCOL_VERSION;
71 93 : nScanningErrorCount = 0;
72 93 : nLastScanningErrorBlockHeight = 0;
73 93 : mnPayeeScript.clear();
74 93 : }
75 :
76 1890 : CMasternode::CMasternode(const CMasternode& other) :
77 1890 : CSignedMessage(other)
78 : {
79 1890 : LOCK(cs);
80 1890 : vin = other.vin;
81 1890 : addr = other.addr;
82 1890 : pubKeyCollateralAddress = other.pubKeyCollateralAddress;
83 1890 : pubKeyMasternode = other.pubKeyMasternode;
84 1890 : sigTime = other.sigTime;
85 1890 : lastPing = other.lastPing;
86 1890 : protocolVersion = other.protocolVersion;
87 1890 : nScanningErrorCount = other.nScanningErrorCount;
88 1890 : nLastScanningErrorBlockHeight = other.nLastScanningErrorBlockHeight;
89 1890 : mnPayeeScript = other.mnPayeeScript;
90 1890 : }
91 :
92 183 : CMasternode::CMasternode(const CDeterministicMNCPtr& dmn, int64_t registeredTime, const uint256& registeredHash) :
93 183 : CSignedMessage()
94 : {
95 183 : LOCK(cs);
96 183 : vin = CTxIn(dmn->collateralOutpoint);
97 183 : addr = dmn->pdmnState->addr;
98 183 : pubKeyCollateralAddress = CPubKey();
99 183 : pubKeyMasternode = CPubKey();
100 183 : sigTime = registeredTime;
101 183 : lastPing = CMasternodePing(vin, registeredHash, registeredTime);
102 183 : protocolVersion = PROTOCOL_VERSION;
103 183 : nScanningErrorCount = 0;
104 183 : nLastScanningErrorBlockHeight = 0;
105 183 : mnPayeeScript = dmn->pdmnState->scriptPayout;
106 183 : }
107 :
108 43 : uint256 CMasternode::GetSignatureHash() const
109 : {
110 43 : int version = !addr.IsAddrV1Compatible() ? PROTOCOL_VERSION | ADDRV2_FORMAT : PROTOCOL_VERSION;
111 43 : CHashWriter ss(SER_GETHASH, version);
112 43 : ss << nMessVersion;
113 43 : ss << addr;
114 43 : ss << sigTime;
115 43 : ss << pubKeyCollateralAddress;
116 43 : ss << pubKeyMasternode;
117 43 : ss << protocolVersion;
118 43 : 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 2 : bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb)
135 : {
136 2 : if (mnb.sigTime > sigTime) {
137 : // TODO: lock cs. Need to be careful as mnb.lastPing.CheckAndUpdate locks cs_main internally.
138 2 : nMessVersion = mnb.nMessVersion;
139 2 : pubKeyMasternode = mnb.pubKeyMasternode;
140 2 : pubKeyCollateralAddress = mnb.pubKeyCollateralAddress;
141 2 : sigTime = mnb.sigTime;
142 2 : vchSig = mnb.vchSig;
143 2 : protocolVersion = mnb.protocolVersion;
144 2 : addr = mnb.addr;
145 2 : int nDoS = 0;
146 2 : 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 2 : 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 39390 : arith_uint256 CMasternode::CalculateScore(const uint256& hash) const
161 : {
162 39390 : CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
163 39390 : ss << hash;
164 78780 : const arith_uint256& hash2 = UintToArith256(ss.GetHash());
165 :
166 39390 : CHashWriter ss2(SER_GETHASH, PROTOCOL_VERSION);
167 39390 : ss2 << hash;
168 118170 : const arith_uint256& aux = UintToArith256(vin.prevout.hash) + vin.prevout.n;
169 39390 : ss2 << aux;
170 78780 : const arith_uint256& hash3 = UintToArith256(ss2.GetHash());
171 :
172 39390 : return (hash3 > hash2 ? hash3 - hash2 : hash2 - hash3);
173 : }
174 :
175 107038 : CMasternode::state CMasternode::GetActiveState() const
176 : {
177 214076 : LOCK(cs);
178 107038 : if (fCollateralSpent) {
179 : return MASTERNODE_VIN_SPENT;
180 : }
181 104463 : if (!IsPingedWithin(MasternodeRemovalSeconds())) {
182 : return MASTERNODE_REMOVE;
183 : }
184 104226 : if (!IsPingedWithin(MasternodeExpirationSeconds())) {
185 : return MASTERNODE_EXPIRED;
186 : }
187 104129 : if(lastPing.sigTime - sigTime < MasternodeMinPingSeconds()){
188 3266 : return MASTERNODE_PRE_ENABLED;
189 : }
190 : return MASTERNODE_ENABLED;
191 : }
192 :
193 10 : 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 10 : return Params().IsRegTestNet() ||
198 0 : (IsReachable(addr) && addr.IsRoutable());
199 : }
200 :
201 43 : CMasternodeBroadcast::CMasternodeBroadcast() :
202 43 : CMasternode()
203 43 : { }
204 :
205 10 : CMasternodeBroadcast::CMasternodeBroadcast(CService newAddr, CTxIn newVin, CPubKey pubKeyCollateralAddressNew, CPubKey pubKeyMasternodeNew, int protocolVersionIn, const CMasternodePing& _lastPing) :
206 10 : CMasternode()
207 : {
208 10 : vin = newVin;
209 10 : addr = newAddr;
210 10 : pubKeyCollateralAddress = pubKeyCollateralAddressNew;
211 10 : pubKeyMasternode = pubKeyMasternodeNew;
212 10 : protocolVersion = protocolVersionIn;
213 10 : lastPing = _lastPing;
214 10 : sigTime = lastPing.sigTime;
215 10 : }
216 :
217 539 : CMasternodeBroadcast::CMasternodeBroadcast(const CMasternode& mn) :
218 539 : CMasternode(mn)
219 539 : { }
220 :
221 10 : 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 10 : CPubKey pubKeyCollateralAddressNew;
231 20 : CKey keyCollateralAddressNew;
232 10 : CPubKey pubKeyMasternodeNew;
233 20 : CKey keyMasternodeNew;
234 :
235 : //need correct blocks to send ping
236 10 : 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 20 : std::string strError;
243 10 : 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 10 : const uint256 collateralHash = uint256S(strTxHash);
249 10 : int collateralOutputIndex;
250 10 : try {
251 20 : 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 10 : 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 10 : COutPoint collateralOut(collateralHash, collateralOutputIndex);
265 10 : 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 10 : int nPort = 0;
276 10 : int nDefaultPort = Params().GetDefaultPort();
277 20 : std::string strHost;
278 20 : SplitHostPort(strService, nPort, strHost);
279 10 : if (nPort == 0) nPort = nDefaultPort;
280 20 : CService _service(LookupNumeric(strHost.c_str(), nPort));
281 :
282 : // The service needs the correct default port to work properly
283 30 : if (!CheckDefaultPort(_service, strErrorRet, "CMasternodeBroadcast::Create"))
284 : return false;
285 :
286 20 : CTxIn txin(collateralOut.hash, collateralOut.n);
287 10 : return Create(txin, _service, keyCollateralAddressNew, pubKeyCollateralAddressNew, keyMasternodeNew, pubKeyMasternodeNew, strErrorRet, mnbRet);
288 : }
289 :
290 10 : 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 10 : if (fImporting || fReindex) return false;
301 :
302 30 : 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 10 : const uint256& nBlockHashToPing = mnodeman.GetBlockHashToPing();
308 20 : CMasternodePing mnp(txin, nBlockHashToPing, GetAdjustedTime());
309 10 : 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 20 : mnbRet = CMasternodeBroadcast(service, txin, pubKeyCollateralAddressNew, pubKeyMasternodeNew, PROTOCOL_VERSION, mnp);
317 :
318 10 : 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 10 : 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 10 : bool CMasternodeBroadcast::Sign(const CKey& key, const CPubKey& pubKey)
336 : {
337 20 : std::string strError = "";
338 10 : nMessVersion = MessageVersion::MESS_VER_HASH;
339 20 : const std::string strMessage = GetSignatureHash().GetHex();
340 :
341 10 : if (!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
342 0 : return error("%s : SignMessage() (nMessVersion=%d) failed", __func__, nMessVersion);
343 : }
344 :
345 10 : 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 33 : bool CMasternodeBroadcast::CheckSignature() const
354 : {
355 66 : std::string strError = "";
356 33 : std::string strMessage = (
357 33 : nMessVersion == MessageVersion::MESS_VER_HASH ?
358 33 : GetSignatureHash().GetHex() :
359 0 : GetStrMessage()
360 99 : );
361 :
362 33 : 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 10 : bool CMasternodeBroadcast::CheckDefaultPort(CService service, std::string& strErrorRet, const std::string& strContext)
369 : {
370 10 : int nDefaultPort = Params().GetDefaultPort();
371 :
372 10 : 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 33 : bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
383 : {
384 : // make sure signature isn't in the future (past is OK)
385 33 : 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 33 : 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 33 : 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 66 : CScript pubkeyScript;
404 33 : pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID());
405 :
406 33 : 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 66 : CScript pubkeyScript2;
413 33 : pubkeyScript2 = GetScriptForDestination(pubKeyMasternode.GetID());
414 :
415 33 : 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 33 : 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 66 : std::string strError = "";
427 33 : 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 66 : if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
435 0 : if (addr.GetPort() != 51472) return false;
436 33 : } else if (addr.GetPort() == 51472)
437 : return false;
438 :
439 : // incorrect ping or its sigTime
440 33 : 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 33 : CMasternode* pmn = mnodeman.Find(vin.prevout);
446 :
447 : // no such masternode, nothing to update
448 33 : 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 2 : 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 2 : if (!pmn->IsEnabled()) return true;
460 :
461 : // mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below,
462 : // after that they just need to match
463 2 : if (pmn->pubKeyCollateralAddress == pubKeyCollateralAddress && !pmn->IsBroadcastedWithin(MasternodeBroadcastSeconds())) {
464 : //take the newest entry
465 4 : LogPrint(BCLog::MASTERNODE,"mnb - Got updated entry for %s\n", vin.prevout.hash.ToString());
466 2 : if (pmn->UpdateFromNewBroadcast((*this))) {
467 2 : if (pmn->IsEnabled()) Relay();
468 : }
469 2 : g_tiertwo_sync_state.AddedMasternodeList(GetHash());
470 : }
471 :
472 : return true;
473 : }
474 :
475 43 : void CMasternodeBroadcast::Relay()
476 : {
477 43 : CInv inv(MSG_MASTERNODE_ANNOUNCE, GetHash());
478 43 : g_connman->RelayInv(inv);
479 43 : }
480 :
481 670 : uint256 CMasternodeBroadcast::GetHash() const
482 : {
483 670 : CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
484 670 : ss << sigTime;
485 670 : ss << pubKeyCollateralAddress;
486 670 : return ss.GetHash();
487 : }
488 :
489 52668 : CMasternodePing::CMasternodePing() :
490 : CSignedMessage(),
491 : vin(),
492 : blockHash(),
493 52668 : sigTime(0)
494 52668 : { }
495 :
496 410 : CMasternodePing::CMasternodePing(const CTxIn& newVin, const uint256& nBlockHash, uint64_t _sigTime) :
497 : CSignedMessage(),
498 : vin(newVin),
499 : blockHash(nBlockHash),
500 410 : sigTime(_sigTime)
501 410 : { }
502 :
503 152885 : uint256 CMasternodePing::GetHash() const
504 : {
505 152885 : CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
506 152885 : ss << vin;
507 152885 : if (nMessVersion == MessageVersion::MESS_VER_HASH) ss << blockHash;
508 152885 : ss << sigTime;
509 152885 : 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 50477 : bool CMasternodePing::CheckAndUpdate(int& nDos, bool fRequireAvailable, bool fCheckSigTimeOnly)
518 : {
519 50477 : 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 50477 : 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 50477 : 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 50477 : 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 50476 : CMasternode* pmn = mnodeman.Find(vin.prevout);
549 50476 : const bool isMasternodeFound = (pmn != nullptr);
550 50476 : const bool isSignatureValid = (isMasternodeFound && CheckSignature(pmn->pubKeyMasternode.GetID()));
551 :
552 50476 : if(fCheckSigTimeOnly) {
553 66 : if (isMasternodeFound && !isSignatureValid) {
554 0 : nDos = 33;
555 0 : return false;
556 : }
557 : return true;
558 : }
559 :
560 151230 : LogPrint(BCLog::MNPING, "%s: New Ping - %s - %s - %lli\n", __func__, GetHash().ToString(), blockHash.ToString(), sigTime);
561 :
562 50410 : if (isMasternodeFound && pmn->protocolVersion >= ActiveProtocol()) {
563 :
564 : // Update ping only if the masternode is in available state (pre-enabled or enabled)
565 818 : if (fRequireAvailable && !pmn->IsAvailableState()) {
566 1 : nDos = 20;
567 1 : 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 409 : if (!pmn->IsPingedWithin(MasternodeMinPingSeconds() - 60, sigTime)) {
573 406 : if (!isSignatureValid) {
574 0 : nDos = 33;
575 0 : return false;
576 : }
577 :
578 : // ping have passed the basic checks, can be updated now
579 406 : mnodeman.mapSeenMasternodePing.emplace(GetHash(), *this);
580 :
581 : // SetLastPing locks masternode cs. Be careful with the lock ordering.
582 406 : pmn->SetLastPing(*this);
583 :
584 : //mnodeman.mapSeenMasternodeBroadcast.lastPing is probably outdated, so we'll update it
585 812 : CMasternodeBroadcast mnb(*pmn);
586 406 : const uint256& hash = mnb.GetHash();
587 406 : if (mnodeman.mapSeenMasternodeBroadcast.count(hash)) {
588 406 : mnodeman.mapSeenMasternodeBroadcast[hash].lastPing = *this;
589 : }
590 :
591 406 : if (!pmn->IsEnabled()) return false;
592 :
593 764 : LogPrint(BCLog::MNPING, "%s: Masternode ping accepted, vin: %s\n", __func__, vin.prevout.hash.ToString());
594 :
595 382 : Relay();
596 : return true;
597 : }
598 6 : 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 3 : 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 511 : void CMasternodePing::Relay()
608 : {
609 511 : CInv inv(MSG_MASTERNODE_PING, GetHash());
610 511 : g_connman->RelayInv(inv);
611 511 : }
612 :
613 183 : MasternodeRef MakeMasternodeRefForDMN(const CDeterministicMNCPtr& dmn)
614 : {
615 : // create legacy masternode for DMN
616 183 : int refHeight = std::max(dmn->pdmnState->nRegisteredHeight, dmn->pdmnState->nPoSeRevivedHeight);
617 732 : const CBlockIndex* pindex = WITH_LOCK(cs_main, return mapBlockIndex.at(chainActive[refHeight]->GetBlockHash()); );
618 183 : return std::make_shared<CMasternode>(CMasternode(dmn, pindex->GetBlockTime(), pindex->GetBlockHash()));
619 : }
|