2016-12-20 14:26:45 +01:00
// Copyright (c) 2014-2017 The Dash Core developers
2015-02-24 15:02:22 +01:00
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2015-02-23 21:01:21 +01:00
# include "activemasternode.h"
2016-12-20 14:27:59 +01:00
# include "addrman.h"
2016-11-13 18:52:34 +01:00
# include "governance.h"
2016-01-24 20:05:31 +01:00
# include "masternode-payments.h"
# include "masternode-sync.h"
2016-12-20 14:27:59 +01:00
# include "masternodeman.h"
2017-04-12 09:04:06 +02:00
# include "messagesigner.h"
2016-10-20 23:11:30 +02:00
# include "netfulfilledman.h"
2017-12-01 19:53:34 +01:00
# ifdef ENABLE_WALLET
2017-05-05 13:26:27 +02:00
# include "privatesend-client.h"
2017-12-01 19:53:34 +01:00
# endif // ENABLE_WALLET
# include "script/standard.h"
2015-02-23 21:01:21 +01:00
# include "util.h"
/** Masternode manager */
CMasternodeMan mnodeman ;
2017-09-14 15:58:29 +02:00
const std : : string CMasternodeMan : : SERIALIZATION_VERSION_STRING = " CMasternodeMan-Version-7 " ;
2016-10-20 23:11:30 +02:00
2016-09-11 22:22:37 +02:00
struct CompareLastPaidBlock
2015-02-23 21:01:21 +01:00
{
2016-09-20 00:27:36 +02:00
bool operator ( ) ( const std : : pair < int , CMasternode * > & t1 ,
const std : : pair < int , CMasternode * > & t2 ) const
2015-02-23 21:01:21 +01:00
{
2016-09-20 00:27:36 +02:00
return ( t1 . first ! = t2 . first ) ? ( t1 . first < t2 . first ) : ( t1 . second - > vin < t2 . second - > vin ) ;
2015-07-30 18:00:28 +02:00
}
} ;
struct CompareScoreMN
2015-03-14 19:34:51 +01:00
{
2017-09-14 15:58:29 +02:00
bool operator ( ) ( const std : : pair < arith_uint256 , CMasternode * > & t1 ,
const std : : pair < arith_uint256 , CMasternode * > & t2 ) const
2015-03-14 19:34:51 +01:00
{
2016-09-20 00:27:36 +02:00
return ( t1 . first ! = t2 . first ) ? ( t1 . first < t2 . first ) : ( t1 . second - > vin < t2 . second - > vin ) ;
2015-03-14 19:34:51 +01:00
}
} ;
2015-02-23 21:01:21 +01:00
2016-10-20 23:11:30 +02:00
struct CompareByAddr
2016-11-13 18:52:34 +01:00
2016-10-20 23:11:30 +02:00
{
bool operator ( ) ( const CMasternode * t1 ,
const CMasternode * t2 ) const
{
return t1 - > addr < t2 - > addr ;
}
} ;
2015-02-23 21:01:21 +01:00
2016-11-13 18:52:34 +01:00
CMasternodeMan : : CMasternodeMan ( )
: cs ( ) ,
2017-09-11 16:13:48 +02:00
mapMasternodes ( ) ,
2016-11-13 18:52:34 +01:00
mAskedUsForMasternodeList ( ) ,
mWeAskedForMasternodeList ( ) ,
mWeAskedForMasternodeListEntry ( ) ,
2017-02-17 21:08:29 +01:00
mWeAskedForVerification ( ) ,
mMnbRecoveryRequests ( ) ,
mMnbRecoveryGoodReplies ( ) ,
2017-01-21 20:03:55 +01:00
listScheduledMnbRequestConnections ( ) ,
2016-11-13 18:52:34 +01:00
fMasternodesAdded ( false ) ,
fMasternodesRemoved ( false ) ,
vecDirtyGovernanceObjectHashes ( ) ,
nLastWatchdogVoteTime ( 0 ) ,
mapSeenMasternodeBroadcast ( ) ,
mapSeenMasternodePing ( ) ,
nDsqCount ( 0 )
{ }
2015-02-23 21:01:21 +01:00
bool CMasternodeMan : : Add ( CMasternode & mn )
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
if ( Has ( mn . vin . prevout ) ) return false ;
2015-02-23 21:01:21 +01:00
2017-08-25 14:57:19 +02:00
LogPrint ( " masternode " , " CMasternodeMan::Add -- Adding new Masternode: addr=%s, %i now \n " , mn . addr . ToString ( ) , size ( ) + 1 ) ;
2017-09-11 16:13:48 +02:00
mapMasternodes [ mn . vin . prevout ] = mn ;
2017-08-25 14:57:19 +02:00
fMasternodesAdded = true ;
return true ;
2015-02-23 21:01:21 +01:00
}
2017-09-19 16:51:38 +02:00
void CMasternodeMan : : AskForMN ( CNode * pnode , const COutPoint & outpoint , CConnman & connman )
2015-08-07 05:07:40 +02:00
{
2016-10-22 18:52:14 +02:00
if ( ! pnode ) return ;
2016-12-21 00:55:55 +01:00
LOCK ( cs ) ;
2015-08-07 05:07:40 +02:00
2017-09-11 16:13:48 +02:00
std : : map < COutPoint , std : : map < CNetAddr , int64_t > > : : iterator it1 = mWeAskedForMasternodeListEntry . find ( outpoint ) ;
2016-12-21 00:55:55 +01:00
if ( it1 ! = mWeAskedForMasternodeListEntry . end ( ) ) {
std : : map < CNetAddr , int64_t > : : iterator it2 = it1 - > second . find ( pnode - > addr ) ;
if ( it2 ! = it1 - > second . end ( ) ) {
if ( GetTime ( ) < it2 - > second ) {
// we've asked recently, should not repeat too often or we could get banned
return ;
}
// we asked this node for this outpoint but it's ok to ask again already
2017-09-11 16:13:48 +02:00
LogPrintf ( " CMasternodeMan::AskForMN -- Asking same peer %s for missing masternode entry again: %s \n " , pnode - > addr . ToString ( ) , outpoint . ToStringShort ( ) ) ;
2016-12-21 00:55:55 +01:00
} else {
// we already asked for this outpoint but not this node
2017-09-11 16:13:48 +02:00
LogPrintf ( " CMasternodeMan::AskForMN -- Asking new peer %s for missing masternode entry: %s \n " , pnode - > addr . ToString ( ) , outpoint . ToStringShort ( ) ) ;
2016-12-21 00:55:55 +01:00
}
} else {
// we never asked any node for this outpoint
2017-09-11 16:13:48 +02:00
LogPrintf ( " CMasternodeMan::AskForMN -- Asking peer %s for missing masternode entry for the first time: %s \n " , pnode - > addr . ToString ( ) , outpoint . ToStringShort ( ) ) ;
2016-12-21 00:55:55 +01:00
}
2017-09-11 16:13:48 +02:00
mWeAskedForMasternodeListEntry [ outpoint ] [ pnode - > addr ] = GetTime ( ) + DSEG_UPDATE_SECONDS ;
2015-08-07 05:07:40 +02:00
2017-09-19 16:51:38 +02:00
connman . PushMessage ( pnode , NetMsgType : : DSEG , CTxIn ( outpoint ) ) ;
2017-09-11 16:13:48 +02:00
}
bool CMasternodeMan : : AllowMixing ( const COutPoint & outpoint )
{
LOCK ( cs ) ;
CMasternode * pmn = Find ( outpoint ) ;
if ( ! pmn ) {
return false ;
}
nDsqCount + + ;
pmn - > nLastDsq = nDsqCount ;
pmn - > fAllowMixingTx = true ;
return true ;
}
bool CMasternodeMan : : DisallowMixing ( const COutPoint & outpoint )
{
LOCK ( cs ) ;
CMasternode * pmn = Find ( outpoint ) ;
if ( ! pmn ) {
return false ;
}
pmn - > fAllowMixingTx = false ;
return true ;
2015-08-07 05:07:40 +02:00
}
2017-09-14 13:41:40 +02:00
bool CMasternodeMan : : PoSeBan ( const COutPoint & outpoint )
{
LOCK ( cs ) ;
CMasternode * pmn = Find ( outpoint ) ;
if ( ! pmn ) {
return false ;
}
pmn - > PoSeBan ( ) ;
return true ;
}
2015-02-23 21:01:21 +01:00
void CMasternodeMan : : Check ( )
{
LOCK ( cs ) ;
2016-12-24 03:49:13 +01:00
LogPrint ( " masternode " , " CMasternodeMan::Check -- nLastWatchdogVoteTime=%d, IsWatchdogActive()=%d \n " , nLastWatchdogVoteTime , IsWatchdogActive ( ) ) ;
2016-10-17 20:54:28 +02:00
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
mnpair . second . Check ( ) ;
2015-06-24 18:41:03 +02:00
}
2015-02-23 21:01:21 +01:00
}
2017-09-19 16:51:38 +02:00
void CMasternodeMan : : CheckAndRemove ( CConnman & connman )
2015-02-23 21:01:21 +01:00
{
2017-01-14 23:29:08 +01:00
if ( ! masternodeSync . IsMasternodeListSynced ( ) ) return ;
2016-05-30 08:22:30 +02:00
2017-01-14 23:29:08 +01:00
LogPrintf ( " CMasternodeMan::CheckAndRemove \n " ) ;
2015-02-23 21:01:21 +01:00
2016-11-13 18:52:34 +01:00
{
2017-01-01 18:48:53 +01:00
// Need LOCK2 here to ensure consistent locking order because code below locks cs_main
2017-01-21 20:03:55 +01:00
// in CheckMnbAndUpdateMasternodeList()
2017-01-01 18:48:53 +01:00
LOCK2 ( cs_main , cs ) ;
Check ( ) ;
2015-07-30 15:44:18 +02:00
2017-01-01 18:48:53 +01:00
// Remove spent masternodes, prepare structures and make requests to reasure the state of inactive ones
2017-09-14 15:58:29 +02:00
rank_pair_vec_t vecMasternodeRanks ;
2017-01-31 16:29:27 +01:00
// ask for up to MNB_RECOVERY_MAX_ASK_ENTRIES masternode entries at a time
int nAskForMnbRecovery = MNB_RECOVERY_MAX_ASK_ENTRIES ;
2017-09-11 16:13:48 +02:00
std : : map < COutPoint , CMasternode > : : iterator it = mapMasternodes . begin ( ) ;
while ( it ! = mapMasternodes . end ( ) ) {
CMasternodeBroadcast mnb = CMasternodeBroadcast ( it - > second ) ;
2017-01-01 18:48:53 +01:00
uint256 hash = mnb . GetHash ( ) ;
2016-12-24 03:49:13 +01:00
// If collateral was spent ...
2017-09-11 16:13:48 +02:00
if ( it - > second . IsOutpointSpent ( ) ) {
LogPrint ( " masternode " , " CMasternodeMan::CheckAndRemove -- Removing Masternode: %s addr=%s %i now \n " , it - > second . GetStateString ( ) , it - > second . addr . ToString ( ) , size ( ) - 1 ) ;
2016-11-13 18:52:34 +01:00
// erase all of the broadcasts we've seen from this txin, ...
2017-01-01 18:48:53 +01:00
mapSeenMasternodeBroadcast . erase ( hash ) ;
2017-09-11 16:13:48 +02:00
mWeAskedForMasternodeListEntry . erase ( it - > first ) ;
2016-11-13 18:52:34 +01:00
// and finally remove it from the list
2017-09-11 16:13:48 +02:00
it - > second . FlagGovernanceItemsAsDirty ( ) ;
mapMasternodes . erase ( it + + ) ;
2016-11-13 18:52:34 +01:00
fMasternodesRemoved = true ;
} else {
2017-08-25 14:57:05 +02:00
bool fAsk = ( nAskForMnbRecovery > 0 ) & &
2017-01-14 23:29:08 +01:00
masternodeSync . IsSynced ( ) & &
2017-09-11 16:13:48 +02:00
it - > second . IsNewStartRequired ( ) & &
2017-01-14 23:29:08 +01:00
! IsMnbRecoveryRequested ( hash ) ;
if ( fAsk ) {
2017-01-01 18:48:53 +01:00
// this mn is in a non-recoverable state and we haven't asked other nodes yet
std : : set < CNetAddr > setRequested ;
// calulate only once and only when it's needed
if ( vecMasternodeRanks . empty ( ) ) {
2017-08-25 14:57:05 +02:00
int nRandomBlockHeight = GetRandInt ( nCachedBlockHeight ) ;
2017-09-14 15:58:29 +02:00
GetMasternodeRanks ( vecMasternodeRanks , nRandomBlockHeight ) ;
2017-01-01 18:48:53 +01:00
}
2017-01-31 16:29:27 +01:00
bool fAskedForMnbRecovery = false ;
// ask first MNB_RECOVERY_QUORUM_TOTAL masternodes we can connect to and we haven't asked recently
2017-01-01 18:48:53 +01:00
for ( int i = 0 ; setRequested . size ( ) < MNB_RECOVERY_QUORUM_TOTAL & & i < ( int ) vecMasternodeRanks . size ( ) ; i + + ) {
// avoid banning
2017-09-11 16:13:48 +02:00
if ( mWeAskedForMasternodeListEntry . count ( it - > first ) & & mWeAskedForMasternodeListEntry [ it - > first ] . count ( vecMasternodeRanks [ i ] . second . addr ) ) continue ;
2017-01-01 18:48:53 +01:00
// didn't ask recently, ok to ask now
CService addr = vecMasternodeRanks [ i ] . second . addr ;
2017-01-21 20:03:55 +01:00
setRequested . insert ( addr ) ;
listScheduledMnbRequestConnections . push_back ( std : : make_pair ( addr , hash ) ) ;
fAskedForMnbRecovery = true ;
2017-01-01 18:48:53 +01:00
}
2017-01-31 16:29:27 +01:00
if ( fAskedForMnbRecovery ) {
2017-09-11 16:13:48 +02:00
LogPrint ( " masternode " , " CMasternodeMan::CheckAndRemove -- Recovery initiated, masternode=%s \n " , it - > first . ToStringShort ( ) ) ;
2017-01-31 16:29:27 +01:00
nAskForMnbRecovery - - ;
}
2017-01-01 18:48:53 +01:00
// wait for mnb recovery replies for MNB_RECOVERY_WAIT_SECONDS seconds
mMnbRecoveryRequests [ hash ] = std : : make_pair ( GetTime ( ) + MNB_RECOVERY_WAIT_SECONDS , setRequested ) ;
}
2016-11-13 18:52:34 +01:00
+ + it ;
}
2015-02-23 21:01:21 +01:00
}
2015-02-26 00:21:28 +01:00
2017-01-01 18:48:53 +01:00
// proces replies for MASTERNODE_NEW_START_REQUIRED masternodes
LogPrint ( " masternode " , " CMasternodeMan::CheckAndRemove -- mMnbRecoveryGoodReplies size=%d \n " , ( int ) mMnbRecoveryGoodReplies . size ( ) ) ;
std : : map < uint256 , std : : vector < CMasternodeBroadcast > > : : iterator itMnbReplies = mMnbRecoveryGoodReplies . begin ( ) ;
while ( itMnbReplies ! = mMnbRecoveryGoodReplies . end ( ) ) {
if ( mMnbRecoveryRequests [ itMnbReplies - > first ] . first < GetTime ( ) ) {
// all nodes we asked should have replied now
if ( itMnbReplies - > second . size ( ) > = MNB_RECOVERY_QUORUM_REQUIRED ) {
// majority of nodes we asked agrees that this mn doesn't require new mnb, reprocess one of new mnbs
LogPrint ( " masternode " , " CMasternodeMan::CheckAndRemove -- reprocessing mnb, masternode=%s \n " , itMnbReplies - > second [ 0 ] . vin . prevout . ToStringShort ( ) ) ;
// mapSeenMasternodeBroadcast.erase(itMnbReplies->first);
int nDos ;
itMnbReplies - > second [ 0 ] . fRecovery = true ;
2017-09-19 16:51:38 +02:00
CheckMnbAndUpdateMasternodeList ( NULL , itMnbReplies - > second [ 0 ] , nDos , connman ) ;
2017-01-01 18:48:53 +01:00
}
LogPrint ( " masternode " , " CMasternodeMan::CheckAndRemove -- removing mnb recovery reply, masternode=%s, size=%d \n " , itMnbReplies - > second [ 0 ] . vin . prevout . ToStringShort ( ) , ( int ) itMnbReplies - > second . size ( ) ) ;
mMnbRecoveryGoodReplies . erase ( itMnbReplies + + ) ;
} else {
+ + itMnbReplies ;
}
}
}
{
// no need for cm_main below
LOCK ( cs ) ;
std : : map < uint256 , std : : pair < int64_t , std : : set < CNetAddr > > > : : iterator itMnbRequest = mMnbRecoveryRequests . begin ( ) ;
while ( itMnbRequest ! = mMnbRecoveryRequests . end ( ) ) {
// Allow this mnb to be re-verified again after MNB_RECOVERY_RETRY_SECONDS seconds
// if mn is still in MASTERNODE_NEW_START_REQUIRED state.
if ( GetTime ( ) - itMnbRequest - > second . first > MNB_RECOVERY_RETRY_SECONDS ) {
mMnbRecoveryRequests . erase ( itMnbRequest + + ) ;
} else {
+ + itMnbRequest ;
}
}
2016-11-13 18:52:34 +01:00
// check who's asked for the Masternode list
std : : map < CNetAddr , int64_t > : : iterator it1 = mAskedUsForMasternodeList . begin ( ) ;
while ( it1 ! = mAskedUsForMasternodeList . end ( ) ) {
if ( ( * it1 ) . second < GetTime ( ) ) {
mAskedUsForMasternodeList . erase ( it1 + + ) ;
} else {
+ + it1 ;
}
2015-02-26 15:02:39 +01:00
}
2015-02-26 00:21:28 +01:00
2016-11-13 18:52:34 +01:00
// check who we asked for the Masternode list
it1 = mWeAskedForMasternodeList . begin ( ) ;
while ( it1 ! = mWeAskedForMasternodeList . end ( ) ) {
if ( ( * it1 ) . second < GetTime ( ) ) {
mWeAskedForMasternodeList . erase ( it1 + + ) ;
} else {
+ + it1 ;
}
2015-02-26 15:02:39 +01:00
}
2015-02-26 00:21:28 +01:00
2016-11-13 18:52:34 +01:00
// check which Masternodes we've asked for
2016-12-21 00:55:55 +01:00
std : : map < COutPoint , std : : map < CNetAddr , int64_t > > : : iterator it2 = mWeAskedForMasternodeListEntry . begin ( ) ;
2016-11-13 18:52:34 +01:00
while ( it2 ! = mWeAskedForMasternodeListEntry . end ( ) ) {
2016-12-21 00:55:55 +01:00
std : : map < CNetAddr , int64_t > : : iterator it3 = it2 - > second . begin ( ) ;
while ( it3 ! = it2 - > second . end ( ) ) {
if ( it3 - > second < GetTime ( ) ) {
it2 - > second . erase ( it3 + + ) ;
} else {
+ + it3 ;
}
}
if ( it2 - > second . empty ( ) ) {
2016-11-13 18:52:34 +01:00
mWeAskedForMasternodeListEntry . erase ( it2 + + ) ;
} else {
+ + it2 ;
}
2015-02-26 15:02:39 +01:00
}
2015-08-29 05:25:55 +02:00
2016-12-24 03:49:13 +01:00
std : : map < CNetAddr , CMasternodeVerification > : : iterator it3 = mWeAskedForVerification . begin ( ) ;
while ( it3 ! = mWeAskedForVerification . end ( ) ) {
2017-08-25 14:57:05 +02:00
if ( it3 - > second . nBlockHeight < nCachedBlockHeight - MAX_POSE_BLOCKS ) {
2016-12-24 03:49:13 +01:00
mWeAskedForVerification . erase ( it3 + + ) ;
2016-11-13 18:52:34 +01:00
} else {
+ + it3 ;
}
2016-03-14 13:17:23 +01:00
}
2016-12-24 03:49:13 +01:00
// NOTE: do not expire mapSeenMasternodeBroadcast entries here, clean them on mnb updates!
2016-11-13 18:52:34 +01:00
// remove expired mapSeenMasternodePing
std : : map < uint256 , CMasternodePing > : : iterator it4 = mapSeenMasternodePing . begin ( ) ;
while ( it4 ! = mapSeenMasternodePing . end ( ) ) {
2016-12-24 03:49:13 +01:00
if ( ( * it4 ) . second . IsExpired ( ) ) {
2016-11-13 18:52:34 +01:00
LogPrint ( " masternode " , " CMasternodeMan::CheckAndRemove -- Removing expired Masternode ping: hash=%s \n " , ( * it4 ) . second . GetHash ( ) . ToString ( ) ) ;
mapSeenMasternodePing . erase ( it4 + + ) ;
} else {
+ + it4 ;
}
2015-08-25 04:24:30 +02:00
}
2016-11-13 18:52:34 +01:00
// remove expired mapSeenMasternodeVerification
std : : map < uint256 , CMasternodeVerification > : : iterator itv2 = mapSeenMasternodeVerification . begin ( ) ;
while ( itv2 ! = mapSeenMasternodeVerification . end ( ) ) {
2017-08-25 14:57:05 +02:00
if ( ( * itv2 ) . second . nBlockHeight < nCachedBlockHeight - MAX_POSE_BLOCKS ) {
2016-11-13 18:52:34 +01:00
LogPrint ( " masternode " , " CMasternodeMan::CheckAndRemove -- Removing expired Masternode verification: hash=%s \n " , ( * itv2 ) . first . ToString ( ) ) ;
mapSeenMasternodeVerification . erase ( itv2 + + ) ;
} else {
+ + itv2 ;
}
}
LogPrintf ( " CMasternodeMan::CheckAndRemove -- %s \n " , ToString ( ) ) ;
2016-10-20 23:11:30 +02:00
}
2016-10-22 18:52:14 +02:00
2016-11-13 18:52:34 +01:00
if ( fMasternodesRemoved ) {
2017-09-19 16:51:38 +02:00
NotifyMasternodeUpdates ( connman ) ;
2016-11-13 18:52:34 +01:00
}
2015-02-23 21:01:21 +01:00
}
2015-03-01 01:04:17 +01:00
void CMasternodeMan : : Clear ( )
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
mapMasternodes . clear ( ) ;
2015-03-01 01:04:17 +01:00
mAskedUsForMasternodeList . clear ( ) ;
mWeAskedForMasternodeList . clear ( ) ;
mWeAskedForMasternodeListEntry . clear ( ) ;
2015-09-30 03:24:29 +02:00
mapSeenMasternodeBroadcast . clear ( ) ;
mapSeenMasternodePing . clear ( ) ;
2015-03-06 18:25:48 +01:00
nDsqCount = 0 ;
2016-10-17 20:54:28 +02:00
nLastWatchdogVoteTime = 0 ;
}
2016-10-22 18:52:14 +02:00
int CMasternodeMan : : CountMasternodes ( int nProtocolVersion )
2016-10-17 20:54:28 +02:00
{
LOCK ( cs ) ;
2016-10-22 18:52:14 +02:00
int nCount = 0 ;
nProtocolVersion = nProtocolVersion = = - 1 ? mnpayments . GetMinMasternodePaymentsProto ( ) : nProtocolVersion ;
2016-10-17 20:54:28 +02:00
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
if ( mnpair . second . nProtocolVersion < nProtocolVersion ) continue ;
2016-10-22 18:52:14 +02:00
nCount + + ;
2016-10-17 20:54:28 +02:00
}
2016-10-22 18:52:14 +02:00
return nCount ;
2015-03-01 01:04:17 +01:00
}
2016-10-22 18:52:14 +02:00
int CMasternodeMan : : CountEnabled ( int nProtocolVersion )
2015-02-23 21:01:21 +01:00
{
2016-10-17 20:54:28 +02:00
LOCK ( cs ) ;
2016-10-22 18:52:14 +02:00
int nCount = 0 ;
nProtocolVersion = nProtocolVersion = = - 1 ? mnpayments . GetMinMasternodePaymentsProto ( ) : nProtocolVersion ;
2015-02-23 21:01:21 +01:00
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
if ( mnpair . second . nProtocolVersion < nProtocolVersion | | ! mnpair . second . IsEnabled ( ) ) continue ;
2016-10-22 18:52:14 +02:00
nCount + + ;
2015-02-23 21:01:21 +01:00
}
2016-10-22 18:52:14 +02:00
return nCount ;
2016-08-06 22:52:01 +02:00
}
2016-10-22 18:52:14 +02:00
/* Only IPv4 masternodes are allowed in 12.1, saving this for later
2016-08-12 07:58:55 +02:00
int CMasternodeMan : : CountByIP ( int nNetworkType )
2016-08-06 22:52:01 +02:00
{
2016-10-17 20:54:28 +02:00
LOCK ( cs ) ;
2016-08-12 07:58:55 +02:00
int nNodeCount = 0 ;
2016-08-06 22:52:01 +02:00
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes )
if ( ( nNetworkType = = NET_IPV4 & & mnpair . second . addr . IsIPv4 ( ) ) | |
( nNetworkType = = NET_TOR & & mnpair . second . addr . IsTor ( ) ) | |
( nNetworkType = = NET_IPV6 & & mnpair . second . addr . IsIPv6 ( ) ) ) {
2016-08-12 07:58:55 +02:00
nNodeCount + + ;
2016-08-06 22:52:01 +02:00
}
2016-08-12 07:58:55 +02:00
return nNodeCount ;
2015-02-23 21:01:21 +01:00
}
2016-10-22 18:52:14 +02:00
*/
2015-02-23 21:01:21 +01:00
2017-09-19 16:51:38 +02:00
void CMasternodeMan : : DsegUpdate ( CNode * pnode , CConnman & connman )
2015-02-26 00:21:28 +01:00
{
2015-02-27 00:12:43 +01:00
LOCK ( cs ) ;
2016-02-02 16:28:56 +01:00
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : MAIN ) {
2016-10-22 18:52:14 +02:00
if ( ! ( pnode - > addr . IsRFC1918 ( ) | | pnode - > addr . IsLocal ( ) ) ) {
2015-07-29 10:06:30 +02:00
std : : map < CNetAddr , int64_t > : : iterator it = mWeAskedForMasternodeList . find ( pnode - > addr ) ;
2016-10-22 18:52:14 +02:00
if ( it ! = mWeAskedForMasternodeList . end ( ) & & GetTime ( ) < ( * it ) . second ) {
LogPrintf ( " CMasternodeMan::DsegUpdate -- we already asked %s for the list; skipping... \n " , pnode - > addr . ToString ( ) ) ;
return ;
2015-07-02 17:07:30 +02:00
}
2015-02-26 00:21:28 +01:00
}
}
2017-07-21 17:21:09 +02:00
2017-09-19 16:51:38 +02:00
connman . PushMessage ( pnode , NetMsgType : : DSEG , CTxIn ( ) ) ;
2016-10-20 23:11:30 +02:00
int64_t askAgain = GetTime ( ) + DSEG_UPDATE_SECONDS ;
2015-02-26 00:21:28 +01:00
mWeAskedForMasternodeList [ pnode - > addr ] = askAgain ;
2016-10-22 18:52:14 +02:00
LogPrint ( " masternode " , " CMasternodeMan::DsegUpdate -- asked %s for the list \n " , pnode - > addr . ToString ( ) ) ;
2015-02-26 00:21:28 +01:00
}
2017-09-11 16:13:48 +02:00
CMasternode * CMasternodeMan : : Find ( const COutPoint & outpoint )
2015-05-28 19:45:31 +02:00
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
auto it = mapMasternodes . find ( outpoint ) ;
return it = = mapMasternodes . end ( ) ? NULL : & ( it - > second ) ;
2015-05-28 19:45:31 +02:00
}
2017-09-11 16:13:48 +02:00
bool CMasternodeMan : : Get ( const COutPoint & outpoint , CMasternode & masternodeRet )
2016-09-05 01:44:10 +02:00
{
// Theses mutexes are recursive so double locking by the same thread is safe.
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
auto it = mapMasternodes . find ( outpoint ) ;
if ( it = = mapMasternodes . end ( ) ) {
2016-09-05 01:44:10 +02:00
return false ;
}
2017-09-11 16:13:48 +02:00
masternodeRet = it - > second ;
2016-09-05 01:44:10 +02:00
return true ;
}
2017-09-11 16:13:48 +02:00
bool CMasternodeMan : : GetMasternodeInfo ( const COutPoint & outpoint , masternode_info_t & mnInfoRet )
2016-09-15 08:49:24 +02:00
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
auto it = mapMasternodes . find ( outpoint ) ;
if ( it = = mapMasternodes . end ( ) ) {
2016-09-15 08:49:24 +02:00
return false ;
}
2017-09-11 16:13:48 +02:00
mnInfoRet = it - > second . GetInfo ( ) ;
2016-09-15 08:49:24 +02:00
return true ;
}
2017-09-11 16:13:48 +02:00
bool CMasternodeMan : : GetMasternodeInfo ( const CPubKey & pubKeyMasternode , masternode_info_t & mnInfoRet )
2016-10-17 20:54:28 +02:00
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
if ( mnpair . second . pubKeyMasternode = = pubKeyMasternode ) {
mnInfoRet = mnpair . second . GetInfo ( ) ;
return true ;
}
2016-10-17 20:54:28 +02:00
}
2017-09-11 16:13:48 +02:00
return false ;
2016-10-17 20:54:28 +02:00
}
2017-09-20 22:31:23 +02:00
bool CMasternodeMan : : GetMasternodeInfo ( const CScript & payee , masternode_info_t & mnInfoRet )
{
LOCK ( cs ) ;
for ( auto & mnpair : mapMasternodes ) {
CScript scriptCollateralAddress = GetScriptForDestination ( mnpair . second . pubKeyCollateralAddress . GetID ( ) ) ;
if ( scriptCollateralAddress = = payee ) {
mnInfoRet = mnpair . second . GetInfo ( ) ;
return true ;
}
}
return false ;
}
2017-09-11 16:13:48 +02:00
bool CMasternodeMan : : Has ( const COutPoint & outpoint )
2016-10-17 20:54:28 +02:00
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
return mapMasternodes . find ( outpoint ) ! = mapMasternodes . end ( ) ;
2016-10-17 20:54:28 +02:00
}
2016-10-22 18:52:14 +02:00
//
2015-07-22 05:07:23 +02:00
// Deterministically select the oldest/best masternode to pay on the network
//
2017-10-17 18:40:25 +02:00
bool CMasternodeMan : : GetNextMasternodeInQueueForPayment ( bool fFilterSigTime , int & nCountRet , masternode_info_t & mnInfoRet )
2016-11-28 15:21:50 +01:00
{
2017-10-17 18:40:25 +02:00
return GetNextMasternodeInQueueForPayment ( nCachedBlockHeight , fFilterSigTime , nCountRet , mnInfoRet ) ;
2016-11-28 15:21:50 +01:00
}
2017-10-17 18:40:25 +02:00
bool CMasternodeMan : : GetNextMasternodeInQueueForPayment ( int nBlockHeight , bool fFilterSigTime , int & nCountRet , masternode_info_t & mnInfoRet )
2015-02-26 00:21:28 +01:00
{
2017-09-11 16:13:48 +02:00
mnInfoRet = masternode_info_t ( ) ;
nCountRet = 0 ;
2017-08-25 14:57:05 +02:00
if ( ! masternodeSync . IsWinnersListSynced ( ) ) {
// without winner list we can't reliably find the next winner anyway
2017-09-11 16:13:48 +02:00
return false ;
2017-08-25 14:57:05 +02:00
}
2016-10-27 17:58:12 +02:00
// Need LOCK2 here to ensure consistent locking order because the GetBlockHash call below locks cs_main
LOCK2 ( cs_main , cs ) ;
2015-02-26 00:21:28 +01:00
2016-09-20 00:27:36 +02:00
std : : vector < std : : pair < int , CMasternode * > > vecMasternodeLastPaid ;
2015-07-22 05:07:23 +02:00
/*
Make a vector with all of the last paid times
*/
2015-03-01 16:38:53 +01:00
2017-09-14 15:58:29 +02:00
int nMnCount = CountMasternodes ( ) ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
if ( ! mnpair . second . IsValidForPayment ( ) ) continue ;
2015-02-26 00:21:28 +01:00
2017-07-03 15:14:07 +02:00
//check protocol version
2017-09-11 16:13:48 +02:00
if ( mnpair . second . nProtocolVersion < mnpayments . GetMinMasternodePaymentsProto ( ) ) continue ;
2015-06-25 21:59:11 +02:00
2015-07-23 15:45:43 +02:00
//it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it
2017-10-17 18:40:25 +02:00
if ( mnpayments . IsScheduled ( mnpair . second , nBlockHeight ) ) continue ;
2015-05-27 21:47:01 +02:00
2015-07-23 16:16:55 +02:00
//it's too new, wait for a cycle
2017-09-11 16:13:48 +02:00
if ( fFilterSigTime & & mnpair . second . sigTime + ( nMnCount * 2.6 * 60 ) > GetAdjustedTime ( ) ) continue ;
2015-07-23 16:16:55 +02:00
2016-10-22 18:52:14 +02:00
//make sure it has at least as many confirmations as there are masternodes
2017-09-11 16:13:48 +02:00
if ( GetUTXOConfirmations ( mnpair . first ) < nMnCount ) continue ;
2015-05-30 19:27:51 +02:00
2017-09-11 16:13:48 +02:00
vecMasternodeLastPaid . push_back ( std : : make_pair ( mnpair . second . GetLastPaidBlock ( ) , & mnpair . second ) ) ;
2015-02-26 00:21:28 +01:00
}
2017-09-11 16:13:48 +02:00
nCountRet = ( int ) vecMasternodeLastPaid . size ( ) ;
2015-08-20 18:27:34 +02:00
2015-08-20 17:36:44 +02:00
//when the network is in the process of upgrading, don't penalize nodes that recently restarted
2017-09-11 16:13:48 +02:00
if ( fFilterSigTime & & nCountRet < nMnCount / 3 )
2017-10-17 18:40:25 +02:00
return GetNextMasternodeInQueueForPayment ( nBlockHeight , false , nCountRet , mnInfoRet ) ;
2015-08-20 17:36:44 +02:00
2016-09-11 22:22:37 +02:00
// Sort them low to high
sort ( vecMasternodeLastPaid . begin ( ) , vecMasternodeLastPaid . end ( ) , CompareLastPaidBlock ( ) ) ;
2015-07-22 05:07:23 +02:00
2016-10-13 11:45:18 +02:00
uint256 blockHash ;
if ( ! GetBlockHash ( blockHash , nBlockHeight - 101 ) ) {
LogPrintf ( " CMasternode::GetNextMasternodeInQueueForPayment -- ERROR: GetBlockHash() failed at nBlockHeight %d \n " , nBlockHeight - 101 ) ;
2017-09-11 16:13:48 +02:00
return false ;
2016-10-13 11:45:18 +02:00
}
2015-07-22 05:07:23 +02:00
// Look at 1/10 of the oldest nodes (by last payment), calculate their scores and pay the best one
2015-07-23 15:45:43 +02:00
// -- This doesn't look at who is being paid in the +8-10 blocks, allowing for double payments very rarely
2015-07-30 18:00:28 +02:00
// -- 1/100 payments should be a double payment on mainnet - (1/(3000/10))*2
// -- (chance per block * chances before IsScheduled will fire)
2016-12-24 03:49:13 +01:00
int nTenthNetwork = nMnCount / 10 ;
2016-09-11 22:22:37 +02:00
int nCountTenth = 0 ;
2016-10-13 11:45:18 +02:00
arith_uint256 nHighest = 0 ;
2017-09-11 16:13:48 +02:00
CMasternode * pBestMasternode = NULL ;
2016-09-20 00:27:36 +02:00
BOOST_FOREACH ( PAIRTYPE ( int , CMasternode * ) & s , vecMasternodeLastPaid ) {
2016-10-13 11:45:18 +02:00
arith_uint256 nScore = s . second - > CalculateScore ( blockHash ) ;
if ( nScore > nHighest ) {
nHighest = nScore ;
2016-09-20 00:27:36 +02:00
pBestMasternode = s . second ;
2015-07-22 05:07:23 +02:00
}
2015-08-20 17:36:44 +02:00
nCountTenth + + ;
2015-08-20 17:50:29 +02:00
if ( nCountTenth > = nTenthNetwork ) break ;
2015-07-22 05:07:23 +02:00
}
2017-09-11 16:13:48 +02:00
if ( pBestMasternode ) {
mnInfoRet = pBestMasternode - > GetInfo ( ) ;
}
return mnInfoRet . fInfoValid ;
2015-02-26 00:21:28 +01:00
}
2017-09-11 16:13:48 +02:00
masternode_info_t CMasternodeMan : : FindRandomNotInVec ( const std : : vector < COutPoint > & vecToExclude , int nProtocolVersion )
2015-02-26 00:21:28 +01:00
{
LOCK ( cs ) ;
2016-07-29 07:29:41 +02:00
nProtocolVersion = nProtocolVersion = = - 1 ? mnpayments . GetMinMasternodePaymentsProto ( ) : nProtocolVersion ;
2015-07-29 17:11:43 +02:00
2016-07-29 07:29:41 +02:00
int nCountEnabled = CountEnabled ( nProtocolVersion ) ;
int nCountNotExcluded = nCountEnabled - vecToExclude . size ( ) ;
2015-07-29 17:11:43 +02:00
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeMan::FindRandomNotInVec -- %d enabled masternodes, %d masternodes to choose from \n " , nCountEnabled , nCountNotExcluded ) ;
2017-05-05 13:26:27 +02:00
if ( nCountNotExcluded < 1 ) return masternode_info_t ( ) ;
2015-02-26 00:21:28 +01:00
2016-09-20 00:27:36 +02:00
// fill a vector of pointers
std : : vector < CMasternode * > vpMasternodesShuffled ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
vpMasternodesShuffled . push_back ( & mnpair . second ) ;
2016-09-20 00:27:36 +02:00
}
2016-11-20 07:52:45 +01:00
InsecureRand insecureRand ;
2016-09-20 00:27:36 +02:00
// shuffle pointers
2016-11-20 07:52:45 +01:00
std : : random_shuffle ( vpMasternodesShuffled . begin ( ) , vpMasternodesShuffled . end ( ) , insecureRand ) ;
2016-07-29 07:29:41 +02:00
bool fExclude ;
2016-09-20 00:27:36 +02:00
// loop through
BOOST_FOREACH ( CMasternode * pmn , vpMasternodesShuffled ) {
if ( pmn - > nProtocolVersion < nProtocolVersion | | ! pmn - > IsEnabled ( ) ) continue ;
2016-07-29 07:29:41 +02:00
fExclude = false ;
2017-09-11 16:13:48 +02:00
BOOST_FOREACH ( const COutPoint & outpointToExclude , vecToExclude ) {
if ( pmn - > vin . prevout = = outpointToExclude ) {
2016-07-29 07:29:41 +02:00
fExclude = true ;
2015-07-29 17:11:43 +02:00
break ;
}
}
2016-07-29 07:29:41 +02:00
if ( fExclude ) continue ;
// found the one not in vecToExclude
2016-09-20 00:27:36 +02:00
LogPrint ( " masternode " , " CMasternodeMan::FindRandomNotInVec -- found, masternode=%s \n " , pmn - > vin . prevout . ToStringShort ( ) ) ;
2017-05-05 13:26:27 +02:00
return pmn - > GetInfo ( ) ;
2015-07-29 17:11:43 +02:00
}
2016-09-20 00:27:36 +02:00
LogPrint ( " masternode " , " CMasternodeMan::FindRandomNotInVec -- failed \n " ) ;
2017-05-05 13:26:27 +02:00
return masternode_info_t ( ) ;
2015-02-26 00:21:28 +01:00
}
2017-09-14 15:58:29 +02:00
bool CMasternodeMan : : GetMasternodeScores ( const uint256 & nBlockHash , CMasternodeMan : : score_pair_vec_t & vecMasternodeScoresRet , int nMinProtocol )
2015-02-23 21:01:21 +01:00
{
2017-09-14 15:58:29 +02:00
vecMasternodeScoresRet . clear ( ) ;
2015-02-23 21:01:21 +01:00
2017-09-14 15:58:29 +02:00
if ( ! masternodeSync . IsMasternodeListSynced ( ) )
return false ;
2015-03-23 13:59:22 +01:00
2017-09-14 15:58:29 +02:00
AssertLockHeld ( cs ) ;
if ( mapMasternodes . empty ( ) )
return false ;
2016-09-20 00:27:36 +02:00
2017-09-14 15:58:29 +02:00
// calculate scores
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
2017-09-14 15:58:29 +02:00
if ( mnpair . second . nProtocolVersion > = nMinProtocol ) {
vecMasternodeScoresRet . push_back ( std : : make_pair ( mnpair . second . CalculateScore ( nBlockHash ) , & mnpair . second ) ) ;
2016-11-23 16:30:36 +01:00
}
2017-09-14 15:58:29 +02:00
}
sort ( vecMasternodeScoresRet . rbegin ( ) , vecMasternodeScoresRet . rend ( ) , CompareScoreMN ( ) ) ;
return ! vecMasternodeScoresRet . empty ( ) ;
}
bool CMasternodeMan : : GetMasternodeRank ( const COutPoint & outpoint , int & nRankRet , int nBlockHeight , int nMinProtocol )
{
nRankRet = - 1 ;
if ( ! masternodeSync . IsMasternodeListSynced ( ) )
return false ;
2015-02-23 21:01:21 +01:00
2017-09-14 15:58:29 +02:00
// 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 ;
2015-02-23 21:01:21 +01:00
}
2017-09-14 15:58:29 +02:00
LOCK ( cs ) ;
score_pair_vec_t vecMasternodeScores ;
if ( ! GetMasternodeScores ( nBlockHash , vecMasternodeScores , nMinProtocol ) )
return false ;
2015-02-23 21:01:21 +01:00
2016-09-20 00:27:36 +02:00
int nRank = 0 ;
2017-09-14 15:58:29 +02:00
for ( auto & scorePair : vecMasternodeScores ) {
2016-09-20 00:27:36 +02:00
nRank + + ;
2017-09-14 15:58:29 +02:00
if ( scorePair . second - > vin . prevout = = outpoint ) {
nRankRet = nRank ;
return true ;
}
2015-02-23 21:01:21 +01:00
}
2017-09-14 15:58:29 +02:00
return false ;
2015-02-23 21:01:21 +01:00
}
2017-09-14 15:58:29 +02:00
bool CMasternodeMan : : GetMasternodeRanks ( CMasternodeMan : : rank_pair_vec_t & vecMasternodeRanksRet , int nBlockHeight , int nMinProtocol )
2015-03-14 19:34:51 +01:00
{
2017-09-14 15:58:29 +02:00
vecMasternodeRanksRet . clear ( ) ;
2016-09-20 00:27:36 +02:00
2017-09-14 15:58:29 +02:00
if ( ! masternodeSync . IsMasternodeListSynced ( ) )
return false ;
2015-03-14 19:34:51 +01:00
2017-09-14 15:58:29 +02:00
// 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 ;
2015-03-14 19:34:51 +01:00
}
2017-09-14 15:58:29 +02:00
LOCK ( cs ) ;
score_pair_vec_t vecMasternodeScores ;
if ( ! GetMasternodeScores ( nBlockHash , vecMasternodeScores , nMinProtocol ) )
return false ;
2015-03-14 19:34:51 +01:00
2016-09-20 00:27:36 +02:00
int nRank = 0 ;
2017-09-14 15:58:29 +02:00
for ( auto & scorePair : vecMasternodeScores ) {
2016-09-20 00:27:36 +02:00
nRank + + ;
2017-09-14 15:58:29 +02:00
vecMasternodeRanksRet . push_back ( std : : make_pair ( nRank , * scorePair . second ) ) ;
2015-03-14 19:34:51 +01:00
}
2017-09-14 15:58:29 +02:00
return true ;
2015-03-14 19:34:51 +01:00
}
2017-09-19 16:51:38 +02:00
void CMasternodeMan : : ProcessMasternodeConnections ( CConnman & connman )
2015-03-02 00:09:33 +01:00
{
2015-03-24 03:03:34 +01:00
//we don't care about this for regtest
2016-02-02 16:28:56 +01:00
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : REGTEST ) return ;
2015-03-06 23:17:51 +01:00
2017-09-19 16:51:38 +02:00
connman . ForEachNode ( CConnman : : AllNodes , [ ] ( CNode * pnode ) {
2017-12-01 19:53:34 +01:00
# ifdef ENABLE_WALLET
2017-12-04 07:06:07 +01:00
if ( pnode - > fMasternode & & ! privateSendClient . IsMixingMasternode ( pnode ) ) {
# else
if ( pnode - > fMasternode ) {
2017-12-01 19:53:34 +01:00
# endif // ENABLE_WALLET
2016-10-22 18:52:14 +02:00
LogPrintf ( " Closing Masternode connection: peer=%d, addr=%s \n " , pnode - > id , pnode - > addr . ToString ( ) ) ;
2016-07-30 13:05:41 +02:00
pnode - > fDisconnect = true ;
2015-03-02 00:09:33 +01:00
}
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
} ) ;
2015-03-02 00:09:33 +01:00
}
2017-01-31 16:29:27 +01:00
std : : pair < CService , std : : set < uint256 > > CMasternodeMan : : PopScheduledMnbRequestConnection ( )
2017-01-21 20:03:55 +01:00
{
LOCK ( cs ) ;
2017-01-31 16:29:27 +01:00
if ( listScheduledMnbRequestConnections . empty ( ) ) {
return std : : make_pair ( CService ( ) , std : : set < uint256 > ( ) ) ;
}
std : : set < uint256 > setResult ;
listScheduledMnbRequestConnections . sort ( ) ;
std : : pair < CService , uint256 > pairFront = listScheduledMnbRequestConnections . front ( ) ;
// squash hashes from requests with the same CService as the first one into setResult
std : : list < std : : pair < CService , uint256 > > : : iterator it = listScheduledMnbRequestConnections . begin ( ) ;
while ( it ! = listScheduledMnbRequestConnections . end ( ) ) {
if ( pairFront . first = = it - > first ) {
setResult . insert ( it - > second ) ;
it = listScheduledMnbRequestConnections . erase ( it ) ;
} else {
// since list is sorted now, we can be sure that there is no more hashes left
// to ask for from this addr
break ;
}
}
return std : : make_pair ( pairFront . first , setResult ) ;
2017-01-21 20:03:55 +01:00
}
2017-09-19 16:51:38 +02:00
void CMasternodeMan : : ProcessMessage ( CNode * pfrom , std : : string & strCommand , CDataStream & vRecv , CConnman & connman )
2015-02-23 21:01:21 +01:00
{
2016-10-22 18:52:14 +02:00
if ( fLiteMode ) return ; // disable all Dash specific functionality
2015-02-23 21:01:21 +01:00
2016-02-17 23:18:57 +01:00
if ( strCommand = = NetMsgType : : MNANNOUNCE ) { //Masternode Broadcast
2016-10-22 18:52:14 +02:00
2016-11-28 15:21:50 +01:00
CMasternodeBroadcast mnb ;
vRecv > > mnb ;
2015-02-23 21:01:21 +01:00
2017-01-17 21:02:59 +01:00
pfrom - > setAskFor . erase ( mnb . GetHash ( ) ) ;
2017-11-22 15:27:06 +01:00
if ( ! masternodeSync . IsBlockchainSynced ( ) ) return ;
2016-12-24 03:49:13 +01:00
LogPrint ( " masternode " , " MNANNOUNCE -- Masternode announce, masternode=%s \n " , mnb . vin . prevout . ToStringShort ( ) ) ;
2016-11-28 15:21:50 +01:00
int nDos = 0 ;
2015-02-23 21:01:21 +01:00
2017-09-19 16:51:38 +02:00
if ( CheckMnbAndUpdateMasternodeList ( pfrom , mnb , nDos , connman ) ) {
2016-11-28 15:21:50 +01:00
// use announced Masternode as a peer
2017-09-19 16:51:38 +02:00
connman . AddNewAddress ( CAddress ( mnb . addr , NODE_NETWORK ) , pfrom - > addr , 2 * 60 * 60 ) ;
2016-11-28 15:21:50 +01:00
} else if ( nDos > 0 ) {
Misbehaving ( pfrom - > GetId ( ) , nDos ) ;
2016-11-13 18:52:34 +01:00
}
2016-11-28 15:21:50 +01:00
2016-11-13 18:52:34 +01:00
if ( fMasternodesAdded ) {
2017-09-19 16:51:38 +02:00
NotifyMasternodeUpdates ( connman ) ;
2016-11-13 18:52:34 +01:00
}
2016-08-29 21:11:34 +02:00
} else if ( strCommand = = NetMsgType : : MNPING ) { //Masternode Ping
2015-04-17 17:10:38 +02:00
CMasternodePing mnp ;
vRecv > > mnp ;
2015-02-23 21:01:21 +01:00
2017-01-17 21:02:59 +01:00
uint256 nHash = mnp . GetHash ( ) ;
pfrom - > setAskFor . erase ( nHash ) ;
2017-11-22 15:27:06 +01:00
if ( ! masternodeSync . IsBlockchainSynced ( ) ) return ;
2016-10-22 18:52:14 +02:00
LogPrint ( " masternode " , " MNPING -- Masternode ping, masternode=%s \n " , mnp . vin . prevout . ToStringShort ( ) ) ;
2015-07-14 07:25:07 +02:00
2016-11-28 15:21:50 +01:00
// Need LOCK2 here to ensure consistent locking order because the CheckAndUpdate call below locks cs_main
LOCK2 ( cs_main , cs ) ;
2016-10-30 20:40:30 +01:00
2017-01-17 21:02:59 +01:00
if ( mapSeenMasternodePing . count ( nHash ) ) return ; //seen
mapSeenMasternodePing . insert ( std : : make_pair ( nHash , mnp ) ) ;
2015-02-23 21:01:21 +01:00
2016-10-22 18:52:14 +02:00
LogPrint ( " masternode " , " MNPING -- Masternode ping, masternode=%s new \n " , mnp . vin . prevout . ToStringShort ( ) ) ;
2016-02-17 19:53:55 +01:00
2016-12-24 03:49:13 +01:00
// see if we have this Masternode
2017-09-11 16:13:48 +02:00
CMasternode * pmn = Find ( mnp . vin . prevout ) ;
2016-12-24 03:49:13 +01:00
2017-07-04 19:31:57 +02:00
// if masternode uses sentinel ping instead of watchdog
// we shoud update nTimeLastWatchdogVote here if sentinel
// ping flag is actual
if ( pmn & & mnp . fSentinelIsCurrent )
2017-10-12 14:05:17 +02:00
UpdateWatchdogVoteTime ( mnp . vin . prevout , mnp . sigTime ) ;
2017-07-04 19:31:57 +02:00
2016-12-24 03:49:13 +01:00
// too late, new MNANNOUNCE is required
if ( pmn & & pmn - > IsNewStartRequired ( ) ) return ;
2016-03-15 00:16:29 +01:00
int nDos = 0 ;
2017-09-19 16:51:38 +02:00
if ( mnp . CheckAndUpdate ( pmn , false , nDos , connman ) ) return ;
2015-07-14 07:25:07 +02:00
2016-03-15 00:16:29 +01:00
if ( nDos > 0 ) {
2015-08-07 05:07:40 +02:00
// if anything significant failed, mark that node
2016-03-15 00:16:29 +01:00
Misbehaving ( pfrom - > GetId ( ) , nDos ) ;
2016-12-24 03:49:13 +01:00
} else if ( pmn ! = NULL ) {
// nothing significant failed, mn is a known one too
return ;
2015-02-23 21:01:21 +01:00
}
2015-08-07 05:07:40 +02:00
// something significant is broken or mn is unknown,
// we might have to ask for a masternode entry once
2017-09-19 16:51:38 +02:00
AskForMN ( pfrom , mnp . vin . prevout , connman ) ;
2015-02-23 21:01:21 +01:00
2016-02-17 23:18:57 +01:00
} else if ( strCommand = = NetMsgType : : DSEG ) { //Get Masternode list or specific entry
2016-08-29 21:11:34 +02:00
// Ignore such requests until we are fully synced.
// We could start processing this after masternode list is synced
// but this is a heavy one so it's better to finish sync first.
2016-08-05 18:25:03 +02:00
if ( ! masternodeSync . IsSynced ( ) ) return ;
2015-02-23 21:01:21 +01:00
CTxIn vin ;
vRecv > > vin ;
2016-10-22 18:52:14 +02:00
LogPrint ( " masternode " , " DSEG -- Masternode list, masternode=%s \n " , vin . prevout . ToStringShort ( ) ) ;
2016-02-17 19:53:55 +01:00
2016-10-30 20:40:30 +01:00
LOCK ( cs ) ;
2015-02-23 21:01:21 +01:00
if ( vin = = CTxIn ( ) ) { //only should ask for this once
//local network
2015-07-02 17:07:30 +02:00
bool isLocal = ( pfrom - > addr . IsRFC1918 ( ) | | pfrom - > addr . IsLocal ( ) ) ;
2016-02-02 16:28:56 +01:00
if ( ! isLocal & & Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : MAIN ) {
2017-07-03 15:14:07 +02:00
std : : map < CNetAddr , int64_t > : : iterator it = mAskedUsForMasternodeList . find ( pfrom - > addr ) ;
if ( it ! = mAskedUsForMasternodeList . end ( ) & & it - > second > GetTime ( ) ) {
Misbehaving ( pfrom - > GetId ( ) , 34 ) ;
LogPrintf ( " DSEG -- peer already asked me for the list, peer=%d \n " , pfrom - > id ) ;
return ;
2015-02-23 21:01:21 +01:00
}
2016-10-20 23:11:30 +02:00
int64_t askAgain = GetTime ( ) + DSEG_UPDATE_SECONDS ;
2015-02-26 00:21:28 +01:00
mAskedUsForMasternodeList [ pfrom - > addr ] = askAgain ;
2015-02-23 21:01:21 +01:00
}
} //else, asking for a specific node which is ok
2015-08-31 06:05:10 +02:00
int nInvCount = 0 ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
if ( vin ! = CTxIn ( ) & & vin ! = mnpair . second . vin ) continue ; // asked for specific vin but we are not there yet
if ( mnpair . second . addr . IsRFC1918 ( ) | | mnpair . second . addr . IsLocal ( ) ) continue ; // do not send local network masternode
if ( mnpair . second . IsUpdateRequired ( ) ) continue ; // do not send outdated masternodes
2016-09-15 15:30:51 +02:00
2017-09-11 16:13:48 +02:00
LogPrint ( " masternode " , " DSEG -- Sending Masternode entry: masternode=%s addr=%s \n " , mnpair . first . ToStringShort ( ) , mnpair . second . addr . ToString ( ) ) ;
CMasternodeBroadcast mnb = CMasternodeBroadcast ( mnpair . second ) ;
2017-12-13 13:42:37 +01:00
CMasternodePing mnp = mnpair . second . lastPing ;
uint256 hashMNB = mnb . GetHash ( ) ;
uint256 hashMNP = mnp . GetHash ( ) ;
pfrom - > PushInventory ( CInv ( MSG_MASTERNODE_ANNOUNCE , hashMNB ) ) ;
pfrom - > PushInventory ( CInv ( MSG_MASTERNODE_PING , hashMNP ) ) ;
2016-09-15 15:30:51 +02:00
nInvCount + + ;
2017-12-13 13:42:37 +01:00
mapSeenMasternodeBroadcast . insert ( std : : make_pair ( hashMNB , std : : make_pair ( GetTime ( ) , mnb ) ) ) ;
mapSeenMasternodePing . insert ( std : : make_pair ( hashMNP , mnp ) ) ;
2015-08-26 02:18:01 +02:00
2017-09-11 16:13:48 +02:00
if ( vin . prevout = = mnpair . first ) {
2016-10-22 18:52:14 +02:00
LogPrintf ( " DSEG -- Sent 1 Masternode inv to peer %d \n " , pfrom - > id ) ;
2016-09-15 15:30:51 +02:00
return ;
2015-02-23 21:01:21 +01:00
}
}
2015-07-29 06:16:11 +02:00
2015-08-31 06:05:10 +02:00
if ( vin = = CTxIn ( ) ) {
2017-09-19 16:51:38 +02:00
connman . PushMessage ( pfrom , NetMsgType : : SYNCSTATUSCOUNT , MASTERNODE_SYNC_LIST , nInvCount ) ;
2016-10-22 18:52:14 +02:00
LogPrintf ( " DSEG -- Sent %d Masternode invs to peer %d \n " , nInvCount , pfrom - > id ) ;
2016-09-15 15:30:51 +02:00
return ;
2015-08-31 06:05:10 +02:00
}
2016-09-15 15:30:51 +02:00
// smth weird happen - someone asked us for vin we have no idea about?
2016-10-22 18:52:14 +02:00
LogPrint ( " masternode " , " DSEG -- No invs sent to peer %d \n " , pfrom - > id ) ;
2016-10-20 23:11:30 +02:00
} else if ( strCommand = = NetMsgType : : MNVERIFY ) { // Masternode Verify
2016-11-30 01:48:05 +01:00
// Need LOCK2 here to ensure consistent locking order because the all functions below call GetBlockHash which locks cs_main
LOCK2 ( cs_main , cs ) ;
2016-11-13 18:52:34 +01:00
2016-10-20 23:11:30 +02:00
CMasternodeVerification mnv ;
vRecv > > mnv ;
2017-11-22 15:27:06 +01:00
pfrom - > setAskFor . erase ( mnv . GetHash ( ) ) ;
if ( ! masternodeSync . IsMasternodeListSynced ( ) ) return ;
2016-10-20 23:11:30 +02:00
if ( mnv . vchSig1 . empty ( ) ) {
// CASE 1: someone asked me to verify myself /IP we are using/
2017-09-19 16:51:38 +02:00
SendVerifyReply ( pfrom , mnv , connman ) ;
2016-10-20 23:11:30 +02:00
} 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 ) ;
}
}
}
2016-10-22 18:52:14 +02:00
// Verification of masternodes via unique direct requests.
2017-09-19 16:51:38 +02:00
void CMasternodeMan : : DoFullVerificationStep ( CConnman & connman )
2016-10-20 23:11:30 +02:00
{
2017-09-11 16:13:48 +02:00
if ( activeMasternode . outpoint = = COutPoint ( ) ) return ;
2017-01-14 23:29:08 +01:00
if ( ! masternodeSync . IsSynced ( ) ) return ;
2016-10-20 23:11:30 +02:00
2017-09-14 15:58:29 +02:00
rank_pair_vec_t vecMasternodeRanks ;
GetMasternodeRanks ( vecMasternodeRanks , nCachedBlockHeight - 1 , MIN_POSE_PROTO_VERSION ) ;
2016-10-20 23:11:30 +02:00
2016-11-28 15:21:50 +01:00
// Need LOCK2 here to ensure consistent locking order because the SendVerifyRequest call below locks cs_main
// through GetHeight() signal in ConnectNode
LOCK2 ( cs_main , cs ) ;
2016-10-20 23:11:30 +02:00
int nCount = 0 ;
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 ;
}
2017-09-11 16:13:48 +02:00
if ( it - > second . vin . prevout = = activeMasternode . outpoint ) {
2016-10-20 23:11:30 +02:00
nMyRank = it - > first ;
LogPrint ( " masternode " , " CMasternodeMan::DoFullVerificationStep -- Found self at rank %d/%d, verifying up to %d masternodes \n " ,
2017-02-17 21:08:29 +01:00
nMyRank , nRanksTotal , ( int ) MAX_POSE_CONNECTIONS ) ;
2016-10-20 23:11:30 +02:00
break ;
}
+ + it ;
}
// edge case: list is too short and this masternode is not enabled
if ( nMyRank = = - 1 ) return ;
2017-02-17 21:08:29 +01:00
// send verify requests to up to MAX_POSE_CONNECTIONS masternodes
// starting from MAX_POSE_RANK + nMyRank and using MAX_POSE_CONNECTIONS as a step
int nOffset = MAX_POSE_RANK + nMyRank - 1 ;
2016-10-20 23:11:30 +02:00
if ( nOffset > = ( int ) vecMasternodeRanks . size ( ) ) return ;
std : : vector < CMasternode * > vSortedByAddr ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
vSortedByAddr . push_back ( & mnpair . second ) ;
2016-10-20 23:11:30 +02:00
}
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 ( ) ) ;
2017-02-17 21:08:29 +01:00
nOffset + = MAX_POSE_CONNECTIONS ;
if ( nOffset > = ( int ) vecMasternodeRanks . size ( ) ) break ;
it + = MAX_POSE_CONNECTIONS ;
2016-10-20 23:11:30 +02:00
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 ( ) ) ;
2017-09-19 16:51:38 +02:00
if ( SendVerifyRequest ( CAddress ( it - > second . addr , NODE_NETWORK ) , vSortedByAddr , connman ) ) {
2016-10-20 23:11:30 +02:00
nCount + + ;
2017-02-17 21:08:29 +01:00
if ( nCount > = MAX_POSE_CONNECTIONS ) break ;
2016-10-20 23:11:30 +02:00
}
2017-02-17 21:08:29 +01:00
nOffset + = MAX_POSE_CONNECTIONS ;
if ( nOffset > = ( int ) vecMasternodeRanks . size ( ) ) break ;
it + = MAX_POSE_CONNECTIONS ;
2016-10-20 23:11:30 +02:00
}
LogPrint ( " masternode " , " CMasternodeMan::DoFullVerificationStep -- Sent verification requests to %d masternodes \n " , nCount ) ;
}
2016-10-22 18:52:14 +02:00
// This function tries to find masternodes with the same addr,
// find a verified one and ban all the other. If there are many nodes
// with the same addr but none of them is verified yet, then none of them are banned.
// It could take many times to run this before most of the duplicate nodes are banned.
2016-10-20 23:11:30 +02:00
void CMasternodeMan : : CheckSameAddr ( )
{
2017-09-11 16:13:48 +02:00
if ( ! masternodeSync . IsSynced ( ) | | mapMasternodes . empty ( ) ) return ;
2016-10-20 23:11:30 +02:00
std : : vector < CMasternode * > vBan ;
std : : vector < CMasternode * > vSortedByAddr ;
{
LOCK ( cs ) ;
CMasternode * pprevMasternode = NULL ;
CMasternode * pverifiedMasternode = NULL ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
vSortedByAddr . push_back ( & mnpair . second ) ;
2016-10-20 23:11:30 +02:00
}
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 ) {
2016-10-30 21:56:47 +01:00
LogPrintf ( " CMasternodeMan::CheckSameAddr -- increasing PoSe ban score for masternode %s \n " , pmn - > vin . prevout . ToStringShort ( ) ) ;
pmn - > IncreasePoSeBanScore ( ) ;
2016-10-20 23:11:30 +02:00
}
}
2017-09-19 16:51:38 +02:00
bool CMasternodeMan : : SendVerifyRequest ( const CAddress & addr , const std : : vector < CMasternode * > & vSortedByAddr , CConnman & connman )
2016-10-20 23:11:30 +02:00
{
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 ;
}
2017-09-19 16:51:38 +02:00
CNode * pnode = connman . ConnectNode ( addr , NULL , true ) ;
2016-12-11 07:18:52 +01:00
if ( pnode = = NULL ) {
LogPrintf ( " CMasternodeMan::SendVerifyRequest -- can't connect to node to verify it, addr=%s \n " , addr . ToString ( ) ) ;
2016-10-20 23:11:30 +02:00
return false ;
}
2016-12-11 07:18:52 +01:00
netfulfilledman . AddFulfilledRequest ( addr , strprintf ( " %s " , NetMsgType : : MNVERIFY ) + " -request " ) ;
// use random nonce, store it and require node to reply with correct one later
2017-08-25 14:57:05 +02:00
CMasternodeVerification mnv ( addr , GetRandInt ( 999999 ) , nCachedBlockHeight - 1 ) ;
2016-12-11 07:18:52 +01:00
mWeAskedForVerification [ addr ] = mnv ;
LogPrintf ( " CMasternodeMan::SendVerifyRequest -- verifying node using nonce %d addr=%s \n " , mnv . nonce , addr . ToString ( ) ) ;
2017-09-19 16:51:38 +02:00
connman . PushMessage ( pnode , NetMsgType : : MNVERIFY , mnv ) ;
2016-12-11 07:18:52 +01:00
return true ;
2016-10-20 23:11:30 +02:00
}
2017-09-19 16:51:38 +02:00
void CMasternodeMan : : SendVerifyReply ( CNode * pnode , CMasternodeVerification & mnv , CConnman & connman )
2016-10-20 23:11:30 +02:00
{
// 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 ( ) ) ;
2017-04-12 09:04:06 +02:00
if ( ! CMessageSigner : : SignMessage ( strMessage , mnv . vchSig1 , activeMasternode . keyMasternode ) ) {
2016-10-20 23:11:30 +02:00
LogPrintf ( " MasternodeMan::SendVerifyReply -- SignMessage() failed \n " ) ;
return ;
}
std : : string strError ;
2017-04-12 09:04:06 +02:00
if ( ! CMessageSigner : : VerifyMessage ( activeMasternode . pubKeyMasternode , mnv . vchSig1 , strMessage , strError ) ) {
2016-10-20 23:11:30 +02:00
LogPrintf ( " MasternodeMan::SendVerifyReply -- VerifyMessage() failed, error: %s \n " , strError ) ;
return ;
}
2017-09-19 16:51:38 +02:00
connman . PushMessage ( pnode , NetMsgType : : MNVERIFY , mnv ) ;
2016-10-20 23:11:30 +02:00
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 : : string strMessage1 = strprintf ( " %s%d%s " , pnode - > addr . ToString ( false ) , mnv . nonce , blockHash . ToString ( ) ) ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
if ( CAddress ( mnpair . second . addr , NODE_NETWORK ) = = pnode - > addr ) {
if ( CMessageSigner : : VerifyMessage ( mnpair . second . pubKeyMasternode , mnv . vchSig1 , strMessage1 , strError ) ) {
2016-10-20 23:11:30 +02:00
// found it!
2017-09-11 16:13:48 +02:00
prealMasternode = & mnpair . second ;
if ( ! mnpair . second . IsPoSeVerified ( ) ) {
mnpair . second . DecreasePoSeBanScore ( ) ;
2016-10-20 23:11:30 +02:00
}
netfulfilledman . AddFulfilledRequest ( pnode - > addr , strprintf ( " %s " , NetMsgType : : MNVERIFY ) + " -done " ) ;
// we can only broadcast it if we are an activated masternode
2017-09-11 16:13:48 +02:00
if ( activeMasternode . outpoint = = COutPoint ( ) ) continue ;
2016-10-20 23:11:30 +02:00
// update ...
2017-09-11 16:13:48 +02:00
mnv . addr = mnpair . second . addr ;
mnv . vin1 = mnpair . second . vin ;
mnv . vin2 = CTxIn ( activeMasternode . outpoint ) ;
2016-10-20 23:11:30 +02:00
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
2017-04-12 09:04:06 +02:00
if ( ! CMessageSigner : : SignMessage ( strMessage2 , mnv . vchSig2 , activeMasternode . keyMasternode ) ) {
2016-10-20 23:11:30 +02:00
LogPrintf ( " MasternodeMan::ProcessVerifyReply -- SignMessage() failed \n " ) ;
return ;
}
std : : string strError ;
2017-04-12 09:04:06 +02:00
if ( ! CMessageSigner : : VerifyMessage ( activeMasternode . pubKeyMasternode , mnv . vchSig2 , strMessage2 , strError ) ) {
2016-10-20 23:11:30 +02:00
LogPrintf ( " MasternodeMan::ProcessVerifyReply -- VerifyMessage() failed, error: %s \n " , strError ) ;
return ;
}
mWeAskedForVerification [ pnode - > addr ] = mnv ;
2017-12-13 13:42:37 +01:00
mapSeenMasternodeVerification . insert ( std : : make_pair ( mnv . GetHash ( ) , mnv ) ) ;
2016-10-20 23:11:30 +02:00
mnv . Relay ( ) ;
} else {
2017-09-11 16:13:48 +02:00
vpMasternodesToBan . push_back ( & mnpair . second ) ;
2016-10-20 23:11:30 +02:00
}
}
}
// 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 ) {
2016-10-30 21:56:47 +01:00
pmn - > IncreasePoSeBanScore ( ) ;
2016-10-20 23:11:30 +02:00
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 ) ;
}
2016-11-30 02:33:47 +01:00
LogPrintf ( " CMasternodeMan::ProcessVerifyBroadcast -- PoSe score increased for %d fake masternodes, addr %s \n " ,
2016-10-20 23:11:30 +02:00
( 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
2017-08-25 14:57:05 +02:00
if ( mnv . nBlockHeight < nCachedBlockHeight - MAX_POSE_BLOCKS ) {
2017-06-06 01:47:23 +02:00
LogPrint ( " masternode " , " CMasternodeMan::ProcessVerifyBroadcast -- Outdated: current block %d, verification block %d, peer=%d \n " ,
2017-08-25 14:57:05 +02:00
nCachedBlockHeight , mnv . nBlockHeight , pnode - > id ) ;
2016-10-20 23:11:30 +02:00
return ;
}
if ( mnv . vin1 . prevout = = mnv . vin2 . prevout ) {
2017-06-06 01:47:23 +02:00
LogPrint ( " masternode " , " CMasternodeMan::ProcessVerifyBroadcast -- ERROR: same vins %s, peer=%d \n " ,
2016-10-20 23:11:30 +02:00
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...
2017-06-06 01:47:23 +02:00
LogPrintf ( " CMasternodeMan::ProcessVerifyBroadcast -- Can't get block hash for unknown block height %d, peer=%d \n " , mnv . nBlockHeight , pnode - > id ) ;
2016-10-20 23:11:30 +02:00
return ;
}
2017-09-14 15:58:29 +02:00
int nRank ;
2017-04-01 19:40:28 +02:00
2017-09-14 15:58:29 +02:00
if ( ! GetMasternodeRank ( mnv . vin2 . prevout , nRank , mnv . nBlockHeight , MIN_POSE_PROTO_VERSION ) ) {
2017-04-01 19:40:28 +02:00
LogPrint ( " masternode " , " CMasternodeMan::ProcessVerifyBroadcast -- Can't calculate rank for masternode %s \n " ,
mnv . vin2 . prevout . ToStringShort ( ) ) ;
return ;
}
if ( nRank > MAX_POSE_RANK ) {
2017-06-06 01:47:23 +02:00
LogPrint ( " masternode " , " CMasternodeMan::ProcessVerifyBroadcast -- Masternode %s is not in top %d, current rank %d, peer=%d \n " ,
2017-04-01 19:40:28 +02:00
mnv . vin2 . prevout . ToStringShort ( ) , ( int ) MAX_POSE_RANK , nRank , pnode - > id ) ;
2016-10-20 23:11:30 +02:00
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 ( ) ) ;
2017-09-11 16:13:48 +02:00
CMasternode * pmn1 = Find ( mnv . vin1 . prevout ) ;
2016-10-20 23:11:30 +02:00
if ( ! pmn1 ) {
LogPrintf ( " CMasternodeMan::ProcessVerifyBroadcast -- can't find masternode1 %s \n " , mnv . vin1 . prevout . ToStringShort ( ) ) ;
return ;
}
2017-09-11 16:13:48 +02:00
CMasternode * pmn2 = Find ( mnv . vin2 . prevout ) ;
2016-10-20 23:11:30 +02:00
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 ;
}
2017-04-12 09:04:06 +02:00
if ( CMessageSigner : : VerifyMessage ( pmn1 - > pubKeyMasternode , mnv . vchSig1 , strMessage1 , strError ) ) {
2017-06-06 01:47:23 +02:00
LogPrintf ( " CMasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode1 failed, error: %s \n " , strError ) ;
2016-10-20 23:11:30 +02:00
return ;
}
2017-04-12 09:04:06 +02:00
if ( CMessageSigner : : VerifyMessage ( pmn2 - > pubKeyMasternode , mnv . vchSig2 , strMessage2 , strError ) ) {
2017-06-06 01:47:23 +02:00
LogPrintf ( " CMasternodeMan::ProcessVerifyBroadcast -- VerifyMessage() for masternode2 failed, error: %s \n " , strError ) ;
2016-10-20 23:11:30 +02:00
return ;
}
if ( ! pmn1 - > IsPoSeVerified ( ) ) {
2016-10-30 21:56:47 +01:00
pmn1 - > DecreasePoSeBanScore ( ) ;
2016-10-20 23:11:30 +02:00
}
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 ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
if ( mnpair . second . addr ! = mnv . addr | | mnpair . first = = mnv . vin1 . prevout ) continue ;
mnpair . second . IncreasePoSeBanScore ( ) ;
2016-10-20 23:11:30 +02:00
nCount + + ;
LogPrint ( " masternode " , " CMasternodeMan::ProcessVerifyBroadcast -- increased PoSe ban score for %s addr %s, new score %d \n " ,
2017-09-11 16:13:48 +02:00
mnpair . first . ToStringShort ( ) , mnpair . second . addr . ToString ( ) , mnpair . second . nPoSeBanScore ) ;
2016-10-20 23:11:30 +02:00
}
LogPrintf ( " CMasternodeMan::ProcessVerifyBroadcast -- PoSe score incresed for %d fake masternodes, addr %s \n " ,
nCount , pnode - > addr . ToString ( ) ) ;
2015-08-09 15:06:54 +02:00
}
2015-02-23 21:01:21 +01:00
}
2015-03-01 00:56:52 +01:00
2015-03-05 00:46:50 +01:00
std : : string CMasternodeMan : : ToString ( ) const
2015-03-01 00:56:52 +01:00
{
std : : ostringstream info ;
2017-09-11 16:13:48 +02:00
info < < " Masternodes: " < < ( int ) mapMasternodes . size ( ) < <
2015-03-05 09:10:15 +01:00
" , peers who asked us for Masternode list: " < < ( int ) mAskedUsForMasternodeList . size ( ) < <
" , peers we asked for Masternode list: " < < ( int ) mWeAskedForMasternodeList . size ( ) < <
2015-03-06 18:25:48 +01:00
" , entries in Masternode list we asked for: " < < ( int ) mWeAskedForMasternodeListEntry . size ( ) < <
" , nDsqCount: " < < ( int ) nDsqCount ;
2015-03-01 00:56:52 +01:00
return info . str ( ) ;
}
2016-02-04 20:29:09 +01:00
2017-09-19 16:51:38 +02:00
void CMasternodeMan : : UpdateMasternodeList ( CMasternodeBroadcast mnb , CConnman & connman )
2016-10-22 18:52:14 +02:00
{
2017-07-17 15:59:04 +02:00
LOCK2 ( cs_main , cs ) ;
2016-10-22 18:52:14 +02:00
mapSeenMasternodePing . insert ( std : : make_pair ( mnb . lastPing . GetHash ( ) , mnb . lastPing ) ) ;
2016-12-26 07:44:36 +01:00
mapSeenMasternodeBroadcast . insert ( std : : make_pair ( mnb . GetHash ( ) , std : : make_pair ( GetTime ( ) , mnb ) ) ) ;
2016-03-16 16:30:22 +01:00
2016-10-22 18:52:14 +02:00
LogPrintf ( " CMasternodeMan::UpdateMasternodeList -- masternode=%s addr=%s \n " , mnb . vin . prevout . ToStringShort ( ) , mnb . addr . ToString ( ) ) ;
2016-03-16 16:30:22 +01:00
2017-09-11 16:13:48 +02:00
CMasternode * pmn = Find ( mnb . vin . prevout ) ;
2016-10-22 18:52:14 +02:00
if ( pmn = = NULL ) {
2017-08-09 18:07:03 +02:00
if ( Add ( mnb ) ) {
masternodeSync . BumpAssetLastTime ( " CMasternodeMan::UpdateMasternodeList - new " ) ;
2016-09-29 22:23:02 +02:00
}
2016-12-24 03:49:13 +01:00
} else {
2016-12-26 07:44:36 +01:00
CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast [ CMasternodeBroadcast ( * pmn ) . GetHash ( ) ] . second ;
2017-09-19 16:51:38 +02:00
if ( pmn - > UpdateFromNewBroadcast ( mnb , connman ) ) {
2017-08-09 18:07:03 +02:00
masternodeSync . BumpAssetLastTime ( " CMasternodeMan::UpdateMasternodeList - seen " ) ;
2016-12-24 03:49:13 +01:00
mapSeenMasternodeBroadcast . erase ( mnbOld . GetHash ( ) ) ;
}
2016-03-16 16:30:22 +01:00
}
}
2016-03-18 00:37:48 +01:00
2017-09-19 16:51:38 +02:00
bool CMasternodeMan : : CheckMnbAndUpdateMasternodeList ( CNode * pfrom , CMasternodeBroadcast mnb , int & nDos , CConnman & connman )
2016-10-20 23:11:30 +02:00
{
2017-07-21 17:21:09 +02:00
// Need to lock cs_main here to ensure consistent locking order because the SimpleCheck call below locks cs_main
LOCK ( cs_main ) ;
2016-10-20 23:11:30 +02:00
2017-07-21 17:21:09 +02:00
{
LOCK ( cs ) ;
nDos = 0 ;
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s \n " , mnb . vin . prevout . ToStringShort ( ) ) ;
uint256 hash = mnb . GetHash ( ) ;
if ( mapSeenMasternodeBroadcast . count ( hash ) & & ! mnb . fRecovery ) { //seen
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen \n " , mnb . vin . prevout . ToStringShort ( ) ) ;
// less then 2 pings left before this MN goes into non-recoverable state, bump sync timeout
if ( GetTime ( ) - mapSeenMasternodeBroadcast [ hash ] . first > MASTERNODE_NEW_START_REQUIRED_SECONDS - MASTERNODE_MIN_MNP_SECONDS * 2 ) {
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen update \n " , mnb . vin . prevout . ToStringShort ( ) ) ;
mapSeenMasternodeBroadcast [ hash ] . first = GetTime ( ) ;
2017-08-09 18:07:03 +02:00
masternodeSync . BumpAssetLastTime ( " CMasternodeMan::CheckMnbAndUpdateMasternodeList - seen " ) ;
2017-07-21 17:21:09 +02:00
}
// did we ask this node for it?
if ( pfrom & & IsMnbRecoveryRequested ( hash ) & & GetTime ( ) < mMnbRecoveryRequests [ hash ] . first ) {
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request \n " , hash . ToString ( ) ) ;
if ( mMnbRecoveryRequests [ hash ] . second . count ( pfrom - > addr ) ) {
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s \n " , hash . ToString ( ) , pfrom - > addr . ToString ( ) ) ;
// do not allow node to send same mnb multiple times in recovery mode
mMnbRecoveryRequests [ hash ] . second . erase ( pfrom - > addr ) ;
// does it have newer lastPing?
if ( mnb . lastPing . sigTime > mapSeenMasternodeBroadcast [ hash ] . second . lastPing . sigTime ) {
// simulate Check
CMasternode mnTemp = CMasternode ( mnb ) ;
mnTemp . Check ( ) ;
2017-08-29 01:51:44 +02:00
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- mnb=%s seen request, addr=%s, better lastPing: %d min ago, projected mn state: %s \n " , hash . ToString ( ) , pfrom - > addr . ToString ( ) , ( GetAdjustedTime ( ) - mnb . lastPing . sigTime ) / 60 , mnTemp . GetStateString ( ) ) ;
2017-07-21 17:21:09 +02:00
if ( mnTemp . IsValidStateForAutoStart ( mnTemp . nActiveState ) ) {
// this node thinks it's a good one
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s seen good \n " , mnb . vin . prevout . ToStringShort ( ) ) ;
mMnbRecoveryGoodReplies [ hash ] . push_back ( mnb ) ;
}
2017-01-01 18:48:53 +01:00
}
}
}
2017-07-21 17:21:09 +02:00
return true ;
2017-01-01 18:48:53 +01:00
}
2017-07-21 17:21:09 +02:00
mapSeenMasternodeBroadcast . insert ( std : : make_pair ( hash , std : : make_pair ( GetTime ( ) , mnb ) ) ) ;
2016-03-18 00:37:48 +01:00
2017-07-21 17:21:09 +02:00
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- masternode=%s new \n " , mnb . vin . prevout . ToStringShort ( ) ) ;
2016-03-18 00:37:48 +01:00
2017-07-21 17:21:09 +02:00
if ( ! mnb . SimpleCheck ( nDos ) ) {
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- SimpleCheck() failed, masternode=%s \n " , mnb . vin . prevout . ToStringShort ( ) ) ;
2016-10-20 23:11:30 +02:00
return false ;
}
2017-07-21 17:21:09 +02:00
// search Masternode list
2017-09-11 16:13:48 +02:00
CMasternode * pmn = Find ( mnb . vin . prevout ) ;
2017-07-21 17:21:09 +02:00
if ( pmn ) {
CMasternodeBroadcast mnbOld = mapSeenMasternodeBroadcast [ CMasternodeBroadcast ( * pmn ) . GetHash ( ) ] . second ;
2017-09-19 16:51:38 +02:00
if ( ! mnb . Update ( pmn , nDos , connman ) ) {
2017-07-21 17:21:09 +02:00
LogPrint ( " masternode " , " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Update() failed, masternode=%s \n " , mnb . vin . prevout . ToStringShort ( ) ) ;
return false ;
}
if ( hash ! = mnbOld . GetHash ( ) ) {
mapSeenMasternodeBroadcast . erase ( mnbOld . GetHash ( ) ) ;
}
return true ;
2016-12-24 03:49:13 +01:00
}
2017-07-21 17:21:09 +02:00
}
if ( mnb . CheckOutpoint ( nDos ) ) {
Add ( mnb ) ;
2017-08-09 18:07:03 +02:00
masternodeSync . BumpAssetLastTime ( " CMasternodeMan::CheckMnbAndUpdateMasternodeList - new " ) ;
2017-07-21 17:21:09 +02:00
// 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 ( ) ) ;
2017-09-19 16:51:38 +02:00
activeMasternode . ManageState ( connman ) ;
2017-07-21 17:21:09 +02:00
} 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 ;
2016-10-20 23:11:30 +02:00
}
}
2017-09-19 16:51:38 +02:00
mnb . Relay ( connman ) ;
2017-07-21 17:21:09 +02:00
} else {
LogPrintf ( " CMasternodeMan::CheckMnbAndUpdateMasternodeList -- Rejected Masternode entry: %s addr=%s \n " , mnb . vin . prevout . ToStringShort ( ) , mnb . addr . ToString ( ) ) ;
return false ;
2016-03-18 00:37:48 +01:00
}
return true ;
}
2016-09-11 22:22:37 +02:00
2017-08-25 14:57:05 +02:00
void CMasternodeMan : : UpdateLastPaid ( const CBlockIndex * pindex )
2016-10-20 23:11:30 +02:00
{
2016-10-17 20:54:28 +02:00
LOCK ( cs ) ;
2016-10-20 23:11:30 +02:00
2017-09-11 16:13:48 +02:00
if ( fLiteMode | | ! masternodeSync . IsWinnersListSynced ( ) | | mapMasternodes . empty ( ) ) return ;
2016-09-11 22:22:37 +02:00
static bool IsFirstRun = true ;
// Do full scan on first run or if we are not a masternode
// (MNs should update this info on every block, so limited scan should be enough for them)
2016-10-20 23:11:30 +02:00
int nMaxBlocksToScanBack = ( IsFirstRun | | ! fMasterNode ) ? mnpayments . GetStorageLimit ( ) : LAST_PAID_SCAN_BLOCKS ;
2016-09-11 22:22:37 +02:00
// LogPrint("mnpayments", "CMasternodeMan::UpdateLastPaid -- nHeight=%d, nMaxBlocksToScanBack=%d, IsFirstRun=%s\n",
2017-08-25 14:57:05 +02:00
// nCachedBlockHeight, nMaxBlocksToScanBack, IsFirstRun ? "true" : "false");
2016-09-11 22:22:37 +02:00
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
mnpair . second . UpdateLastPaid ( pindex , nMaxBlocksToScanBack ) ;
2016-09-11 22:22:37 +02:00
}
2017-08-09 18:07:03 +02:00
IsFirstRun = false ;
2016-09-11 22:22:37 +02:00
}
2016-10-17 20:54:28 +02:00
2017-10-12 14:05:17 +02:00
void CMasternodeMan : : UpdateWatchdogVoteTime ( const COutPoint & outpoint , uint64_t nVoteTime )
2016-10-17 20:54:28 +02:00
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
CMasternode * pmn = Find ( outpoint ) ;
if ( ! pmn ) {
2016-10-17 20:54:28 +02:00
return ;
}
2017-10-12 14:05:17 +02:00
pmn - > UpdateWatchdogVoteTime ( nVoteTime ) ;
2016-10-17 20:54:28 +02:00
nLastWatchdogVoteTime = GetTime ( ) ;
}
bool CMasternodeMan : : IsWatchdogActive ( )
{
LOCK ( cs ) ;
// Check if any masternodes have voted recently, otherwise return false
return ( GetTime ( ) - nLastWatchdogVoteTime ) < = MASTERNODE_WATCHDOG_MAX_SECONDS ;
}
2017-09-11 16:13:48 +02:00
bool CMasternodeMan : : AddGovernanceVote ( const COutPoint & outpoint , uint256 nGovernanceObjectHash )
2016-10-17 20:54:28 +02:00
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
CMasternode * pmn = Find ( outpoint ) ;
if ( ! pmn ) {
2017-04-02 21:58:54 +02:00
return false ;
2016-10-17 20:54:28 +02:00
}
2017-09-11 16:13:48 +02:00
pmn - > AddGovernanceVote ( nGovernanceObjectHash ) ;
2017-04-02 21:58:54 +02:00
return true ;
2016-10-17 20:54:28 +02:00
}
void CMasternodeMan : : RemoveGovernanceObject ( uint256 nGovernanceObjectHash )
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
mnpair . second . RemoveGovernanceObject ( nGovernanceObjectHash ) ;
2016-10-17 20:54:28 +02:00
}
}
void CMasternodeMan : : CheckMasternode ( const CPubKey & pubKeyMasternode , bool fForce )
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
for ( auto & mnpair : mapMasternodes ) {
if ( mnpair . second . pubKeyMasternode = = pubKeyMasternode ) {
mnpair . second . Check ( fForce ) ;
return ;
}
2016-10-17 20:54:28 +02:00
}
}
2017-09-11 16:13:48 +02:00
bool CMasternodeMan : : IsMasternodePingedWithin ( const COutPoint & outpoint , int nSeconds , int64_t nTimeToCheckAt )
2016-10-17 20:54:28 +02:00
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
CMasternode * pmn = Find ( outpoint ) ;
return pmn ? pmn - > IsPingedWithin ( nSeconds , nTimeToCheckAt ) : false ;
2016-10-17 20:54:28 +02:00
}
2017-09-11 16:13:48 +02:00
void CMasternodeMan : : SetMasternodeLastPing ( const COutPoint & outpoint , const CMasternodePing & mnp )
2016-10-17 20:54:28 +02:00
{
LOCK ( cs ) ;
2017-09-11 16:13:48 +02:00
CMasternode * pmn = Find ( outpoint ) ;
if ( ! pmn ) {
2016-10-17 20:54:28 +02:00
return ;
}
2017-09-11 16:13:48 +02:00
pmn - > lastPing = mnp ;
2017-07-04 19:31:57 +02:00
// if masternode uses sentinel ping instead of watchdog
// we shoud update nTimeLastWatchdogVote here if sentinel
// ping flag is actual
2017-09-11 16:13:48 +02:00
if ( mnp . fSentinelIsCurrent ) {
2017-10-12 14:05:17 +02:00
UpdateWatchdogVoteTime ( mnp . vin . prevout , mnp . sigTime ) ;
2017-09-11 16:13:48 +02:00
}
2016-10-17 20:54:28 +02:00
mapSeenMasternodePing . insert ( std : : make_pair ( mnp . GetHash ( ) , mnp ) ) ;
2017-09-11 16:13:48 +02:00
CMasternodeBroadcast mnb ( * pmn ) ;
2016-10-17 20:54:28 +02:00
uint256 hash = mnb . GetHash ( ) ;
if ( mapSeenMasternodeBroadcast . count ( hash ) ) {
2016-12-26 07:44:36 +01:00
mapSeenMasternodeBroadcast [ hash ] . second . lastPing = mnp ;
2016-10-17 20:54:28 +02:00
}
}
2016-10-20 23:11:30 +02:00
void CMasternodeMan : : UpdatedBlockTip ( const CBlockIndex * pindex )
{
2017-08-25 14:57:05 +02:00
nCachedBlockHeight = pindex - > nHeight ;
LogPrint ( " masternode " , " CMasternodeMan::UpdatedBlockTip -- nCachedBlockHeight=%d \n " , nCachedBlockHeight ) ;
2016-10-20 23:11:30 +02:00
CheckSameAddr ( ) ;
if ( fMasterNode ) {
// normal wallet does not need to update this every block, doing update on rpc call should be enough
2017-08-25 14:57:05 +02:00
UpdateLastPaid ( pindex ) ;
2016-10-20 23:11:30 +02:00
}
}
2016-11-13 18:52:34 +01:00
2017-09-19 16:51:38 +02:00
void CMasternodeMan : : NotifyMasternodeUpdates ( CConnman & connman )
2016-11-13 18:52:34 +01:00
{
// Avoid double locking
bool fMasternodesAddedLocal = false ;
bool fMasternodesRemovedLocal = false ;
{
LOCK ( cs ) ;
fMasternodesAddedLocal = fMasternodesAdded ;
fMasternodesRemovedLocal = fMasternodesRemoved ;
}
if ( fMasternodesAddedLocal ) {
2017-09-19 16:51:38 +02:00
governance . CheckMasternodeOrphanObjects ( connman ) ;
governance . CheckMasternodeOrphanVotes ( connman ) ;
2016-11-13 18:52:34 +01:00
}
if ( fMasternodesRemovedLocal ) {
governance . UpdateCachesAndClean ( ) ;
}
LOCK ( cs ) ;
fMasternodesAdded = false ;
fMasternodesRemoved = false ;
}