new PoSe - MNVERIFY (#1066)

This commit is contained in:
UdjinM6 2016-10-21 01:11:30 +04:00 committed by GitHub
parent cce7896d70
commit 342bda5fdc
10 changed files with 785 additions and 206 deletions

View File

@ -1578,6 +1578,7 @@ bool CDarksendPool::DoAutomaticDenominating(bool fDryRun)
LogPrintf("CDarksendPool::DoAutomaticDenominating -- error connecting\n"); LogPrintf("CDarksendPool::DoAutomaticDenominating -- error connecting\n");
strAutoDenomResult = _("Error connecting to Masternode."); strAutoDenomResult = _("Error connecting to Masternode.");
dsq.nTime = 0; //remove node dsq.nTime = 0; //remove node
pmn->nPoSeBanScore++;
continue; continue;
} }
} }
@ -1624,6 +1625,7 @@ bool CDarksendPool::DoAutomaticDenominating(bool fDryRun)
} else { } else {
LogPrintf("CDarksendPool::DoAutomaticDenominating -- can't connect %s\n", pmn->vin.ToString()); LogPrintf("CDarksendPool::DoAutomaticDenominating -- can't connect %s\n", pmn->vin.ToString());
nTries++; nTries++;
pmn->nPoSeBanScore++;
continue; continue;
} }
} }

View File

@ -5,6 +5,7 @@
#include "dsnotificationinterface.h" #include "dsnotificationinterface.h"
#include "darksend.h" #include "darksend.h"
#include "governance.h" #include "governance.h"
#include "masternodeman.h"
#include "masternode-payments.h" #include "masternode-payments.h"
#include "masternode-sync.h" #include "masternode-sync.h"
@ -18,6 +19,7 @@ CDSNotificationInterface::~CDSNotificationInterface()
void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindex) void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindex)
{ {
mnodeman.UpdatedBlockTip(pindex);
darkSendPool.UpdatedBlockTip(pindex); darkSendPool.UpdatedBlockTip(pindex);
mnpayments.UpdatedBlockTip(pindex); mnpayments.UpdatedBlockTip(pindex);
governance.UpdatedBlockTip(pindex); governance.UpdatedBlockTip(pindex);

View File

@ -1880,6 +1880,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// force UpdatedBlockTip to initialize pCurrentBlockIndex for DS, MN payments and budgets // force UpdatedBlockTip to initialize pCurrentBlockIndex for DS, MN payments and budgets
// but don't call it directly to prevent triggering of other listeners like zmq etc. // but don't call it directly to prevent triggering of other listeners like zmq etc.
// GetMainSignals().UpdatedBlockTip(chainActive.Tip()); // GetMainSignals().UpdatedBlockTip(chainActive.Tip());
mnodeman.UpdatedBlockTip(chainActive.Tip());
darkSendPool.UpdatedBlockTip(chainActive.Tip()); darkSendPool.UpdatedBlockTip(chainActive.Tip());
mnpayments.UpdatedBlockTip(chainActive.Tip()); mnpayments.UpdatedBlockTip(chainActive.Tip());
masternodeSync.UpdatedBlockTip(chainActive.Tip()); masternodeSync.UpdatedBlockTip(chainActive.Tip());

View File

@ -4959,6 +4959,10 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
case MSG_GOVERNANCE_OBJECT_VOTE: case MSG_GOVERNANCE_OBJECT_VOTE:
return governance.HaveVoteForHash(inv.hash); return governance.HaveVoteForHash(inv.hash);
case MSG_MASTERNODE_VERIFY:
return mnodeman.mapSeenMasternodeVerification.count(inv.hash);
} }
// Don't know what it is, just say we already got one // Don't know what it is, just say we already got one
@ -5205,6 +5209,16 @@ void static ProcessGetData(CNode* pfrom, const Consensus::Params& consensusParam
} }
} }
if (!pushed && inv.type == MSG_MASTERNODE_VERIFY) {
if(mnodeman.mapSeenMasternodeVerification.count(inv.hash)) {
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
ss.reserve(1000);
ss << mnodeman.mapSeenMasternodeVerification[inv.hash];
pfrom->PushMessage(NetMsgType::MNVERIFY, ss);
pushed = true;
}
}
if (!pushed) if (!pushed)
vNotFound.push_back(inv); vNotFound.push_back(inv);
} }

View File

