2016-02-02 16:28:56 +01:00
// Copyright (c) 2014-2016 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.
2016-02-02 16:28:56 +01:00
# include "consensus/validation.h"
2016-08-05 21:49:45 +02:00
# include "activemasternode.h"
2016-01-24 20:05:31 +01:00
# include "darksend.h"
2016-08-05 21:49:45 +02:00
# include "init.h"
2014-12-09 02:17:57 +01:00
# include "masternode.h"
2016-01-24 20:05:31 +01:00
# include "masternode-payments.h"
# include "masternode-sync.h"
2015-02-23 21:01:21 +01:00
# include "masternodeman.h"
2016-08-17 09:08:25 +02:00
# include "governance.h"
2014-12-09 02:17:57 +01:00
# include "util.h"
2015-03-22 04:26:48 +01:00
# include "sync.h"
2014-12-09 02:17:57 +01:00
# include "addrman.h"
# include <boost/lexical_cast.hpp>
// keep track of the scanning errors I've seen
map < uint256 , int > mapSeenMasternodeScanningErrors ;
2015-02-05 23:56:59 +01:00
2015-02-23 21:01:21 +01:00
CMasternode : : CMasternode ( )
{
LOCK ( cs ) ;
vin = CTxIn ( ) ;
addr = CService ( ) ;
pubkey = CPubKey ( ) ;
pubkey2 = CPubKey ( ) ;
2016-03-15 00:16:29 +01:00
vchSig = std : : vector < unsigned char > ( ) ;
2015-02-23 21:01:21 +01:00
activeState = MASTERNODE_ENABLED ;
2015-03-01 16:38:53 +01:00
sigTime = GetAdjustedTime ( ) ;
2015-07-14 07:25:07 +02:00
lastPing = CMasternodePing ( ) ;
2016-09-11 22:22:37 +02:00
nTimeLastPaid = 0 ;
nBlockLastPaid = 0 ;
nCacheCollateralBlock = 0 ;
2015-02-23 21:01:21 +01:00
unitTest = false ;
allowFreeTx = true ;
2015-07-19 01:20:48 +02:00
protocolVersion = PROTOCOL_VERSION ;
2015-02-23 21:01:21 +01:00
nLastDsq = 0 ;
2015-03-24 02:52:27 +01:00
nScanningErrorCount = 0 ;
nLastScanningErrorBlockHeight = 0 ;
2015-08-08 12:36:30 +02:00
lastTimeChecked = 0 ;
2015-02-23 21:01:21 +01:00
}
CMasternode : : CMasternode ( const CMasternode & other )
{
LOCK ( cs ) ;
vin = other . vin ;
addr = other . addr ;
pubkey = other . pubkey ;
pubkey2 = other . pubkey2 ;
2016-03-15 00:16:29 +01:00
vchSig = other . vchSig ;
2015-02-23 21:01:21 +01:00
activeState = other . activeState ;
2015-03-01 16:38:53 +01:00
sigTime = other . sigTime ;
2015-07-14 07:25:07 +02:00
lastPing = other . lastPing ;
2016-09-11 22:22:37 +02:00
nTimeLastPaid = other . nTimeLastPaid ;
nBlockLastPaid = other . nBlockLastPaid ;
nCacheCollateralBlock = other . nCacheCollateralBlock ;
2015-02-23 21:01:21 +01:00
unitTest = other . unitTest ;
allowFreeTx = other . allowFreeTx ;
protocolVersion = other . protocolVersion ;
nLastDsq = other . nLastDsq ;
2015-03-24 02:52:27 +01:00
nScanningErrorCount = other . nScanningErrorCount ;
nLastScanningErrorBlockHeight = other . nLastScanningErrorBlockHeight ;
2015-08-08 12:36:30 +02:00
lastTimeChecked = 0 ;
2015-02-23 21:01:21 +01:00
}
2015-04-17 17:10:38 +02:00
CMasternode : : CMasternode ( const CMasternodeBroadcast & mnb )
{
LOCK ( cs ) ;
vin = mnb . vin ;
addr = mnb . addr ;
pubkey = mnb . pubkey ;
pubkey2 = mnb . pubkey2 ;
2016-03-15 00:16:29 +01:00
vchSig = mnb . vchSig ;
2015-04-17 17:10:38 +02:00
activeState = MASTERNODE_ENABLED ;
sigTime = mnb . sigTime ;
2015-07-14 07:25:07 +02:00
lastPing = mnb . lastPing ;
2016-09-11 22:22:37 +02:00
nTimeLastPaid = 0 ;
nBlockLastPaid = 0 ;
nCacheCollateralBlock = 0 ;
2015-04-17 17:10:38 +02:00
unitTest = false ;
allowFreeTx = true ;
protocolVersion = mnb . protocolVersion ;
2015-08-12 00:54:27 +02:00
nLastDsq = mnb . nLastDsq ;
2015-04-17 17:10:38 +02:00
nScanningErrorCount = 0 ;
nLastScanningErrorBlockHeight = 0 ;
2015-08-08 12:36:30 +02:00
lastTimeChecked = 0 ;
2015-04-17 17:10:38 +02:00
}
//
// When a new masternode broadcast is sent, update our information
//
2015-08-12 03:39:22 +02:00
bool CMasternode : : UpdateFromNewBroadcast ( CMasternodeBroadcast & mnb )
2015-04-17 17:10:38 +02:00
{
2016-05-30 08:22:30 +02:00
if ( mnb . sigTime > sigTime ) {
2015-08-12 03:39:22 +02:00
pubkey2 = mnb . pubkey2 ;
sigTime = mnb . sigTime ;
2016-03-15 00:16:29 +01:00
vchSig = mnb . vchSig ;
2015-08-12 03:39:22 +02:00
protocolVersion = mnb . protocolVersion ;
addr = mnb . addr ;
lastTimeChecked = 0 ;
2016-03-15 00:16:29 +01:00
int nDos = 0 ;
if ( mnb . lastPing = = CMasternodePing ( ) | | ( mnb . lastPing ! = CMasternodePing ( ) & & mnb . lastPing . CheckAndUpdate ( nDos , false ) ) ) {
2015-08-12 03:39:22 +02:00
lastPing = mnb . lastPing ;
mnodeman . mapSeenMasternodePing . insert ( make_pair ( lastPing . GetHash ( ) , lastPing ) ) ;
}
return true ;
2015-07-14 07:25:07 +02:00
}
2015-08-12 03:39:22 +02:00
return false ;
2015-02-23 21:01:21 +01:00
}
2014-12-09 02:17:57 +01:00
//
2015-03-05 09:11:56 +01:00
// Deterministically calculate a given "score" for a Masternode depending on how close it's hash is to
2014-12-09 02:17:57 +01:00
// the proof of work for that block. The further away they are the better, the furthest will win the election
// and get paid this block
//
2016-09-15 08:50:41 +02:00
uint256 CMasternode : : CalculateScore ( int nBlockHeight )
2014-12-09 02:17:57 +01:00
{
2016-09-15 08:50:41 +02:00
uint256 hash ;
2016-02-02 16:28:56 +01:00
uint256 aux = ArithToUint256 ( UintToArith256 ( vin . prevout . hash ) + vin . prevout . n ) ;
2015-02-05 23:56:59 +01:00
2015-07-24 18:10:08 +02:00
if ( ! GetBlockHash ( hash , nBlockHeight ) ) {
2016-08-06 16:31:51 +02:00
LogPrintf ( " CMasternode::CalculateScore -- ERROR: GetBlockHash() failed at nBlockHeight %d \n " , nBlockHeight ) ;
2016-02-02 16:28:56 +01:00
return uint256 ( ) ;
2015-07-24 18:10:08 +02:00
}
2015-02-07 19:31:15 +01:00
2015-07-24 17:50:10 +02:00
CHashWriter ss ( SER_GETHASH , PROTOCOL_VERSION ) ;
ss < < hash ;
2016-02-02 16:28:56 +01:00
arith_uint256 hash2 = UintToArith256 ( ss . GetHash ( ) ) ;
2015-07-24 17:50:10 +02:00
CHashWriter ss2 ( SER_GETHASH , PROTOCOL_VERSION ) ;
ss2 < < hash ;
ss2 < < aux ;
2016-02-02 16:28:56 +01:00
arith_uint256 hash3 = UintToArith256 ( ss2 . GetHash ( ) ) ;
2015-02-07 19:31:15 +01:00
2016-02-02 16:28:56 +01:00
arith_uint256 r = ( hash3 > hash2 ? hash3 - hash2 : hash2 - hash3 ) ;
2015-02-07 19:31:15 +01:00
2016-02-02 16:28:56 +01:00
return ArithToUint256 ( r ) ;
2014-12-09 02:17:57 +01:00
}
2015-08-08 12:36:30 +02:00
void CMasternode : : Check ( bool forceCheck )
2014-12-09 02:17:57 +01:00
{
2016-09-15 15:30:51 +02:00
//once spent, stop doing the checks
if ( activeState = = MASTERNODE_VIN_SPENT ) return ;
2015-07-03 00:09:14 +02:00
if ( ShutdownRequested ( ) ) return ;
2015-08-08 12:36:30 +02:00
if ( ! forceCheck & & ( GetTime ( ) - lastTimeChecked < MASTERNODE_CHECK_SECONDS ) ) return ;
lastTimeChecked = GetTime ( ) ;
2016-09-15 15:30:51 +02:00
bool fRemove = // If there were no pings for quite a long time ...
! IsPingedWithin ( MASTERNODE_REMOVAL_SECONDS ) | |
// or masternode doesn't meet payment protocol requirements ...
protocolVersion < mnpayments . GetMinMasternodePaymentsProto ( ) | |
// or it's our own node and we just updated it to the new protocol but we are still waiting for activation ...
( pubkey2 = = activeMasternode . pubKeyMasternode & & protocolVersion < PROTOCOL_VERSION ) ;
2015-08-08 12:36:30 +02:00
2016-09-15 15:30:51 +02:00
if ( fRemove ) {
// it should be removed from the list
2015-02-23 21:01:21 +01:00
activeState = MASTERNODE_REMOVE ;
2016-08-17 09:08:25 +02:00
// RESCAN AFFECTED VOTES
2016-09-05 18:09:25 +02:00
FlagGovernanceItemsAsDirty ( ) ;
2014-12-09 02:17:57 +01:00
return ;
}
2016-09-15 15:30:51 +02:00
if ( ! IsPingedWithin ( MASTERNODE_EXPIRATION_SECONDS ) ) {
2015-02-23 21:01:21 +01:00
activeState = MASTERNODE_EXPIRED ;
2016-08-17 09:08:25 +02:00
// RESCAN AFFECTED VOTES
FlagGovernanceItemsAsDirty ( ) ;
2014-12-09 02:17:57 +01:00
return ;
}
2016-09-15 15:30:51 +02:00
if ( lastPing . sigTime - sigTime < MASTERNODE_MIN_MNP_SECONDS ) {
2016-03-16 16:30:22 +01:00
activeState = MASTERNODE_PRE_ENABLED ;
return ;
}
2016-09-15 15:30:51 +02:00
if ( ! unitTest ) {
2014-12-09 02:17:57 +01:00
CValidationState state ;
2015-04-03 00:51:08 +02:00
CMutableTransaction tx = CMutableTransaction ( ) ;
2016-09-05 18:09:25 +02:00
CTxOut txout = CTxOut ( 999.99 * COIN , mnodeman . dummyScriptPubkey ) ;
2014-12-09 02:17:57 +01:00
tx . vin . push_back ( vin ) ;
2016-09-05 18:09:25 +02:00
tx . vout . push_back ( txout ) ;
2014-12-09 02:17:57 +01:00
2015-07-30 15:44:18 +02:00
{
TRY_LOCK ( cs_main , lockMain ) ;
if ( ! lockMain ) return ;
2016-02-02 16:28:56 +01:00
if ( ! AcceptToMemoryPool ( mempool , state , CTransaction ( tx ) , false , NULL , false , true , true ) ) {
2015-07-30 15:44:18 +02:00
activeState = MASTERNODE_VIN_SPENT ;
return ;
}
2014-12-09 02:17:57 +01:00
}
}
2015-02-23 21:01:21 +01:00
activeState = MASTERNODE_ENABLED ; // OK
2015-04-17 17:10:38 +02:00
}
2016-09-11 22:22:37 +02:00
int CMasternode : : GetCollateralAge ( )
{
2016-09-12 20:06:59 +02:00
int nHeight ;
2016-03-02 21:57:24 +01:00
{
2016-09-12 20:06:59 +02:00
TRY_LOCK ( cs_main , lockMain ) ;
if ( ! lockMain | | ! chainActive . Tip ( ) ) return - 1 ;
nHeight = chainActive . Height ( ) ;
}
2016-09-11 22:22:37 +02:00
if ( nCacheCollateralBlock = = 0 ) {
int nInputAge = GetInputAge ( vin ) ;
if ( nInputAge > 0 ) {
2016-09-12 20:06:59 +02:00
nCacheCollateralBlock = nHeight - nInputAge ;
2016-09-11 22:22:37 +02:00
} else {
return nInputAge ;
}
2016-03-02 21:57:24 +01:00
}
2016-09-12 20:06:59 +02:00
return nHeight - nCacheCollateralBlock ;
2016-09-11 22:22:37 +02:00
}
2015-07-21 00:09:42 +02:00
2016-09-11 22:22:37 +02:00
void CMasternode : : UpdateLastPaid ( const CBlockIndex * pindex , int nMaxBlocksToScanBack )
{
if ( ! pindex ) return ;
2015-07-21 00:09:42 +02:00
2016-09-11 22:22:37 +02:00
const CBlockIndex * BlockReading = pindex ;
2015-07-22 01:11:49 +02:00
2016-09-11 22:22:37 +02:00
CScript mnpayee = GetScriptForDestination ( pubkey . GetID ( ) ) ;
// LogPrint("masternode", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s\n", vin.prevout.ToStringShort());
2015-07-22 01:11:49 +02:00
2016-09-11 22:22:37 +02:00
LOCK ( cs_mapMasternodeBlocks ) ;
2015-07-22 01:57:21 +02:00
2016-09-11 22:22:37 +02:00
for ( int i = 0 ; BlockReading & & BlockReading - > nHeight > nBlockLastPaid & & i < nMaxBlocksToScanBack ; i + + ) {
if ( mnpayments . mapMasternodeBlocks . count ( BlockReading - > nHeight ) & &
mnpayments . mapMasternodeBlocks [ BlockReading - > nHeight ] . HasPayeeWithVotes ( mnpayee , 2 ) )
{
CBlock block ;
if ( ! ReadBlockFromDisk ( block , BlockReading , Params ( ) . GetConsensus ( ) ) ) // shouldn't really happen
continue ;
CAmount nMasternodePayment = GetMasternodePayment ( BlockReading - > nHeight , block . vtx [ 0 ] . GetValueOut ( ) ) ;
BOOST_FOREACH ( CTxOut txout , block . vtx [ 0 ] . vout )
if ( mnpayee = = txout . scriptPubKey & & nMasternodePayment = = txout . nValue ) {
nBlockLastPaid = BlockReading - > nHeight ;
nTimeLastPaid = BlockReading - > nTime ;
LogPrint ( " masternode " , " CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- found new %d \n " , vin . prevout . ToStringShort ( ) , nBlockLastPaid ) ;
return ;
}
2015-07-21 00:09:42 +02:00
}
2015-07-22 01:57:21 +02:00
if ( BlockReading - > pprev = = NULL ) { assert ( BlockReading ) ; break ; }
BlockReading = BlockReading - > pprev ;
2015-07-21 00:09:42 +02:00
}
2015-06-23 18:38:28 +02:00
2016-09-11 22:22:37 +02:00
// Last payment for this masternode wasn't found in latest mnpayments blocks
// or it was found in mnpayments blocks but wasn't found in the blockchain.
// LogPrint("masternode", "CMasternode::UpdateLastPaidBlock -- searching for block with payment to %s -- keeping old %d\n", vin.prevout.ToStringShort(), nBlockLastPaid);
2015-06-23 18:38:28 +02:00
}
2015-04-17 17:10:38 +02:00
CMasternodeBroadcast : : CMasternodeBroadcast ( )
{
vin = CTxIn ( ) ;
addr = CService ( ) ;
pubkey = CPubKey ( ) ;
pubkey2 = CPubKey ( ) ;
2016-03-15 00:16:29 +01:00
vchSig = std : : vector < unsigned char > ( ) ;
2015-04-17 17:10:38 +02:00
activeState = MASTERNODE_ENABLED ;
sigTime = GetAdjustedTime ( ) ;
2015-07-14 07:25:07 +02:00
lastPing = CMasternodePing ( ) ;
2016-09-11 22:22:37 +02:00
nTimeLastPaid = 0 ;
nBlockLastPaid = 0 ;
nCacheCollateralBlock = 0 ;
2015-04-17 17:10:38 +02:00
unitTest = false ;
allowFreeTx = true ;
2015-07-19 01:20:48 +02:00
protocolVersion = PROTOCOL_VERSION ;
2015-08-12 14:27:58 +02:00
nLastDsq = 0 ;
2015-04-17 17:10:38 +02:00
nScanningErrorCount = 0 ;
nLastScanningErrorBlockHeight = 0 ;
}
2015-06-23 18:38:28 +02:00
CMasternodeBroadcast : : CMasternodeBroadcast ( CService newAddr , CTxIn newVin , CPubKey newPubkey , CPubKey newPubkey2 , int protocolVersionIn )
2015-04-17 17:10:38 +02:00
{
vin = newVin ;
addr = newAddr ;
pubkey = newPubkey ;
pubkey2 = newPubkey2 ;
2016-03-15 00:16:29 +01:00
vchSig = std : : vector < unsigned char > ( ) ;
2015-04-17 17:10:38 +02:00
activeState = MASTERNODE_ENABLED ;
sigTime = GetAdjustedTime ( ) ;
2015-07-14 07:25:07 +02:00
lastPing = CMasternodePing ( ) ;
2016-09-11 22:22:37 +02:00
nTimeLastPaid = 0 ;
nBlockLastPaid = 0 ;
nCacheCollateralBlock = 0 ;
2015-04-17 17:10:38 +02:00
unitTest = false ;
allowFreeTx = true ;
protocolVersion = protocolVersionIn ;
nLastDsq = 0 ;
nScanningErrorCount = 0 ;
nLastScanningErrorBlockHeight = 0 ;
}
2015-07-14 07:25:07 +02:00
CMasternodeBroadcast : : CMasternodeBroadcast ( const CMasternode & mn )
2015-04-17 17:10:38 +02:00
{
2015-07-14 07:25:07 +02:00
vin = mn . vin ;
addr = mn . addr ;
pubkey = mn . pubkey ;
pubkey2 = mn . pubkey2 ;
2016-03-15 00:16:29 +01:00
vchSig = mn . vchSig ;
2015-07-14 07:25:07 +02:00
activeState = mn . activeState ;
sigTime = mn . sigTime ;
lastPing = mn . lastPing ;
2016-09-11 22:22:37 +02:00
nTimeLastPaid = mn . nTimeLastPaid ;
nBlockLastPaid = mn . nBlockLastPaid ;
nCacheCollateralBlock = mn . nCacheCollateralBlock ;
2015-07-14 07:25:07 +02:00
unitTest = mn . unitTest ;
allowFreeTx = mn . allowFreeTx ;
protocolVersion = mn . protocolVersion ;
nLastDsq = mn . nLastDsq ;
nScanningErrorCount = mn . nScanningErrorCount ;
nLastScanningErrorBlockHeight = mn . nLastScanningErrorBlockHeight ;
2015-04-17 17:10:38 +02:00
}
2016-09-05 18:09:25 +02:00
bool CMasternodeBroadcast : : Create ( std : : string strService , std : : string strKeyMasternode , std : : string strTxHash , std : : string strOutputIndex , std : : string & strErrorRet , CMasternodeBroadcast & mnbRet , bool fOffline )
2016-07-29 07:32:08 +02:00
{
CTxIn txin ;
CPubKey pubKeyCollateral ;
CKey keyCollateral ;
CPubKey pubKeyMasternodeNew ;
CKey keyMasternodeNew ;
//need correct blocks to send ping
if ( ! fOffline & & ! masternodeSync . IsBlockchainSynced ( ) ) {
2016-09-05 18:09:25 +02:00
strErrorRet = " Sync in progress. Must wait until sync is complete to start Masternode " ;
LogPrintf ( " CMasternodeBroadcast::Create -- %s \n " , strErrorRet ) ;
2016-07-29 07:32:08 +02:00
return false ;
}
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . GetKeysFromSecret ( strKeyMasternode , keyMasternodeNew , pubKeyMasternodeNew ) ) {
2016-09-05 18:09:25 +02:00
strErrorRet = strprintf ( " Invalid masternode key %s " , strKeyMasternode ) ;
LogPrintf ( " CMasternodeBroadcast::Create -- %s \n " , strErrorRet ) ;
2016-07-29 07:32:08 +02:00
return false ;
}
if ( ! pwalletMain - > GetMasternodeVinAndKeys ( txin , pubKeyCollateral , keyCollateral , strTxHash , strOutputIndex ) ) {
2016-09-05 18:09:25 +02:00
strErrorRet = strprintf ( " Could not allocate txin %s:%s for masternode %s " , strTxHash , strOutputIndex , strService ) ;
LogPrintf ( " CMasternodeBroadcast::Create -- %s \n " , strErrorRet ) ;
2016-07-29 07:32:08 +02:00
return false ;
}
CService service = CService ( strService ) ;
2016-09-05 18:09:25 +02:00
int mainnetDefaultPort = Params ( CBaseChainParams : : MAIN ) . GetDefaultPort ( ) ;
2016-07-29 07:32:08 +02:00
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : MAIN ) {
if ( service . GetPort ( ) ! = mainnetDefaultPort ) {
2016-09-05 18:09:25 +02:00
strErrorRet = strprintf ( " Invalid port %u for masternode %s, only %d is supported on mainnet. " , service . GetPort ( ) , strService , mainnetDefaultPort ) ;
LogPrintf ( " CMasternodeBroadcast::Create -- %s \n " , strErrorRet ) ;
2016-07-29 07:32:08 +02:00
return false ;
}
2016-09-05 18:09:25 +02:00
} else if ( service . GetPort ( ) = = mainnetDefaultPort ) {
strErrorRet = strprintf ( " Invalid port %u for masternode %s, %d is the only supported on mainnet. " , service . GetPort ( ) , strService , mainnetDefaultPort ) ;
LogPrintf ( " CMasternodeBroadcast::Create -- %s \n " , strErrorRet ) ;
2016-07-29 07:32:08 +02:00
return false ;
}
2016-09-05 18:09:25 +02:00
return Create ( txin , CService ( strService ) , keyCollateral , pubKeyCollateral , keyMasternodeNew , pubKeyMasternodeNew , strErrorRet , mnbRet ) ;
2016-07-29 07:32:08 +02:00
}
2016-09-05 18:09:25 +02:00
bool CMasternodeBroadcast : : Create ( CTxIn txin , CService service , CKey keyCollateral , CPubKey pubKeyCollateral , CKey keyMasternodeNew , CPubKey pubKeyMasternodeNew , std : : string & strErrorRet , CMasternodeBroadcast & mnbRet )
2016-07-29 07:32:08 +02:00
{
// wait for reindex and/or import to finish
if ( fImporting | | fReindex ) return false ;
CMasternodePing mnp ( txin ) ;
if ( ! mnp . Sign ( keyMasternodeNew , pubKeyMasternodeNew ) ) {
2016-09-05 18:09:25 +02:00
strErrorRet = strprintf ( " Failed to sign ping: %s " , txin . ToString ( ) ) ;
LogPrintf ( " CMasternodeBroadcast::Create -- %s \n " , strErrorRet ) ;
mnbRet = CMasternodeBroadcast ( ) ;
2016-07-29 07:32:08 +02:00
return false ;
}
2016-09-05 18:09:25 +02:00
mnbRet = CMasternodeBroadcast ( service , txin , pubKeyCollateral , pubKeyMasternodeNew , PROTOCOL_VERSION ) ;
mnbRet . lastPing = mnp ;
if ( ! mnbRet . Sign ( keyCollateral ) ) {
strErrorRet = strprintf ( " Failed to sign broadcast: %s " , txin . ToString ( ) ) ;
LogPrintf ( " CMasternodeBroadcast::Create -- %s \n " , strErrorRet ) ;
mnbRet = CMasternodeBroadcast ( ) ;
2016-07-29 07:32:08 +02:00
return false ;
}
return true ;
}
2015-07-14 07:25:07 +02:00
bool CMasternodeBroadcast : : CheckAndUpdate ( int & nDos )
2015-04-17 17:10:38 +02:00
{
2016-06-03 06:59:19 +02:00
nDos = 0 ;
2015-04-17 17:10:38 +02:00
// make sure signature isn't in the future (past is OK)
if ( sigTime > GetAdjustedTime ( ) + 60 * 60 ) {
2016-03-15 00:16:29 +01:00
LogPrintf ( " CMasternodeBroadcast::CheckAndUpdate - Signature rejected, too far into the future %s \n " , vin . ToString ( ) ) ;
2015-07-14 07:25:07 +02:00
nDos = 1 ;
2015-04-17 17:10:38 +02:00
return false ;
}
2016-03-16 16:30:22 +01:00
// incorrect ping or its sigTime
2016-09-05 18:09:25 +02:00
if ( lastPing = = CMasternodePing ( ) | | ! lastPing . CheckAndUpdate ( nDos , false , true ) ) {
2016-03-16 16:30:22 +01:00
return false ;
2016-09-05 18:09:25 +02:00
}
2016-03-16 16:30:22 +01:00
2016-02-04 20:29:09 +01:00
if ( protocolVersion < mnpayments . GetMinMasternodePaymentsProto ( ) ) {
2016-03-15 00:16:29 +01:00
LogPrintf ( " CMasternodeBroadcast::CheckAndUpdate - ignoring outdated Masternode %s protocol version %d \n " , vin . ToString ( ) , protocolVersion ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
CScript pubkeyScript ;
pubkeyScript = GetScriptForDestination ( pubkey . GetID ( ) ) ;
if ( pubkeyScript . size ( ) ! = 25 ) {
2016-03-15 00:16:29 +01:00
LogPrintf ( " CMasternodeBroadcast::CheckAndUpdate - pubkey the wrong size \n " ) ;
2015-04-17 17:10:38 +02:00
nDos = 100 ;
return false ;
}
CScript pubkeyScript2 ;
pubkeyScript2 = GetScriptForDestination ( pubkey2 . GetID ( ) ) ;
if ( pubkeyScript2 . size ( ) ! = 25 ) {
2016-03-15 00:16:29 +01:00
LogPrintf ( " CMasternodeBroadcast::CheckAndUpdate - pubkey2 the wrong size \n " ) ;
2015-04-17 17:10:38 +02:00
nDos = 100 ;
return false ;
}
if ( ! vin . scriptSig . empty ( ) ) {
2016-03-15 00:16:29 +01:00
LogPrintf ( " CMasternodeBroadcast::CheckAndUpdate - Ignore Not Empty ScriptSig %s \n " , vin . ToString ( ) ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
2016-06-03 06:59:19 +02:00
if ( ! VerifySignature ( nDos ) )
{
LogPrintf ( " CMasternodeBroadcast::CheckAndUpdate - VerifySignature failed %s \n " , vin . ToString ( ) ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
2016-02-17 17:00:17 +01:00
int mainnetDefaultPort = Params ( CBaseChainParams : : MAIN ) . GetDefaultPort ( ) ;
2016-02-02 16:28:56 +01:00
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : MAIN ) {
2016-02-17 17:00:17 +01:00
if ( addr . GetPort ( ) ! = mainnetDefaultPort ) return false ;
} else if ( addr . GetPort ( ) = = mainnetDefaultPort ) return false ;
2015-04-17 17:10:38 +02:00
2015-06-23 17:40:08 +02:00
//search existing Masternode list, this is where we update existing Masternodes with new mnb broadcasts
2015-04-17 17:10:38 +02:00
CMasternode * pmn = mnodeman . Find ( vin ) ;
2015-06-20 21:56:56 +02:00
2016-03-07 09:42:37 +01:00
// no such masternode, nothing to update
2016-03-16 16:30:22 +01:00
if ( pmn = = NULL ) return true ;
// this broadcast is older or equal than the one that we already have - it's bad and should never happen
// unless someone is doing something fishy
// (mapSeenMasternodeBroadcast in CMasternodeMan::ProcessMessage should filter legit duplicates)
if ( pmn - > sigTime > = sigTime ) {
LogPrintf ( " CMasternodeBroadcast::CheckAndUpdate - Bad sigTime %d for Masternode %20s %105s (existing broadcast is at %d) \n " ,
sigTime , addr . ToString ( ) , vin . ToString ( ) , pmn - > sigTime ) ;
return false ;
2016-03-07 09:42:37 +01:00
}
2015-07-14 07:25:07 +02:00
2016-03-16 16:30:22 +01:00
// masternode is not enabled yet/already, nothing to update
if ( ! pmn - > IsEnabled ( ) ) return true ;
2015-07-14 07:25:07 +02:00
// mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below,
// after that they just need to match
if ( pmn - > pubkey = = pubkey & & ! pmn - > IsBroadcastedWithin ( MASTERNODE_MIN_MNB_SECONDS ) ) {
//take the newest entry
2016-03-15 00:16:29 +01:00
LogPrintf ( " CMasternodeBroadcast::CheckAndUpdate - Got updated entry for %s \n " , addr . ToString ( ) ) ;
2015-08-12 03:39:22 +02:00
if ( pmn - > UpdateFromNewBroadcast ( ( * this ) ) ) {
pmn - > Check ( ) ;
2016-05-27 08:24:44 +02:00
// normally masternode should be in pre-enabled status after update, if not - do not relay
2016-09-05 18:09:25 +02:00
if ( pmn - > IsPreEnabled ( ) ) {
Relay ( ) ;
}
2015-08-12 03:39:22 +02:00
}
2016-09-11 19:49:40 +02:00
masternodeSync . AddedMasternodeList ( ) ;
2015-04-17 17:10:38 +02:00
}
return true ;
}
2016-03-15 00:16:29 +01:00
bool CMasternodeBroadcast : : CheckInputsAndAdd ( int & nDos )
2015-04-17 17:10:38 +02:00
{
2015-07-14 07:25:07 +02:00
// we are a masternode with the same vin (i.e. already activated) and this mnb is ours (matches our Masternode privkey)
// so nothing to do here for us
if ( fMasterNode & & vin . prevout = = activeMasternode . vin . prevout & & pubkey2 = = activeMasternode . pubKeyMasternode )
return true ;
2016-03-16 16:30:22 +01:00
// incorrect ping or its sigTime
2016-09-05 18:09:25 +02:00
if ( lastPing = = CMasternodePing ( ) | | ! lastPing . CheckAndUpdate ( nDos , false , true ) ) {
2016-03-16 16:30:22 +01:00
return false ;
2016-09-05 18:09:25 +02:00
}
2016-03-16 16:30:22 +01:00
2015-07-14 07:25:07 +02:00
// search existing Masternode list
CMasternode * pmn = mnodeman . Find ( vin ) ;
if ( pmn ! = NULL ) {
2015-08-05 05:16:29 +02:00
// nothing to do here if we already know about this masternode and it's (pre)enabled
if ( pmn - > IsEnabled ( ) | | pmn - > IsPreEnabled ( ) ) return true ;
2016-05-27 08:24:44 +02:00
// if it's not (pre)enabled, remove old MN first and continue
2016-09-05 18:09:25 +02:00
mnodeman . Remove ( pmn - > vin ) ;
2015-07-14 07:25:07 +02:00
}
2016-09-05 18:09:25 +02:00
if ( GetInputAge ( vin ) < Params ( ) . GetConsensus ( ) . nMasternodeMinimumConfirmations ) {
LogPrintf ( " CMasternodeBroadcast::CheckInputsAndAdd -- Input must have at least %d confirmations \n " , Params ( ) . GetConsensus ( ) . nMasternodeMinimumConfirmations ) ;
2016-05-24 02:08:16 +02:00
// maybe we miss few blocks, let this mnb to be checked again later
mnodeman . mapSeenMasternodeBroadcast . erase ( GetHash ( ) ) ;
return false ;
}
2015-04-17 17:10:38 +02:00
CValidationState state ;
2016-09-05 18:09:25 +02:00
CMutableTransaction dummyTx = CMutableTransaction ( ) ;
CTxOut dummyTxOut = CTxOut ( 999.99 * COIN , mnodeman . dummyScriptPubkey ) ;
dummyTx . vin . push_back ( vin ) ;
dummyTx . vout . push_back ( dummyTxOut ) ;
2015-04-17 17:10:38 +02:00
2015-07-30 15:44:18 +02:00
{
TRY_LOCK ( cs_main , lockMain ) ;
2015-08-10 02:38:00 +02:00
if ( ! lockMain ) {
// not mnb fault, let it to be checked again later
mnodeman . mapSeenMasternodeBroadcast . erase ( GetHash ( ) ) ;
return false ;
}
2015-07-30 15:44:18 +02:00
2016-09-05 18:09:25 +02:00
if ( ! AcceptToMemoryPool ( mempool , state , CTransaction ( dummyTx ) , false , NULL , false , true , true ) ) {
2015-07-30 15:44:18 +02:00
//set nDos
2016-09-05 18:09:25 +02:00
LogPrint ( " masternode " , " CMasternodeBroadcast::CheckInputsAndAdd -- Failed to accepted Masternode entry to mempool: dummyTx=%s " , dummyTx . ToString ( ) ) ;
2016-03-15 00:16:29 +01:00
state . IsInvalid ( nDos ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
2015-07-30 15:44:18 +02:00
}
2015-04-17 17:10:38 +02:00
2016-09-05 18:09:25 +02:00
LogPrint ( " masternode " , " CMasternodeBroadcast::CheckInputsAndAdd -- Accepted Masternode entry to mempool (dry-run mode) \n " ) ;
2015-04-17 17:10:38 +02:00
2016-05-24 02:08:16 +02:00
// make sure the vout that was signed is related to the transaction that spawned the Masternode
// - this is expensive, so it's only done once per Masternode
if ( ! darkSendSigner . IsVinAssociatedWithPubkey ( vin , pubkey ) ) {
LogPrintf ( " CMasternodeMan::CheckInputsAndAdd - Got mismatched pubkey and vin \n " ) ;
nDos = 33 ;
2015-07-30 15:44:18 +02:00
return false ;
}
2015-04-17 17:10:38 +02:00
2015-07-30 15:44:18 +02:00
// verify that sig time is legit in past
2016-05-19 21:03:17 +02:00
// should be at least not earlier than block when 1000 DASH tx got nMasternodeMinimumConfirmations
2016-02-02 16:28:56 +01:00
uint256 hashBlock = uint256 ( ) ;
2015-07-30 15:44:18 +02:00
CTransaction tx2 ;
2016-02-02 16:28:56 +01:00
GetTransaction ( vin . prevout . hash , tx2 , Params ( ) . GetConsensus ( ) , hashBlock , true ) ;
2015-07-30 15:44:18 +02:00
{
2016-03-02 21:57:24 +01:00
LOCK ( cs_main ) ;
BlockMap : : iterator mi = mapBlockIndex . find ( hashBlock ) ;
2016-09-05 18:09:25 +02:00
if ( mi ! = mapBlockIndex . end ( ) & & ( * mi ) . second ) {
2016-03-02 21:57:24 +01:00
CBlockIndex * pMNIndex = ( * mi ) . second ; // block for 1000 DASH tx -> 1 confirmation
2016-05-19 21:03:17 +02:00
CBlockIndex * pConfIndex = chainActive [ pMNIndex - > nHeight + Params ( ) . GetConsensus ( ) . nMasternodeMinimumConfirmations - 1 ] ; // block where tx got nMasternodeMinimumConfirmations
2016-03-02 21:57:24 +01:00
if ( pConfIndex - > GetBlockTime ( ) > sigTime )
{
2016-03-15 00:16:29 +01:00
LogPrintf ( " CMasternodeBroadcast::CheckInputsAndAdd - Bad sigTime %d for Masternode %20s %105s (%i conf block is at %d) \n " ,
2016-05-19 21:03:17 +02:00
sigTime , addr . ToString ( ) , vin . ToString ( ) , Params ( ) . GetConsensus ( ) . nMasternodeMinimumConfirmations , pConfIndex - > GetBlockTime ( ) ) ;
2016-03-02 21:57:24 +01:00
return false ;
}
2015-04-17 17:10:38 +02:00
}
2015-07-30 15:44:18 +02:00
}
2016-05-24 02:08:16 +02:00
2016-05-27 08:24:44 +02:00
// if it matches our Masternode privkey...
if ( fMasterNode & & pubkey2 = = activeMasternode . pubKeyMasternode ) {
if ( protocolVersion = = PROTOCOL_VERSION ) {
// ... and PROTOCOL_VERSION, then we've been remotely activated ...
2016-09-05 18:09:25 +02:00
activeMasternode . EnableRemoteMasterNode ( vin , addr ) ;
2016-05-27 08:24:44 +02:00
} else {
// ... otherwise we need to reactivate our node, don not add it to the list and do not relay
// but also do not ban the node we get this message from
LogPrintf ( " CMasternodeBroadcast::CheckInputsAndAdd - wrong PROTOCOL_VERSION, announce message: %d MN: %d - re-activate your MN \n " , protocolVersion , PROTOCOL_VERSION ) ;
return false ;
}
}
2016-03-15 00:16:29 +01:00
LogPrintf ( " CMasternodeBroadcast::CheckInputsAndAdd - Got NEW Masternode entry - %s - %s - %s - %lli \n " , GetHash ( ) . ToString ( ) , addr . ToString ( ) , vin . ToString ( ) , sigTime ) ;
2015-07-30 15:44:18 +02:00
CMasternode mn ( * this ) ;
mnodeman . Add ( mn ) ;
2015-04-17 17:10:38 +02:00
2015-07-30 15:44:18 +02:00
bool isLocal = addr . IsRFC1918 ( ) | | addr . IsLocal ( ) ;
2016-09-05 18:09:25 +02:00
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : REGTEST ) {
isLocal = false ;
}
2015-07-30 15:44:18 +02:00
2016-09-05 18:09:25 +02:00
if ( ! isLocal ) {
Relay ( ) ;
}
2015-07-30 15:44:18 +02:00
return true ;
2015-04-17 17:10:38 +02:00
}
2015-07-14 07:25:07 +02:00
void CMasternodeBroadcast : : Relay ( )
2015-04-17 17:10:38 +02:00
{
2015-04-22 16:33:44 +02:00
CInv inv ( MSG_MASTERNODE_ANNOUNCE , GetHash ( ) ) ;
2015-07-08 02:37:23 +02:00
RelayInv ( inv ) ;
2015-04-17 17:10:38 +02:00
}
bool CMasternodeBroadcast : : Sign ( CKey & keyCollateralAddress )
2015-06-24 01:44:31 +02:00
{
2016-08-19 13:50:04 +02:00
std : : string strError ;
2016-06-03 06:59:19 +02:00
std : : string strMessage ;
2015-04-17 17:10:38 +02:00
sigTime = GetAdjustedTime ( ) ;
2016-06-03 06:59:19 +02:00
strMessage = addr . ToString ( false ) + boost : : lexical_cast < std : : string > ( sigTime ) +
pubkey . GetID ( ) . ToString ( ) + pubkey2 . GetID ( ) . ToString ( ) +
boost : : lexical_cast < std : : string > ( protocolVersion ) ;
2015-04-17 17:10:38 +02:00
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . SignMessage ( strMessage , vchSig , keyCollateralAddress ) ) {
LogPrintf ( " CMasternodeBroadcast::Sign -- SignMessage() failed \n " ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . VerifyMessage ( pubkey , vchSig , strMessage , strError ) ) {
LogPrintf ( " CMasternodeBroadcast::Sign -- VerifyMessage() failed, error: %s \n " , strError ) ;
2016-06-03 06:59:19 +02:00
return false ;
}
2016-03-16 16:30:22 +01:00
return true ;
}
2016-06-03 06:59:19 +02:00
bool CMasternodeBroadcast : : VerifySignature ( int & nDos )
2016-03-16 16:30:22 +01:00
{
2016-05-30 09:31:57 +02:00
std : : string strMessage ;
2016-08-19 13:50:04 +02:00
std : : string strError = " " ;
2016-06-03 06:59:19 +02:00
nDos = 0 ;
//
// REMOVE AFTER MIGRATION TO 12.1
//
2016-05-30 09:31:57 +02:00
if ( protocolVersion < 70201 ) {
std : : string vchPubKey ( pubkey . begin ( ) , pubkey . end ( ) ) ;
std : : string vchPubKey2 ( pubkey2 . begin ( ) , pubkey2 . end ( ) ) ;
2016-06-03 06:59:19 +02:00
strMessage = addr . ToString ( false ) + boost : : lexical_cast < std : : string > ( sigTime ) +
vchPubKey + vchPubKey2 + boost : : lexical_cast < std : : string > ( protocolVersion ) ;
LogPrint ( " masternode " , " CMasternodeBroadcast::VerifySignature - sanitized strMessage: %s, pubkey address: %s, sig: %s \n " ,
SanitizeString ( strMessage ) , CBitcoinAddress ( pubkey . GetID ( ) ) . ToString ( ) ,
EncodeBase64 ( & vchSig [ 0 ] , vchSig . size ( ) ) ) ;
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . VerifyMessage ( pubkey , vchSig , strMessage , strError ) ) {
2016-06-03 06:59:19 +02:00
if ( addr . ToString ( ) ! = addr . ToString ( false ) )
{
// maybe it's wrong format, try again with the old one
strMessage = addr . ToString ( ) + boost : : lexical_cast < std : : string > ( sigTime ) +
vchPubKey + vchPubKey2 + boost : : lexical_cast < std : : string > ( protocolVersion ) ;
LogPrint ( " masternode " , " CMasternodeBroadcast::VerifySignature - second try, sanitized strMessage: %s, pubkey address: %s, sig: %s \n " ,
SanitizeString ( strMessage ) , CBitcoinAddress ( pubkey . GetID ( ) ) . ToString ( ) ,
EncodeBase64 ( & vchSig [ 0 ] , vchSig . size ( ) ) ) ;
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . VerifyMessage ( pubkey , vchSig , strMessage , strError ) ) {
2016-06-03 06:59:19 +02:00
// didn't work either
2016-08-19 13:50:04 +02:00
LogPrintf ( " CMasternodeBroadcast::VerifySignature -- Got bad Masternode announce signature, second try, sanitized error: %s \n " ,
SanitizeString ( strError ) ) ;
2016-06-03 06:59:19 +02:00
// don't ban for old masternodes, their sigs could be broken because of the bug
return false ;
}
} else {
// nope, sig is actually wrong
2016-08-19 13:50:04 +02:00
LogPrintf ( " CMasternodeBroadcast::VerifySignature -- Got bad Masternode announce signature, sanitized error: %s \n " ,
SanitizeString ( strError ) ) ;
2016-06-03 06:59:19 +02:00
// don't ban for old masternodes, their sigs could be broken because of the bug
return false ;
}
}
2016-05-30 09:31:57 +02:00
} else {
2016-06-03 06:59:19 +02:00
//
// END REMOVE
//
2016-06-02 08:11:56 +02:00
strMessage = addr . ToString ( false ) + boost : : lexical_cast < std : : string > ( sigTime ) +
2016-05-30 09:31:57 +02:00
pubkey . GetID ( ) . ToString ( ) + pubkey2 . GetID ( ) . ToString ( ) +
boost : : lexical_cast < std : : string > ( protocolVersion ) ;
2016-03-16 16:30:22 +01:00
2016-06-03 06:59:19 +02:00
LogPrint ( " masternode " , " CMasternodeBroadcast::VerifySignature - strMessage: %s, pubkey address: %s, sig: %s \n " , strMessage , CBitcoinAddress ( pubkey . GetID ( ) ) . ToString ( ) , EncodeBase64 ( & vchSig [ 0 ] , vchSig . size ( ) ) ) ;
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . VerifyMessage ( pubkey , vchSig , strMessage , strError ) ) {
LogPrintf ( " CMasternodeBroadcast::VerifySignature -- Got bad Masternode announce signature, error: %s \n " , strError ) ;
2016-06-03 06:59:19 +02:00
nDos = 100 ;
return false ;
}
2015-04-17 17:10:38 +02:00
}
return true ;
}
CMasternodePing : : CMasternodePing ( )
{
vin = CTxIn ( ) ;
2016-02-02 16:28:56 +01:00
blockHash = uint256 ( ) ;
2015-07-14 07:25:07 +02:00
sigTime = 0 ;
vchSig = std : : vector < unsigned char > ( ) ;
2015-04-17 17:10:38 +02:00
}
CMasternodePing : : CMasternodePing ( CTxIn & newVin )
{
2016-03-02 21:57:24 +01:00
int nHeight ;
{
LOCK ( cs_main ) ;
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( ! pindexPrev ) return ;
nHeight = pindexPrev - > nHeight ;
}
2015-04-17 17:10:38 +02:00
vin = newVin ;
2016-03-02 21:57:24 +01:00
blockHash = chainActive [ nHeight - 12 ] - > GetBlockHash ( ) ;
2015-07-14 07:25:07 +02:00
sigTime = GetAdjustedTime ( ) ;
vchSig = std : : vector < unsigned char > ( ) ;
2015-04-17 17:10:38 +02:00
}
bool CMasternodePing : : Sign ( CKey & keyMasternode , CPubKey & pubKeyMasternode )
{
2016-08-19 13:50:04 +02:00
std : : string strError ;
2015-04-17 17:10:38 +02:00
std : : string strMasterNodeSignMessage ;
sigTime = GetAdjustedTime ( ) ;
2015-06-09 03:36:33 +02:00
std : : string strMessage = vin . ToString ( ) + blockHash . ToString ( ) + boost : : lexical_cast < std : : string > ( sigTime ) ;
2015-04-17 17:10:38 +02:00
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . SignMessage ( strMessage , vchSig , keyMasternode ) ) {
LogPrintf ( " CMasternodePing::Sign -- SignMessage() failed \n " ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . VerifyMessage ( pubKeyMasternode , vchSig , strMessage , strError ) ) {
LogPrintf ( " CMasternodePing::Sign -- VerifyMessage() failed, error: %s \n " , strError ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
return true ;
}
2016-03-16 16:30:22 +01:00
bool CMasternodePing : : VerifySignature ( CPubKey & pubKeyMasternode , int & nDos ) {
std : : string strMessage = vin . ToString ( ) + blockHash . ToString ( ) + boost : : lexical_cast < std : : string > ( sigTime ) ;
2016-08-19 13:50:04 +02:00
std : : string strError = " " ;
2016-06-03 06:59:19 +02:00
nDos = 0 ;
2016-03-16 16:30:22 +01:00
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . VerifyMessage ( pubKeyMasternode , vchSig , strMessage , strError ) ) {
LogPrintf ( " CMasternodePing::VerifySignature -- Got bad Masternode ping signature: %s error: %s \n " , vin . ToString ( ) , strError ) ;
2016-03-16 16:30:22 +01:00
nDos = 33 ;
return false ;
}
return true ;
}
bool CMasternodePing : : CheckAndUpdate ( int & nDos , bool fRequireEnabled , bool fCheckSigTimeOnly )
2015-04-17 17:10:38 +02:00
{
if ( sigTime > GetAdjustedTime ( ) + 60 * 60 ) {
2016-09-15 15:30:51 +02:00
LogPrintf ( " CMasternodePing::CheckAndUpdate -- Signature rejected, too far into the future, masternode=%s \n " , vin . prevout . ToStringShort ( ) ) ;
2015-07-14 07:25:07 +02:00
nDos = 1 ;
2015-04-17 17:10:38 +02:00
return false ;
}
if ( sigTime < = GetAdjustedTime ( ) - 60 * 60 ) {
2016-09-15 15:30:51 +02:00
LogPrintf ( " CMasternodePing::CheckAndUpdate -- Signature rejected, too far into the past: masternode=%s sigTime=%d GetAdjustedTime()=%d \n " , vin . prevout . ToStringShort ( ) , sigTime , GetAdjustedTime ( ) ) ;
2015-07-14 07:25:07 +02:00
nDos = 1 ;
2015-04-17 17:10:38 +02:00
return false ;
}
2016-09-15 15:30:51 +02:00
if ( fCheckSigTimeOnly ) {
2016-03-16 16:30:22 +01:00
CMasternode * pmn = mnodeman . Find ( vin ) ;
2016-09-15 15:30:51 +02:00
if ( pmn ) return VerifySignature ( pmn - > pubkey2 , nDos ) ;
2016-03-16 16:30:22 +01:00
return true ;
}
2016-09-15 15:30:51 +02:00
LogPrint ( " masternode " , " CMasternodePing::CheckAndUpdate -- New ping: masternode=%s blockHash=%s sigTime=%d \n " , vin . prevout . ToStringShort ( ) , blockHash . ToString ( ) , sigTime ) ;
2015-07-20 20:43:10 +02:00
2015-04-17 17:10:38 +02:00
// see if we have this Masternode
CMasternode * pmn = mnodeman . Find ( vin ) ;
2015-07-20 20:56:02 +02:00
2016-09-15 15:30:51 +02:00
if ( pmn = = NULL | | pmn - > protocolVersion < mnpayments . GetMinMasternodePaymentsProto ( ) ) {
LogPrint ( " masternode " , " CMasternodePing::CheckAndUpdate -- Couldn't find compatible Masternode entry, masternode=%s \n " , vin . prevout . ToStringShort ( ) ) ;
return false ;
}
2015-04-17 17:10:38 +02:00
2016-09-15 15:30:51 +02:00
if ( fRequireEnabled & & ! pmn - > IsEnabled ( ) & & ! pmn - > IsPreEnabled ( ) ) return false ;
2015-06-20 21:56:56 +02:00
2016-09-15 15:30:51 +02:00
// LogPrintf("mnping - Found corresponding mn for vin: %s\n", vin.prevout.ToStringShort());
// update only if there is no known ping for this masternode or
// last ping was more then MASTERNODE_MIN_MNP_SECONDS-60 ago comparing to this one
if ( pmn - > IsPingedWithin ( MASTERNODE_MIN_MNP_SECONDS - 60 , sigTime ) ) {
LogPrint ( " masternode " , " CMasternodePing::CheckAndUpdate -- Masternode ping arrived too early, masternode=%s \n " , vin . prevout . ToStringShort ( ) ) ;
//nDos = 1; //disable, this is happening frequently and causing banned peers
return false ;
}
2015-07-14 07:25:07 +02:00
2016-09-15 15:30:51 +02:00
if ( ! VerifySignature ( pmn - > pubkey2 , nDos ) ) return false ;
2015-07-26 06:13:17 +02:00
2016-09-15 15:30:51 +02:00
{
LOCK ( cs_main ) ;
BlockMap : : iterator mi = mapBlockIndex . find ( blockHash ) ;
if ( mi = = mapBlockIndex . end ( ) ) {
LogPrint ( " masternode " , " CMasternodePing::CheckAndUpdate -- Masternode is unknown: masternode=%s blockHash=%s \n " , vin . prevout . ToStringShort ( ) , blockHash . ToString ( ) ) ;
// maybe we stuck so we shouldn't ban this node, just fail to accept it
// TODO: or should we also request this block?
return false ;
}
if ( ( * mi ) . second & & ( * mi ) . second - > nHeight < chainActive . Height ( ) - 24 ) {
LogPrintf ( " CMasternodePing::CheckAndUpdate -- Masternode is too old: masternode=%s blockHash=%s \n " , vin . prevout . ToStringShort ( ) , blockHash . ToString ( ) ) ;
// Do nothing here (no Masternode update, no mnping relay)
// Let this node to be visible but fail to accept mnping
return false ;
}
}
2015-06-09 03:36:33 +02:00
2016-09-15 15:30:51 +02:00
// so, ping seems to be ok, let's store it
LogPrint ( " masternode " , " CMasternodePing::CheckAndUpdate -- Masternode ping accepted, masternode=%s \n " , vin . prevout . ToStringShort ( ) ) ;
pmn - > lastPing = * this ;
2015-07-14 07:25:07 +02:00
2016-09-15 15:30:51 +02:00
// and update mnodeman.mapSeenMasternodeBroadcast.lastPing which is probably outdated
CMasternodeBroadcast mnb ( * pmn ) ;
uint256 hash = mnb . GetHash ( ) ;
if ( mnodeman . mapSeenMasternodeBroadcast . count ( hash ) ) {
mnodeman . mapSeenMasternodeBroadcast [ hash ] . lastPing = * this ;
2015-04-17 17:10:38 +02:00
}
2016-09-15 15:30:51 +02:00
pmn - > Check ( true ) ; // force update, ignoring cache
if ( ! pmn - > IsEnabled ( ) ) return false ;
LogPrint ( " masternode " , " CMasternodePing::CheckAndUpdate -- Masternode ping acceepted and relayed, masternode=%s \n " , vin . prevout . ToStringShort ( ) ) ;
Relay ( ) ;
return true ;
2015-04-17 17:10:38 +02:00
}
void CMasternodePing : : Relay ( )
{
2015-04-22 16:33:44 +02:00
CInv inv ( MSG_MASTERNODE_PING , GetHash ( ) ) ;
2015-07-08 02:37:23 +02:00
RelayInv ( inv ) ;
2015-06-09 03:36:33 +02:00
}
2016-08-17 09:08:25 +02:00
void CMasternode : : AddGovernanceVote ( uint256 nGovernanceObjectHash )
{
if ( mapGovernaceObjectsVotedOn . count ( nGovernanceObjectHash ) )
{
mapGovernaceObjectsVotedOn [ nGovernanceObjectHash ] + + ;
} else {
mapGovernaceObjectsVotedOn . insert ( make_pair ( nGovernanceObjectHash , 1 ) ) ;
}
}
/**
* FLAG GOVERNANCE ITEMS AS DIRTY
*
* - When masternode come and go on the network , we must flag the items they voted on to recalc it ' s cached flags
*
*/
void CMasternode : : FlagGovernanceItemsAsDirty ( )
{
std : : map < uint256 , int > : : iterator it = mapGovernaceObjectsVotedOn . begin ( ) ;
while ( it ! = mapGovernaceObjectsVotedOn . end ( ) ) {
CGovernanceObject * pObj = governance . FindGovernanceObject ( ( * it ) . first ) ;
if ( pObj ) pObj - > fDirtyCache = true ;
+ + it ;
}
}