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");
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
|
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:
|
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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
|
||||||
sigTime = mnb.sigTime;
|
pubKeyMasternode = mnb.pubKeyMasternode;
|
||||||
vchSig = mnb.vchSig;
|
sigTime = mnb.sigTime;
|
||||||
nProtocolVersion = mnb.nProtocolVersion;
|
vchSig = mnb.vchSig;
|
||||||
addr = mnb.addr;
|
nProtocolVersion = mnb.nProtocolVersion;
|
||||||
nTimeLastChecked = 0;
|
addr = mnb.addr;
|
||||||
int nDos = 0;
|
nPoSeBanScore = 0;
|
||||||
if(mnb.lastPing == CMasternodePing() || (mnb.lastPing != CMasternodePing() && mnb.lastPing.CheckAndUpdate(nDos, false))) {
|
nTimeLastChecked = 0;
|
||||||
lastPing = mnb.lastPing;
|
int nDos = 0;
|
||||||
mnodeman.mapSeenMasternodePing.insert(std::make_pair(lastPing.GetHash(), lastPing));
|
if(mnb.lastPing == CMasternodePing() || (mnb.lastPing != CMasternodePing() && mnb.lastPing.CheckAndUpdate(nDos, false))) {
|
||||||
}
|
lastPing = mnb.lastPing;
|
||||||
return true;
|
mnodeman.mapSeenMasternodePing.insert(std::make_pair(lastPing.GetHash(), lastPing));
|
||||||
}
|
}
|
||||||
return false;
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,14 +14,15 @@ class CMasternode;
|
|||||||
class CMasternodeBroadcast;
|
class CMasternodeBroadcast;
|
||||||
class CMasternodePing;
|
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
|
||||||
|
@ -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);
|
||||||
return false;
|
if(pmn) {
|
||||||
}
|
if(!mnb.Update(pmn, nDos)) {
|
||||||
|
LogPrint("masternode", "CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Update() failed, masternode=%s\n", mnb.vin.prevout.ToStringShort());
|
||||||
// make sure it's still unspent
|
return false;
|
||||||
// - 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)) {
|
||||||
return false;
|
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;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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));
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user