@ -32,6 +32,7 @@ CMasternode::CMasternode() :
nCacheCollateralBlock(0), nCacheCollateralBlock(0),
nBlockLastPaid(0), nBlockLastPaid(0),
nProtocolVersion(PROTOCOL_VERSION), nProtocolVersion(PROTOCOL_VERSION),
nPoSeBanScore(0),
fAllowMixingTx(true), fAllowMixingTx(true),
fUnitTest(false) fUnitTest(false)
{} {}
@ -52,6 +53,7 @@ CMasternode::CMasternode(CService addrNew, CTxIn vinNew, CPubKey pubKeyCollatera
nCacheCollateralBlock(0), nCacheCollateralBlock(0),
nBlockLastPaid(0), nBlockLastPaid(0),
nProtocolVersion(nProtocolVersionIn), nProtocolVersion(nProtocolVersionIn),
nPoSeBanScore(0),
fAllowMixingTx(true), fAllowMixingTx(true),
fUnitTest(false) fUnitTest(false)
{} {}
@ -72,6 +74,7 @@ CMasternode::CMasternode(const CMasternode& other) :
nCacheCollateralBlock(other.nCacheCollateralBlock), nCacheCollateralBlock(other.nCacheCollateralBlock),
nBlockLastPaid(other.nBlockLastPaid), nBlockLastPaid(other.nBlockLastPaid),
nProtocolVersion(other.nProtocolVersion), nProtocolVersion(other.nProtocolVersion),
nPoSeBanScore(other.nPoSeBanScore),
fAllowMixingTx(other.fAllowMixingTx), fAllowMixingTx(other.fAllowMixingTx),
fUnitTest(other.fUnitTest) fUnitTest(other.fUnitTest)
{} {}
@ -92,6 +95,7 @@ CMasternode::CMasternode(const CMasternodeBroadcast& mnb) :
nCacheCollateralBlock(0), nCacheCollateralBlock(0),
nBlockLastPaid(0), nBlockLastPaid(0),
nProtocolVersion(mnb.nProtocolVersion), nProtocolVersion(mnb.nProtocolVersion),
nPoSeBanScore(0),
fAllowMixingTx(true), fAllowMixingTx(true),
fUnitTest(false) fUnitTest(false)
{} {}
@ -101,21 +105,34 @@ CMasternode::CMasternode(const CMasternodeBroadcast& mnb) :
// //
bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb) bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb)
{ {
if(mnb.sigTime > sigTime) { if(mnb.sigTime <= sigTime) return false;
pubKeyMasternode = mnb.pubKeyMasternode; pubKeyMasternode = mnb.pubKeyMasternode;
sigTime = mnb.sigTime; sigTime = mnb.sigTime;
vchSig = mnb.vchSig; vchSig = mnb.vchSig;
nProtocolVersion = mnb.nProtocolVersion; nProtocolVersion = mnb.nProtocolVersion;
addr = mnb.addr; addr = mnb.addr;
nPoSeBanScore = 0;
nTimeLastChecked = 0; nTimeLastChecked = 0;
int nDos = 0; int nDos = 0;
if(mnb.lastPing == CMasternodePing() || (mnb.lastPing != CMasternodePing() && mnb.lastPing.CheckAndUpdate(nDos, false))) { if(mnb.lastPing == CMasternodePing() || (mnb.lastPing != CMasternodePing() && mnb.lastPing.CheckAndUpdate(nDos, false))) {
lastPing = mnb.lastPing; lastPing = mnb.lastPing;
mnodeman.mapSeenMasternodePing.insert(std::make_pair(lastPing.GetHash(), lastPing)); mnodeman.mapSeenMasternodePing.insert(std::make_pair(lastPing.GetHash(), lastPing));
} }
return true; // if it matches our Masternode privkey...
} if(fMasterNode && pubKeyMasternode == activeMasternode.pubKeyMasternode) {
nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
if(nProtocolVersion == PROTOCOL_VERSION) {
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
activeMasternode.ManageState();
} else {
// ... otherwise we need to reactivate our node, do not add it to the list and do not relay
// but also do not ban the node we get this message from
LogPrintf("CMasternode::UpdateFromNewBroadcast -- wrong PROTOCOL_VERSION, re-activate your MN: message nProtocolVersion=%d PROTOCOL_VERSION=%d\n", nProtocolVersion, PROTOCOL_VERSION);
return false; return false;
}
}
return true;
} }
// //
@ -143,10 +160,9 @@ void CMasternode::Check(bool fForce)
{ {
LOCK(cs); LOCK(cs);
bool fWatchdogActive = mnodeman.IsWatchdogActive(); static int64_t nTimeStart = GetTime();
LogPrint("masternode", "CMasternode::Check start -- vin = %s\n", LogPrint("masternode", "CMasternode::Check start -- vin %s\n", vin.prevout.ToStringShort());
vin.prevout.ToStringShort());
//once spent, stop doing the checks //once spent, stop doing the checks
if(nActiveState == MASTERNODE_OUTPOINT_SPENT) return; if(nActiveState == MASTERNODE_OUTPOINT_SPENT) return;
@ -156,9 +172,18 @@ void CMasternode::Check(bool fForce)
if(!fForce && (GetTime() - nTimeLastChecked < MASTERNODE_CHECK_SECONDS)) return; if(!fForce && (GetTime() - nTimeLastChecked < MASTERNODE_CHECK_SECONDS)) return;
nTimeLastChecked = GetTime(); nTimeLastChecked = GetTime();
if((nActiveState == MASTERNODE_WATCHDOG_EXPIRED) && !fWatchdogActive) { if(!fUnitTest) {
// Redo the checks TRY_LOCK(cs_main, lockMain);
nActiveState = MASTERNODE_ENABLED; if(!lockMain) return;
CCoins coins;
if(!pcoinsTip->GetCoins(vin.prevout.hash, coins) ||
(unsigned int)vin.prevout.n>=coins.vout.size() ||
coins.vout[vin.prevout.n].IsNull()) {
nActiveState = MASTERNODE_OUTPOINT_SPENT;
LogPrint("masternode", "CMasternode::Check -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort());
return;
}
} }
// masternode doesn't meet payment protocol requirements ... // masternode doesn't meet payment protocol requirements ...
@ -166,6 +191,24 @@ void CMasternode::Check(bool fForce)
// or it's our own node and we just updated it to the new protocol but we are still waiting for activation ... // or it's our own node and we just updated it to the new protocol but we are still waiting for activation ...
(pubKeyMasternode == activeMasternode.pubKeyMasternode && nProtocolVersion < PROTOCOL_VERSION); (pubKeyMasternode == activeMasternode.pubKeyMasternode && nProtocolVersion < PROTOCOL_VERSION);
// keep old masternodes on start, give them a chance to receive an updated ping without removal/expiry
if(!masternodeSync.IsMasternodeListSynced()) nTimeStart = GetTime();
bool fWaitForPing = (GetTime() - nTimeStart < MASTERNODE_MIN_MNP_SECONDS);
if(nActiveState == MASTERNODE_POSE_BAN) {
if(IsPingedWithin(MASTERNODE_POSE_BAN_SECONDS)) {
// Still alive? Good luck with that.
return;
} else {
// It's finally dead, good...
// or did we just start our node and it's too early to decide?
fRemove = !fWaitForPing;
}
} else if(nPoSeBanScore >= MASTERNODE_POSE_BAN_MAX_SCORE) {
nActiveState = MASTERNODE_POSE_BAN;
return;
}
if(fRemove) { if(fRemove) {
// it should be removed from the list // it should be removed from the list
nActiveState = MASTERNODE_REMOVE; nActiveState = MASTERNODE_REMOVE;
@ -175,47 +218,26 @@ void CMasternode::Check(bool fForce)
return; return;
} }
if(!IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS)) { bool fWatchdogActive = mnodeman.IsWatchdogActive();
if(nActiveState != MASTERNODE_WATCHDOG_EXPIRED) { bool fWatchdogExpired = (fWatchdogActive && ((GetTime() - nTimeLastWatchdogVote) > MASTERNODE_WATCHDOG_MAX_SECONDS));
nActiveState = MASTERNODE_EXPIRED;
LogPrint("masternode", "CMasternode::Check -- vin %s, nTimeLastWatchdogVote %d, GetTime() %d, fWatchdogExpired %d\n",
vin.prevout.ToStringShort(), nTimeLastWatchdogVote, GetTime(), fWatchdogExpired);
if(fWatchdogExpired) {
nActiveState = MASTERNODE_WATCHDOG_EXPIRED;
return;
} }
if(!fWaitForPing && !IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS)) {
nActiveState = MASTERNODE_EXPIRED;
// RESCAN AFFECTED VOTES // RESCAN AFFECTED VOTES
FlagGovernanceItemsAsDirty(); FlagGovernanceItemsAsDirty();
return; return;
} }
if(lastPing.sigTime - sigTime < MASTERNODE_MIN_MNP_SECONDS) { if(lastPing.sigTime - sigTime < MASTERNODE_MIN_MNP_SECONDS) {
if(nActiveState != MASTERNODE_WATCHDOG_EXPIRED) {
nActiveState = MASTERNODE_PRE_ENABLED; nActiveState = MASTERNODE_PRE_ENABLED;
}
return;
}
if(!fUnitTest) {
CValidationState state;
CMutableTransaction tx = CMutableTransaction();
CTxOut txout = CTxOut(999.99*COIN, mnodeman.dummyScriptPubkey);
tx.vin.push_back(vin);
tx.vout.push_back(txout);
{
TRY_LOCK(cs_main, lockMain);
if(!lockMain) return;
if(!AcceptToMemoryPool(mempool, state, CTransaction(tx), false, NULL, false, true, true)) {
nActiveState = MASTERNODE_OUTPOINT_SPENT;
return;
}
}
}
bool fWatchdogExpired = (fWatchdogActive && ((GetTime() - nTimeLastWatchdogVote) > MASTERNODE_WATCHDOG_MAX_SECONDS));
LogPrint("masternode", "CMasternode::Check -- vin = %s, nTimeLastWatchdogVote = %d, GetTime() = %d, fWatchdogExpired = %d\n",
vin.prevout.ToStringShort(), nTimeLastWatchdogVote, GetTime(), fWatchdogExpired);
if(fWatchdogExpired) {
nActiveState = MASTERNODE_WATCHDOG_EXPIRED;
return; return;
} }
@ -257,6 +279,7 @@ std::string CMasternode::GetStatus()
case CMasternode::MASTERNODE_OUTPOINT_SPENT: return "OUTPOINT_SPENT"; case CMasternode::MASTERNODE_OUTPOINT_SPENT: return "OUTPOINT_SPENT";
case CMasternode::MASTERNODE_REMOVE: return "REMOVE"; case CMasternode::MASTERNODE_REMOVE: return "REMOVE";
case CMasternode::MASTERNODE_WATCHDOG_EXPIRED: return "WATCHDOG_EXPIRED"; case CMasternode::MASTERNODE_WATCHDOG_EXPIRED: return "WATCHDOG_EXPIRED";
case CMasternode::MASTERNODE_POSE_BAN: return "POSE_BAN";
default: return "UNKNOWN"; default: return "UNKNOWN";
} }
} }
@ -398,12 +421,20 @@ bool CMasternodeBroadcast::Create(CTxIn txin, CService service, CKey keyCollater
return true; return true;
} }
bool CMasternodeBroadcast::CheckAndUpdate(int& nDos) bool CMasternodeBroadcast::SimpleCheck(int& nDos)
{ {
nDos = 0; nDos = 0;
// make sure addr is valid
if(!IsValidNetAddr()) {
LogPrintf("CMasternodeBroadcast::SimpleCheck -- Invalid addr, rejected: masternode=%s addr=%s\n",
vin.prevout.ToStringShort(), addr.ToString());
return false;
}
// make sure signature isn't in the future (past is OK) // make sure signature isn't in the future (past is OK)
if (sigTime > GetAdjustedTime() + 60 * 60) { if (sigTime > GetAdjustedTime() + 60 * 60) {
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- Signature rejected, too far into the future: masternode=%s\n", vin.prevout.ToStringShort()); LogPrintf("CMasternodeBroadcast::SimpleCheck -- Signature rejected, too far into the future: masternode=%s\n", vin.prevout.ToStringShort());
nDos = 1; nDos = 1;
return false; return false;
} }
@ -414,7 +445,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
} }
if(nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) { if(nProtocolVersion < mnpayments.GetMinMasternodePaymentsProto()) {
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- ignoring outdated Masternode: masternode=%s nProtocolVersion=%d\n", vin.prevout.ToStringShort(), nProtocolVersion); LogPrintf("CMasternodeBroadcast::SimpleCheck -- ignoring outdated Masternode: masternode=%s nProtocolVersion=%d\n", vin.prevout.ToStringShort(), nProtocolVersion);
return false; return false;
} }
@ -422,7 +453,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID()); pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID());
if(pubkeyScript.size() != 25) { if(pubkeyScript.size() != 25) {
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- pubKeyCollateralAddress has the wrong size\n"); LogPrintf("CMasternodeBroadcast::SimpleCheck -- pubKeyCollateralAddress has the wrong size\n");
nDos = 100; nDos = 100;
return false; return false;
} }
@ -431,18 +462,18 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
pubkeyScript2 = GetScriptForDestination(pubKeyMasternode.GetID()); pubkeyScript2 = GetScriptForDestination(pubKeyMasternode.GetID());
if(pubkeyScript2.size() != 25) { if(pubkeyScript2.size() != 25) {
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- pubKeyMasternode has the wrong size\n"); LogPrintf("CMasternodeBroadcast::SimpleCheck -- pubKeyMasternode has the wrong size\n");
nDos = 100; nDos = 100;
return false; return false;
} }
if(!vin.scriptSig.empty()) { if(!vin.scriptSig.empty()) {
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- Ignore Not Empty ScriptSig %s\n",vin.ToString()); LogPrintf("CMasternodeBroadcast::SimpleCheck -- Ignore Not Empty ScriptSig %s\n",vin.ToString());
return false; return false;
} }
if (!CheckSignature(nDos)) { if (!CheckSignature(nDos)) {
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- CheckSignature() failed, masternode=%s\n", vin.prevout.ToStringShort()); LogPrintf("CMasternodeBroadcast::SimpleCheck -- CheckSignature() failed, masternode=%s\n", vin.prevout.ToStringShort());
return false; return false;
} }
@ -451,28 +482,47 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
if(addr.GetPort() != mainnetDefaultPort) return false; if(addr.GetPort() != mainnetDefaultPort) return false;
} else if(addr.GetPort() == mainnetDefaultPort) return false; } else if(addr.GetPort() == mainnetDefaultPort) return false;
//search existing Masternode list, this is where we update existing Masternodes with new mnb broadcasts return true;
CMasternode* pmn = mnodeman.Find(vin); }
// no such masternode, nothing to update bool CMasternodeBroadcast::Update(CMasternode* pmn, int& nDos)
if(pmn == NULL) return true; {
if(pmn->sigTime == sigTime) {
// mapSeenMasternodeBroadcast in CMasternodeMan::CheckMnbAndUpdateMasternodeList should filter legit duplicates
// but this still can happen if we just started, which is ok, just do nothing here.
return true;
}
// this broadcast is older or equal than the one that we already have - it's bad and should never happen // this broadcast is older than the one that we already have - it's bad and should never happen
// unless someone is doing something fishy // unless someone is doing something fishy
// (mapSeenMasternodeBroadcast in CMasternodeMan::ProcessMessage should filter legit duplicates) if(pmn->sigTime > sigTime) {
if(pmn->sigTime >= sigTime) { LogPrintf("CMasternodeBroadcast::Update -- Bad sigTime %d (existing broadcast is at %d) for Masternode %s %s\n",
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- Bad sigTime %d (existing broadcast is at %d) for Masternode %s %s\n",
sigTime, pmn->sigTime, vin.prevout.ToStringShort(), addr.ToString()); sigTime, pmn->sigTime, vin.prevout.ToStringShort(), addr.ToString());
return false; return false;
} }
// masternode is not enabled yet/already, nothing to update pmn->Check();
if(!pmn->IsEnabled()) return true;
// IsVnAssociatedWithPubkey is validated once below, after that they just need to match // masternode is banned by PoSe
if(pmn->pubKeyCollateralAddress == pubKeyCollateralAddress && !pmn->IsBroadcastedWithin(MASTERNODE_MIN_MNB_SECONDS)) { if(pmn->IsPoSeBanned()) {
//take the newest entry LogPrintf("CMasternodeBroadcast::Update -- Banned by PoSe, masternode=%s\n", vin.prevout.ToStringShort());
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- Got UPDATED Masternode entry: addr=%s\n", addr.ToString()); return false;
}
// masternode is not enabled yet/already, nothing to update
if(!pmn->IsEnabled()) return false;
// IsVnAssociatedWithPubkey is validated once in CheckOutpoint, after that they just need to match
if(pmn->pubKeyCollateralAddress != pubKeyCollateralAddress) {
LogPrintf("CMasternodeMan::Update -- Got mismatched pubKeyCollateralAddress and vin\n");
nDos = 33;
return false;
}
// if ther was no masternode broadcast recently or if it matches our Masternode privkey...
if(!pmn->IsBroadcastedWithin(MASTERNODE_MIN_MNB_SECONDS) || (fMasterNode && pubKeyMasternode == activeMasternode.pubKeyMasternode)) {
// take the newest entry
LogPrintf("CMasternodeBroadcast::Update -- Got UPDATED Masternode entry: addr=%s\n", addr.ToString());
if(pmn->UpdateFromNewBroadcast((*this))) { if(pmn->UpdateFromNewBroadcast((*this))) {
pmn->Check(); pmn->Check();
// normally masternode should be in pre-enabled status after update, if not - do not relay // normally masternode should be in pre-enabled status after update, if not - do not relay
@ -486,66 +536,49 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
return true; return true;
} }
bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDos) bool CMasternodeBroadcast::CheckOutpoint(int& nDos)
{ {
// we are a masternode with the same vin (i.e. already activated) and this mnb is ours (matches our Masternode privkey) // we are a masternode with the same vin (i.e. already activated) and this mnb is ours (matches our Masternode privkey)
// so nothing to do here for us // so nothing to do here for us
if(fMasterNode && vin.prevout == activeMasternode.vin.prevout && pubKeyMasternode == activeMasternode.pubKeyMasternode) { if(fMasterNode && vin.prevout == activeMasternode.vin.prevout && pubKeyMasternode == activeMasternode.pubKeyMasternode) {
return true;
}
// incorrect ping or its sigTime
if(lastPing == CMasternodePing() || !lastPing.CheckAndUpdate(nDos, false, true)) {
return false; return false;
} }
// search existing Masternode list
CMasternode* pmn = mnodeman.Find(vin);
if(pmn != NULL) {
// nothing to do here if we already know about this masternode and it's (pre)enabled
if(pmn->IsEnabled() || pmn->IsPreEnabled() || pmn->IsWatchdogExpired()) return true;
// if it's not (pre)enabled, remove old MN first and continue
mnodeman.Remove(pmn->vin);
}
if(GetInputAge(vin) < Params().GetConsensus().nMasternodeMinimumConfirmations) {
LogPrintf("CMasternodeBroadcast::CheckInputsAndAdd -- Input must have at least %d confirmations\n", Params().GetConsensus().nMasternodeMinimumConfirmations);
// maybe we miss few blocks, let this mnb to be checked again later
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
return false;
}
CValidationState state;
CMutableTransaction dummyTx = CMutableTransaction();
CTxOut dummyTxOut = CTxOut(999.99*COIN, mnodeman.dummyScriptPubkey);
dummyTx.vin.push_back(vin);
dummyTx.vout.push_back(dummyTxOut);
{ {
TRY_LOCK(cs_main, lockMain); TRY_LOCK(cs_main, lockMain);
if(!lockMain) { if(!lockMain) {
// not mnb fault, let it to be checked again later // not mnb fault, let it to be checked again later
LogPrint("masternode", "CMasternodeBroadcast::CheckInputsAndAdd -- Failed to aquire lock, addr=%s", addr.ToString()); LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to aquire lock, addr=%s", addr.ToString());
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash()); mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
return false; return false;
} }
if(!AcceptToMemoryPool(mempool, state, CTransaction(dummyTx), false, NULL, false, true, true)) { CCoins coins;
//set nDos if(!pcoinsTip->GetCoins(vin.prevout.hash, coins) ||
LogPrint("masternode", "CMasternodeBroadcast::CheckInputsAndAdd -- Failed to accepted Masternode entry to mempool: dummyTx=%s", dummyTx.ToString()); (unsigned int)vin.prevout.n>=coins.vout.size() ||
state.IsInvalid(nDos); coins.vout[vin.prevout.n].IsNull()) {
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Failed to find Masternode UTXO, masternode=%s\n", vin.prevout.ToStringShort());
return false;
}
if(coins.vout[vin.prevout.n].nValue != 1000 * COIN) {
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO should have 1000 DASH, masternode=%s\n", vin.prevout.ToStringShort());
return false;
}
if(chainActive.Height() - coins.nHeight + 1 < Params().GetConsensus().nMasternodeMinimumConfirmations) {
LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO must have at least %d confirmations, masternode=\n",
Params().GetConsensus().nMasternodeMinimumConfirmations, vin.prevout.ToStringShort());
// maybe we miss few blocks, let this mnb to be checked again later
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
return false; return false;
} }
} }
LogPrint("masternode", "CMasternodeBroadcast::CheckInputsAndAdd -- Accepted Masternode entry to mempool (dry-run mode)\n"); LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO verified\n");
// make sure the vout that was signed is related to the transaction that spawned the Masternode // make sure the vout that was signed is related to the transaction that spawned the Masternode
// - this is expensive, so it's only done once per Masternode // - this is expensive, so it's only done once per Masternode
if(!darkSendSigner.IsVinAssociatedWithPubkey(vin, pubKeyCollateralAddress)) { if(!darkSendSigner.IsVinAssociatedWithPubkey(vin, pubKeyCollateralAddress)) {
LogPrintf("CMasternodeMan::CheckInputsAndAdd -- Got mismatched pubKeyCollateralAddress and vin\n"); LogPrintf("CMasternodeMan::CheckOutpoint -- Got mismatched pubKeyCollateralAddress and vin\n");
nDos = 33; nDos = 33;
return false; return false;
} }
@ -562,39 +595,13 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDos)
CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation
CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]; // block where tx got nMasternodeMinimumConfirmations CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]; // block where tx got nMasternodeMinimumConfirmations
if(pConfIndex->GetBlockTime() > sigTime) { if(pConfIndex->GetBlockTime() > sigTime) {
LogPrintf("CMasternodeBroadcast::CheckInputsAndAdd -- Bad sigTime %d (%d conf block is at %d) for Masternode %s %s\n", LogPrintf("CMasternodeBroadcast::CheckOutpoint -- Bad sigTime %d (%d conf block is at %d) for Masternode %s %s\n",
sigTime, Params().GetConsensus().nMasternodeMinimumConfirmations, pConfIndex->GetBlockTime(), vin.prevout.ToStringShort(), addr.ToString()); sigTime, Params().GetConsensus().nMasternodeMinimumConfirmations, pConfIndex->GetBlockTime(), vin.prevout.ToStringShort(), addr.ToString());
return false; return false;
} }
} }
} }
// if it matches our Masternode privkey...
if(fMasterNode && pubKeyMasternode == activeMasternode.pubKeyMasternode) {
if(nProtocolVersion == PROTOCOL_VERSION) {
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
activeMasternode.EnableRemoteMasterNode(vin, addr);
} else {
// ... otherwise we need to reactivate our node, don not add it to the list and do not relay
// but also do not ban the node we get this message from
LogPrintf("CMasternodeBroadcast::CheckInputsAndAdd -- wrong PROTOCOL_VERSION, re-activate your MN: message nProtocolVersion=%d PROTOCOL_VERSION=%d\n", nProtocolVersion, PROTOCOL_VERSION);
return false;
}
}
LogPrintf("CMasternodeBroadcast::CheckInputsAndAdd -- Got NEW Masternode entry: masternode=%s sigTime=%lld addr=%s\n", vin.prevout.ToStringShort(), sigTime, addr.ToString());
CMasternode mn(*this);
mnodeman.Add(mn);
bool isLocal = addr.IsRFC1918() || addr.IsLocal();
if(Params().NetworkIDString() == CBaseChainParams::REGTEST) {
isLocal = false;
}
if(!isLocal) {
Relay();
}
return true; return true;
} }

