2015-03-18 00:06:58 +01:00
// Copyright (c) 2014-2015 The Dash 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.
2014-12-09 02:17:57 +01:00
# include "masternode.h"
2015-02-23 21:01:21 +01:00
# include "masternodeman.h"
2014-12-09 02:17:57 +01:00
# include "darksend.h"
# 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
// cache block hashes as we calculate them
std : : map < int64_t , uint256 > mapCacheBlockHashes ;
2014-12-09 02:17:57 +01:00
struct CompareValueOnly
{
bool operator ( ) ( const pair < int64_t , CTxIn > & t1 ,
const pair < int64_t , CTxIn > & t2 ) const
{
return t1 . first < t2 . first ;
}
} ;
2015-02-05 23:56:59 +01:00
//Get the last hash that matches the modulus given. Processed in reverse order
bool GetBlockHash ( uint256 & hash , int nBlockHeight )
{
2015-02-13 15:55:08 +01:00
if ( chainActive . Tip ( ) = = NULL ) return false ;
if ( nBlockHeight = = 0 )
nBlockHeight = chainActive . Tip ( ) - > nHeight ;
2015-02-05 23:56:59 +01:00
if ( mapCacheBlockHashes . count ( nBlockHeight ) ) {
hash = mapCacheBlockHashes [ nBlockHeight ] ;
return true ;
}
const CBlockIndex * BlockLastSolved = chainActive . Tip ( ) ;
const CBlockIndex * BlockReading = chainActive . Tip ( ) ;
if ( BlockLastSolved = = NULL | | BlockLastSolved - > nHeight = = 0 | | chainActive . Tip ( ) - > nHeight + 1 < nBlockHeight ) return false ;
int nBlocksAgo = 0 ;
if ( nBlockHeight > 0 ) nBlocksAgo = ( chainActive . Tip ( ) - > nHeight + 1 ) - nBlockHeight ;
assert ( nBlocksAgo > = 0 ) ;
int n = 0 ;
for ( unsigned int i = 1 ; BlockReading & & BlockReading - > nHeight > 0 ; i + + ) {
if ( n > = nBlocksAgo ) {
hash = BlockReading - > GetBlockHash ( ) ;
2015-02-09 21:36:45 +01:00
mapCacheBlockHashes [ nBlockHeight ] = hash ;
2015-02-05 23:56:59 +01:00
return true ;
}
n + + ;
if ( BlockReading - > pprev = = NULL ) { assert ( BlockReading ) ; break ; }
BlockReading = BlockReading - > pprev ;
}
return false ;
}
2015-02-23 21:01:21 +01:00
CMasternode : : CMasternode ( )
{
LOCK ( cs ) ;
vin = CTxIn ( ) ;
addr = CService ( ) ;
pubkey = CPubKey ( ) ;
pubkey2 = CPubKey ( ) ;
sig = std : : vector < unsigned char > ( ) ;
activeState = MASTERNODE_ENABLED ;
2015-03-01 16:38:53 +01:00
sigTime = GetAdjustedTime ( ) ;
2015-07-14 07:25:07 +02:00
lastPing = CMasternodePing ( ) ;
2015-02-23 21:01:21 +01:00
cacheInputAge = 0 ;
cacheInputAgeBlock = 0 ;
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-04-22 16:33:44 +02:00
nVotedTimes = 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 ;
sig = other . sig ;
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 ;
2015-02-23 21:01:21 +01:00
cacheInputAge = other . cacheInputAge ;
cacheInputAgeBlock = other . cacheInputAgeBlock ;
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-04-22 16:33:44 +02:00
nVotedTimes = other . nVotedTimes ;
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 ;
sig = mnb . sig ;
activeState = MASTERNODE_ENABLED ;
sigTime = mnb . sigTime ;
2015-07-14 07:25:07 +02:00
lastPing = mnb . lastPing ;
2015-04-17 17:10:38 +02:00
cacheInputAge = 0 ;
cacheInputAgeBlock = 0 ;
unitTest = false ;
allowFreeTx = true ;
protocolVersion = mnb . protocolVersion ;
nLastDsq = 0 ;
nScanningErrorCount = 0 ;
nLastScanningErrorBlockHeight = 0 ;
2015-04-22 16:33:44 +02:00
nVotedTimes = 0 ;
2015-04-17 17:10:38 +02:00
}
//
// When a new masternode broadcast is sent, update our information
//
void CMasternode : : UpdateFromNewBroadcast ( CMasternodeBroadcast & mnb )
{
pubkey2 = mnb . pubkey2 ;
sigTime = mnb . sigTime ;
sig = mnb . sig ;
protocolVersion = mnb . protocolVersion ;
addr = mnb . addr ;
2015-07-14 07:25:07 +02:00
int nDoS = 0 ;
2015-07-20 19:38:02 +02:00
if ( mnb . lastPing = = CMasternodePing ( ) | | ( mnb . lastPing ! = CMasternodePing ( ) & & mnb . lastPing . CheckAndUpdate ( nDoS , false ) ) ) {
2015-07-14 07:25:07 +02:00
lastPing = mnb . lastPing ;
mapSeenMasternodePing [ lastPing . GetHash ( ) ] = lastPing ;
}
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
//
2015-02-23 21:01:21 +01:00
uint256 CMasternode : : CalculateScore ( int mod , int64_t nBlockHeight )
2014-12-09 02:17:57 +01:00
{
if ( chainActive . Tip ( ) = = NULL ) return 0 ;
uint256 hash = 0 ;
2015-02-07 20:35:33 +01:00
uint256 aux = vin . prevout . hash + vin . prevout . n ;
2015-02-05 23:56:59 +01:00
if ( ! GetBlockHash ( hash , nBlockHeight ) ) return 0 ;
2015-02-07 19:31:15 +01:00
2015-02-09 05:57:50 +01:00
uint256 hash2 = Hash ( BEGIN ( hash ) , END ( hash ) ) ;
2015-03-23 18:28:36 +01:00
uint256 hash3 = Hash ( BEGIN ( hash ) , END ( hash ) , BEGIN ( aux ) , END ( aux ) ) ;
2015-02-07 19:31:15 +01:00
uint256 r = ( hash3 > hash2 ? hash3 - hash2 : hash2 - hash3 ) ;
return r ;
2014-12-09 02:17:57 +01:00
}
2015-02-23 21:01:21 +01:00
void CMasternode : : Check ( )
2014-12-09 02:17:57 +01:00
{
2015-07-03 00:09:14 +02:00
if ( ShutdownRequested ( ) ) return ;
2015-03-22 04:26:48 +01:00
//TODO: Random segfault with this line removed
TRY_LOCK ( cs_main , lockRecv ) ;
if ( ! lockRecv ) return ;
2015-03-06 23:17:51 +01:00
2014-12-09 02:17:57 +01:00
//once spent, stop doing the checks
2015-02-23 21:01:21 +01:00
if ( activeState = = MASTERNODE_VIN_SPENT ) return ;
2014-12-09 02:17:57 +01:00
2015-07-14 07:25:07 +02:00
if ( ! IsPingedWithin ( MASTERNODE_REMOVAL_SECONDS ) ) {
2015-02-23 21:01:21 +01:00
activeState = MASTERNODE_REMOVE ;
2014-12-09 02:17:57 +01:00
return ;
}
2015-07-14 07:25:07 +02:00
if ( ! IsPingedWithin ( MASTERNODE_EXPIRATION_SECONDS ) ) {
2015-02-23 21:01:21 +01:00
activeState = MASTERNODE_EXPIRED ;
2014-12-09 02:17:57 +01:00
return ;
}
if ( ! unitTest ) {
CValidationState state ;
2015-04-03 00:51:08 +02:00
CMutableTransaction tx = CMutableTransaction ( ) ;
2014-12-09 02:17:57 +01:00
CTxOut vout = CTxOut ( 999.99 * COIN , darkSendPool . collateralPubKey ) ;
tx . vin . push_back ( vin ) ;
tx . vout . push_back ( vout ) ;
2015-04-07 04:56:10 +02:00
if ( ! AcceptableInputs ( mempool , state , CTransaction ( tx ) , false , NULL ) ) {
2015-02-23 21:01:21 +01:00
activeState = MASTERNODE_VIN_SPENT ;
2014-12-09 02:17:57 +01:00
return ;
}
}
2015-02-23 21:01:21 +01:00
activeState = MASTERNODE_ENABLED ; // OK
2015-04-17 17:10:38 +02:00
}
2015-06-17 22:00:02 +02:00
int64_t CMasternode : : SecondsSincePayment ( ) {
2015-06-23 18:38:28 +02:00
CScript pubkeyScript ;
pubkeyScript = GetScriptForDestination ( pubkey . GetID ( ) ) ;
2015-07-21 00:09:42 +02:00
int64_t sec = ( GetAdjustedTime ( ) - GetLastPaid ( ) ) ;
2015-06-17 22:00:02 +02:00
int64_t month = 60 * 60 * 24 * 30 ;
if ( sec < month ) return sec ; //if it's less than 30 days, give seconds
CHashWriter ss ( SER_GETHASH , PROTOCOL_VERSION ) ;
ss < < vin ;
ss < < sigTime ;
uint256 hash = ss . GetHash ( ) ;
// return some deterministic value for unknown/unpaid but force it to be more than 30 days old
return month + hash . GetCompact ( false ) ;
}
2015-04-17 17:10:38 +02:00
2015-06-23 18:38:28 +02:00
int64_t CMasternode : : GetLastPaid ( ) {
2015-07-21 00:09:42 +02:00
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( pindexPrev = = NULL ) return false ;
CScript mnpayee ;
mnpayee = GetScriptForDestination ( pubkey . GetID ( ) ) ;
2015-07-22 01:11:49 +02:00
CHashWriter ss ( SER_GETHASH , PROTOCOL_VERSION ) ;
ss < < vin ;
ss < < sigTime ;
uint256 hash = ss . GetHash ( ) ;
// use a deterministic offset to break a tie -- 2.5 minutes
int64_t nOffset = hash . GetCompact ( false ) % 150 ;
2015-07-21 00:09:42 +02:00
for ( int64_t h = pindexPrev - > nHeight - mnodeman . CountEnabled ( ) * 0.95 ; h < = pindexPrev - > nHeight + 10 ; h + + ) {
2015-07-21 04:24:43 +02:00
if ( masternodePayments . mapMasternodeBlocks . count ( h ) ) {
2015-07-21 00:09:42 +02:00
/*
Search for this payee , with at least 2 votes . This will aid in consensus allowing the network
to converge on the same payees quickly , then keep the same schedule .
*/
2015-07-21 04:24:43 +02:00
if ( masternodePayments . mapMasternodeBlocks [ h ] . HasPayeeWithVotes ( mnpayee , 2 ) ) {
2015-07-22 01:11:49 +02:00
int64_t nTimeEstimate = pindexPrev - > nTime - ( pindexPrev - > nHeight - h ) * 2.5 ;
return nTimeEstimate + nOffset ;
2015-07-21 00:09:42 +02:00
}
}
}
2015-06-23 18:38:28 +02:00
2015-07-21 00:09:42 +02:00
return 0 ;
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 ( ) ;
sig = std : : vector < unsigned char > ( ) ;
activeState = MASTERNODE_ENABLED ;
sigTime = GetAdjustedTime ( ) ;
2015-07-14 07:25:07 +02:00
lastPing = CMasternodePing ( ) ;
2015-04-17 17:10:38 +02:00
cacheInputAge = 0 ;
cacheInputAgeBlock = 0 ;
unitTest = false ;
allowFreeTx = true ;
2015-07-19 01:20:48 +02:00
protocolVersion = PROTOCOL_VERSION ;
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 ;
sig = std : : vector < unsigned char > ( ) ;
activeState = MASTERNODE_ENABLED ;
sigTime = GetAdjustedTime ( ) ;
2015-07-14 07:25:07 +02:00
lastPing = CMasternodePing ( ) ;
2015-04-17 17:10:38 +02:00
cacheInputAge = 0 ;
cacheInputAgeBlock = 0 ;
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 ;
sig = mn . sig ;
activeState = mn . activeState ;
sigTime = mn . sigTime ;
lastPing = mn . lastPing ;
cacheInputAge = mn . cacheInputAge ;
cacheInputAgeBlock = mn . cacheInputAgeBlock ;
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
}
2015-07-14 07:25:07 +02:00
bool CMasternodeBroadcast : : CheckAndUpdate ( int & nDos )
2015-04-17 17:10:38 +02:00
{
// make sure signature isn't in the future (past is OK)
if ( sigTime > GetAdjustedTime ( ) + 60 * 60 ) {
2015-07-14 07:25:07 +02:00
LogPrintf ( " mnb - Signature rejected, too far into the future %s \n " , vin . ToString ( ) ) ;
nDos = 1 ;
2015-04-17 17:10:38 +02:00
return false ;
}
std : : string vchPubKey ( pubkey . begin ( ) , pubkey . end ( ) ) ;
std : : string vchPubKey2 ( pubkey2 . begin ( ) , pubkey2 . end ( ) ) ;
2015-06-23 18:38:28 +02:00
std : : string strMessage = addr . ToString ( ) + boost : : lexical_cast < std : : string > ( sigTime ) + vchPubKey + vchPubKey2 + boost : : lexical_cast < std : : string > ( protocolVersion ) ;
2015-04-17 17:10:38 +02:00
2015-07-20 07:03:36 +02:00
if ( protocolVersion < masternodePayments . GetMinMasternodePaymentsProto ( ) ) {
2015-06-23 17:40:08 +02:00
LogPrintf ( " mnb - ignoring outdated Masternode %s protocol version %d \n " , vin . ToString ( ) . c_str ( ) , protocolVersion ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
CScript pubkeyScript ;
pubkeyScript = GetScriptForDestination ( pubkey . GetID ( ) ) ;
if ( pubkeyScript . size ( ) ! = 25 ) {
2015-06-23 17:40:08 +02:00
LogPrintf ( " mnb - 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 ) {
2015-06-23 17:40:08 +02:00
LogPrintf ( " mnb - pubkey2 the wrong size \n " ) ;
2015-04-17 17:10:38 +02:00
nDos = 100 ;
return false ;
}
if ( ! vin . scriptSig . empty ( ) ) {
2015-06-23 17:40:08 +02:00
LogPrintf ( " mnb - Ignore Not Empty ScriptSig %s \n " , vin . ToString ( ) . c_str ( ) ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
std : : string errorMessage = " " ;
if ( ! darkSendSigner . VerifyMessage ( pubkey , sig , strMessage , errorMessage ) ) {
2015-06-23 17:40:08 +02:00
LogPrintf ( " mnb - Got bad Masternode address signature \n " ) ;
2015-04-17 17:10:38 +02:00
nDos = 100 ;
return false ;
}
if ( Params ( ) . NetworkID ( ) = = CBaseChainParams : : MAIN ) {
if ( addr . GetPort ( ) ! = 9999 ) return false ;
} else if ( addr . GetPort ( ) = = 9999 ) return false ;
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
2015-07-14 07:25:07 +02:00
// no such masternode or it's not enabled already, nothing to update
if ( pmn = = NULL | | ( pmn ! = NULL & & ! pmn - > IsEnabled ( ) ) ) return true ;
// 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
LogPrintf ( " mnb - Got updated entry for %s \n " , addr . ToString ( ) . c_str ( ) ) ;
pmn - > UpdateFromNewBroadcast ( ( * this ) ) ;
pmn - > Check ( ) ;
if ( pmn - > IsEnabled ( ) ) Relay ( ) ;
2015-07-19 01:25:52 +02:00
masternodeSync . AddedMasternodeList ( ) ;
2015-04-17 17:10:38 +02:00
}
return true ;
}
2015-07-14 07:25:07 +02: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 ;
// search existing Masternode list
CMasternode * pmn = mnodeman . Find ( vin ) ;
if ( pmn ! = NULL ) {
// nothing to do here if we already know about this masternode and it's enabled
if ( pmn - > IsEnabled ( ) ) return true ;
// if it's not enabled, remove old MN first and continue
else mnodeman . Remove ( pmn - > vin ) ;
}
2015-04-17 17:10:38 +02:00
CValidationState state ;
CMutableTransaction tx = CMutableTransaction ( ) ;
CTxOut vout = CTxOut ( 999.99 * COIN , darkSendPool . collateralPubKey ) ;
tx . vin . push_back ( vin ) ;
tx . vout . push_back ( vout ) ;
if ( AcceptableInputs ( mempool , state , CTransaction ( tx ) , false , NULL ) ) {
2015-06-23 17:40:08 +02:00
if ( fDebug ) LogPrintf ( " mnb - Accepted Masternode entry \n " ) ;
2015-04-17 17:10:38 +02:00
if ( GetInputAge ( vin ) < MASTERNODE_MIN_CONFIRMATIONS ) {
2015-06-23 17:40:08 +02:00
LogPrintf ( " mnb - Input must have least %d confirmations \n " , MASTERNODE_MIN_CONFIRMATIONS ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
// verify that sig time is legit in past
// should be at least not earlier than block when 1000 DASH tx got MASTERNODE_MIN_CONFIRMATIONS
uint256 hashBlock = 0 ;
CTransaction tx2 ;
GetTransaction ( vin . prevout . hash , tx2 , hashBlock , true ) ;
BlockMap : : iterator mi = mapBlockIndex . find ( hashBlock ) ;
if ( mi ! = mapBlockIndex . end ( ) & & ( * mi ) . second )
{
CBlockIndex * pMNIndex = ( * mi ) . second ; // block for 1000 DASH tx -> 1 confirmation
CBlockIndex * pConfIndex = chainActive [ pMNIndex - > nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1 ] ; // block where tx got MASTERNODE_MIN_CONFIRMATIONS
if ( pConfIndex - > GetBlockTime ( ) > sigTime )
{
2015-06-23 17:40:08 +02:00
LogPrintf ( " mnb - Bad sigTime %d for Masternode %20s %105s (%i conf block is at %d) \n " ,
2015-04-17 17:10:38 +02:00
sigTime , addr . ToString ( ) , vin . ToString ( ) , MASTERNODE_MIN_CONFIRMATIONS , pConfIndex - > GetBlockTime ( ) ) ;
return false ;
}
}
2015-07-20 20:43:10 +02:00
LogPrintf ( " mnb - Got NEW Masternode entry - %s - %s - %s - %lli \n " , GetHash ( ) . ToString ( ) , addr . ToString ( ) , vin . ToString ( ) , sigTime ) ;
2015-07-14 07:25:07 +02:00
CMasternode mn ( * this ) ;
2015-04-17 17:10:38 +02:00
mnodeman . Add ( mn ) ;
// if it matches our Masternode privkey, then we've been remotely activated
if ( pubkey2 = = activeMasternode . pubKeyMasternode & & protocolVersion = = PROTOCOL_VERSION ) {
activeMasternode . EnableHotColdMasterNode ( vin , addr ) ;
}
bool isLocal = addr . IsRFC1918 ( ) | | addr . IsLocal ( ) ;
if ( Params ( ) . NetworkID ( ) = = CBaseChainParams : : REGTEST ) isLocal = false ;
2015-07-14 07:25:07 +02:00
if ( ! isLocal ) Relay ( ) ;
2015-04-17 17:10:38 +02:00
return true ;
} else {
//set nDos
state . IsInvalid ( nDoS ) ;
}
return false ;
}
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
{
2015-04-17 17:10:38 +02:00
std : : string errorMessage ;
std : : string vchPubKey ( pubkey . begin ( ) , pubkey . end ( ) ) ;
std : : string vchPubKey2 ( pubkey2 . begin ( ) , pubkey2 . end ( ) ) ;
sigTime = GetAdjustedTime ( ) ;
2015-06-23 18:38:28 +02:00
std : : string strMessage = addr . ToString ( ) + boost : : lexical_cast < std : : string > ( sigTime ) + vchPubKey + vchPubKey2 + boost : : lexical_cast < std : : string > ( protocolVersion ) ;
2015-04-17 17:10:38 +02:00
if ( ! darkSendSigner . SignMessage ( strMessage , errorMessage , sig , keyCollateralAddress ) ) {
LogPrintf ( " CMasternodeBroadcast::Sign() - Error: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
}
if ( ! darkSendSigner . VerifyMessage ( pubkey , sig , strMessage , errorMessage ) ) {
LogPrintf ( " CMasternodeBroadcast::Sign() - Error: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
}
return true ;
}
CMasternodePing : : CMasternodePing ( )
{
vin = CTxIn ( ) ;
2015-07-14 07:25:07 +02:00
blockHash = uint256 ( 0 ) ;
sigTime = 0 ;
vchSig = std : : vector < unsigned char > ( ) ;
2015-04-17 17:10:38 +02:00
}
CMasternodePing : : CMasternodePing ( CTxIn & newVin )
{
vin = newVin ;
2015-06-09 03:36:33 +02:00
blockHash = chainActive [ chainActive . Height ( ) - 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 )
{
std : : string errorMessage ;
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
if ( ! darkSendSigner . SignMessage ( strMessage , errorMessage , vchSig , keyMasternode ) ) {
LogPrintf ( " CMasternodePing::Sign() - Error: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
}
if ( ! darkSendSigner . VerifyMessage ( pubKeyMasternode , vchSig , strMessage , errorMessage ) ) {
LogPrintf ( " CMasternodePing::Sign() - Error: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
}
return true ;
}
2015-07-20 19:38:02 +02:00
bool CMasternodePing : : CheckAndUpdate ( int & nDos , bool fRequireEnabled )
2015-04-17 17:10:38 +02:00
{
if ( sigTime > GetAdjustedTime ( ) + 60 * 60 ) {
2015-07-14 07:25:07 +02:00
LogPrintf ( " CMasternodePing::CheckAndUpdate - Signature rejected, too far into the future %s \n " , vin . ToString ( ) . c_str ( ) ) ;
nDos = 1 ;
2015-04-17 17:10:38 +02:00
return false ;
}
if ( sigTime < = GetAdjustedTime ( ) - 60 * 60 ) {
2015-07-14 07:25:07 +02:00
LogPrintf ( " CMasternodePing::CheckAndUpdate - Signature rejected, too far into the past %s - %d %d \n " , vin . ToString ( ) . c_str ( ) , sigTime , GetAdjustedTime ( ) ) ;
nDos = 1 ;
2015-04-17 17:10:38 +02:00
return false ;
}
2015-07-20 20:43:10 +02:00
if ( fDebug ) LogPrintf ( " CMasternodePing::CheckAndUpdate - New Ping - %s - %s - %lli \n " , GetHash ( ) . ToString ( ) , blockHash . ToString ( ) , sigTime ) ;
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
if ( pmn ! = NULL & & pmn - > protocolVersion > = masternodePayments . GetMinMasternodePaymentsProto ( ) )
2015-04-17 17:10:38 +02:00
{
2015-07-20 20:56:02 +02:00
if ( fRequireEnabled & & ! pmn - > IsEnabled ( ) ) return false ;
2015-04-17 17:10:38 +02:00
// LogPrintf("mnping - Found corresponding mn for vin: %s\n", vin.ToString().c_str());
2015-07-14 07:25:07 +02:00
// 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 ) )
2015-04-17 17:10:38 +02:00
{
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
std : : string errorMessage = " " ;
if ( ! darkSendSigner . VerifyMessage ( pmn - > pubkey2 , vchSig , strMessage , errorMessage ) )
{
2015-07-14 07:25:07 +02:00
LogPrintf ( " CMasternodePing::CheckAndUpdate - Got bad Masternode address signature %s \n " , vin . ToString ( ) ) ;
2015-04-17 17:10:38 +02:00
nDos = 33 ;
return false ;
}
2015-06-09 03:36:33 +02:00
BlockMap : : iterator mi = mapBlockIndex . find ( blockHash ) ;
if ( mi ! = mapBlockIndex . end ( ) & & ( * mi ) . second )
2015-04-17 17:10:38 +02:00
{
2015-06-09 03:36:33 +02:00
if ( ( * mi ) . second - > nHeight < chainActive . Height ( ) - 24 )
{
2015-07-14 07:25:07 +02:00
LogPrintf ( " CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is too old \n " , vin . ToString ( ) , blockHash . ToString ( ) ) ;
2015-06-18 20:41:01 +02:00
// Do nothing here (no Masternode update, no mnping relay)
// Let this node to be visible but fail to accept mnping
2015-06-20 21:56:56 +02:00
2015-06-09 03:36:33 +02:00
return false ;
}
} else {
2015-07-14 07:25:07 +02:00
if ( fDebug ) LogPrintf ( " CMasternodePing::CheckAndUpdate - Masternode %s block hash %s is unknown \n " , vin . ToString ( ) , blockHash . ToString ( ) ) ;
2015-06-09 03:36:33 +02:00
// maybe we stuck so we shouldn't ban this node, just fail to accept it
// TODO: or should we also request this block?
2015-06-20 21:56:56 +02:00
2015-06-09 03:36:33 +02:00
return false ;
2015-04-17 17:10:38 +02:00
}
2015-06-09 03:36:33 +02:00
2015-07-14 07:25:07 +02:00
pmn - > lastPing = * this ;
2015-06-09 03:36:33 +02:00
pmn - > Check ( ) ;
if ( ! pmn - > IsEnabled ( ) ) return false ;
2015-07-14 07:25:07 +02:00
if ( fDebug ) LogPrintf ( " CMasternodePing::CheckAndUpdate - Masternode ping accepted, vin: %s \n " , vin . ToString ( ) ) ;
2015-06-09 03:36:33 +02:00
Relay ( ) ;
return true ;
2015-04-17 17:10:38 +02:00
}
2015-07-14 07:25:07 +02:00
if ( fDebug ) LogPrintf ( " CMasternodePing::CheckAndUpdate - Masternode ping arrived too early, vin: %s \n " , vin . ToString ( ) ) ;
2015-07-19 17:49:46 +02:00
//nDos = 1; //disable, this is happening frequently and causing banned peers
2015-07-14 07:25:07 +02:00
return false ;
2015-04-17 17:10:38 +02:00
}
2015-07-14 07:25:07 +02:00
if ( fDebug ) LogPrintf ( " CMasternodePing::CheckAndUpdate - Couldn't find compatible Masternode entry, vin: %s \n " , vin . ToString ( ) ) ;
2015-04-17 17:10:38 +02:00
return false ;
}
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
}