new PoSe - MNVERIFY (#1066)
This commit is contained in:
parent
cce7896d70
commit
342bda5fdc
@ -1578,6 +1578,7 @@ bool CDarksendPool::DoAutomaticDenominating(bool fDryRun)
|
||||
LogPrintf("CDarksendPool::DoAutomaticDenominating -- error connecting\n");
|
||||
strAutoDenomResult = _("Error connecting to Masternode.");
|
||||
dsq.nTime = 0; //remove node
|
||||
pmn->nPoSeBanScore++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -1624,6 +1625,7 @@ bool CDarksendPool::DoAutomaticDenominating(bool fDryRun)
|
||||
} else {
|
||||
LogPrintf("CDarksendPool::DoAutomaticDenominating -- can't connect %s\n", pmn->vin.ToString());
|
||||
nTries++;
|
||||
pmn->nPoSeBanScore++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "dsnotificationinterface.h"
|
||||
#include "darksend.h"
|
||||
#include "governance.h"
|
||||
#include "masternodeman.h"
|
||||
#include "masternode-payments.h"
|
||||
#include "masternode-sync.h"
|
||||
|
||||
@ -18,6 +19,7 @@ CDSNotificationInterface::~CDSNotificationInterface()
|
||||
|
||||
void CDSNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindex)
|
||||
{
|
||||
mnodeman.UpdatedBlockTip(pindex);
|
||||
darkSendPool.UpdatedBlockTip(pindex);
|
||||
mnpayments.UpdatedBlockTip(pindex);
|
||||
governance.UpdatedBlockTip(pindex);
|
||||
|
@ -1880,6 +1880,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
|
||||
// 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.
|
||||
// GetMainSignals().UpdatedBlockTip(chainActive.Tip());
|
||||
mnodeman.UpdatedBlockTip(chainActive.Tip());
|
||||
darkSendPool.UpdatedBlockTip(chainActive.Tip());
|
||||
mnpayments.UpdatedBlockTip(chainActive.Tip());
|
||||
masternodeSync.UpdatedBlockTip(chainActive.Tip());
|
||||
|
14
src/main.cpp
14
src/main.cpp
@ -4959,6 +4959,10 @@ bool static AlreadyHave(const CInv& inv) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
|
||||
case MSG_GOVERNANCE_OBJECT_VOTE:
|
||||
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
|
||||
@ -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)
|
||||
vNotFound.push_back(inv);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ CMasternode::CMasternode() :
|
||||
nCacheCollateralBlock(0),
|
||||
nBlockLastPaid(0),
|
||||
nProtocolVersion(PROTOCOL_VERSION),
|
||||
nPoSeBanScore(0),
|
||||
fAllowMixingTx(true),
|
||||
fUnitTest(false)
|
||||
{}
|
||||
@ -52,6 +53,7 @@ CMasternode::CMasternode(CService addrNew, CTxIn vinNew, CPubKey pubKeyCollatera
|
||||
nCacheCollateralBlock(0),
|
||||
nBlockLastPaid(0),
|
||||
nProtocolVersion(nProtocolVersionIn),
|
||||
nPoSeBanScore(0),
|
||||
fAllowMixingTx(true),
|
||||
fUnitTest(false)
|
||||
{}
|
||||
@ -72,6 +74,7 @@ CMasternode::CMasternode(const CMasternode& other) :
|
||||
nCacheCollateralBlock(other.nCacheCollateralBlock),
|
||||
nBlockLastPaid(other.nBlockLastPaid),
|
||||
nProtocolVersion(other.nProtocolVersion),
|
||||
nPoSeBanScore(other.nPoSeBanScore),
|
||||
fAllowMixingTx(other.fAllowMixingTx),
|
||||
fUnitTest(other.fUnitTest)
|
||||
{}
|
||||
@ -92,6 +95,7 @@ CMasternode::CMasternode(const CMasternodeBroadcast& mnb) :
|
||||
nCacheCollateralBlock(0),
|
||||
nBlockLastPaid(0),
|
||||
nProtocolVersion(mnb.nProtocolVersion),
|
||||
nPoSeBanScore(0),
|
||||
fAllowMixingTx(true),
|
||||
fUnitTest(false)
|
||||
{}
|
||||
@ -101,22 +105,35 @@ CMasternode::CMasternode(const CMasternodeBroadcast& mnb) :
|
||||
//
|
||||
bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb)
|
||||
{
|
||||
if(mnb.sigTime > sigTime) {
|
||||
if(mnb.sigTime <= sigTime) return false;
|
||||
|
||||
pubKeyMasternode = mnb.pubKeyMasternode;
|
||||
sigTime = mnb.sigTime;
|
||||
vchSig = mnb.vchSig;
|
||||
nProtocolVersion = mnb.nProtocolVersion;
|
||||
addr = mnb.addr;
|
||||
nPoSeBanScore = 0;
|
||||
nTimeLastChecked = 0;
|
||||
int nDos = 0;
|
||||
if(mnb.lastPing == CMasternodePing() || (mnb.lastPing != CMasternodePing() && mnb.lastPing.CheckAndUpdate(nDos, false))) {
|
||||
lastPing = mnb.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 true;
|
||||
}
|
||||
|
||||
//
|
||||
// Deterministically calculate a given "score" for a Masternode depending on how close it's hash is to
|
||||
@ -143,10 +160,9 @@ void CMasternode::Check(bool fForce)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
bool fWatchdogActive = mnodeman.IsWatchdogActive();
|
||||
static int64_t nTimeStart = GetTime();
|
||||
|
||||
LogPrint("masternode", "CMasternode::Check start -- vin = %s\n",
|
||||
vin.prevout.ToStringShort());
|
||||
LogPrint("masternode", "CMasternode::Check start -- vin %s\n", vin.prevout.ToStringShort());
|
||||
|
||||
//once spent, stop doing the checks
|
||||
if(nActiveState == MASTERNODE_OUTPOINT_SPENT) return;
|
||||
@ -156,9 +172,18 @@ void CMasternode::Check(bool fForce)
|
||||
if(!fForce && (GetTime() - nTimeLastChecked < MASTERNODE_CHECK_SECONDS)) return;
|
||||
nTimeLastChecked = GetTime();
|
||||
|
||||
if((nActiveState == MASTERNODE_WATCHDOG_EXPIRED) && !fWatchdogActive) {
|
||||
// Redo the checks
|
||||
nActiveState = MASTERNODE_ENABLED;
|
||||
if(!fUnitTest) {
|
||||
TRY_LOCK(cs_main, lockMain);
|
||||
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 ...
|
||||
@ -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 ...
|
||||
(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) {
|
||||
// it should be removed from the list
|
||||
nActiveState = MASTERNODE_REMOVE;
|
||||
@ -175,47 +218,26 @@ void CMasternode::Check(bool fForce)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS)) {
|
||||
if(nActiveState != MASTERNODE_WATCHDOG_EXPIRED) {
|
||||
nActiveState = MASTERNODE_EXPIRED;
|
||||
bool fWatchdogActive = mnodeman.IsWatchdogActive();
|
||||
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;
|
||||
}
|
||||
|
||||
if(!fWaitForPing && !IsPingedWithin(MASTERNODE_EXPIRATION_SECONDS)) {
|
||||
nActiveState = MASTERNODE_EXPIRED;
|
||||
// RESCAN AFFECTED VOTES
|
||||
FlagGovernanceItemsAsDirty();
|
||||
return;
|
||||
}
|
||||
|
||||
if(lastPing.sigTime - sigTime < MASTERNODE_MIN_MNP_SECONDS) {
|
||||
if(nActiveState != MASTERNODE_WATCHDOG_EXPIRED) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -257,6 +279,7 @@ std::string CMasternode::GetStatus()
|
||||
case CMasternode::MASTERNODE_OUTPOINT_SPENT: return "OUTPOINT_SPENT";
|
||||
case CMasternode::MASTERNODE_REMOVE: return "REMOVE";
|
||||
case CMasternode::MASTERNODE_WATCHDOG_EXPIRED: return "WATCHDOG_EXPIRED";
|
||||
case CMasternode::MASTERNODE_POSE_BAN: return "POSE_BAN";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
@ -398,12 +421,20 @@ bool CMasternodeBroadcast::Create(CTxIn txin, CService service, CKey keyCollater
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
|
||||
bool CMasternodeBroadcast::SimpleCheck(int& nDos)
|
||||
{
|
||||
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)
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
@ -414,7 +445,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -422,7 +453,7 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
|
||||
pubkeyScript = GetScriptForDestination(pubKeyCollateralAddress.GetID());
|
||||
|
||||
if(pubkeyScript.size() != 25) {
|
||||
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- pubKeyCollateralAddress has the wrong size\n");
|
||||
LogPrintf("CMasternodeBroadcast::SimpleCheck -- pubKeyCollateralAddress has the wrong size\n");
|
||||
nDos = 100;
|
||||
return false;
|
||||
}
|
||||
@ -431,18 +462,18 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
|
||||
pubkeyScript2 = GetScriptForDestination(pubKeyMasternode.GetID());
|
||||
|
||||
if(pubkeyScript2.size() != 25) {
|
||||
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- pubKeyMasternode has the wrong size\n");
|
||||
LogPrintf("CMasternodeBroadcast::SimpleCheck -- pubKeyMasternode has the wrong size\n");
|
||||
nDos = 100;
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -451,28 +482,47 @@ bool CMasternodeBroadcast::CheckAndUpdate(int& nDos)
|
||||
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
|
||||
CMasternode* pmn = mnodeman.Find(vin);
|
||||
return true;
|
||||
}
|
||||
|
||||
// no such masternode, nothing to update
|
||||
if(pmn == NULL) return true;
|
||||
bool CMasternodeBroadcast::Update(CMasternode* pmn, int& nDos)
|
||||
{
|
||||
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
|
||||
// (mapSeenMasternodeBroadcast in CMasternodeMan::ProcessMessage should filter legit duplicates)
|
||||
if(pmn->sigTime >= sigTime) {
|
||||
LogPrintf("CMasternodeBroadcast::CheckAndUpdate -- Bad sigTime %d (existing broadcast is at %d) for Masternode %s %s\n",
|
||||
if(pmn->sigTime > sigTime) {
|
||||
LogPrintf("CMasternodeBroadcast::Update -- Bad sigTime %d (existing broadcast is at %d) for Masternode %s %s\n",
|
||||
sigTime, pmn->sigTime, vin.prevout.ToStringShort(), addr.ToString());
|
||||
return false;
|
||||
}
|
||||
|
||||
// masternode is not enabled yet/already, nothing to update
|
||||
if(!pmn->IsEnabled()) return true;
|
||||
pmn->Check();
|
||||
|
||||
// IsVnAssociatedWithPubkey is validated once below, after that they just need to match
|
||||
if(pmn->pubKeyCollateralAddress == pubKeyCollateralAddress && !pmn->IsBroadcastedWithin(MASTERNODE_MIN_MNB_SECONDS)) {
|
||||
// masternode is banned by PoSe
|
||||
if(pmn->IsPoSeBanned()) {
|
||||
LogPrintf("CMasternodeBroadcast::Update -- Banned by PoSe, masternode=%s\n", vin.prevout.ToStringShort());
|
||||
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::CheckAndUpdate -- Got UPDATED Masternode entry: addr=%s\n", addr.ToString());
|
||||
LogPrintf("CMasternodeBroadcast::Update -- Got UPDATED Masternode entry: addr=%s\n", addr.ToString());
|
||||
if(pmn->UpdateFromNewBroadcast((*this))) {
|
||||
pmn->Check();
|
||||
// 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;
|
||||
}
|
||||
|
||||
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)
|
||||
// so nothing to do here for us
|
||||
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;
|
||||
}
|
||||
|
||||
// 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);
|
||||
if(!lockMain) {
|
||||
// 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());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!AcceptToMemoryPool(mempool, state, CTransaction(dummyTx), false, NULL, false, true, true)) {
|
||||
//set nDos
|
||||
LogPrint("masternode", "CMasternodeBroadcast::CheckInputsAndAdd -- Failed to accepted Masternode entry to mempool: dummyTx=%s", dummyTx.ToString());
|
||||
state.IsInvalid(nDos);
|
||||
CCoins coins;
|
||||
if(!pcoinsTip->GetCoins(vin.prevout.hash, coins) ||
|
||||
(unsigned int)vin.prevout.n>=coins.vout.size() ||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// - this is expensive, so it's only done once per Masternode
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
@ -562,39 +595,13 @@ bool CMasternodeBroadcast::CheckInputsAndAdd(int& nDos)
|
||||
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
|
||||
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());
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -16,12 +16,13 @@ class CMasternodePing;
|
||||
|
||||
static const int MASTERNODE_MIN_MNP_SECONDS = 10 * 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_REMOVAL_SECONDS = 75 * 60;
|
||||
static const int MASTERNODE_CHECK_SECONDS = 5;
|
||||
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
|
||||
//
|
||||
@ -144,7 +145,8 @@ public:
|
||||
MASTERNODE_EXPIRED,
|
||||
MASTERNODE_OUTPOINT_SPENT,
|
||||
MASTERNODE_REMOVE,
|
||||
MASTERNODE_WATCHDOG_EXPIRED
|
||||
MASTERNODE_WATCHDOG_EXPIRED,
|
||||
MASTERNODE_POSE_BAN
|
||||
};
|
||||
|
||||
CTxIn vin;
|
||||
@ -162,6 +164,7 @@ public:
|
||||
int nCacheCollateralBlock;
|
||||
int nBlockLastPaid;
|
||||
int nProtocolVersion;
|
||||
int nPoSeBanScore;
|
||||
bool fAllowMixingTx;
|
||||
bool fUnitTest;
|
||||
|
||||
@ -193,6 +196,7 @@ public:
|
||||
READWRITE(nCacheCollateralBlock);
|
||||
READWRITE(nBlockLastPaid);
|
||||
READWRITE(nProtocolVersion);
|
||||
READWRITE(nPoSeBanScore);
|
||||
READWRITE(fAllowMixingTx);
|
||||
READWRITE(fUnitTest);
|
||||
READWRITE(mapGovernanceObjectsVotedOn);
|
||||
@ -220,6 +224,7 @@ public:
|
||||
swap(first.nCacheCollateralBlock, second.nCacheCollateralBlock);
|
||||
swap(first.nBlockLastPaid, second.nBlockLastPaid);
|
||||
swap(first.nProtocolVersion, second.nProtocolVersion);
|
||||
swap(first.nPoSeBanScore, second.nPoSeBanScore);
|
||||
swap(first.fAllowMixingTx, second.fAllowMixingTx);
|
||||
swap(first.fUnitTest, second.fUnitTest);
|
||||
swap(first.mapGovernanceObjectsVotedOn, second.mapGovernanceObjectsVotedOn);
|
||||
@ -246,6 +251,8 @@ public:
|
||||
|
||||
bool IsEnabled() { return nActiveState == MASTERNODE_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; }
|
||||
|
||||
@ -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(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 CheckInputsAndAdd(int& nDos);
|
||||
bool SimpleCheck(int& nDos);
|
||||
bool Update(CMasternode* pmn, int& nDos);
|
||||
bool CheckOutpoint(int& nDos);
|
||||
|
||||
bool Sign(CKey& keyCollateralAddress);
|
||||
bool CheckSignature(int& nDos);
|
||||
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
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "masternode.h"
|
||||
#include "masternode-payments.h"
|
||||
#include "masternode-sync.h"
|
||||
#include "netfulfilledman.h"
|
||||
#include "util.h"
|
||||
#include "addrman.h"
|
||||
#include "spork.h"
|
||||
@ -17,6 +18,8 @@
|
||||
/** Masternode manager */
|
||||
CMasternodeMan mnodeman;
|
||||
|
||||
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-1";
|
||||
|
||||
struct CompareLastPaidBlock
|
||||
{
|
||||
bool operator()(const std::pair<int, CMasternode*>& t1,
|
||||
@ -35,12 +38,14 @@ struct CompareScoreMN
|
||||
}
|
||||
};
|
||||
|
||||
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-1";
|
||||
|
||||
CMasternodeMan::CMasternodeMan() {
|
||||
nDsqCount = 0;
|
||||
nLastWatchdogVoteTime = 0;
|
||||
struct CompareByAddr
|
||||
{
|
||||
bool operator()(const CMasternode* t1,
|
||||
const CMasternode* t2) const
|
||||
{
|
||||
return t1->addr < t2->addr;
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
map<uint256, CMasternodeBroadcast>::iterator it3 = mapSeenMasternodeBroadcast.begin();
|
||||
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()
|
||||
@ -250,7 +274,7 @@ void CMasternodeMan::DsegUpdate(CNode* pnode)
|
||||
}
|
||||
|
||||
pnode->PushMessage(NetMsgType::DSEG, CTxIn());
|
||||
int64_t askAgain = GetTime() + MASTERNODES_DSEG_SECONDS;
|
||||
int64_t askAgain = GetTime() + DSEG_UPDATE_SECONDS;
|
||||
mWeAskedForMasternodeList[pnode->addr] = askAgain;
|
||||
}
|
||||
|
||||
@ -670,7 +694,7 @@ void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CData
|
||||
return;
|
||||
}
|
||||
}
|
||||
int64_t askAgain = GetTime() + MASTERNODES_DSEG_SECONDS;
|
||||
int64_t askAgain = GetTime() + DSEG_UPDATE_SECONDS;
|
||||
mAskedUsForMasternodeList[pfrom->addr] = askAgain;
|
||||
}
|
||||
} //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?
|
||||
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);
|
||||
|
||||
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
|
||||
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());
|
||||
// We check addr before both initial mnb and update
|
||||
if(!mnb.IsValidNetAddr()) {
|
||||
LogPrintf("CMasternodeBroadcast::CheckMnbAndUpdateMasternodeList -- Invalid addr, rejected: masternode=%s sigTime=%lld addr=%s\n",
|
||||
mnb.vin.prevout.ToStringShort(), mnb.sigTime, mnb.addr.ToString());
|
||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s new\n", mnb.vin.prevout.ToStringShort());
|
||||
|
||||
if(!mnb.SimpleCheck(nDos)) {
|
||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- SimpleCheck() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!mnb.CheckAndUpdate(nDos)){
|
||||
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList - Masternode broadcast, vin: %s CheckAndUpdate failed\n", mnb.vin.ToString());
|
||||
// search Masternode list
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 {
|
||||
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;
|
||||
}
|
||||
}
|
||||
mnb.Relay();
|
||||
} else {
|
||||
LogPrintf("CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Rejected Masternode entry: %s addr=%s\n", mnb.vin.prevout.ToStringShort(), mnb.addr.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMasternodeMan::UpdateLastPaid(const CBlockIndex *pindex) {
|
||||
void CMasternodeMan::UpdateLastPaid(const CBlockIndex *pindex)
|
||||
{
|
||||
LOCK(cs);
|
||||
|
||||
if(fLiteMode) return;
|
||||
|
||||
static bool IsFirstRun = true;
|
||||
// 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)
|
||||
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",
|
||||
// pindex->nHeight, nMaxBlocksToScanBack, IsFirstRun ? "true" : "false");
|
||||
@ -935,3 +1395,17 @@ void CMasternodeMan::SetMasternodeLastPing(const CTxIn& vin, const CMasternodePi
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -5,20 +5,13 @@
|
||||
#ifndef 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"
|
||||
|
||||
#define MASTERNODES_DUMP_SECONDS (15*60)
|
||||
#define MASTERNODES_DSEG_SECONDS (3*60*60)
|
||||
#include "sync.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class CMasternodeMan;
|
||||
|
||||
extern CMasternodeMan mnodeman;
|
||||
|
||||
class CMasternodeMan
|
||||
@ -26,13 +19,20 @@ class CMasternodeMan
|
||||
private:
|
||||
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
|
||||
mutable CCriticalSection cs;
|
||||
|
||||
// critical section to protect the inner data structures specifically on messaging
|
||||
mutable CCriticalSection cs_process_message;
|
||||
// Keep track of current block index
|
||||
const CBlockIndex *pCurrentBlockIndex;
|
||||
|
||||
// map to hold all MNs
|
||||
std::vector<CMasternode> vMasternodes;
|
||||
@ -42,6 +42,8 @@ private:
|
||||
std::map<CNetAddr, int64_t> mWeAskedForMasternodeList;
|
||||
// which Masternodes we've asked for
|
||||
std::map<COutPoint, int64_t> mWeAskedForMasternodeListEntry;
|
||||
// who we asked for the masternode verification
|
||||
std::map<CNetAddr, CMasternodeVerification> mWeAskedForVerification;
|
||||
|
||||
std::vector<uint256> vecDirtyGovernanceObjectHashes;
|
||||
|
||||
@ -49,16 +51,19 @@ private:
|
||||
|
||||
public:
|
||||
// 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
|
||||
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
|
||||
int64_t nDsqCount;
|
||||
|
||||
// dummy script pubkey to test masternodes' vins against mempool
|
||||
CScript dummyScriptPubkey;
|
||||
|
||||
CMasternodeMan() : nLastWatchdogVoteTime(0), nDsqCount(0) {}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
@ -83,14 +88,10 @@ public:
|
||||
READWRITE(mapSeenMasternodeBroadcast);
|
||||
READWRITE(mapSeenMasternodePing);
|
||||
if(ser_action.ForRead() && (strVersion != SERIALIZATION_VERSION_STRING)) {
|
||||
LogPrintf("CMasternodeMan::SerializationOp - Incompatible format detected, resetting data\n");
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
|
||||
CMasternodeMan();
|
||||
CMasternodeMan(CMasternodeMan& other);
|
||||
|
||||
/// Add an entry
|
||||
bool Add(CMasternode &mn);
|
||||
|
||||
@ -148,6 +149,13 @@ public:
|
||||
|
||||
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
|
||||
int size() { return vMasternodes.size(); }
|
||||
|
||||
@ -179,24 +187,20 @@ public:
|
||||
}
|
||||
|
||||
bool IsWatchdogActive();
|
||||
|
||||
void UpdateWatchdogVoteTime(const CTxIn& vin);
|
||||
|
||||
void AddGovernanceVote(const CTxIn& vin, uint256 nGovernanceObjectHash);
|
||||
|
||||
void RemoveGovernanceObject(uint256 nGovernanceObjectHash);
|
||||
|
||||
void CheckMasternode(const CTxIn& vin, bool fForce = false);
|
||||
|
||||
void CheckMasternode(const CPubKey& pubKeyMasternode, bool fForce = false);
|
||||
|
||||
int GetMasternodeState(const CTxIn& vin);
|
||||
|
||||
int GetMasternodeState(const CPubKey& pubKeyMasternode);
|
||||
|
||||
bool IsMasternodePingedWithin(const CTxIn& vin, int nSeconds, int64_t nTimeToCheckAt = -1);
|
||||
|
||||
void SetMasternodeLastPing(const CTxIn& vin, const CMasternodePing& mnp);
|
||||
|
||||
void UpdatedBlockTip(const CBlockIndex *pindex);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -65,6 +65,7 @@ const char *SYNCSTATUSCOUNT="ssc";
|
||||
const char *MNGOVERNANCESYNC="govsync";
|
||||
const char *MNGOVERNANCEOBJECT="govobj";
|
||||
const char *MNGOVERNANCEOBJECTVOTE="govobjvote";
|
||||
const char *MNVERIFY="mnv";
|
||||
};
|
||||
|
||||
static const char* ppszTypeName[] =
|
||||
@ -89,7 +90,8 @@ static const char* ppszTypeName[] =
|
||||
NetMsgType::MNPING,
|
||||
NetMsgType::DSTX,
|
||||
NetMsgType::MNGOVERNANCEOBJECT,
|
||||
NetMsgType::MNGOVERNANCEOBJECTVOTE
|
||||
NetMsgType::MNGOVERNANCEOBJECTVOTE,
|
||||
NetMsgType::MNVERIFY,
|
||||
};
|
||||
|
||||
/** 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::MNGOVERNANCESYNC,
|
||||
NetMsgType::MNGOVERNANCEOBJECT,
|
||||
NetMsgType::MNGOVERNANCEOBJECTVOTE
|
||||
NetMsgType::MNGOVERNANCEOBJECTVOTE,
|
||||
NetMsgType::MNVERIFY,
|
||||
};
|
||||
const static std::vector<std::string> allNetMessageTypesVec(allNetMessageTypes, allNetMessageTypes+ARRAYLEN(allNetMessageTypes));
|
||||
|
||||
|
@ -243,6 +243,7 @@ extern const char *SYNCSTATUSCOUNT;
|
||||
extern const char *MNGOVERNANCESYNC;
|
||||
extern const char *MNGOVERNANCEOBJECT;
|
||||
extern const char *MNGOVERNANCEOBJECTVOTE;
|
||||
extern const char *MNVERIFY;
|
||||
};
|
||||
|
||||
/* Get a vector of all valid message types (see above) */
|
||||
@ -356,7 +357,8 @@ enum {
|
||||
MSG_MASTERNODE_PING,
|
||||
MSG_DSTX,
|
||||
MSG_GOVERNANCE_OBJECT,
|
||||
MSG_GOVERNANCE_OBJECT_VOTE
|
||||
MSG_GOVERNANCE_OBJECT_VOTE,
|
||||
MSG_MASTERNODE_VERIFY,
|
||||
};
|
||||
|
||||
#endif // BITCOIN_PROTOCOL_H
|
||||
|
Loading…
Reference in New Issue
Block a user