View File

@ -16,12 +16,13 @@ class CMasternodePing;
static const int MASTERNODE_MIN_MNP_SECONDS = 10 * 60; static const int MASTERNODE_MIN_MNP_SECONDS = 10 * 60;
static const int MASTERNODE_MIN_MNB_SECONDS = 5 * 60; static const int MASTERNODE_MIN_MNB_SECONDS = 5 * 60;
static const int MASTERNODE_MIN_DSEG_SECONDS = 10 * 60;
static const int MASTERNODE_EXPIRATION_SECONDS = 65 * 60; static const int MASTERNODE_EXPIRATION_SECONDS = 65 * 60;
static const int MASTERNODE_REMOVAL_SECONDS = 75 * 60; static const int MASTERNODE_REMOVAL_SECONDS = 75 * 60;
static const int MASTERNODE_CHECK_SECONDS = 5; static const int MASTERNODE_CHECK_SECONDS = 5;
static const int MASTERNODE_WATCHDOG_MAX_SECONDS = 2 * 60 * 60; static const int MASTERNODE_WATCHDOG_MAX_SECONDS = 2 * 60 * 60;
static const int MASTERNODE_POSE_BAN_SECONDS = 24 * 60 * 60;
static const int MASTERNODE_POSE_BAN_MAX_SCORE = 5;
// //
// The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network // The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network
// //
@ -144,7 +145,8 @@ public:
MASTERNODE_EXPIRED, MASTERNODE_EXPIRED,
MASTERNODE_OUTPOINT_SPENT, MASTERNODE_OUTPOINT_SPENT,
MASTERNODE_REMOVE, MASTERNODE_REMOVE,
MASTERNODE_WATCHDOG_EXPIRED MASTERNODE_WATCHDOG_EXPIRED,
MASTERNODE_POSE_BAN
}; };
CTxIn vin; CTxIn vin;
@ -162,6 +164,7 @@ public:
int nCacheCollateralBlock; int nCacheCollateralBlock;
int nBlockLastPaid; int nBlockLastPaid;
int nProtocolVersion; int nProtocolVersion;
int nPoSeBanScore;
bool fAllowMixingTx; bool fAllowMixingTx;
bool fUnitTest; bool fUnitTest;
@ -193,6 +196,7 @@ public:
READWRITE(nCacheCollateralBlock); READWRITE(nCacheCollateralBlock);
READWRITE(nBlockLastPaid); READWRITE(nBlockLastPaid);
READWRITE(nProtocolVersion); READWRITE(nProtocolVersion);
READWRITE(nPoSeBanScore);
READWRITE(fAllowMixingTx); READWRITE(fAllowMixingTx);
READWRITE(fUnitTest); READWRITE(fUnitTest);
READWRITE(mapGovernanceObjectsVotedOn); READWRITE(mapGovernanceObjectsVotedOn);
@ -220,6 +224,7 @@ public:
swap(first.nCacheCollateralBlock, second.nCacheCollateralBlock); swap(first.nCacheCollateralBlock, second.nCacheCollateralBlock);
swap(first.nBlockLastPaid, second.nBlockLastPaid); swap(first.nBlockLastPaid, second.nBlockLastPaid);
swap(first.nProtocolVersion, second.nProtocolVersion); swap(first.nProtocolVersion, second.nProtocolVersion);
swap(first.nPoSeBanScore, second.nPoSeBanScore);
swap(first.fAllowMixingTx, second.fAllowMixingTx); swap(first.fAllowMixingTx, second.fAllowMixingTx);
swap(first.fUnitTest, second.fUnitTest); swap(first.fUnitTest, second.fUnitTest);
swap(first.mapGovernanceObjectsVotedOn, second.mapGovernanceObjectsVotedOn); swap(first.mapGovernanceObjectsVotedOn, second.mapGovernanceObjectsVotedOn);
@ -246,6 +251,8 @@ public:
bool IsEnabled() { return nActiveState == MASTERNODE_ENABLED; } bool IsEnabled() { return nActiveState == MASTERNODE_ENABLED; }
bool IsPreEnabled() { return nActiveState == MASTERNODE_PRE_ENABLED; } bool IsPreEnabled() { return nActiveState == MASTERNODE_PRE_ENABLED; }
bool IsPoSeBanned() { return nActiveState == MASTERNODE_POSE_BAN; }
bool IsPoSeVerified() { return nPoSeBanScore <= -MASTERNODE_POSE_BAN_MAX_SCORE; }
bool IsWatchdogExpired() { return nActiveState == MASTERNODE_WATCHDOG_EXPIRED; } bool IsWatchdogExpired() { return nActiveState == MASTERNODE_WATCHDOG_EXPIRED; }
@ -339,12 +346,75 @@ public:
static bool Create(CTxIn vin, CService service, CKey keyCollateralAddressNew, CPubKey pubKeyCollateralAddressNew, CKey keyMasternodeNew, CPubKey pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet); static bool Create(CTxIn vin, CService service, CKey keyCollateralAddressNew, CPubKey pubKeyCollateralAddressNew, CKey keyMasternodeNew, CPubKey pubKeyMasternodeNew, std::string &strErrorRet, CMasternodeBroadcast &mnbRet);
static bool Create(std::string strService, std::string strKey, std::string strTxHash, std::string strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast &mnbRet, bool fOffline = false); static bool Create(std::string strService, std::string strKey, std::string strTxHash, std::string strOutputIndex, std::string& strErrorRet, CMasternodeBroadcast &mnbRet, bool fOffline = false);
bool CheckAndUpdate(int& nDos); bool SimpleCheck(int& nDos);
bool CheckInputsAndAdd(int& nDos); bool Update(CMasternode* pmn, int& nDos);
bool CheckOutpoint(int& nDos);
bool Sign(CKey& keyCollateralAddress); bool Sign(CKey& keyCollateralAddress);
bool CheckSignature(int& nDos); bool CheckSignature(int& nDos);
void Relay(); void Relay();
}; };
class CMasternodeVerification
{
public:
CTxIn vin1;
CTxIn vin2;
CService addr;
int nonce;
int nBlockHeight;
std::vector<unsigned char> vchSig1;
std::vector<unsigned char> vchSig2;
CMasternodeVerification() :
vin1(),
vin2(),
addr(),
nonce(0),
nBlockHeight(0),
vchSig1(),
vchSig2()
{}
CMasternodeVerification(CService addr, int nonce, int nBlockHeight) :
vin1(),
vin2(),
addr(addr),
nonce(nonce),
nBlockHeight(nBlockHeight),
vchSig1(),
vchSig2()
{}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
READWRITE(vin1);
READWRITE(vin2);
READWRITE(addr);
READWRITE(nonce);
READWRITE(nBlockHeight);
READWRITE(vchSig1);
READWRITE(vchSig2);
}
uint256 GetHash() const
{
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
ss << vin1;
ss << vin2;
ss << addr;
ss << nonce;
ss << nBlockHeight;
return ss.GetHash();
}
void Relay() const
{
CInv inv(MSG_MASTERNODE_VERIFY, GetHash());
RelayInv(inv);
}
};
#endif #endif

