2016-02-02 16:28:56 +01:00
// Copyright (c) 2014-2016 The Dash Core developers
2015-04-16 21:58:09 +02:00
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# include "masternode-payments.h"
2016-04-15 04:54:11 +02:00
# include "governance.h"
2015-07-15 04:44:58 +02:00
# include "masternode-sync.h"
2015-04-16 21:58:09 +02:00
# include "masternodeman.h"
# include "darksend.h"
2016-08-05 21:49:45 +02:00
# include "activemasternode.h"
2016-08-17 09:08:25 +02:00
# include "governance-classes.h"
2015-04-16 21:58:09 +02:00
# include "util.h"
# include "sync.h"
2015-05-30 19:27:51 +02:00
# include "spork.h"
2015-04-16 21:58:09 +02:00
# include "addrman.h"
# include <boost/lexical_cast.hpp>
2015-07-21 04:24:43 +02:00
# include <boost/filesystem.hpp>
2015-04-16 21:58:09 +02:00
/** Object for who's going to get paid on which blocks */
2016-02-04 20:29:09 +01:00
CMasternodePayments mnpayments ;
2015-07-21 04:24:43 +02:00
2015-07-29 17:28:49 +02:00
CCriticalSection cs_vecPayments ;
CCriticalSection cs_mapMasternodeBlocks ;
CCriticalSection cs_mapMasternodePayeeVotes ;
2016-08-17 09:08:25 +02:00
/**
* IsBlockValueValid
*
* Determine if coinbase outgoing created money is the correct value
*
* Why is this needed ?
* - In Dash some blocks are superblocks , which output much higher amounts of coins
* - Otherblocks are 10 % lower in outgoing value , so in total , no extra coins are created
* - When non - superblocks are detected , the normal schedule should be maintained
*/
2016-08-22 03:41:40 +02:00
bool IsBlockValueValid ( const CBlock & block , int nBlockHeight , CAmount blockReward )
{
bool isNormalBlockValueMet = ( block . vtx [ 0 ] . GetValueOut ( ) < = blockReward ) ;
if ( fDebug ) LogPrintf ( " block.vtx[0].GetValueOut() %lld <= blockReward %lld \n " , block . vtx [ 0 ] . GetValueOut ( ) , blockReward ) ;
// we are still using budgets, but we have no data about them anymore,
// all we know is predefined budget cycle and window
const Consensus : : Params & consensusParams = Params ( ) . GetConsensus ( ) ;
if ( nBlockHeight < consensusParams . nSuperblockStartBlock ) {
int nOffset = nBlockHeight % consensusParams . nBudgetPaymentsCycleBlocks ;
if ( nBlockHeight > = consensusParams . nBudgetPaymentsStartBlock & &
nOffset < consensusParams . nBudgetPaymentsWindowBlocks ) {
// NOTE: make sure SPORK_13_OLD_SUPERBLOCK_FLAG is disabled when 12.1 starts to go live
if ( masternodeSync . IsSynced ( ) & & ! sporkManager . IsSporkActive ( SPORK_13_OLD_SUPERBLOCK_FLAG ) ) {
// no budget blocks should be accepted here, if SPORK_13_OLD_SUPERBLOCK_FLAG is disabled
LogPrint ( " gobject " , " IsBlockValueValid -- Client synced but budget spork is disabled, checking block value against normal block reward \n " ) ;
return isNormalBlockValueMet ;
2016-08-17 09:08:25 +02:00
}
2016-08-22 03:41:40 +02:00
LogPrint ( " gobject " , " IsBlockValueValid -- WARNING: Skipping budget block value checks, accepting block \n " ) ;
// TODO: reprocess blocks to make sure they are legit?
return true ;
2016-03-02 21:57:24 +01:00
}
2016-08-22 03:41:40 +02:00
// LogPrint("gobject", "IsBlockValueValid -- Block is not in budget cycle window, checking block value against normal block reward\n");
return isNormalBlockValueMet ;
2016-03-02 21:57:24 +01:00
}
2016-08-17 09:08:25 +02:00
2016-08-22 03:41:40 +02:00
// superblocks started
2015-07-04 16:49:49 +02:00
2016-08-22 03:41:40 +02:00
CAmount nSuperblockPaymentsLimit = CSuperblock : : GetPaymentsLimit ( nBlockHeight ) ;
bool isSuperblockMaxValueMet = ( block . vtx [ 0 ] . GetValueOut ( ) < = blockReward + nSuperblockPaymentsLimit ) ;
2015-08-11 23:54:42 +02:00
2016-08-22 03:41:40 +02:00
LogPrint ( " gobject " , " block.vtx[0].GetValueOut() %lld <= nSuperblockPaymentsLimit %lld \n " , block . vtx [ 0 ] . GetValueOut ( ) , nSuperblockPaymentsLimit ) ;
2016-07-30 13:04:27 +02:00
2016-08-17 09:08:25 +02:00
if ( ! masternodeSync . IsSynced ( ) ) {
2016-08-22 03:41:40 +02:00
// not enough data but at least it must NOT exceed superblock max value
if ( CSuperblock : : IsValidBlockHeight ( nBlockHeight ) ) {
if ( fDebug ) LogPrintf ( " IsBlockPayeeValid -- WARNING: Client not synced, checking superblock max bounds only \n " ) ;
return isSuperblockMaxValueMet ;
}
// it MUST be a regular block otherwise
return isNormalBlockValueMet ;
2016-08-17 09:08:25 +02:00
}
2016-08-22 03:41:40 +02:00
// we are synced, let's try to check as much data as we can
2016-08-17 09:08:25 +02:00
2016-08-22 03:41:40 +02:00
if ( CSuperblockManager : : IsSuperblockTriggered ( nBlockHeight ) ) {
if ( CSuperblockManager : : IsValid ( block . vtx [ 0 ] , nBlockHeight , blockReward ) ) {
LogPrint ( " gobject " , " IsBlockValueValid -- Valid superblock at height %d: %s " , nBlockHeight , block . vtx [ 0 ] . ToString ( ) ) ;
// all checks are done in CSuperblock::IsValid, nothing to do here
return true ;
}
2016-08-17 09:08:25 +02:00
2016-08-22 03:41:40 +02:00
// triggered but invalid? that's weird
if ( sporkManager . IsSporkActive ( SPORK_9_MASTERNODE_SUPERBLOCK_ENFORCEMENT ) ) {
LogPrintf ( " IsBlockValueValid -- ERROR: Invalid superblock detected at height %d: %s " , nBlockHeight , block . vtx [ 0 ] . ToString ( ) ) ;
// should NOT allow invalid superblocks, when superblock enforcement is enabled
return false ;
}
// should NOT allow superblocks at all, when superblock enforcement is disabled
LogPrintf ( " IsBlockValueValid -- Superblock enforcement is disabled, no superblocks allowed \n " ) ;
2015-05-30 19:27:51 +02:00
}
2016-08-22 03:41:40 +02:00
LogPrint ( " gobject " , " IsBlockValueValid -- No valid superblock detected at height %d \n " , nBlockHeight ) ;
// it MUST be a regular block
return isNormalBlockValueMet ;
2015-05-30 19:27:51 +02:00
}
2016-08-22 03:41:40 +02:00
bool IsBlockPayeeValid ( const CTransaction & txNew , int nBlockHeight , CAmount blockReward )
2015-05-04 17:04:09 +02:00
{
2016-08-22 03:41:40 +02:00
if ( ! masternodeSync . IsSynced ( ) ) {
//there is no budget data to use to check anything, let's just accept the longest chain
if ( fDebug ) LogPrintf ( " IsBlockPayeeValid -- WARNING: Client not synced, skipping block payee checks \n " ) ;
2015-07-18 15:46:54 +02:00
return true ;
}
2016-08-22 03:41:40 +02:00
// we are still using budgets, but we have no data about them anymore,
// we can only check masternode payments
2016-08-17 09:08:25 +02:00
2016-08-22 03:41:40 +02:00
const Consensus : : Params & consensusParams = Params ( ) . GetConsensus ( ) ;
2016-08-17 09:08:25 +02:00
2016-08-22 03:41:40 +02:00
if ( nBlockHeight < consensusParams . nSuperblockStartBlock ) {
if ( mnpayments . IsTransactionValid ( txNew , nBlockHeight ) ) {
LogPrint ( " mnpayments " , " IsBlockPayeeValid -- Valid masternode payment at height %d: %s " , nBlockHeight , txNew . ToString ( ) ) ;
2016-08-17 09:08:25 +02:00
return true ;
2016-08-22 03:41:40 +02:00
}
int nOffset = nBlockHeight % consensusParams . nBudgetPaymentsCycleBlocks ;
if ( nBlockHeight > = consensusParams . nBudgetPaymentsStartBlock & &
nOffset < consensusParams . nBudgetPaymentsWindowBlocks ) {
if ( ! sporkManager . IsSporkActive ( SPORK_13_OLD_SUPERBLOCK_FLAG ) ) {
// no budget blocks should be accepted here, if SPORK_13_OLD_SUPERBLOCK_FLAG is disabled
LogPrint ( " gobject " , " IsBlockPayeeValid -- ERROR: Client synced but budget spork is disabled and masternode payment is invalid \n " ) ;
2016-08-17 09:08:25 +02:00
return false ;
}
2016-08-22 03:41:40 +02:00
// NOTE: this should never happen in real, SPORK_13_OLD_SUPERBLOCK_FLAG MUST be disabled when 12.1 starts to go live
LogPrint ( " gobject " , " IsBlockPayeeValid -- WARNING: Probably valid budget block, have no data, accepting \n " ) ;
// TODO: reprocess blocks to make sure they are legit?
return true ;
}
if ( sporkManager . IsSporkActive ( SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT ) ) {
LogPrintf ( " IsBlockPayeeValid -- ERROR: Invalid masternode payment detected at height %d: %s " , nBlockHeight , txNew . ToString ( ) ) ;
return false ;
2016-08-17 09:08:25 +02:00
}
2016-08-22 03:41:40 +02:00
LogPrintf ( " IsBlockPayeeValid -- WARNING: Masternode payment enforcement is disabled, accepting any payee \n " ) ;
return true ;
2016-08-17 09:08:25 +02:00
}
2016-08-22 03:41:40 +02:00
// superblocks started
// SEE IF THIS IS A VALID SUPERBLOCK
2016-08-17 09:08:25 +02:00
2016-08-22 03:41:40 +02:00
if ( CSuperblockManager : : IsSuperblockTriggered ( nBlockHeight ) ) {
if ( CSuperblockManager : : IsValid ( txNew , nBlockHeight , blockReward ) ) {
LogPrint ( " gobject " , " IsBlockPayeeValid -- Valid superblock at height %d: %s " , nBlockHeight , txNew . ToString ( ) ) ;
2015-05-30 19:27:51 +02:00
return true ;
}
2015-05-04 17:04:09 +02:00
2016-08-22 03:41:40 +02:00
if ( sporkManager . IsSporkActive ( SPORK_9_MASTERNODE_SUPERBLOCK_ENFORCEMENT ) ) {
LogPrintf ( " IsBlockPayeeValid -- ERROR: Invalid superblock detected at height %d: %s " , nBlockHeight , txNew . ToString ( ) ) ;
// should NOT allow such superblocks, when superblock enforcement is enabled
return false ;
}
2015-05-04 17:04:09 +02:00
2016-08-22 03:41:40 +02:00
// should NOT allow superblocks at all, when superblock enforcement is disabled
LogPrintf ( " IsBlockPayeeValid -- Superblock enforcement is disabled, no superblocks allowed \n " ) ;
}
2015-05-30 19:27:51 +02:00
2016-08-22 03:41:40 +02:00
// continue validation, should pay MN
LogPrint ( " gobject " , " IsBlockPayeeValid -- No valid superblock detected at height %d \n " , nBlockHeight ) ;
2015-06-25 17:17:53 +02:00
2016-08-22 03:41:40 +02:00
// IF THIS ISN'T A SUPERBLOCK OR SUPERBLOCK IS INVALID, IT SHOULD PAY A MASTERNODE DIRECTLY
if ( mnpayments . IsTransactionValid ( txNew , nBlockHeight ) ) {
LogPrint ( " mnpayments " , " IsBlockPayeeValid -- Valid masternode payment at height %d: %s " , nBlockHeight , txNew . ToString ( ) ) ;
return true ;
}
2016-08-17 09:08:25 +02:00
2016-08-22 03:41:40 +02:00
if ( sporkManager . IsSporkActive ( SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT ) ) {
LogPrintf ( " IsBlockPayeeValid -- ERROR: Invalid masternode payment detected at height %d: %s " , nBlockHeight , txNew . ToString ( ) ) ;
return false ;
}
LogPrintf ( " IsBlockPayeeValid -- WARNING: Masternode payment enforcement is disabled, accepting any payee \n " ) ;
return true ;
}
2016-08-17 09:08:25 +02:00
2016-08-28 12:11:36 +02:00
void FillBlockPayments ( CMutableTransaction & txNew , int nBlockHeight , CAmount blockReward , CTxOut & txoutMasternodeRet , std : : vector < CTxOut > & voutSuperblockRet )
2016-08-22 03:41:40 +02:00
{
// only create superblocks if spork is enabled AND if superblock is actually triggered
// (height should be validated inside)
if ( sporkManager . IsSporkActive ( SPORK_9_MASTERNODE_SUPERBLOCK_ENFORCEMENT ) & &
CSuperblockManager : : IsSuperblockTriggered ( nBlockHeight ) ) {
2016-08-28 12:11:36 +02:00
LogPrint ( " gobject " , " FillBlockPayments -- triggered superblock creation at height %d \n " , nBlockHeight ) ;
CSuperblockManager : : CreateSuperblock ( txNew , nBlockHeight , voutSuperblockRet ) ;
2016-08-22 03:41:40 +02:00
return ;
2016-08-17 09:08:25 +02:00
}
// FILL BLOCK PAYEE WITH MASTERNODE PAYMENT OTHERWISE
2016-08-28 12:11:36 +02:00
mnpayments . FillBlockPayee ( txNew , nBlockHeight , blockReward , txoutMasternodeRet ) ;
LogPrint ( " mnpayments " , " FillBlockPayments -- nBlockHeight %d blockReward %lld txoutMasternodeRet %s txNew %s " ,
nBlockHeight , blockReward , txoutMasternodeRet . ToString ( ) , txNew . ToString ( ) ) ;
2015-05-30 19:27:51 +02:00
}
2015-07-17 17:07:07 +02:00
std : : string GetRequiredPaymentsString ( int nBlockHeight )
2015-05-26 16:56:51 +02:00
{
2016-08-22 03:41:40 +02:00
// IF WE HAVE A ACTIVATED TRIGGER FOR THIS HEIGHT - IT IS A SUPERBLOCK, GET THE REQUIRED PAYEES
2016-08-17 09:08:25 +02:00
if ( CSuperblockManager : : IsSuperblockTriggered ( nBlockHeight ) ) {
return CSuperblockManager : : GetRequiredPaymentsString ( nBlockHeight ) ;
}
// OTHERWISE, PAY MASTERNODE
2016-05-24 23:16:42 +02:00
return mnpayments . GetRequiredPaymentsString ( nBlockHeight ) ;
2015-05-26 16:56:51 +02:00
}
2016-08-17 09:08:25 +02:00
/**
* FillBlockPayee
*
* Fill Masternode ONLY payment block
*/
2016-08-28 12:11:36 +02:00
void CMasternodePayments : : FillBlockPayee ( CMutableTransaction & txNew , int nBlockHeight , CAmount blockReward , CTxOut & txoutMasternodeRet )
2015-05-30 19:27:51 +02:00
{
2016-08-28 12:11:36 +02:00
// make sure it's not filled yet
txoutMasternodeRet = CTxOut ( ) ;
2015-05-30 19:27:51 +02:00
CScript payee ;
2015-06-25 17:17:53 +02:00
2016-08-22 03:41:40 +02:00
if ( ! mnpayments . GetBlockPayee ( nBlockHeight , payee ) ) {
2016-08-28 12:11:36 +02:00
// no masternode detected...
2016-01-24 20:05:31 +01:00
CMasternode * winningNode = mnodeman . GetCurrentMasterNode ( ) ;
2016-08-28 12:11:36 +02:00
if ( ! winningNode ) {
// ...and we can't calculate it on our own
2016-08-22 03:41:40 +02:00
LogPrintf ( " CMasternodePayments::FillBlockPayee -- Failed to detect masternode to pay \n " ) ;
2016-08-28 12:11:36 +02:00
return ;
2015-05-30 19:27:51 +02:00
}
2016-08-28 12:11:36 +02:00
// fill payee with locally calculated winner and hope for the best
payee = GetScriptForDestination ( winningNode - > pubkey . GetID ( ) ) ;
2015-05-30 19:27:51 +02:00
}
2016-08-17 09:08:25 +02:00
// GET MASTERNODE PAYMENT VARIABLES SETUP
2016-08-22 03:41:40 +02:00
CAmount masternodePayment = GetMasternodePayment ( nBlockHeight , blockReward ) ;
2015-05-30 19:27:51 +02:00
2016-08-28 12:11:36 +02:00
// split reward between miner ...
txNew . vout [ 0 ] . nValue - = masternodePayment ;
// ... and masternode
txoutMasternodeRet = CTxOut ( masternodePayment , payee ) ;
txNew . vout . push_back ( txoutMasternodeRet ) ;
2015-05-30 19:27:51 +02:00
2016-08-28 12:11:36 +02:00
CTxDestination address1 ;
ExtractDestination ( payee , address1 ) ;
CBitcoinAddress address2 ( address1 ) ;
2015-05-30 19:27:51 +02:00
2016-08-28 12:11:36 +02:00
LogPrintf ( " CMasternodePayments::FillBlockPayee -- Masternode payment %lld to %s \n " , masternodePayment , address2 . ToString ( ) ) ;
2015-05-30 19:27:51 +02:00
}
2015-07-08 03:57:32 +02:00
int CMasternodePayments : : GetMinMasternodePaymentsProto ( ) {
2016-07-30 13:04:27 +02:00
return sporkManager . IsSporkActive ( SPORK_10_MASTERNODE_PAY_UPDATED_NODES )
2015-07-22 01:11:49 +02:00
? MIN_MASTERNODE_PAYMENT_PROTO_VERSION_2
: MIN_MASTERNODE_PAYMENT_PROTO_VERSION_1 ;
2015-07-08 03:57:32 +02:00
}
2016-05-24 23:16:42 +02:00
void CMasternodePayments : : ProcessMessage ( CNode * pfrom , std : : string & strCommand , CDataStream & vRecv )
2015-04-16 21:58:09 +02:00
{
2015-08-07 06:48:55 +02:00
if ( ! masternodeSync . IsBlockchainSynced ( ) ) return ;
2015-04-16 21:58:09 +02:00
2015-08-25 00:01:02 +02:00
if ( fLiteMode ) return ; //disable all Darksend/Masternode related functionality
2016-02-17 23:18:57 +01:00
if ( strCommand = = NetMsgType : : MNWINNERSSYNC ) { //Masternode Payments Request Sync
2016-08-05 18:25:03 +02:00
// ignore such request until we are fully synced
if ( ! masternodeSync . IsSynced ( ) ) return ;
2015-04-16 21:58:09 +02:00
2015-07-21 00:09:42 +02:00
int nCountNeeded ;
vRecv > > nCountNeeded ;
2016-02-02 16:28:56 +01:00
if ( Params ( ) . NetworkIDString ( ) = = CBaseChainParams : : MAIN ) {
2016-02-17 23:18:57 +01:00
if ( pfrom - > HasFulfilledRequest ( NetMsgType : : MNWINNERSSYNC ) ) {
2015-07-21 04:24:43 +02:00
LogPrintf ( " mnget - peer already asked me for the list \n " ) ;
Misbehaving ( pfrom - > GetId ( ) , 20 ) ;
return ;
}
2015-04-16 21:58:09 +02:00
}
2015-07-21 04:24:43 +02:00
2016-02-17 23:18:57 +01:00
pfrom - > FulfilledRequest ( NetMsgType : : MNWINNERSSYNC ) ;
2016-05-30 08:22:30 +02:00
Sync ( pfrom , nCountNeeded ) ;
2016-03-04 06:58:53 +01:00
LogPrintf ( " mnget - Sent Masternode winners to %s \n " , pfrom - > addr . ToString ( ) ) ;
2015-04-16 21:58:09 +02:00
}
2016-02-17 23:18:57 +01:00
else if ( strCommand = = NetMsgType : : MNWINNER ) { //Masternode Payments Declare Winner
2015-05-27 21:47:01 +02:00
//this is required in litemodef
2015-04-16 21:58:09 +02:00
CMasternodePaymentWinner winner ;
vRecv > > winner ;
2015-08-15 01:19:46 +02:00
if ( pfrom - > nVersion < MIN_MNW_PEER_PROTO_VERSION ) return ;
2016-03-02 22:20:04 +01:00
if ( ! pCurrentBlockIndex ) return ;
2015-04-16 21:58:09 +02:00
2016-08-05 18:25:03 +02:00
// can't really verify it until masternode list is synced, reject it for now
2016-08-28 12:12:14 +02:00
if ( masternodeSync . GetAssetID ( ) < MASTERNODE_SYNC_MNW ) return ;
2016-08-05 18:25:03 +02:00
if ( mapMasternodePayeeVotes . count ( winner . GetHash ( ) ) ) {
LogPrint ( " mnpayments " , " MNWINNER -- Already seen: hash=%s, nHeight=%d \n " , winner . GetHash ( ) . ToString ( ) , pCurrentBlockIndex - > nHeight ) ;
2015-08-05 02:54:02 +02:00
masternodeSync . AddedMasternodeWinner ( winner . GetHash ( ) ) ;
2015-07-30 18:00:28 +02:00
return ;
2015-04-16 21:58:09 +02:00
}
2016-08-05 18:25:03 +02:00
int nFirstBlock = pCurrentBlockIndex - > nHeight - mnodeman . CountEnabled ( ) * 1.25 ;
if ( winner . nBlockHeight < nFirstBlock | | winner . nBlockHeight > pCurrentBlockIndex - > nHeight + 20 ) {
LogPrint ( " mnpayments " , " MNWINNER -- winner out of range: nFirstBlock=%d, nBlockHeight=%d, nHeight=%d \n " , nFirstBlock , winner . nBlockHeight , pCurrentBlockIndex - > nHeight ) ;
2015-04-16 21:58:09 +02:00
return ;
}
2015-07-18 21:24:06 +02:00
std : : string strError = " " ;
2016-08-05 18:25:03 +02:00
if ( ! winner . IsValid ( pfrom , pCurrentBlockIndex - > nHeight , strError ) ) {
LogPrint ( " mnpayments " , " MNWINNER -- invalid message, error: %s \n " , strError ) ;
2015-04-16 21:58:09 +02:00
return ;
}
2016-05-30 08:22:30 +02:00
if ( ! CanVote ( winner . vinMasternode . prevout , winner . nBlockHeight ) ) {
2016-08-05 18:25:03 +02:00
LogPrintf ( " MNWINNER -- masternode already voted: prevout=%s \n " , winner . vinMasternode . prevout . ToStringShort ( ) ) ;
2015-07-24 16:12:48 +02:00
return ;
}
2016-08-05 18:25:03 +02:00
if ( ! winner . SignatureValid ( ) ) {
// do not ban for old mnw, MN simply might be not active anymore
if ( masternodeSync . IsSynced ( ) & & winner . nBlockHeight > pCurrentBlockIndex - > nHeight ) {
LogPrintf ( " MNWINNER -- invalid signature \n " ) ;
Misbehaving ( pfrom - > GetId ( ) , 20 ) ;
}
2015-08-07 05:07:40 +02:00
// it could just be a non-synced masternode
mnodeman . AskForMN ( pfrom , winner . vinMasternode ) ;
2015-04-16 21:58:09 +02:00
return ;
}
2015-04-22 16:33:44 +02:00
CTxDestination address1 ;
2015-06-25 20:08:50 +02:00
ExtractDestination ( winner . payee , address1 ) ;
2015-04-22 16:33:44 +02:00
CBitcoinAddress address2 ( address1 ) ;
2016-08-05 18:25:03 +02:00
LogPrint ( " mnpayments " , " MNWINNER -- winning vote: address=%s, nBlockHeight=%d, nHeight=%d, prevout=%s \n " , address2 . ToString ( ) , winner . nBlockHeight , pCurrentBlockIndex - > nHeight , winner . vinMasternode . prevout . ToStringShort ( ) ) ;
2015-04-16 21:58:09 +02:00
2016-05-30 08:22:30 +02:00
if ( AddWinningMasternode ( winner ) ) {
2015-04-22 16:33:44 +02:00
winner . Relay ( ) ;
2015-08-05 02:54:02 +02:00
masternodeSync . AddedMasternodeWinner ( winner . GetHash ( ) ) ;
2015-04-16 21:58:09 +02:00
}
}
}
2015-04-22 16:33:44 +02:00
bool CMasternodePaymentWinner : : Sign ( CKey & keyMasternode , CPubKey & pubKeyMasternode )
2015-04-16 21:58:09 +02:00
{
2016-08-19 13:50:04 +02:00
std : : string strError ;
2015-04-22 16:33:44 +02:00
std : : string strMasterNodeSignMessage ;
std : : string strMessage = vinMasternode . prevout . ToStringShort ( ) +
2015-06-25 17:17:53 +02:00
boost : : lexical_cast < std : : string > ( nBlockHeight ) +
2016-02-02 16:28:56 +01:00
ScriptToAsmStr ( payee ) ;
2015-06-25 17:17:53 +02:00
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . SignMessage ( strMessage , vchSig , keyMasternode ) ) {
LogPrintf ( " CMasternodePaymentWinner::Sign -- SignMessage() failed \n " ) ;
2015-04-22 16:33:44 +02:00
return false ;
}
2015-04-16 21:58:09 +02:00
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-16 21:58:09 +02:00
return false ;
}
return true ;
}
2015-04-22 16:33:44 +02:00
bool CMasternodePayments : : GetBlockPayee ( int nBlockHeight , CScript & payee )
2015-04-16 21:58:09 +02:00
{
2015-05-28 19:45:31 +02:00
if ( mapMasternodeBlocks . count ( nBlockHeight ) ) {
2015-04-22 16:33:44 +02:00
return mapMasternodeBlocks [ nBlockHeight ] . GetPayee ( payee ) ;
}
2015-04-16 21:58:09 +02:00
2015-04-22 16:33:44 +02:00
return false ;
}
2015-04-16 21:58:09 +02:00
2015-07-22 05:07:23 +02:00
// Is this masternode scheduled to get paid soon?
2015-07-23 15:45:43 +02:00
// -- Only look ahead up to 8 blocks to allow for propagation of the latest 2 winners
2015-06-15 02:05:51 +02:00
bool CMasternodePayments : : IsScheduled ( CMasternode & mn , int nNotBlockHeight )
2015-05-27 21:47:01 +02:00
{
2015-07-29 17:28:49 +02:00
LOCK ( cs_mapMasternodeBlocks ) ;
2016-03-02 22:20:04 +01:00
if ( ! pCurrentBlockIndex ) return false ;
2015-05-27 21:47:01 +02:00
CScript mnpayee ;
mnpayee = GetScriptForDestination ( mn . pubkey . GetID ( ) ) ;
CScript payee ;
2016-03-02 22:20:04 +01:00
for ( int64_t h = pCurrentBlockIndex - > nHeight ; h < = pCurrentBlockIndex - > nHeight + 8 ; h + + ) {
2015-06-15 02:05:51 +02:00
if ( h = = nNotBlockHeight ) continue ;
2015-05-27 21:47:01 +02:00
if ( mapMasternodeBlocks . count ( h ) ) {
2015-05-28 19:45:31 +02:00
if ( mapMasternodeBlocks [ h ] . GetPayee ( payee ) ) {
2015-06-23 18:38:28 +02:00
if ( mnpayee = = payee ) {
2015-05-28 19:45:31 +02:00
return true ;
}
}
2015-05-27 21:47:01 +02:00
}
}
return false ;
}
2015-08-30 01:48:19 +02:00
bool CMasternodePayments : : AddWinningMasternode ( CMasternodePaymentWinner & winnerIn )
2015-04-22 16:33:44 +02:00
{
2016-02-02 16:28:56 +01:00
uint256 blockHash = uint256 ( ) ;
2016-08-06 16:31:51 +02:00
if ( ! GetBlockHash ( blockHash , winnerIn . nBlockHeight - 101 ) ) return false ;
2015-04-16 21:58:09 +02:00
2015-07-29 17:28:49 +02:00
{
LOCK2 ( cs_mapMasternodePayeeVotes , cs_mapMasternodeBlocks ) ;
if ( mapMasternodePayeeVotes . count ( winnerIn . GetHash ( ) ) ) {
return false ;
}
2015-04-16 21:58:09 +02:00
2015-07-29 17:28:49 +02:00
mapMasternodePayeeVotes [ winnerIn . GetHash ( ) ] = winnerIn ;
2015-04-22 16:33:44 +02:00
2015-07-29 17:28:49 +02:00
if ( ! mapMasternodeBlocks . count ( winnerIn . nBlockHeight ) ) {
CMasternodeBlockPayees blockPayees ( winnerIn . nBlockHeight ) ;
mapMasternodeBlocks [ winnerIn . nBlockHeight ] = blockPayees ;
}
2015-04-16 21:58:09 +02:00
}
2016-05-24 23:16:42 +02:00
mapMasternodeBlocks [ winnerIn . nBlockHeight ] . AddPayee ( winnerIn . payee , 1 ) ;
2015-04-22 16:33:44 +02:00
2015-04-16 21:58:09 +02:00
return true ;
}
2015-04-22 16:33:44 +02:00
bool CMasternodeBlockPayees : : IsTransactionValid ( const CTransaction & txNew )
2015-04-16 21:58:09 +02:00
{
2015-07-29 17:28:49 +02:00
LOCK ( cs_vecPayments ) ;
2015-05-04 17:04:09 +02:00
int nMaxSignatures = 0 ;
std : : string strPayeesPossible = " " ;
2015-06-25 20:08:50 +02:00
CAmount masternodePayment = GetMasternodePayment ( nBlockHeight , txNew . GetValueOut ( ) ) ;
2016-03-04 06:58:53 +01:00
//require at least MNPAYMENTS_SIGNATURES_REQUIRED signatures
2015-05-04 17:04:09 +02:00
BOOST_FOREACH ( CMasternodePayee & payee , vecPayments )
2015-05-16 04:53:53 +02:00
if ( payee . nVotes > = nMaxSignatures & & payee . nVotes > = MNPAYMENTS_SIGNATURES_REQUIRED )
2015-05-04 17:04:09 +02:00
nMaxSignatures = payee . nVotes ;
2015-06-25 17:17:53 +02:00
2016-03-04 06:58:53 +01:00
// if we don't have at least MNPAYMENTS_SIGNATURES_REQUIRED signatures on a payee, approve whichever is the longest chain
2015-06-21 19:06:25 +02:00
if ( nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED ) return true ;
2015-05-04 17:04:09 +02:00
BOOST_FOREACH ( CMasternodePayee & payee , vecPayments )
2015-04-22 16:33:44 +02:00
{
bool found = false ;
2015-06-25 17:17:53 +02:00
BOOST_FOREACH ( CTxOut out , txNew . vout ) {
2015-06-25 20:08:50 +02:00
if ( payee . scriptPubKey = = out . scriptPubKey & & masternodePayment = = out . nValue ) {
2015-04-22 16:33:44 +02:00
found = true ;
2015-06-25 17:17:53 +02:00
}
}
2015-04-16 21:58:09 +02:00
2015-06-25 17:17:53 +02:00
if ( payee . nVotes > = MNPAYMENTS_SIGNATURES_REQUIRED ) {
2015-05-04 17:04:09 +02:00
if ( found ) return true ;
2015-04-16 21:58:09 +02:00
2015-04-22 16:33:44 +02:00
CTxDestination address1 ;
ExtractDestination ( payee . scriptPubKey , address1 ) ;
CBitcoinAddress address2 ( address1 ) ;
2015-04-16 21:58:09 +02:00
2015-05-04 17:04:09 +02:00
if ( strPayeesPossible = = " " ) {
2015-06-25 20:08:50 +02:00
strPayeesPossible + = address2 . ToString ( ) ;
2015-05-04 17:04:09 +02:00
} else {
2015-06-25 20:08:50 +02:00
strPayeesPossible + = " , " + address2 . ToString ( ) ;
2015-05-04 17:04:09 +02:00
}
2015-04-16 21:58:09 +02:00
}
}
2015-05-04 17:04:09 +02:00
2016-02-19 19:11:44 +01:00
LogPrintf ( " CMasternodePayments::IsTransactionValid - Missing required payment - %s %d \n " , strPayeesPossible , masternodePayment ) ;
2015-05-04 17:04:09 +02:00
return false ;
2015-04-16 21:58:09 +02:00
}
2015-04-22 16:33:44 +02:00
std : : string CMasternodeBlockPayees : : GetRequiredPaymentsString ( )
2015-04-16 21:58:09 +02:00
{
2015-07-29 17:28:49 +02:00
LOCK ( cs_vecPayments ) ;
2015-04-22 16:33:44 +02:00
std : : string ret = " Unknown " ;
2015-05-04 17:04:09 +02:00
BOOST_FOREACH ( CMasternodePayee & payee , vecPayments )
2015-04-22 16:33:44 +02:00
{
2015-05-26 16:56:51 +02:00
CTxDestination address1 ;
ExtractDestination ( payee . scriptPubKey , address1 ) ;
CBitcoinAddress address2 ( address1 ) ;
2015-04-22 16:33:44 +02:00
2015-05-26 16:56:51 +02:00
if ( ret ! = " Unknown " ) {
2015-06-25 20:08:50 +02:00
ret + = " , " + address2 . ToString ( ) + " : " + boost : : lexical_cast < std : : string > ( payee . nVotes ) ;
2015-05-26 16:56:51 +02:00
} else {
2015-06-25 20:22:11 +02:00
ret = address2 . ToString ( ) + " : " + boost : : lexical_cast < std : : string > ( payee . nVotes ) ;
2015-04-16 21:58:09 +02:00
}
}
2015-05-04 17:04:09 +02:00
2015-04-22 16:33:44 +02:00
return ret ;
2015-04-16 21:58:09 +02:00
}
2015-04-22 16:33:44 +02:00
std : : string CMasternodePayments : : GetRequiredPaymentsString ( int nBlockHeight )
2015-04-16 21:58:09 +02:00
{
2015-07-29 17:28:49 +02:00
LOCK ( cs_mapMasternodeBlocks ) ;
2015-04-22 16:33:44 +02:00
if ( mapMasternodeBlocks . count ( nBlockHeight ) ) {
return mapMasternodeBlocks [ nBlockHeight ] . GetRequiredPaymentsString ( ) ;
2015-04-16 21:58:09 +02:00
}
2015-04-22 16:33:44 +02:00
return " Unknown " ;
}
2015-04-16 21:58:09 +02:00
2015-04-22 16:33:44 +02:00
bool CMasternodePayments : : IsTransactionValid ( const CTransaction & txNew , int nBlockHeight )
{
2015-07-29 17:28:49 +02:00
LOCK ( cs_mapMasternodeBlocks ) ;
2015-04-22 16:33:44 +02:00
if ( mapMasternodeBlocks . count ( nBlockHeight ) ) {
return mapMasternodeBlocks [ nBlockHeight ] . IsTransactionValid ( txNew ) ;
2015-04-16 21:58:09 +02:00
}
2015-04-22 16:33:44 +02:00
return true ;
2015-04-16 21:58:09 +02:00
}
2016-04-13 19:49:47 +02:00
void CMasternodePayments : : CheckAndRemove ( )
2015-04-16 21:58:09 +02:00
{
2016-03-02 22:20:04 +01:00
if ( ! pCurrentBlockIndex ) return ;
2015-04-16 21:58:09 +02:00
2016-03-02 22:20:04 +01:00
LOCK2 ( cs_mapMasternodePayeeVotes , cs_mapMasternodeBlocks ) ;
2015-04-16 21:58:09 +02:00
2016-05-29 20:35:09 +02:00
// keep a bit more for historical sake but at least minBlocksToStore
int nLimit = std : : max ( int ( mnodeman . size ( ) * nStorageCoeff ) , nMinBlocksToStore ) ;
2015-04-16 21:58:09 +02:00
2015-05-04 17:04:09 +02:00
std : : map < uint256 , CMasternodePaymentWinner > : : iterator it = mapMasternodePayeeVotes . begin ( ) ;
while ( it ! = mapMasternodePayeeVotes . end ( ) ) {
CMasternodePaymentWinner winner = ( * it ) . second ;
2015-06-25 17:17:53 +02:00
2016-03-02 22:20:04 +01:00
if ( pCurrentBlockIndex - > nHeight - winner . nBlockHeight > nLimit ) {
2015-07-31 17:46:47 +02:00
LogPrint ( " mnpayments " , " CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d \n " , winner . nBlockHeight ) ;
2015-08-05 02:54:02 +02:00
masternodeSync . mapSeenSyncMNW . erase ( ( * it ) . first ) ;
2015-05-04 17:04:09 +02:00
mapMasternodePayeeVotes . erase ( it + + ) ;
2015-08-25 12:58:48 +02:00
mapMasternodeBlocks . erase ( winner . nBlockHeight ) ;
2015-05-04 17:04:09 +02:00
} else {
+ + it ;
2015-04-16 21:58:09 +02:00
}
2015-05-04 17:04:09 +02:00
}
2016-05-30 08:22:30 +02:00
LogPrintf ( " CMasternodePayments::CleanPaymentList() - %s mapSeenSyncMNW %lld \n " , ToString ( ) , masternodeSync . mapSeenSyncMNW . size ( ) ) ;
2015-04-16 21:58:09 +02:00
}
2016-08-05 18:25:03 +02:00
bool CMasternodePaymentWinner : : IsValid ( CNode * pnode , int nValidationHeight , std : : string & strError )
2015-04-22 16:33:44 +02:00
{
2015-07-21 17:09:17 +02:00
CMasternode * pmn = mnodeman . Find ( vinMasternode ) ;
2015-04-16 21:58:09 +02:00
2016-08-05 18:25:03 +02:00
if ( ! pmn ) {
strError = strprintf ( " Unknown Masternode: prevout=%s " , vinMasternode . prevout . ToStringShort ( ) ) ;
// Only ask if we are already synced and still have no idea about that Masternode
if ( masternodeSync . IsSynced ( ) ) mnodeman . AskForMN ( pnode , vinMasternode ) ;
2015-04-22 16:33:44 +02:00
return false ;
2015-04-16 21:58:09 +02:00
}
2016-08-05 18:25:03 +02:00
if ( pmn - > protocolVersion < MIN_MNW_PEER_PROTO_VERSION ) {
strError = strprintf ( " Masternode protocol is too old: protocolVersion=%d, MIN_MNW_PEER_PROTO_VERSION=%d " , pmn - > protocolVersion , MIN_MNW_PEER_PROTO_VERSION ) ;
2015-07-21 17:09:17 +02:00
return false ;
}
2016-08-06 16:31:51 +02:00
int nRank = mnodeman . GetMasternodeRank ( vinMasternode , nBlockHeight - 101 , MIN_MNW_PEER_PROTO_VERSION ) ;
2015-07-21 17:09:17 +02:00
2016-08-05 18:25:03 +02:00
if ( nRank > MNPAYMENTS_SIGNATURES_TOTAL ) {
// It's common to have masternodes mistakenly think they are in the top 10
// We don't want to print all of these messages in normal mode, debug mode should print though
strError = strprintf ( " Masternode is not in the top %d (%d) \n " , MNPAYMENTS_SIGNATURES_TOTAL , nRank ) ;
// Only ban for new mnw which is out of bounds, for old mnw MN list itself might be way too much off
if ( nRank > MNPAYMENTS_SIGNATURES_TOTAL * 2 & & nBlockHeight > nValidationHeight ) {
LogPrintf ( " CMasternodePaymentWinner::IsValid -- Error: Masternode is not in the top %d (%d) \n " , MNPAYMENTS_SIGNATURES_TOTAL * 2 , nRank ) ;
Misbehaving ( pnode - > GetId ( ) , 20 ) ;
2015-08-28 17:53:08 +02:00
}
2016-08-05 18:25:03 +02:00
// Still invalid however
2015-04-22 16:33:44 +02:00
return false ;
}
return true ;
}
bool CMasternodePayments : : ProcessBlock ( int nBlockHeight )
{
2016-05-25 19:06:48 +02:00
// DETERMINE IF WE SHOULD BE VOTING FOR THE NEXT PAYEE
2015-04-22 16:33:44 +02:00
if ( ! fMasterNode ) return false ;
2016-05-25 19:06:48 +02:00
2016-08-06 16:31:51 +02:00
int n = mnodeman . GetMasternodeRank ( activeMasternode . vin , nBlockHeight - 101 , MIN_MNW_PEER_PROTO_VERSION ) ;
2016-05-25 19:06:48 +02:00
if ( n = = - 1 )
{
LogPrint ( " mnpayments " , " CMasternodePayments::ProcessBlock - Unknown Masternode \n " ) ;
return false ;
}
if ( n > MNPAYMENTS_SIGNATURES_TOTAL )
{
LogPrint ( " mnpayments " , " CMasternodePayments::ProcessBlock - Masternode not in the top %d (%d) \n " , MNPAYMENTS_SIGNATURES_TOTAL , n ) ;
return false ;
}
2015-04-22 16:33:44 +02:00
2015-04-16 21:58:09 +02:00
2016-05-24 23:16:42 +02:00
// LOCATE THE NEXT MASTERNODE WHICH SHOULD BE PAID
2015-04-22 16:33:44 +02:00
2016-05-25 19:06:48 +02:00
CMasternodePaymentWinner newWinner ( activeMasternode . vin ) ;
2016-05-24 23:16:42 +02:00
{
LogPrintf ( " CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n " , nBlockHeight , activeMasternode . vin . ToString ( ) ) ;
2015-04-16 21:58:09 +02:00
2016-05-24 23:16:42 +02:00
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
int nCount = 0 ;
CMasternode * pmn = mnodeman . GetNextMasternodeInQueueForPayment ( nBlockHeight , true , nCount ) ;
if ( pmn ! = NULL )
{
LogPrintf ( " CMasternodePayments::ProcessBlock() Found by FindOldestNotInVec \n " ) ;
2015-04-16 21:58:09 +02:00
2016-05-24 23:16:42 +02:00
newWinner . nBlockHeight = nBlockHeight ;
2015-06-25 17:17:53 +02:00
2016-05-24 23:16:42 +02:00
CScript payee = GetScriptForDestination ( pmn - > pubkey . GetID ( ) ) ;
newWinner . AddPayee ( payee ) ;
2015-04-22 16:33:44 +02:00
2016-05-24 23:16:42 +02:00
CTxDestination address1 ;
ExtractDestination ( payee , address1 ) ;
CBitcoinAddress address2 ( address1 ) ;
2015-04-16 21:58:09 +02:00
2016-05-24 23:16:42 +02:00
LogPrintf ( " CMasternodePayments::ProcessBlock() Winner payee %s nHeight %d. \n " , address2 . ToString ( ) , newWinner . nBlockHeight ) ;
} else {
LogPrintf ( " CMasternodePayments::ProcessBlock() Failed to find masternode to pay \n " ) ;
}
}
2015-04-16 21:58:09 +02:00
2016-05-25 19:06:48 +02:00
// SIGN MESSAGE TO NETWORK WITH OUR MASTERNODE KEYS
2015-04-22 16:33:44 +02:00
std : : string errorMessage ;
2015-04-16 21:58:09 +02:00
2015-06-22 15:50:33 +02:00
LogPrintf ( " CMasternodePayments::ProcessBlock() - Signing Winner \n " ) ;
2016-07-15 08:36:00 +02:00
if ( newWinner . Sign ( activeMasternode . keyMasternode , activeMasternode . pubKeyMasternode ) )
2015-04-16 21:58:09 +02:00
{
2015-06-22 15:50:33 +02:00
LogPrintf ( " CMasternodePayments::ProcessBlock() - AddWinningMasternode \n " ) ;
2015-08-30 01:48:19 +02:00
if ( AddWinningMasternode ( newWinner ) )
2015-04-16 21:58:09 +02:00
{
2015-04-22 16:33:44 +02:00
newWinner . Relay ( ) ;
2015-04-16 21:58:09 +02:00
return true ;
}
}
2015-05-04 17:04:09 +02:00
2015-04-16 21:58:09 +02:00
return false ;
}
2015-04-22 16:33:44 +02:00
void CMasternodePaymentWinner : : Relay ( )
2015-04-16 21:58:09 +02:00
{
2015-04-22 16:33:44 +02:00
CInv inv ( MSG_MASTERNODE_WINNER , GetHash ( ) ) ;
2015-07-08 02:37:23 +02:00
RelayInv ( inv ) ;
2015-04-16 21:58:09 +02:00
}
2015-04-22 16:33:44 +02:00
bool CMasternodePaymentWinner : : SignatureValid ( )
2015-04-16 21:58:09 +02:00
{
2015-04-22 16:33:44 +02:00
CMasternode * pmn = mnodeman . Find ( vinMasternode ) ;
2015-04-16 21:58:09 +02:00
2015-04-22 16:33:44 +02:00
if ( pmn ! = NULL )
{
2016-08-19 13:50:04 +02:00
std : : string strError = " " ;
2015-04-22 16:33:44 +02:00
std : : string strMessage = vinMasternode . prevout . ToStringShort ( ) +
2015-06-25 17:17:53 +02:00
boost : : lexical_cast < std : : string > ( nBlockHeight ) +
2016-02-02 16:28:56 +01:00
ScriptToAsmStr ( payee ) ;
2015-04-16 21:58:09 +02:00
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . VerifyMessage ( pmn - > pubkey2 , vchSig , strMessage , strError ) ) {
return error ( " CMasternodePaymentWinner::CheckSignature -- Got bad Masternode payment signature: vin=%s, error: %s " , vinMasternode . ToString ( ) . c_str ( ) , strError ) ;
2015-04-22 16:33:44 +02:00
}
2015-04-16 21:58:09 +02:00
return true ;
}
2015-04-22 16:33:44 +02:00
return false ;
2015-04-16 21:58:09 +02:00
}
2015-04-22 16:33:44 +02:00
2015-07-21 00:09:42 +02:00
void CMasternodePayments : : Sync ( CNode * node , int nCountNeeded )
2015-04-22 16:33:44 +02:00
{
2015-07-29 17:28:49 +02:00
LOCK ( cs_mapMasternodePayeeVotes ) ;
2015-05-04 17:04:09 +02:00
2016-03-02 22:20:04 +01:00
if ( ! pCurrentBlockIndex ) return ;
2015-05-04 17:04:09 +02:00
2015-09-04 14:22:17 +02:00
int nCount = ( mnodeman . CountEnabled ( ) * 1.25 ) ;
2015-07-21 00:09:42 +02:00
if ( nCountNeeded > nCount ) nCountNeeded = nCount ;
2015-08-28 23:37:53 +02:00
2015-08-31 06:05:10 +02:00
int nInvCount = 0 ;
2015-05-04 17:04:09 +02:00
std : : map < uint256 , CMasternodePaymentWinner > : : iterator it = mapMasternodePayeeVotes . begin ( ) ;
while ( it ! = mapMasternodePayeeVotes . end ( ) ) {
2015-08-30 01:48:19 +02:00
CMasternodePaymentWinner winner = ( * it ) . second ;
2016-03-02 22:20:04 +01:00
if ( winner . nBlockHeight > = pCurrentBlockIndex - > nHeight - nCountNeeded & & winner . nBlockHeight < = pCurrentBlockIndex - > nHeight + 20 ) {
2015-08-31 06:05:10 +02:00
node - > PushInventory ( CInv ( MSG_MASTERNODE_WINNER , winner . GetHash ( ) ) ) ;
nInvCount + + ;
2015-07-23 23:35:14 +02:00
}
2015-05-04 17:04:09 +02:00
+ + it ;
}
2016-02-17 23:18:57 +01:00
node - > PushMessage ( NetMsgType : : SYNCSTATUSCOUNT , MASTERNODE_SYNC_MNW , nInvCount ) ;
2015-05-16 04:53:53 +02:00
}
2015-07-21 04:24:43 +02:00
std : : string CMasternodePayments : : ToString ( ) const
{
std : : ostringstream info ;
info < < " Votes: " < < ( int ) mapMasternodePayeeVotes . size ( ) < <
" , Blocks: " < < ( int ) mapMasternodeBlocks . size ( ) ;
return info . str ( ) ;
}
2015-07-22 00:14:54 +02:00
int CMasternodePayments : : GetOldestBlock ( )
{
2015-07-29 17:28:49 +02:00
LOCK ( cs_mapMasternodeBlocks ) ;
2015-07-22 00:14:54 +02:00
int nOldestBlock = std : : numeric_limits < int > : : max ( ) ;
std : : map < int , CMasternodeBlockPayees > : : iterator it = mapMasternodeBlocks . begin ( ) ;
while ( it ! = mapMasternodeBlocks . end ( ) ) {
if ( ( * it ) . first < nOldestBlock ) {
nOldestBlock = ( * it ) . first ;
}
it + + ;
}
return nOldestBlock ;
}
2015-07-21 04:24:43 +02:00
int CMasternodePayments : : GetNewestBlock ( )
{
2015-07-29 17:28:49 +02:00
LOCK ( cs_mapMasternodeBlocks ) ;
2015-07-21 04:24:43 +02:00
int nNewestBlock = 0 ;
std : : map < int , CMasternodeBlockPayees > : : iterator it = mapMasternodeBlocks . begin ( ) ;
while ( it ! = mapMasternodeBlocks . end ( ) ) {
if ( ( * it ) . first > nNewestBlock ) {
nNewestBlock = ( * it ) . first ;
}
it + + ;
}
return nNewestBlock ;
}
2016-03-02 22:20:04 +01:00
2016-05-29 20:35:09 +02:00
bool CMasternodePayments : : IsEnoughData ( int nMnCount ) {
2016-05-30 14:11:09 +02:00
if ( GetBlockCount ( ) > nMnCount * nStorageCoeff & & GetBlockCount ( ) > nMinBlocksToStore )
2016-05-29 20:35:09 +02:00
{
float nAverageVotes = ( MNPAYMENTS_SIGNATURES_TOTAL + MNPAYMENTS_SIGNATURES_REQUIRED ) / 2 ;
2016-05-30 14:11:09 +02:00
if ( GetVoteCount ( ) > nMnCount * nStorageCoeff * nAverageVotes & & GetVoteCount ( ) > nMinBlocksToStore * nAverageVotes )
2016-05-29 20:35:09 +02:00
{
return true ;
}
}
return false ;
}
2016-03-02 22:20:04 +01:00
void CMasternodePayments : : UpdatedBlockTip ( const CBlockIndex * pindex )
{
pCurrentBlockIndex = pindex ;
LogPrint ( " mnpayments " , " pCurrentBlockIndex->nHeight: %d \n " , pCurrentBlockIndex - > nHeight ) ;
2016-08-28 12:12:14 +02:00
if ( ! fLiteMode & & masternodeSync . GetAssetID ( ) > MASTERNODE_SYNC_LIST ) {
ProcessBlock ( pindex - > nHeight + 10 ) ;
}
2016-03-02 22:20:04 +01:00
}