Skip to content

Commit

Permalink
Fix masternode score/rank calculations (#1620)
Browse files Browse the repository at this point in the history
* fix CMasternode::CalculateScore, new mn score algo activation is triggered by DIP0001 lock-in

* unify rank calculation, base it on full mn vector rather than using active mns only

* bump CMasternodeMan::SERIALIZATION_VERSION_STRING

* unify rank calculations even further

* fix (partially revert previous one)
  • Loading branch information
UdjinM6 authored Sep 14, 2017
1 parent ace0017 commit d7a8489
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 98 deletions.
2 changes: 1 addition & 1 deletion src/darksend-relay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ void CDarkSendRelay::RelayThroughNode(int nRank)
{
masternode_info_t mnInfo;

if(mnodeman.GetMasternodeByRank(nRank, nBlockHeight, MIN_PRIVATESEND_PEER_PROTO_VERSION, false, mnInfo)){
if(mnodeman.GetMasternodeByRank(nRank, mnInfo, nBlockHeight, MIN_PRIVATESEND_PEER_PROTO_VERSION)) {
//printf("RelayThroughNode %s\n", mnInfo.addr.ToString().c_str());
// TODO: Pass CConnman instance somehow and don't use global variable.
CNode* pnode = g_connman->ConnectNode((CAddress)mnInfo.addr, NULL);
Expand Down
22 changes: 10 additions & 12 deletions src/instantx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,22 +195,21 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate)

int nLockInputHeight = nPrevoutHeight + 4;

int n = mnodeman.GetMasternodeRank(activeMasternode.outpoint, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION);

if(n == -1) {
int nRank;
if(!mnodeman.GetMasternodeRank(activeMasternode.outpoint, nRank, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION)) {
LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternode.outpoint.ToStringShort());
++itOutpointLock;
continue;
}

int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL;
if(n > nSignaturesTotal) {
LogPrint("instantsend", "CInstantSend::Vote -- Masternode not in the top %d (%d)\n", nSignaturesTotal, n);
if(nRank > nSignaturesTotal) {
LogPrint("instantsend", "CInstantSend::Vote -- Masternode not in the top %d (%d)\n", nSignaturesTotal, nRank);
++itOutpointLock;
continue;
}

LogPrint("instantsend", "CInstantSend::Vote -- In the top %d (%d)\n", nSignaturesTotal, n);
LogPrint("instantsend", "CInstantSend::Vote -- In the top %d (%d)\n", nSignaturesTotal, nRank);

std::map<COutPoint, std::set<uint256> >::iterator itVoted = mapVotedOutpoints.find(itOutpointLock->first);

Expand Down Expand Up @@ -1000,19 +999,18 @@ bool CTxLockVote::IsValid(CNode* pnode) const

int nLockInputHeight = coins.nHeight + 4;

int n = mnodeman.GetMasternodeRank(outpointMasternode, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION);

if(n == -1) {
int nRank;
if(!mnodeman.GetMasternodeRank(outpointMasternode, nRank, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION)) {
//can be caused by past versions trying to vote with an invalid protocol
LogPrint("instantsend", "CTxLockVote::IsValid -- Can't calculate rank for masternode %s\n", outpointMasternode.ToStringShort());
return false;
}
LogPrint("instantsend", "CTxLockVote::IsValid -- Masternode %s, rank=%d\n", outpointMasternode.ToStringShort(), n);
LogPrint("instantsend", "CTxLockVote::IsValid -- Masternode %s, rank=%d\n", outpointMasternode.ToStringShort(), nRank);

int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL;
if(n > nSignaturesTotal) {
if(nRank > nSignaturesTotal) {
LogPrint("instantsend", "CTxLockVote::IsValid -- Masternode %s is not in the top %d (%d), vote hash=%s\n",
outpointMasternode.ToStringShort(), nSignaturesTotal, n, GetHash().ToString());
outpointMasternode.ToStringShort(), nSignaturesTotal, nRank, GetHash().ToString());
return false;
}

Expand Down
16 changes: 10 additions & 6 deletions src/masternode-payments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -684,9 +684,9 @@ bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::s
// Regular clients (miners included) need to verify masternode rank for future block votes only.
if(!fMasterNode && nBlockHeight < nValidationHeight) return true;

int nRank = mnodeman.GetMasternodeRank(vinMasternode.prevout, nBlockHeight - 101, nMinRequiredProtocol, false);
int nRank;

if(nRank == -1) {
if(!mnodeman.GetMasternodeRank(vinMasternode.prevout, nRank, nBlockHeight - 101, nMinRequiredProtocol)) {
LogPrint("mnpayments", "CMasternodePaymentVote::IsValid -- Can't calculate rank for masternode %s\n",
vinMasternode.prevout.ToStringShort());
return false;
Expand All @@ -700,7 +700,10 @@ bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::s
if(nRank > MNPAYMENTS_SIGNATURES_TOTAL*2 && nBlockHeight > nValidationHeight) {
strError = strprintf("Masternode is not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL*2, nRank);
LogPrintf("CMasternodePaymentVote::IsValid -- Error: %s\n", strError);
Misbehaving(pnode->GetId(), 20);
// do not ban nodes before DIP0001 is locked in to avoid banning majority of (old) masternodes
if (fDIP0001LockedInAtTip) {
Misbehaving(pnode->GetId(), 20);
}
}
// Still invalid however
return false;
Expand All @@ -720,9 +723,9 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
// if we have not enough data about masternodes.
if(!masternodeSync.IsMasternodeListSynced()) return false;

int nRank = mnodeman.GetMasternodeRank(activeMasternode.outpoint, nBlockHeight - 101, GetMinMasternodePaymentsProto(), false);
int nRank;

if (nRank == -1) {
if (!mnodeman.GetMasternodeRank(activeMasternode.outpoint, nRank, nBlockHeight - 101, GetMinMasternodePaymentsProto())) {
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock -- Unknown Masternode\n");
return false;
}
Expand Down Expand Up @@ -779,7 +782,8 @@ void CMasternodePaymentVote::Relay()
// do not relay until synced
if (!masternodeSync.IsWinnersListSynced()) return;
CInv inv(MSG_MASTERNODE_PAYMENT_VOTE, GetHash());
g_connman->RelayInv(inv);
// relay votes only strictly to new nodes until DIP0001 is locked in to avoid being banned by majority of (old) masternodes
g_connman->RelayInv(inv, fDIP0001LockedInAtTip ? mnpayments.GetMinMasternodePaymentsProto() : MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2);
}

bool CMasternodePaymentVote::CheckSignature(const CPubKey& pubKeyMasternode, int nValidationHeight, int &nDos)
Expand Down
13 changes: 12 additions & 1 deletion src/masternode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ CMasternode::CMasternode(const CMasternode& other) :
masternode_info_t{other},
lastPing(other.lastPing),
vchSig(other.vchSig),
nCacheCollateralBlock(other.nCacheCollateralBlock),
nCollateralMinConfBlockHash(other.nCollateralMinConfBlockHash),
nBlockLastPaid(other.nBlockLastPaid),
nPoSeBanScore(other.nPoSeBanScore),
nPoSeBanHeight(other.nPoSeBanHeight),
Expand Down Expand Up @@ -90,6 +90,15 @@ bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb)
//
arith_uint256 CMasternode::CalculateScore(const uint256& blockHash)
{
if (fDIP0001LockedInAtTip) {
// Deterministically calculate a "score" for a Masternode based on any given (block)hash
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
ss << vin.prevout << nCollateralMinConfBlockHash << blockHash;
return UintToArith256(ss.GetHash());
}

// TODO: remove calculations below after migration to 12.2

uint256 aux = ArithToUint256(UintToArith256(vin.prevout.hash) + vin.prevout.n);

CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
Expand Down Expand Up @@ -572,6 +581,8 @@ bool CMasternodeBroadcast::CheckOutpoint(int& nDos)
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
return false;
}
// remember the hash of the block where masternode collateral had minimum required confirmations
nCollateralMinConfBlockHash = chainActive[nHeight + Params().GetConsensus().nMasternodeMinimumConfirmations - 1]->GetBlockHash();
}

LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO verified\n");
Expand Down
6 changes: 3 additions & 3 deletions src/masternode.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ class CMasternode : public masternode_info_t
CMasternodePing lastPing{};
std::vector<unsigned char> vchSig{};

int nCacheCollateralBlock{};
uint256 nCollateralMinConfBlockHash{};
int nBlockLastPaid{};
int nPoSeBanScore{};
int nPoSeBanHeight{};
Expand Down Expand Up @@ -187,7 +187,7 @@ class CMasternode : public masternode_info_t
READWRITE(nTimeLastPaid);
READWRITE(nTimeLastWatchdogVote);
READWRITE(nActiveState);
READWRITE(nCacheCollateralBlock);
READWRITE(nCollateralMinConfBlockHash);
READWRITE(nBlockLastPaid);
READWRITE(nProtocolVersion);
READWRITE(nPoSeBanScore);
Expand Down Expand Up @@ -284,7 +284,7 @@ class CMasternode : public masternode_info_t
static_cast<masternode_info_t&>(*this)=from;
lastPing = from.lastPing;
vchSig = from.vchSig;
nCacheCollateralBlock = from.nCacheCollateralBlock;
nCollateralMinConfBlockHash = from.nCollateralMinConfBlockHash;
nBlockLastPaid = from.nBlockLastPaid;
nPoSeBanScore = from.nPoSeBanScore;
nPoSeBanHeight = from.nPoSeBanHeight;
Expand Down
Loading

0 comments on commit d7a8489

Please sign in to comment.