View File

@ -8,6 +8,7 @@
#include "masternode.h" #include "masternode.h"
#include "masternode-payments.h" #include "masternode-payments.h"
#include "masternode-sync.h" #include "masternode-sync.h"
#include "netfulfilledman.h"
#include "util.h" #include "util.h"
#include "addrman.h" #include "addrman.h"
#include "spork.h" #include "spork.h"
@ -17,6 +18,8 @@
/** Masternode manager */ /** Masternode manager */
CMasternodeMan mnodeman; CMasternodeMan mnodeman;
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-1";
struct CompareLastPaidBlock struct CompareLastPaidBlock
{ {
bool operator()(const std::pair<int, CMasternode*>& t1, bool operator()(const std::pair<int, CMasternode*>& t1,
@ -35,12 +38,14 @@ struct CompareScoreMN
} }
}; };
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-1"; struct CompareByAddr
{
CMasternodeMan::CMasternodeMan() { bool operator()(const CMasternode* t1,
nDsqCount = 0; const CMasternode* t2) const
nLastWatchdogVoteTime = 0; {
} return t1->addr < t2->addr;
}
};
bool CMasternodeMan::Add(CMasternode &mn) bool CMasternodeMan::Add(CMasternode &mn)
{ {
@ -151,6 +156,15 @@ void CMasternodeMan::CheckAndRemove(bool fForceExpiredRemoval)
} }
} }
std::map<CNetAddr, CMasternodeVerification>::iterator itv1 = mWeAskedForVerification.begin();
while(itv1 != mWeAskedForVerification.end()){
if(itv1->second.nBlockHeight < pCurrentBlockIndex->nHeight - MAX_POSE_BLOCKS) {
mWeAskedForVerification.erase(itv1++);
} else {
++itv1;
}
}
// remove expired mapSeenMasternodeBroadcast // remove expired mapSeenMasternodeBroadcast
map<uint256, CMasternodeBroadcast>::iterator it3 = mapSeenMasternodeBroadcast.begin(); map<uint256, CMasternodeBroadcast>::iterator it3 = mapSeenMasternodeBroadcast.begin();
while(it3 != mapSeenMasternodeBroadcast.end()){ while(it3 != mapSeenMasternodeBroadcast.end()){
@ -173,6 +187,16 @@ void CMasternodeMan::CheckAndRemove(bool fForceExpiredRemoval)
} }
} }
// remove expired mapSeenMasternodeVerification
std::map<uint256, CMasternodeVerification>::iterator itv2 = mapSeenMasternodeVerification.begin();
while(itv2 != mapSeenMasternodeVerification.end()){
if((*itv2).second.nBlockHeight < pCurrentBlockIndex->nHeight - MAX_POSE_BLOCKS){
LogPrint("masternode", "CMasternodeMan::CheckAndRemove -- Removing expired Masternode verification: hash=%s\n", (*itv2).first.ToString());
mapSeenMasternodeVerification.erase(itv2++);
} else {
++itv2;
}
}
} }
void CMasternodeMan::Clear() void CMasternodeMan::Clear()
@ -250,7 +274,7 @@ void CMasternodeMan::DsegUpdate(CNode* pnode)
} }
pnode->PushMessage(NetMsgType::DSEG, CTxIn()); pnode->PushMessage(NetMsgType::DSEG, CTxIn());
int64_t askAgain = GetTime() + MASTERNODES_DSEG_SECONDS; int64_t askAgain = GetTime() + DSEG_UPDATE_SECONDS;
mWeAskedForMasternodeList[pnode->addr] = askAgain; mWeAskedForMasternodeList[pnode->addr] = askAgain;
} }
@ -670,7 +694,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
return; return;
} }
} }
int64_t askAgain = GetTime() + MASTERNODES_DSEG_SECONDS; int64_t askAgain = GetTime() + DSEG_UPDATE_SECONDS;
mAskedUsForMasternodeList[pfrom->addr] = askAgain; mAskedUsForMasternodeList[pfrom->addr] = askAgain;
} }
} //else, asking for a specific node which is ok } //else, asking for a specific node which is ok
@ -705,6 +729,420 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
} }
// smth weird happen - someone asked us for vin we have no idea about? // smth weird happen - someone asked us for vin we have no idea about?
LogPrint("masternode", "CMasternodeMan::ProcessMessage -- DSEG -- No invs sent to peer %d\n", pfrom->id); LogPrint("masternode", "CMasternodeMan::ProcessMessage -- DSEG -- No invs sent to peer %d\n", pfrom->id);
} else if (strCommand == NetMsgType::MNVERIFY) { // Masternode Verify
CMasternodeVerification mnv;
vRecv >> mnv;
if(mnv.vchSig1.empty()) {
// CASE 1: someone asked me to verify myself /IP we are using/
SendVerifyReply(pfrom, mnv);
} else if (mnv.vchSig2.empty()) {
// CASE 2: we _probably_ got verification we requested from some masternode
ProcessVerifyReply(pfrom, mnv);
} else {
// CASE 3: we _probably_ got verification broadcast signed by some masternode which verified another one
ProcessVerifyBroadcast(pfrom, mnv);
}
}
}
void CMasternodeMan::DoFullVerificationStep()
{
if(activeMasternode.vin == CTxIn()) return;
std::vector<std::pair<int, CMasternode> > vecMasternodeRanks = GetMasternodeRanks(pCurrentBlockIndex->nHeight - 1, MIN_POSE_PROTO_VERSION);
LOCK(cs);
int nCount = 0;
int nCountMax = std::max(10, (int)vMasternodes.size() / 100); // verify at least 10 masternode at once but at most 1% of all known masternodes
int nMyRank = -1;
int nRanksTotal = (int)vecMasternodeRanks.size();
// send verify requests only if we are in top MAX_POSE_RANK
std::vector<std::pair<int, CMasternode> >::iterator it = vecMasternodeRanks.begin();
while(it != vecMasternodeRanks.end()) {
if(it->first > MAX_POSE_RANK) {
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Must be in top %d to send verify request\n",
(int)MAX_POSE_RANK);
return;
}
if(it->second.vin == activeMasternode.vin) {
nMyRank = it->first;
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Found self at rank %d/%d, verifying up to %d masternodes\n",
nMyRank, nRanksTotal, nCountMax);
break;
}
++it;
}
// edge case: list is too short and this masternode is not enabled
if(nMyRank == -1) return;
// send verify requests to up to nCountMax masternodes starting from
// (MAX_POSE_RANK + nCountMax * (nMyRank - 1) + 1)
int nOffset = MAX_POSE_RANK + nCountMax * (nMyRank - 1);
if(nOffset >= (int)vecMasternodeRanks.size()) return;
std::vector<CMasternode*> vSortedByAddr;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
vSortedByAddr.push_back(&mn);
}
sort(vSortedByAddr.begin(), vSortedByAddr.end(), CompareByAddr());
it = vecMasternodeRanks.begin() + nOffset;
while(it != vecMasternodeRanks.end()) {
if(it->second.IsPoSeVerified() || it->second.IsPoSeBanned()) {
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Already %s%s%s masternode %s address %s, skipping...\n",
it->second.IsPoSeVerified() ? "verified" : "",
it->second.IsPoSeVerified() && it->second.IsPoSeBanned() ? " and " : "",
it->second.IsPoSeBanned() ? "banned" : "",
it->second.vin.prevout.ToStringShort(), it->second.addr.ToString());
++it;
continue;
}
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Verifying masternode %s rank %d/%d address %s\n",
it->second.vin.prevout.ToStringShort(), it->first, nRanksTotal, it->second.addr.ToString());
if(SendVerifyRequest((CAddress)it->second.addr, vSortedByAddr)) {
nCount++;
if(nCount >= nCountMax) break;
}
++it;
}
LogPrint("masternode", "CMasternodeMan::DoFullVerificationStep -- Sent verification requests to %d masternodes\n", nCount);
}
void CMasternodeMan::CheckSameAddr()
{
if(!masternodeSync.IsSynced() || vMasternodes.empty()) return;
std::vector<CMasternode*> vBan;
std::vector<CMasternode*> vSortedByAddr;
{
LOCK(cs);
CMasternode* pprevMasternode = NULL;
CMasternode* pverifiedMasternode = NULL;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
vSortedByAddr.push_back(&mn);
}
sort(vSortedByAddr.begin(), vSortedByAddr.end(), CompareByAddr());
BOOST_FOREACH(CMasternode* pmn, vSortedByAddr) {
// check only (pre)enabled masternodes
if(!pmn->IsEnabled() && !pmn->IsPreEnabled()) continue;
// initial step
if(!pprevMasternode) {
pprevMasternode = pmn;
pverifiedMasternode = pmn->IsPoSeVerified() ? pmn : NULL;
continue;
}
// second+ step
if(pmn->addr == pprevMasternode->addr) {
if(pverifiedMasternode) {
// another masternode with the same ip is verified, ban this one
vBan.push_back(pmn);
} else if(pmn->IsPoSeVerified()) {
// this masternode with the same ip is verified, ban previous one
vBan.push_back(pprevMasternode);
// and keep a reference to be able to ban following masternodes with the same ip
pverifiedMasternode = pmn;
}
} else {
pverifiedMasternode = pmn->IsPoSeVerified() ? pmn : NULL;
}
pprevMasternode = pmn;
}
}
// ban duplicates
BOOST_FOREACH(CMasternode* pmn, vBan) {
pmn->nPoSeBanScore++;
}
}
bool CMasternodeMan::SendVerifyRequest(const CAddress& addr, const std::vector<CMasternode*>& vSortedByAddr)
{
if(netfulfilledman.HasFulfilledRequest(addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request")) {
// we already asked for verification, not a good idea to do this too often, skip it
LogPrint("masternode", "CMasternodeMan::SendVerifyRequest -- too many requests, skipping... addr=%s\n", addr.ToString());
return false;
}
CNode* pnode = ConnectNode(addr, NULL, true);
if(pnode != NULL) {
netfulfilledman.AddFulfilledRequest(addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request");
// use random nonce, store it and require node to reply with correct one later
CMasternodeVerification mnv(addr, GetInsecureRand(999999), pCurrentBlockIndex->nHeight - 1);
mWeAskedForVerification[addr] = mnv;
LogPrintf("CMasternodeMan::SendVerifyRequest -- verifying using nonce %d addr=%s\n", mnv.nonce, addr.ToString());
pnode->PushMessage(NetMsgType::MNVERIFY, mnv);
return true;
} else {
// can't connect, add some PoSe "ban score" to all masternodes with given addr
bool fFound = false;
BOOST_FOREACH(CMasternode* pmn, vSortedByAddr) {
if(pmn->addr != addr) {
if(fFound) break;
continue;
}
fFound = true;
pmn->nPoSeBanScore++;
}
return false;
}
}
void CMasternodeMan::SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv)
{
// only masternodes can sign this, why would someone ask regular node?
if(!fMasterNode) {
// do not ban, malicious node might be using my IP
// and trying to confuse the node which tries to verify it
return;
}
if(netfulfilledman.HasFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-reply")) {
// peer should not ask us that often
LogPrintf("MasternodeMan::SendVerifyReply -- ERROR: peer already asked me recently, peer=%d\n", pnode->id);
Misbehaving(pnode->id, 20);
return;
}
uint256 blockHash;
if(!GetBlockHash(blockHash, mnv.nBlockHeight)) {
LogPrintf("MasternodeMan::SendVerifyReply -- can't get block hash for unknown block height %d, peer=%d\n", mnv.nBlockHeight, pnode->id);
return;
}
std::string strMessage = strprintf("%s%d%s", activeMasternode.service.ToString(false), mnv.nonce, blockHash.ToString());
if(!darkSendSigner.SignMessage(strMessage, mnv.vchSig1, activeMasternode.keyMasternode)) {
LogPrintf("MasternodeMan::SendVerifyReply -- SignMessage() failed\n");
return;
}
std::string strError;
if(!darkSendSigner.VerifyMessage(activeMasternode.pubKeyMasternode, mnv.vchSig1, strMessage, strError)) {
LogPrintf("MasternodeMan::SendVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
return;
}
pnode->PushMessage(NetMsgType::MNVERIFY, mnv);
netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-reply");
}
void CMasternodeMan::ProcessVerifyReply(CNode* pnode, CMasternodeVerification& mnv)
{
std::string strError;
// did we even ask for it? if that's the case we should have matching fulfilled request
if(!netfulfilledman.HasFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-request")) {
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: we didn't ask for verification of %s, peer=%d\n", pnode->addr.ToString(), pnode->id);
Misbehaving(pnode->id, 20);
return;
}
// Received nonce for a known address must match the one we sent
if(mWeAskedForVerification[pnode->addr].nonce != mnv.nonce) {
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: wrong nounce: requested=%d, received=%d, peer=%d\n",
mWeAskedForVerification[pnode->addr].nonce, mnv.nonce, pnode->id);
Misbehaving(pnode->id, 20);
return;
}
// Received nBlockHeight for a known address must match the one we sent
if(mWeAskedForVerification[pnode->addr].nBlockHeight != mnv.nBlockHeight) {
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: wrong nBlockHeight: requested=%d, received=%d, peer=%d\n",
mWeAskedForVerification[pnode->addr].nBlockHeight, mnv.nBlockHeight, pnode->id);
Misbehaving(pnode->id, 20);
return;
}
uint256 blockHash;
if(!GetBlockHash(blockHash, mnv.nBlockHeight)) {
// this shouldn't happen...
LogPrintf("MasternodeMan::ProcessVerifyReply -- can't get block hash for unknown block height %d, peer=%d\n", mnv.nBlockHeight, pnode->id);
return;
}
// we already verified this address, why node is spamming?
if(netfulfilledman.HasFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-done")) {
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: already verified %s recently\n", pnode->addr.ToString());
Misbehaving(pnode->id, 20);
return;
}
{
LOCK(cs);
CMasternode* prealMasternode = NULL;
std::vector<CMasternode*> vpMasternodesToBan;
std::vector<CMasternode>::iterator it = vMasternodes.begin();
std::string strMessage1 = strprintf("%s%d%s", pnode->addr.ToString(false), mnv.nonce, blockHash.ToString());
while(it != vMasternodes.end()) {
if((CAddress)it->addr == pnode->addr) {
if(darkSendSigner.VerifyMessage(it->pubKeyMasternode, mnv.vchSig1, strMessage1, strError)) {
// found it!
prealMasternode = &(*it);
if(!it->IsPoSeVerified()) {
it->nPoSeBanScore--;
}
netfulfilledman.AddFulfilledRequest(pnode->addr, strprintf("%s", NetMsgType::MNVERIFY)+"-done");
// we can only broadcast it if we are an activated masternode
if(activeMasternode.vin == CTxIn()) continue;
// update ...
mnv.addr = it->addr;
mnv.vin1 = it->vin;
mnv.vin2 = activeMasternode.vin;
std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
mnv.vin1.prevout.ToStringShort(), mnv.vin2.prevout.ToStringShort());
// ... and sign it
if(!darkSendSigner.SignMessage(strMessage2, mnv.vchSig2, activeMasternode.keyMasternode)) {
LogPrintf("MasternodeMan::ProcessVerifyReply -- SignMessage() failed\n");
return;
}
std::string strError;
if(!darkSendSigner.VerifyMessage(activeMasternode.pubKeyMasternode, mnv.vchSig2, strMessage2, strError)) {
LogPrintf("MasternodeMan::ProcessVerifyReply -- VerifyMessage() failed, error: %s\n", strError);
return;
}
mWeAskedForVerification[pnode->addr] = mnv;
mnv.Relay();
} else {
vpMasternodesToBan.push_back(&(*it));
}
}
++it;
}
// no real masternode found?...
if(!prealMasternode) {
// this should never be the case normally,
// only if someone is trying to game the system in some way or smth like that
LogPrintf("CMasternodeMan::ProcessVerifyReply -- ERROR: no real masternode found for addr %s\n", pnode->addr.ToString());
Misbehaving(pnode->id, 20);
return;
}
LogPrintf("CMasternodeMan::ProcessVerifyReply -- verified real masternode %s for addr %s\n",
prealMasternode->vin.prevout.ToStringShort(), pnode->addr.ToString());
// increase ban score for everyone else
BOOST_FOREACH(CMasternode* pmn, vpMasternodesToBan) {
pmn->nPoSeBanScore++;
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- increased PoSe ban score for %s addr %s, new score %d\n",
prealMasternode->vin.prevout.ToStringShort(), pnode->addr.ToString(), pmn->nPoSeBanScore);
}
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- PoSe score incresed for %d fake masternodes, addr %s\n",
(int)vpMasternodesToBan.size(), pnode->addr.ToString());
}
}
void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerification& mnv)
{
std::string strError;
if(mapSeenMasternodeVerification.find(mnv.GetHash()) != mapSeenMasternodeVerification.end()) {
// we already have one
return;
}
mapSeenMasternodeVerification[mnv.GetHash()] = mnv;
// we don't care about history
if(mnv.nBlockHeight < pCurrentBlockIndex->nHeight - MAX_POSE_BLOCKS) {
LogPrint("masternode", "MasternodeMan::ProcessVerifyBroadcast -- Outdated: current block %d, verification block %d, peer=%d\n",
pCurrentBlockIndex->nHeight, mnv.nBlockHeight, pnode->id);
return;
}
if(mnv.vin1.prevout == mnv.vin2.prevout) {
LogPrint("masternode", "MasternodeMan::ProcessVerifyBroadcast -- ERROR: same vins %s, peer=%d\n",
mnv.vin1.prevout.ToStringShort(), pnode->id);
// that was NOT a good idea to cheat and verify itself,
// ban the node we received such message from
Misbehaving(pnode->id, 100);
return;
}
uint256 blockHash;
if(!GetBlockHash(blockHash, mnv.nBlockHeight)) {
// this shouldn't happen...
LogPrintf("MasternodeMan::ProcessVerifyBroadcast -- Can't get block hash for unknown block height %d, peer=%d\n", mnv.nBlockHeight, pnode->id);
return;
}
int nRank = GetMasternodeRank(mnv.vin2, mnv.nBlockHeight, MIN_POSE_PROTO_VERSION);
if(nRank < MAX_POSE_RANK) {
LogPrint("masternode", "MasternodeMan::ProcessVerifyBroadcast -- Mastrernode is not in top %d, current rank %d, peer=%d\n",
(int)MAX_POSE_RANK, nRank, pnode->id);
return;
}
{
LOCK(cs);
std::string strMessage1 = strprintf("%s%d%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString());
std::string strMessage2 = strprintf("%s%d%s%s%s", mnv.addr.ToString(false), mnv.nonce, blockHash.ToString(),
mnv.vin1.prevout.ToStringShort(), mnv.vin2.prevout.ToStringShort());
CMasternode* pmn1 = Find(mnv.vin1);
if(!pmn1) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- can't find masternode1 %s\n", mnv.vin1.prevout.ToStringShort());
return;
}
CMasternode* pmn2 = Find(mnv.vin2);
if(!pmn2) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- can't find masternode2 %s\n", mnv.vin2.prevout.ToStringShort());
return;
}
if(pmn1->addr != mnv.addr) {
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- addr %s do not match %s\n", mnv.addr.ToString(), pnode->addr.ToString());
return;
}
if(darkSendSigner.VerifyMessage(pmn1->pubKeyMasternode, mnv.vchSig1, strMessage1, strError)) {
LogPrintf("MasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode1 failed, error: %s\n", strError);
return;
}
if(darkSendSigner.VerifyMessage(pmn2->pubKeyMasternode, mnv.vchSig2, strMessage2, strError)) {
LogPrintf("MasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode2 failed, error: %s\n", strError);
return;
}
if(!pmn1->IsPoSeVerified()) {
pmn1->nPoSeBanScore--;
}
mnv.Relay();
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- verified masternode %s for addr %s\n",
pmn1->vin.prevout.ToStringShort(), pnode->addr.ToString());
// increase ban score for everyone else with the same addr
int nCount = 0;
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
if(mn.addr != mnv.addr || mn.vin.prevout == mnv.vin1.prevout) continue;
mn.nPoSeBanScore++;
nCount++;
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- increased PoSe ban score for %s addr %s, new score %d\n",
mn.vin.prevout.ToStringShort(), mn.addr.ToString(), mn.nPoSeBanScore);
}
LogPrintf("CMasternodeMan::ProcessVerifyBroadcast -- PoSe score incresed for %d fake masternodes, addr %s\n",
nCount, pnode->addr.ToString());
} }
} }
@ -778,49 +1216,71 @@ void CMasternodeMan::UpdateMasternodeList(CMasternodeBroadcast mnb) {
} }
} }
bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, int& nDos) { bool CMasternodeMan::CheckMnbAndUpdateMasternodeList(CMasternodeBroadcast mnb, int& nDos)
{
LOCK(cs); LOCK(cs);
nDos = 0; nDos = 0;
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList - Masternode broadcast, vin: %s\n", mnb.vin.ToString()); LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s\n", mnb.vin.prevout.ToStringShort());
if(mapSeenMasternodeBroadcast.count(mnb.GetHash())) { //seen if(mapSeenMasternodeBroadcast.count(mnb.GetHash())) { //seen
return true; return true;
} }
mapSeenMasternodeBroadcast.insert(make_pair(mnb.GetHash(), mnb)); mapSeenMasternodeBroadcast.insert(std::make_pair(mnb.GetHash(), mnb));
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList - Masternode broadcast, vin: %s new\n", mnb.vin.ToString()); LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s new\n", mnb.vin.prevout.ToStringShort());
// We check addr before both initial mnb and update
if(!mnb.IsValidNetAddr()) { if(!mnb.SimpleCheck(nDos)) {
LogPrintf("CMasternodeBroadcast::CheckMnbAndUpdateMasternodeList -- Invalid addr, rejected: masternode=%s sigTime=%lld addr=%s\n", LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- SimpleCheck() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort());
mnb.vin.prevout.ToStringShort(), mnb.sigTime, mnb.addr.ToString());
return false; return false;
} }
if(!mnb.CheckAndUpdate(nDos)){ // search Masternode list
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList - Masternode broadcast, vin: %s CheckAndUpdate failed\n", mnb.vin.ToString()); CMasternode* pmn = Find(mnb.vin);
if(pmn) {
if(!mnb.Update(pmn, nDos)) {
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Update() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort());
return false; return false;
} }
// make sure it's still unspent
// - this is checked later by .check() in many places and by ThreadCheckDarkSendPool()
if(mnb.CheckInputsAndAdd(nDos)) {
masternodeSync.AddedMasternodeList();
} else { } else {
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList - Rejected Masternode entry %s\n", mnb.addr.ToString()); if(mnb.CheckOutpoint(nDos)) {
Add(mnb);
masternodeSync.AddedMasternodeList();
// if it matches our Masternode privkey...
if(fMasterNode && mnb.pubKeyMasternode == activeMasternode.pubKeyMasternode) {
mnb.nPoSeBanScore = -MASTERNODE_POSE_BAN_MAX_SCORE;
if(mnb.nProtocolVersion == PROTOCOL_VERSION) {
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Got NEW Masternode entry: masternode=%s sigTime=%lld addr=%s\n",
mnb.vin.prevout.ToStringShort(), mnb.sigTime, mnb.addr.ToString());
activeMasternode.ManageState();
} else {
// ... otherwise we need to reactivate our node, do not add it to the list and do not relay
// but also do not ban the node we get this message from
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- wrong PROTOCOL_VERSION, re-activate your MN: message nProtocolVersion=%d PROTOCOL_VERSION=%d\n", mnb.nProtocolVersion, PROTOCOL_VERSION);
return false; return false;
} }
}
mnb.Relay();
} else {
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Rejected Masternode entry: %s addr=%s\n", mnb.vin.prevout.ToStringShort(), mnb.addr.ToString());
return false;
}
}
return true; return true;
} }
void CMasternodeMan::UpdateLastPaid(const CBlockIndex *pindex) { void CMasternodeMan::UpdateLastPaid(const CBlockIndex *pindex)
{
LOCK(cs); LOCK(cs);
if(fLiteMode) return; if(fLiteMode) return;
static bool IsFirstRun = true; static bool IsFirstRun = true;
// Do full scan on first run or if we are not a masternode // Do full scan on first run or if we are not a masternode
// (MNs should update this info on every block, so limited scan should be enough for them) // (MNs should update this info on every block, so limited scan should be enough for them)
int nMaxBlocksToScanBack = (IsFirstRun || !fMasterNode) ? mnpayments.GetStorageLimit() : MASTERNODES_LAST_PAID_SCAN_BLOCKS; int nMaxBlocksToScanBack = (IsFirstRun || !fMasterNode) ? mnpayments.GetStorageLimit() : LAST_PAID_SCAN_BLOCKS;
// LogPrint("mnpayments", "CMasternodeMan::UpdateLastPaid -- nHeight=%d, nMaxBlocksToScanBack=%d, IsFirstRun=%s\n", // LogPrint("mnpayments", "CMasternodeMan::UpdateLastPaid -- nHeight=%d, nMaxBlocksToScanBack=%d, IsFirstRun=%s\n",
// pindex->nHeight, nMaxBlocksToScanBack, IsFirstRun ? "true" : "false"); // pindex->nHeight, nMaxBlocksToScanBack, IsFirstRun ? "true" : "false");
@ -935,3 +1395,17 @@ void CMasternodeMan::SetMasternodeLastPing(const CTxIn& vin, const CMasternodePi
mapSeenMasternodeBroadcast[hash].lastPing = mnp; mapSeenMasternodeBroadcast[hash].lastPing = mnp;
} }
} }
void CMasternodeMan::UpdatedBlockTip(const CBlockIndex *pindex)
{
pCurrentBlockIndex = pindex;
LogPrint("masternode", "CMasternodeMan::UpdatedBlockTip -- pCurrentBlockIndex->nHeight=%d\n", pCurrentBlockIndex->nHeight);
CheckSameAddr();
if(fMasterNode) {
DoFullVerificationStep();
// normal wallet does not need to update this every block, doing update on rpc call should be enough
UpdateLastPaid(pindex);
}
}

