Fix masternode score/rank calculations (#1620)
* 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)
This commit is contained in:
parent
ace00175c4
commit
d7a8489f31
@ -101,7 +101,7 @@ void CDarkSendRelay::RelayThroughNode(int nRank)
|
|||||||
{
|
{
|
||||||
masternode_info_t mnInfo;
|
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());
|
//printf("RelayThroughNode %s\n", mnInfo.addr.ToString().c_str());
|
||||||
// TODO: Pass CConnman instance somehow and don't use global variable.
|
// TODO: Pass CConnman instance somehow and don't use global variable.
|
||||||
CNode* pnode = g_connman->ConnectNode((CAddress)mnInfo.addr, NULL);
|
CNode* pnode = g_connman->ConnectNode((CAddress)mnInfo.addr, NULL);
|
||||||
|
@ -195,22 +195,21 @@ void CInstantSend::Vote(CTxLockCandidate& txLockCandidate)
|
|||||||
|
|
||||||
int nLockInputHeight = nPrevoutHeight + 4;
|
int nLockInputHeight = nPrevoutHeight + 4;
|
||||||
|
|
||||||
int n = mnodeman.GetMasternodeRank(activeMasternode.outpoint, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION);
|
int nRank;
|
||||||
|
if(!mnodeman.GetMasternodeRank(activeMasternode.outpoint, nRank, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION)) {
|
||||||
if(n == -1) {
|
|
||||||
LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternode.outpoint.ToStringShort());
|
LogPrint("instantsend", "CInstantSend::Vote -- Can't calculate rank for masternode %s\n", activeMasternode.outpoint.ToStringShort());
|
||||||
++itOutpointLock;
|
++itOutpointLock;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL;
|
int nSignaturesTotal = COutPointLock::SIGNATURES_TOTAL;
|
||||||
if(n > nSignaturesTotal) {
|
if(nRank > nSignaturesTotal) {
|
||||||
LogPrint("instantsend", "CInstantSend::Vote -- Masternode not in the top %d (%d)\n", nSignaturesTotal, n);
|
LogPrint("instantsend", "CInstantSend::Vote -- Masternode not in the top %d (%d)\n", nSignaturesTotal, nRank);
|
||||||
++itOutpointLock;
|
++itOutpointLock;
|
||||||
continue;
|
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);
|
std::map<COutPoint, std::set<uint256> >::iterator itVoted = mapVotedOutpoints.find(itOutpointLock->first);
|
||||||
|
|
||||||
@ -1000,19 +999,18 @@ bool CTxLockVote::IsValid(CNode* pnode) const
|
|||||||
|
|
||||||
int nLockInputHeight = coins.nHeight + 4;
|
int nLockInputHeight = coins.nHeight + 4;
|
||||||
|
|
||||||
int n = mnodeman.GetMasternodeRank(outpointMasternode, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION);
|
int nRank;
|
||||||
|
if(!mnodeman.GetMasternodeRank(outpointMasternode, nRank, nLockInputHeight, MIN_INSTANTSEND_PROTO_VERSION)) {
|
||||||
if(n == -1) {
|
|
||||||
//can be caused by past versions trying to vote with an invalid protocol
|
//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());
|
LogPrint("instantsend", "CTxLockVote::IsValid -- Can't calculate rank for masternode %s\n", outpointMasternode.ToStringShort());
|
||||||
return false;
|
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;
|
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",
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
// Regular clients (miners included) need to verify masternode rank for future block votes only.
|
||||||
if(!fMasterNode && nBlockHeight < nValidationHeight) return true;
|
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",
|
LogPrint("mnpayments", "CMasternodePaymentVote::IsValid -- Can't calculate rank for masternode %s\n",
|
||||||
vinMasternode.prevout.ToStringShort());
|
vinMasternode.prevout.ToStringShort());
|
||||||
return false;
|
return false;
|
||||||
@ -700,8 +700,11 @@ bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::s
|
|||||||
if(nRank > MNPAYMENTS_SIGNATURES_TOTAL*2 && nBlockHeight > nValidationHeight) {
|
if(nRank > MNPAYMENTS_SIGNATURES_TOTAL*2 && nBlockHeight > nValidationHeight) {
|
||||||
strError = strprintf("Masternode is not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL*2, nRank);
|
strError = strprintf("Masternode is not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL*2, nRank);
|
||||||
LogPrintf("CMasternodePaymentVote::IsValid -- Error: %s\n", strError);
|
LogPrintf("CMasternodePaymentVote::IsValid -- Error: %s\n", strError);
|
||||||
|
// do not ban nodes before DIP0001 is locked in to avoid banning majority of (old) masternodes
|
||||||
|
if (fDIP0001LockedInAtTip) {
|
||||||
Misbehaving(pnode->GetId(), 20);
|
Misbehaving(pnode->GetId(), 20);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Still invalid however
|
// Still invalid however
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -720,9 +723,9 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
|||||||
// if we have not enough data about masternodes.
|
// if we have not enough data about masternodes.
|
||||||
if(!masternodeSync.IsMasternodeListSynced()) return false;
|
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");
|
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock -- Unknown Masternode\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -779,7 +782,8 @@ void CMasternodePaymentVote::Relay()
|
|||||||
// do not relay until synced
|
// do not relay until synced
|
||||||
if (!masternodeSync.IsWinnersListSynced()) return;
|
if (!masternodeSync.IsWinnersListSynced()) return;
|
||||||
CInv inv(MSG_MASTERNODE_PAYMENT_VOTE, GetHash());
|
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)
|
bool CMasternodePaymentVote::CheckSignature(const CPubKey& pubKeyMasternode, int nValidationHeight, int &nDos)
|
||||||
|
@ -30,7 +30,7 @@ CMasternode::CMasternode(const CMasternode& other) :
|
|||||||
masternode_info_t{other},
|
masternode_info_t{other},
|
||||||
lastPing(other.lastPing),
|
lastPing(other.lastPing),
|
||||||
vchSig(other.vchSig),
|
vchSig(other.vchSig),
|
||||||
nCacheCollateralBlock(other.nCacheCollateralBlock),
|
nCollateralMinConfBlockHash(other.nCollateralMinConfBlockHash),
|
||||||
nBlockLastPaid(other.nBlockLastPaid),
|
nBlockLastPaid(other.nBlockLastPaid),
|
||||||
nPoSeBanScore(other.nPoSeBanScore),
|
nPoSeBanScore(other.nPoSeBanScore),
|
||||||
nPoSeBanHeight(other.nPoSeBanHeight),
|
nPoSeBanHeight(other.nPoSeBanHeight),
|
||||||
@ -90,6 +90,15 @@ bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb)
|
|||||||
//
|
//
|
||||||
arith_uint256 CMasternode::CalculateScore(const uint256& blockHash)
|
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);
|
uint256 aux = ArithToUint256(UintToArith256(vin.prevout.hash) + vin.prevout.n);
|
||||||
|
|
||||||
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
||||||
@ -572,6 +581,8 @@ bool CMasternodeBroadcast::CheckOutpoint(int& nDos)
|
|||||||
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
|
mnodeman.mapSeenMasternodeBroadcast.erase(GetHash());
|
||||||
return false;
|
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");
|
LogPrint("masternode", "CMasternodeBroadcast::CheckOutpoint -- Masternode UTXO verified\n");
|
||||||
|
@ -155,7 +155,7 @@ public:
|
|||||||
CMasternodePing lastPing{};
|
CMasternodePing lastPing{};
|
||||||
std::vector<unsigned char> vchSig{};
|
std::vector<unsigned char> vchSig{};
|
||||||
|
|
||||||
int nCacheCollateralBlock{};
|
uint256 nCollateralMinConfBlockHash{};
|
||||||
int nBlockLastPaid{};
|
int nBlockLastPaid{};
|
||||||
int nPoSeBanScore{};
|
int nPoSeBanScore{};
|
||||||
int nPoSeBanHeight{};
|
int nPoSeBanHeight{};
|
||||||
@ -187,7 +187,7 @@ public:
|
|||||||
READWRITE(nTimeLastPaid);
|
READWRITE(nTimeLastPaid);
|
||||||
READWRITE(nTimeLastWatchdogVote);
|
READWRITE(nTimeLastWatchdogVote);
|
||||||
READWRITE(nActiveState);
|
READWRITE(nActiveState);
|
||||||
READWRITE(nCacheCollateralBlock);
|
READWRITE(nCollateralMinConfBlockHash);
|
||||||
READWRITE(nBlockLastPaid);
|
READWRITE(nBlockLastPaid);
|
||||||
READWRITE(nProtocolVersion);
|
READWRITE(nProtocolVersion);
|
||||||
READWRITE(nPoSeBanScore);
|
READWRITE(nPoSeBanScore);
|
||||||
@ -284,7 +284,7 @@ public:
|
|||||||
static_cast<masternode_info_t&>(*this)=from;
|
static_cast<masternode_info_t&>(*this)=from;
|
||||||
lastPing = from.lastPing;
|
lastPing = from.lastPing;
|
||||||
vchSig = from.vchSig;
|
vchSig = from.vchSig;
|
||||||
nCacheCollateralBlock = from.nCacheCollateralBlock;
|
nCollateralMinConfBlockHash = from.nCollateralMinConfBlockHash;
|
||||||
nBlockLastPaid = from.nBlockLastPaid;
|
nBlockLastPaid = from.nBlockLastPaid;
|
||||||
nPoSeBanScore = from.nPoSeBanScore;
|
nPoSeBanScore = from.nPoSeBanScore;
|
||||||
nPoSeBanHeight = from.nPoSeBanHeight;
|
nPoSeBanHeight = from.nPoSeBanHeight;
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
/** Masternode manager */
|
/** Masternode manager */
|
||||||
CMasternodeMan mnodeman;
|
CMasternodeMan mnodeman;
|
||||||
|
|
||||||
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-6";
|
const std::string CMasternodeMan::SERIALIZATION_VERSION_STRING = "CMasternodeMan-Version-7";
|
||||||
|
|
||||||
struct CompareLastPaidBlock
|
struct CompareLastPaidBlock
|
||||||
{
|
{
|
||||||
@ -29,8 +29,8 @@ struct CompareLastPaidBlock
|
|||||||
|
|
||||||
struct CompareScoreMN
|
struct CompareScoreMN
|
||||||
{
|
{
|
||||||
bool operator()(const std::pair<int64_t, CMasternode*>& t1,
|
bool operator()(const std::pair<arith_uint256, CMasternode*>& t1,
|
||||||
const std::pair<int64_t, CMasternode*>& t2) const
|
const std::pair<arith_uint256, CMasternode*>& t2) const
|
||||||
{
|
{
|
||||||
return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->vin < t2.second->vin);
|
return (t1.first != t2.first) ? (t1.first < t2.first) : (t1.second->vin < t2.second->vin);
|
||||||
}
|
}
|
||||||
@ -169,7 +169,7 @@ void CMasternodeMan::CheckAndRemove()
|
|||||||
Check();
|
Check();
|
||||||
|
|
||||||
// Remove spent masternodes, prepare structures and make requests to reasure the state of inactive ones
|
// Remove spent masternodes, prepare structures and make requests to reasure the state of inactive ones
|
||||||
std::vector<std::pair<int, CMasternode> > vecMasternodeRanks;
|
rank_pair_vec_t vecMasternodeRanks;
|
||||||
// ask for up to MNB_RECOVERY_MAX_ASK_ENTRIES masternode entries at a time
|
// ask for up to MNB_RECOVERY_MAX_ASK_ENTRIES masternode entries at a time
|
||||||
int nAskForMnbRecovery = MNB_RECOVERY_MAX_ASK_ENTRIES;
|
int nAskForMnbRecovery = MNB_RECOVERY_MAX_ASK_ENTRIES;
|
||||||
std::map<COutPoint, CMasternode>::iterator it = mapMasternodes.begin();
|
std::map<COutPoint, CMasternode>::iterator it = mapMasternodes.begin();
|
||||||
@ -199,7 +199,7 @@ void CMasternodeMan::CheckAndRemove()
|
|||||||
// calulate only once and only when it's needed
|
// calulate only once and only when it's needed
|
||||||
if(vecMasternodeRanks.empty()) {
|
if(vecMasternodeRanks.empty()) {
|
||||||
int nRandomBlockHeight = GetRandInt(nCachedBlockHeight);
|
int nRandomBlockHeight = GetRandInt(nCachedBlockHeight);
|
||||||
vecMasternodeRanks = GetMasternodeRanks(nRandomBlockHeight);
|
GetMasternodeRanks(vecMasternodeRanks, nRandomBlockHeight);
|
||||||
}
|
}
|
||||||
bool fAskedForMnbRecovery = false;
|
bool fAskedForMnbRecovery = false;
|
||||||
// ask first MNB_RECOVERY_QUORUM_TOTAL masternodes we can connect to and we haven't asked recently
|
// ask first MNB_RECOVERY_QUORUM_TOTAL masternodes we can connect to and we haven't asked recently
|
||||||
@ -493,7 +493,7 @@ bool CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool f
|
|||||||
Make a vector with all of the last paid times
|
Make a vector with all of the last paid times
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int nMnCount = CountEnabled();
|
int nMnCount = CountMasternodes();
|
||||||
|
|
||||||
for (auto& mnpair : mapMasternodes) {
|
for (auto& mnpair : mapMasternodes) {
|
||||||
if(!mnpair.second.IsValidForPayment()) continue;
|
if(!mnpair.second.IsValidForPayment()) continue;
|
||||||
@ -593,103 +593,118 @@ masternode_info_t CMasternodeMan::FindRandomNotInVec(const std::vector<COutPoint
|
|||||||
return masternode_info_t();
|
return masternode_info_t();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int nBlockHeight, int nMinProtocol, bool fOnlyActive)
|
bool CMasternodeMan::GetMasternodeScores(const uint256& nBlockHash, CMasternodeMan::score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<int64_t, CMasternode*> > vecMasternodeScores;
|
vecMasternodeScoresRet.clear();
|
||||||
|
|
||||||
//make sure we know about this block
|
if (!masternodeSync.IsMasternodeListSynced())
|
||||||
uint256 blockHash = uint256();
|
return false;
|
||||||
if(!GetBlockHash(blockHash, nBlockHeight)) return -1;
|
|
||||||
|
|
||||||
LOCK(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
// scan for winner
|
if (mapMasternodes.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// calculate scores
|
||||||
for (auto& mnpair : mapMasternodes) {
|
for (auto& mnpair : mapMasternodes) {
|
||||||
if(mnpair.second.nProtocolVersion < nMinProtocol) continue;
|
if (mnpair.second.nProtocolVersion >= nMinProtocol) {
|
||||||
if(fOnlyActive) {
|
vecMasternodeScoresRet.push_back(std::make_pair(mnpair.second.CalculateScore(nBlockHash), &mnpair.second));
|
||||||
if(!mnpair.second.IsEnabled()) continue;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if(!mnpair.second.IsValidForPayment()) continue;
|
|
||||||
}
|
|
||||||
int64_t nScore = mnpair.second.CalculateScore(blockHash).GetCompact(false);
|
|
||||||
|
|
||||||
vecMasternodeScores.push_back(std::make_pair(nScore, &mnpair.second));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
|
sort(vecMasternodeScoresRet.rbegin(), vecMasternodeScoresRet.rend(), CompareScoreMN());
|
||||||
|
return !vecMasternodeScoresRet.empty();
|
||||||
int nRank = 0;
|
|
||||||
BOOST_FOREACH (PAIRTYPE(int64_t, CMasternode*)& scorePair, vecMasternodeScores) {
|
|
||||||
nRank++;
|
|
||||||
if(scorePair.second->vin.prevout == outpoint) return nRank;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::pair<int, CMasternode> > CMasternodeMan::GetMasternodeRanks(int nBlockHeight, int nMinProtocol)
|
bool CMasternodeMan::GetMasternodeRank(const COutPoint& outpoint, int& nRankRet, int nBlockHeight, int nMinProtocol)
|
||||||
{
|
{
|
||||||
std::vector<std::pair<int64_t, CMasternode*> > vecMasternodeScores;
|
nRankRet = -1;
|
||||||
std::vector<std::pair<int, CMasternode> > vecMasternodeRanks;
|
|
||||||
|
|
||||||
//make sure we know about this block
|
if (!masternodeSync.IsMasternodeListSynced())
|
||||||
uint256 blockHash = uint256();
|
return false;
|
||||||
if(!GetBlockHash(blockHash, nBlockHeight)) return vecMasternodeRanks;
|
|
||||||
|
|
||||||
LOCK(cs);
|
// make sure we know about this block
|
||||||
|
uint256 nBlockHash = uint256();
|
||||||
// scan for winner
|
if (!GetBlockHash(nBlockHash, nBlockHeight)) {
|
||||||
for (auto& mnpair : mapMasternodes) {
|
LogPrintf("CMasternodeMan::%s -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", __func__, nBlockHeight);
|
||||||
|
|
||||||
if(mnpair.second.nProtocolVersion < nMinProtocol || !mnpair.second.IsEnabled()) continue;
|
|
||||||
|
|
||||||
int64_t nScore = mnpair.second.CalculateScore(blockHash).GetCompact(false);
|
|
||||||
|
|
||||||
vecMasternodeScores.push_back(std::make_pair(nScore, &mnpair.second));
|
|
||||||
}
|
|
||||||
|
|
||||||
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
|
|
||||||
|
|
||||||
int nRank = 0;
|
|
||||||
BOOST_FOREACH (PAIRTYPE(int64_t, CMasternode*)& s, vecMasternodeScores) {
|
|
||||||
nRank++;
|
|
||||||
vecMasternodeRanks.push_back(std::make_pair(nRank, *s.second));
|
|
||||||
}
|
|
||||||
|
|
||||||
return vecMasternodeRanks;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CMasternodeMan::GetMasternodeByRank(int nRank, int nBlockHeight, int nMinProtocol, bool fOnlyActive, masternode_info_t& mnInfoRet)
|
|
||||||
{
|
|
||||||
std::vector<std::pair<int64_t, CMasternode*> > vecMasternodeScores;
|
|
||||||
|
|
||||||
LOCK(cs);
|
|
||||||
|
|
||||||
uint256 blockHash;
|
|
||||||
if(!GetBlockHash(blockHash, nBlockHeight)) {
|
|
||||||
LogPrintf("CMasternode::GetMasternodeByRank -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", nBlockHeight);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill scores
|
LOCK(cs);
|
||||||
for (auto& mnpair : mapMasternodes) {
|
|
||||||
|
|
||||||
if(mnpair.second.nProtocolVersion < nMinProtocol) continue;
|
score_pair_vec_t vecMasternodeScores;
|
||||||
if(fOnlyActive && !mnpair.second.IsEnabled()) continue;
|
if (!GetMasternodeScores(nBlockHash, vecMasternodeScores, nMinProtocol))
|
||||||
|
return false;
|
||||||
|
|
||||||
int64_t nScore = mnpair.second.CalculateScore(blockHash).GetCompact(false);
|
int nRank = 0;
|
||||||
|
for (auto& scorePair : vecMasternodeScores) {
|
||||||
vecMasternodeScores.push_back(std::make_pair(nScore, &mnpair.second));
|
nRank++;
|
||||||
|
if(scorePair.second->vin.prevout == outpoint) {
|
||||||
|
nRankRet = nRank;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int rank = 0;
|
bool CMasternodeMan::GetMasternodeRanks(CMasternodeMan::rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight, int nMinProtocol)
|
||||||
BOOST_FOREACH (PAIRTYPE(int64_t, CMasternode*)& s, vecMasternodeScores){
|
{
|
||||||
rank++;
|
vecMasternodeRanksRet.clear();
|
||||||
if(rank == nRank) {
|
|
||||||
mnInfoRet = *s.second;
|
if (!masternodeSync.IsMasternodeListSynced())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// make sure we know about this block
|
||||||
|
uint256 nBlockHash = uint256();
|
||||||
|
if (!GetBlockHash(nBlockHash, nBlockHeight)) {
|
||||||
|
LogPrintf("CMasternodeMan::%s -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", __func__, nBlockHeight);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCK(cs);
|
||||||
|
|
||||||
|
score_pair_vec_t vecMasternodeScores;
|
||||||
|
if (!GetMasternodeScores(nBlockHash, vecMasternodeScores, nMinProtocol))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int nRank = 0;
|
||||||
|
for (auto& scorePair : vecMasternodeScores) {
|
||||||
|
nRank++;
|
||||||
|
vecMasternodeRanksRet.push_back(std::make_pair(nRank, *scorePair.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMasternodeMan::GetMasternodeByRank(int nRankIn, masternode_info_t& mnInfoRet, int nBlockHeight, int nMinProtocol)
|
||||||
|
{
|
||||||
|
mnInfoRet = masternode_info_t();
|
||||||
|
|
||||||
|
if (!masternodeSync.IsMasternodeListSynced())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// make sure we know about this block
|
||||||
|
uint256 nBlockHash = uint256();
|
||||||
|
if (!GetBlockHash(nBlockHash, nBlockHeight)) {
|
||||||
|
LogPrintf("CMasternodeMan::%s -- ERROR: GetBlockHash() failed at nBlockHeight %d\n", __func__, nBlockHeight);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCK(cs);
|
||||||
|
|
||||||
|
score_pair_vec_t vecMasternodeScores;
|
||||||
|
if (!GetMasternodeScores(nBlockHash, vecMasternodeScores, nMinProtocol))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (vecMasternodeScores.size() < nRankIn)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int nRank = 0;
|
||||||
|
for (auto& scorePair : vecMasternodeScores) {
|
||||||
|
nRank++;
|
||||||
|
if(nRank == nRankIn) {
|
||||||
|
mnInfoRet = *scorePair.second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -901,7 +916,8 @@ void CMasternodeMan::DoFullVerificationStep()
|
|||||||
if(activeMasternode.outpoint == COutPoint()) return;
|
if(activeMasternode.outpoint == COutPoint()) return;
|
||||||
if(!masternodeSync.IsSynced()) return;
|
if(!masternodeSync.IsSynced()) return;
|
||||||
|
|
||||||
std::vector<std::pair<int, CMasternode> > vecMasternodeRanks = GetMasternodeRanks(nCachedBlockHeight - 1, MIN_POSE_PROTO_VERSION);
|
rank_pair_vec_t vecMasternodeRanks;
|
||||||
|
GetMasternodeRanks(vecMasternodeRanks, nCachedBlockHeight - 1, MIN_POSE_PROTO_VERSION);
|
||||||
|
|
||||||
// Need LOCK2 here to ensure consistent locking order because the SendVerifyRequest call below locks cs_main
|
// Need LOCK2 here to ensure consistent locking order because the SendVerifyRequest call below locks cs_main
|
||||||
// through GetHeight() signal in ConnectNode
|
// through GetHeight() signal in ConnectNode
|
||||||
@ -1234,9 +1250,9 @@ void CMasternodeMan::ProcessVerifyBroadcast(CNode* pnode, const CMasternodeVerif
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nRank = GetMasternodeRank(mnv.vin2.prevout, mnv.nBlockHeight, MIN_POSE_PROTO_VERSION);
|
int nRank;
|
||||||
|
|
||||||
if (nRank == -1) {
|
if (!GetMasternodeRank(mnv.vin2.prevout, nRank, mnv.nBlockHeight, MIN_POSE_PROTO_VERSION)) {
|
||||||
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Can't calculate rank for masternode %s\n",
|
LogPrint("masternode", "CMasternodeMan::ProcessVerifyBroadcast -- Can't calculate rank for masternode %s\n",
|
||||||
mnv.vin2.prevout.ToStringShort());
|
mnv.vin2.prevout.ToStringShort());
|
||||||
return;
|
return;
|
||||||
|
@ -17,6 +17,10 @@ extern CMasternodeMan mnodeman;
|
|||||||
class CMasternodeMan
|
class CMasternodeMan
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
typedef std::pair<arith_uint256, CMasternode*> score_pair_t;
|
||||||
|
typedef std::vector<score_pair_t> score_pair_vec_t;
|
||||||
|
typedef std::pair<int, CMasternode> rank_pair_t;
|
||||||
|
typedef std::vector<rank_pair_t> rank_pair_vec_t;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const std::string SERIALIZATION_VERSION_STRING;
|
static const std::string SERIALIZATION_VERSION_STRING;
|
||||||
@ -73,6 +77,8 @@ private:
|
|||||||
/// Find an entry
|
/// Find an entry
|
||||||
CMasternode* Find(const COutPoint& outpoint);
|
CMasternode* Find(const COutPoint& outpoint);
|
||||||
|
|
||||||
|
bool GetMasternodeScores(const uint256& nBlockHash, score_pair_vec_t& vecMasternodeScoresRet, int nMinProtocol = 0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Keep track of all broadcasts I've seen
|
// Keep track of all broadcasts I've seen
|
||||||
std::map<uint256, std::pair<int64_t, CMasternodeBroadcast> > mapSeenMasternodeBroadcast;
|
std::map<uint256, std::pair<int64_t, CMasternodeBroadcast> > mapSeenMasternodeBroadcast;
|
||||||
@ -166,9 +172,9 @@ public:
|
|||||||
|
|
||||||
std::map<COutPoint, CMasternode> GetFullMasternodeMap() { return mapMasternodes; }
|
std::map<COutPoint, CMasternode> GetFullMasternodeMap() { return mapMasternodes; }
|
||||||
|
|
||||||
std::vector<std::pair<int, CMasternode> > GetMasternodeRanks(int nBlockHeight = -1, int nMinProtocol=0);
|
bool GetMasternodeRanks(rank_pair_vec_t& vecMasternodeRanksRet, int nBlockHeight = -1, int nMinProtocol = 0);
|
||||||
int GetMasternodeRank(const COutPoint &outpoint, int nBlockHeight, int nMinProtocol=0, bool fOnlyActive=true);
|
bool GetMasternodeRank(const COutPoint &outpoint, int& nRankRet, int nBlockHeight = -1, int nMinProtocol = 0);
|
||||||
bool GetMasternodeByRank(int nRank, int nBlockHeight, int nMinProtocol, bool fOnlyActive, masternode_info_t& mnInfoRet);
|
bool GetMasternodeByRank(int nRank, masternode_info_t& mnInfoRet, int nBlockHeight = -1, int nMinProtocol = 0);
|
||||||
|
|
||||||
void ProcessMasternodeConnections();
|
void ProcessMasternodeConnections();
|
||||||
std::pair<CService, std::set<uint256> > PopScheduledMnbRequestConnection();
|
std::pair<CService, std::set<uint256> > PopScheduledMnbRequestConnection();
|
||||||
|
@ -504,7 +504,8 @@ UniValue masternodelist(const UniValue& params, bool fHelp)
|
|||||||
|
|
||||||
UniValue obj(UniValue::VOBJ);
|
UniValue obj(UniValue::VOBJ);
|
||||||
if (strMode == "rank") {
|
if (strMode == "rank") {
|
||||||
std::vector<std::pair<int, CMasternode> > vMasternodeRanks = mnodeman.GetMasternodeRanks();
|
CMasternodeMan::rank_pair_vec_t vMasternodeRanks;
|
||||||
|
mnodeman.GetMasternodeRanks(vMasternodeRanks);
|
||||||
BOOST_FOREACH(PAIRTYPE(int, CMasternode)& s, vMasternodeRanks) {
|
BOOST_FOREACH(PAIRTYPE(int, CMasternode)& s, vMasternodeRanks) {
|
||||||
std::string strOutpoint = s.second.vin.prevout.ToStringShort();
|
std::string strOutpoint = s.second.vin.prevout.ToStringShort();
|
||||||
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
if (strFilter !="" && strOutpoint.find(strFilter) == std::string::npos) continue;
|
||||||
|
@ -1883,7 +1883,7 @@ int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Para
|
|||||||
const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
|
const struct BIP9DeploymentInfo& vbinfo = VersionBitsDeploymentInfo[pos];
|
||||||
if (vbinfo.check_mn_protocol && state == THRESHOLD_STARTED && !fAssumeMasternodeIsUpgraded) {
|
if (vbinfo.check_mn_protocol && state == THRESHOLD_STARTED && !fAssumeMasternodeIsUpgraded) {
|
||||||
masternode_info_t mnInfo;
|
masternode_info_t mnInfo;
|
||||||
bool fFound = mnodeman.GetMasternodeByRank(1, pindexPrev->nHeight, 0, false, mnInfo);
|
bool fFound = mnodeman.GetMasternodeByRank(1, mnInfo, pindexPrev->nHeight);
|
||||||
if (!fFound || mnInfo.nProtocolVersion < PROTOCOL_VERSION) {
|
if (!fFound || mnInfo.nProtocolVersion < PROTOCOL_VERSION) {
|
||||||
// no masternodes(?) or masternode is not upgraded yet
|
// no masternodes(?) or masternode is not upgraded yet
|
||||||
continue;
|
continue;
|
||||||
@ -2461,7 +2461,8 @@ void static UpdateTip(CBlockIndex *pindexNew) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update global flag
|
// Update global flags
|
||||||
|
fDIP0001LockedInAtTip = (VersionBitsTipState(chainParams.GetConsensus(), Consensus::DEPLOYMENT_DIP0001) == THRESHOLD_LOCKED_IN);
|
||||||
fDIP0001ActiveAtTip = (VersionBitsTipState(chainParams.GetConsensus(), Consensus::DEPLOYMENT_DIP0001) == THRESHOLD_ACTIVE);
|
fDIP0001ActiveAtTip = (VersionBitsTipState(chainParams.GetConsensus(), Consensus::DEPLOYMENT_DIP0001) == THRESHOLD_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ class CValidationState;
|
|||||||
|
|
||||||
struct LockPoints;
|
struct LockPoints;
|
||||||
|
|
||||||
|
static std::atomic<bool> fDIP0001LockedInAtTip{false};
|
||||||
static std::atomic<bool> fDIP0001ActiveAtTip{false};
|
static std::atomic<bool> fDIP0001ActiveAtTip{false};
|
||||||
|
|
||||||
/** Default for accepting alerts from the P2P network. */
|
/** Default for accepting alerts from the P2P network. */
|
||||||
|
Loading…
Reference in New Issue
Block a user