View File

@ -5,20 +5,13 @@
#ifndef MASTERNODEMAN_H #ifndef MASTERNODEMAN_H
#define MASTERNODEMAN_H #define MASTERNODEMAN_H
#include "sync.h"
#include "net.h"
#include "key.h"
#include "util.h"
#include "base58.h"
#include "main.h"
#include "masternode.h" #include "masternode.h"
#include "sync.h"
#define MASTERNODES_DUMP_SECONDS (15*60)
#define MASTERNODES_DSEG_SECONDS (3*60*60)
using namespace std; using namespace std;
class CMasternodeMan; class CMasternodeMan;
extern CMasternodeMan mnodeman; extern CMasternodeMan mnodeman;
class CMasternodeMan class CMasternodeMan
@ -26,13 +19,20 @@ class CMasternodeMan
private: private:
static const std::string SERIALIZATION_VERSION_STRING; static const std::string SERIALIZATION_VERSION_STRING;
static const int MASTERNODES_LAST_PAID_SCAN_BLOCKS = 100; static const int DSEG_UPDATE_SECONDS = 3 * 60 * 60;
static const int LAST_PAID_SCAN_BLOCKS = 100;
static const int MIN_POSE_PROTO_VERSION = 70203;
static const int MAX_POSE_RANK = 10;
static const int MAX_POSE_BLOCKS = 10;
// critical section to protect the inner data structures // critical section to protect the inner data structures
mutable CCriticalSection cs; mutable CCriticalSection cs;
// critical section to protect the inner data structures specifically on messaging // Keep track of current block index
mutable CCriticalSection cs_process_message; const CBlockIndex *pCurrentBlockIndex;
// map to hold all MNs // map to hold all MNs
std::vector<CMasternode> vMasternodes; std::vector<CMasternode> vMasternodes;
@ -42,6 +42,8 @@ private:
std::map<CNetAddr, int64_t> mWeAskedForMasternodeList; std::map<CNetAddr, int64_t> mWeAskedForMasternodeList;
// which Masternodes we've asked for // which Masternodes we've asked for
std::map<COutPoint, int64_t> mWeAskedForMasternodeListEntry; std::map<COutPoint, int64_t> mWeAskedForMasternodeListEntry;
// who we asked for the masternode verification
std::map<CNetAddr, CMasternodeVerification> mWeAskedForVerification;
std::vector<uint256> vecDirtyGovernanceObjectHashes; std::vector<uint256> vecDirtyGovernanceObjectHashes;
@ -49,16 +51,19 @@ private:
public: public:
// Keep track of all broadcasts I've seen // Keep track of all broadcasts I've seen
map<uint256, CMasternodeBroadcast> mapSeenMasternodeBroadcast; std::map<uint256, CMasternodeBroadcast> mapSeenMasternodeBroadcast;
// Keep track of all pings I've seen // Keep track of all pings I've seen
map<uint256, CMasternodePing> mapSeenMasternodePing; std::map<uint256, CMasternodePing> mapSeenMasternodePing;
// Keep track of all verifications I've seen
std::map<uint256, CMasternodeVerification> mapSeenMasternodeVerification;
// keep track of dsq count to prevent masternodes from gaming darksend queue // keep track of dsq count to prevent masternodes from gaming darksend queue
int64_t nDsqCount; int64_t nDsqCount;
// dummy script pubkey to test masternodes' vins against mempool // dummy script pubkey to test masternodes' vins against mempool
CScript dummyScriptPubkey; CScript dummyScriptPubkey;
CMasternodeMan() : nLastWatchdogVoteTime(0), nDsqCount(0) {}
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation> template <typename Stream, typename Operation>
@ -83,14 +88,10 @@ public:
READWRITE(mapSeenMasternodeBroadcast); READWRITE(mapSeenMasternodeBroadcast);
READWRITE(mapSeenMasternodePing); READWRITE(mapSeenMasternodePing);
if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) { if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) {
LogPrintf("CMasternodeMan::SerializationOp - Incompatible format detected, resetting data\n");
Clear(); Clear();
} }
} }
CMasternodeMan();
CMasternodeMan(CMasternodeMan& other);
/// Add an entry /// Add an entry
bool Add(CMasternode &mn); bool Add(CMasternode &mn);
@ -148,6 +149,13 @@ public:
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv); void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
void DoFullVerificationStep();
void CheckSameAddr();
bool SendVerifyRequest(const CAddress& addr, const std::vector<CMasternode*>& vSortedByAddr);
void SendVerifyReply(CNode* pnode, CMasternodeVerification& mnv);
void ProcessVerifyReply(CNode* pnode, CMasternodeVerification& mnv);
void ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerification& mnv);
/// Return the number of (unique) Masternodes /// Return the number of (unique) Masternodes
int size() { return vMasternodes.size(); } int size() { return vMasternodes.size(); }
@ -179,24 +187,20 @@ public:
} }
bool IsWatchdogActive(); bool IsWatchdogActive();
void UpdateWatchdogVoteTime(const CTxIn& vin); void UpdateWatchdogVoteTime(const CTxIn& vin);
void AddGovernanceVote(const CTxIn& vin, uint256 nGovernanceObjectHash); void AddGovernanceVote(const CTxIn& vin, uint256 nGovernanceObjectHash);
void RemoveGovernanceObject(uint256 nGovernanceObjectHash); void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
void CheckMasternode(const CTxIn& vin, bool fForce = false); void CheckMasternode(const CTxIn& vin, bool fForce = false);
void CheckMasternode(const CPubKey& pubKeyMasternode, bool fForce = false); void CheckMasternode(const CPubKey& pubKeyMasternode, bool fForce = false);
int GetMasternodeState(const CTxIn& vin); int GetMasternodeState(const CTxIn& vin);
int GetMasternodeState(const CPubKey& pubKeyMasternode); int GetMasternodeState(const CPubKey& pubKeyMasternode);
bool IsMasternodePingedWithin(const CTxIn& vin, int nSeconds, int64_t nTimeToCheckAt = -1); bool IsMasternodePingedWithin(const CTxIn& vin, int nSeconds, int64_t nTimeToCheckAt = -1);
void SetMasternodeLastPing(const CTxIn& vin, const CMasternodePing& mnp); void SetMasternodeLastPing(const CTxIn& vin, const CMasternodePing& mnp);
void UpdatedBlockTip(const CBlockIndex *pindex);
}; };
#endif #endif

View File

@ -65,6 +65,7 @@ const char *SYNCSTATUSCOUNT="ssc";
const char *MNGOVERNANCESYNC="govsync"; const char *MNGOVERNANCESYNC="govsync";
const char *MNGOVERNANCEOBJECT="govobj"; const char *MNGOVERNANCEOBJECT="govobj";
const char *MNGOVERNANCEOBJECTVOTE="govobjvote"; const char *MNGOVERNANCEOBJECTVOTE="govobjvote";
const char *MNVERIFY="mnv";
}; };
static const char* ppszTypeName[] = static const char* ppszTypeName[] =
@ -89,7 +90,8 @@ static const char* ppszTypeName[] =
NetMsgType::MNPING, NetMsgType::MNPING,
NetMsgType::DSTX, NetMsgType::DSTX,
NetMsgType::MNGOVERNANCEOBJECT, NetMsgType::MNGOVERNANCEOBJECT,
NetMsgType::MNGOVERNANCEOBJECTVOTE NetMsgType::MNGOVERNANCEOBJECTVOTE,
NetMsgType::MNVERIFY,
}; };
/** All known message types. Keep this in the same order as the list of /** All known message types. Keep this in the same order as the list of
@ -141,7 +143,8 @@ const static std::string allNetMessageTypes[] = {
NetMsgType::SYNCSTATUSCOUNT, NetMsgType::SYNCSTATUSCOUNT,
NetMsgType::MNGOVERNANCESYNC, NetMsgType::MNGOVERNANCESYNC,
NetMsgType::MNGOVERNANCEOBJECT, NetMsgType::MNGOVERNANCEOBJECT,
NetMsgType::MNGOVERNANCEOBJECTVOTE NetMsgType::MNGOVERNANCEOBJECTVOTE,
NetMsgType::MNVERIFY,
}; };
const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes)); const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));

View File

@ -243,6 +243,7 @@ extern const char *SYNCSTATUSCOUNT;
extern const char *MNGOVERNANCESYNC; extern const char *MNGOVERNANCESYNC;
extern const char *MNGOVERNANCEOBJECT; extern const char *MNGOVERNANCEOBJECT;
extern const char *MNGOVERNANCEOBJECTVOTE; extern const char *MNGOVERNANCEOBJECTVOTE;
extern const char *MNVERIFY;
}; };
/* Get a vector of all valid message types (see above) */ /* Get a vector of all valid message types (see above) */
@ -356,7 +357,8 @@ enum {
MSG_MASTERNODE_PING, MSG_MASTERNODE_PING,
MSG_DSTX, MSG_DSTX,
MSG_GOVERNANCE_OBJECT, MSG_GOVERNANCE_OBJECT,
MSG_GOVERNANCE_OBJECT_VOTE MSG_GOVERNANCE_OBJECT_VOTE,
MSG_MASTERNODE_VERIFY,
}; };
#endif // BITCOIN_PROTOCOL_H #endif // BITCOIN_PROTOCOL_H