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 "core.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>
2015-03-26 21:46:19 +01:00
CCriticalSection cs_masternodepayments ;
2014-12-09 02:17:57 +01:00
/** Object for who's going to get paid on which blocks */
CMasternodePayments masternodePayments ;
2015-03-05 09:11:56 +01:00
// keep track of Masternode votes I've seen
2015-02-09 21:22:31 +01:00
map < uint256 , CMasternodePaymentWinner > mapSeenMasternodeVotes ;
2014-12-09 02:17:57 +01:00
// 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
2015-02-23 21:12:33 +01:00
void ProcessMessageMasternodePayments ( CNode * pfrom , std : : string & strCommand , CDataStream & vRecv )
2014-12-09 02:17:57 +01:00
{
2015-02-26 15:40:43 +01:00
if ( IsInitialBlockDownload ( ) ) return ;
2015-02-23 21:01:21 +01:00
if ( strCommand = = " mnget " ) { //Masternode Payments Request Sync
2015-03-05 09:11:56 +01:00
if ( fLiteMode ) return ; //disable all Darksend/Masternode related functionality
2014-12-09 02:17:57 +01:00
if ( pfrom - > HasFulfilledRequest ( " mnget " ) ) {
LogPrintf ( " mnget - peer already asked me for the list \n " ) ;
Misbehaving ( pfrom - > GetId ( ) , 20 ) ;
return ;
}
pfrom - > FulfilledRequest ( " mnget " ) ;
masternodePayments . Sync ( pfrom ) ;
2015-03-05 09:11:56 +01:00
LogPrintf ( " mnget - Sent Masternode winners to %s \n " , pfrom - > addr . ToString ( ) . c_str ( ) ) ;
2014-12-09 02:17:57 +01:00
}
else if ( strCommand = = " mnw " ) { //Masternode Payments Declare Winner
2015-03-26 21:46:19 +01:00
LOCK ( cs_masternodepayments ) ;
2015-01-26 23:54:12 +01:00
//this is required in litemode
2014-12-09 02:17:57 +01:00
CMasternodePaymentWinner winner ;
2015-03-16 21:57:07 +01:00
vRecv > > winner ;
2014-12-09 02:17:57 +01:00
if ( chainActive . Tip ( ) = = NULL ) return ;
2015-03-26 21:46:19 +01:00
CTxDestination address1 ;
ExtractDestination ( winner . payee , address1 ) ;
CBitcoinAddress address2 ( address1 ) ;
2014-12-09 02:17:57 +01:00
uint256 hash = winner . GetHash ( ) ;
if ( mapSeenMasternodeVotes . count ( hash ) ) {
2015-03-26 21:46:19 +01:00
if ( fDebug ) LogPrintf ( " mnw - seen vote %s Addr %s Height %d bestHeight %d \n " , hash . ToString ( ) . c_str ( ) , address2 . ToString ( ) . c_str ( ) , winner . nBlockHeight , chainActive . Tip ( ) - > nHeight ) ;
2014-12-09 02:17:57 +01:00
return ;
}
if ( winner . nBlockHeight < chainActive . Tip ( ) - > nHeight - 10 | | winner . nBlockHeight > chainActive . Tip ( ) - > nHeight + 20 ) {
2015-03-26 21:46:19 +01:00
LogPrintf ( " mnw - winner out of range %s Addr %s Height %d bestHeight %d \n " , winner . vin . ToString ( ) . c_str ( ) , address2 . ToString ( ) . c_str ( ) , winner . nBlockHeight , chainActive . Tip ( ) - > nHeight ) ;
2014-12-09 02:17:57 +01:00
return ;
}
if ( winner . vin . nSequence ! = std : : numeric_limits < unsigned int > : : max ( ) ) {
LogPrintf ( " mnw - invalid nSequence \n " ) ;
Misbehaving ( pfrom - > GetId ( ) , 100 ) ;
return ;
}
2015-03-26 21:46:19 +01:00
LogPrintf ( " mnw - winning vote - Vin %s Addr %s Height %d bestHeight %d \n " , winner . vin . ToString ( ) . c_str ( ) , address2 . ToString ( ) . c_str ( ) , winner . nBlockHeight , chainActive . Tip ( ) - > nHeight ) ;
2014-12-09 02:17:57 +01:00
if ( ! masternodePayments . CheckSignature ( winner ) ) {
LogPrintf ( " mnw - invalid signature \n " ) ;
Misbehaving ( pfrom - > GetId ( ) , 100 ) ;
return ;
}
2015-02-09 21:22:31 +01:00
mapSeenMasternodeVotes . insert ( make_pair ( hash , winner ) ) ;
2014-12-09 02:17:57 +01:00
if ( masternodePayments . AddWinningMasternode ( winner ) ) {
masternodePayments . Relay ( winner ) ;
}
2015-02-02 12:05:21 +01:00
}
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-02-23 21:01:21 +01:00
lastDseep = 0 ;
lastTimeSeen = 0 ;
cacheInputAge = 0 ;
cacheInputAgeBlock = 0 ;
unitTest = false ;
allowFreeTx = true ;
protocolVersion = MIN_PEER_PROTO_VERSION ;
nLastDsq = 0 ;
2015-03-16 20:01:11 +01:00
donationAddress = CScript ( ) ;
donationPercentage = 0 ;
2015-03-20 19:24:11 +01:00
nVote = 0 ;
lastVote = 0 ;
2015-03-24 02:52:27 +01:00
nScanningErrorCount = 0 ;
nLastScanningErrorBlockHeight = 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-02-23 21:01:21 +01:00
lastDseep = other . lastDseep ;
lastTimeSeen = other . lastTimeSeen ;
cacheInputAge = other . cacheInputAge ;
cacheInputAgeBlock = other . cacheInputAgeBlock ;
unitTest = other . unitTest ;
allowFreeTx = other . allowFreeTx ;
protocolVersion = other . protocolVersion ;
nLastDsq = other . nLastDsq ;
2015-03-16 20:01:11 +01:00
donationAddress = other . donationAddress ;
donationPercentage = other . donationPercentage ;
2015-03-20 19:24:11 +01:00
nVote = other . nVote ;
lastVote = other . lastVote ;
2015-03-24 02:52:27 +01:00
nScanningErrorCount = other . nScanningErrorCount ;
nLastScanningErrorBlockHeight = other . nLastScanningErrorBlockHeight ;
2015-02-23 21:01:21 +01:00
}
2015-03-16 20:01:11 +01:00
CMasternode : : CMasternode ( CService newAddr , CTxIn newVin , CPubKey newPubkey , std : : vector < unsigned char > newSig , int64_t newSigTime , CPubKey newPubkey2 , int protocolVersionIn , CScript newDonationAddress , int newDonationPercentage )
2015-02-23 21:01:21 +01:00
{
LOCK ( cs ) ;
vin = newVin ;
addr = newAddr ;
pubkey = newPubkey ;
pubkey2 = newPubkey2 ;
sig = newSig ;
activeState = MASTERNODE_ENABLED ;
2015-03-01 16:38:53 +01:00
sigTime = newSigTime ;
2015-02-23 21:01:21 +01:00
lastDseep = 0 ;
lastTimeSeen = 0 ;
cacheInputAge = 0 ;
cacheInputAgeBlock = 0 ;
unitTest = false ;
allowFreeTx = true ;
protocolVersion = protocolVersionIn ;
nLastDsq = 0 ;
2015-03-16 20:01:11 +01:00
donationAddress = newDonationAddress ;
donationPercentage = newDonationPercentage ;
2015-03-21 04:34:36 +01:00
nVote = 0 ;
lastVote = 0 ;
2015-03-24 02:52:27 +01:00
nScanningErrorCount = 0 ;
nLastScanningErrorBlockHeight = 0 ;
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-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
2015-03-22 04:10:34 +01:00
if ( nScanningErrorCount > = MASTERNODE_SCANNING_ERROR_THESHOLD )
2015-03-13 10:28:20 +01:00
{
activeState = MASTERNODE_POS_ERROR ;
return ;
}
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
if ( ! UpdatedWithin ( MASTERNODE_REMOVAL_SECONDS ) ) {
2015-02-23 21:01:21 +01:00
activeState = MASTERNODE_REMOVE ;
2014-12-09 02:17:57 +01:00
return ;
}
if ( ! UpdatedWithin ( 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 ;
CTransaction tx = CTransaction ( ) ;
CTxOut vout = CTxOut ( 999.99 * COIN , darkSendPool . collateralPubKey ) ;
tx . vin . push_back ( vin ) ;
tx . vout . push_back ( vout ) ;
if ( ! AcceptableInputs ( mempool , state , tx ) ) {
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
2014-12-09 02:17:57 +01:00
}
bool CMasternodePayments : : CheckSignature ( CMasternodePaymentWinner & winner )
{
//note: need to investigate why this is failing
2015-02-12 19:54:45 +01:00
std : : string strMessage = winner . vin . ToString ( ) . c_str ( ) + boost : : lexical_cast < std : : string > ( winner . nBlockHeight ) + winner . payee . ToString ( ) ;
2014-12-31 03:54:00 +01:00
std : : string strPubKey = ( Params ( ) . NetworkID ( ) = = CChainParams : : MAIN ) ? strMainPubKey : strTestPubKey ;
2014-12-09 02:17:57 +01:00
CPubKey pubkey ( ParseHex ( strPubKey ) ) ;
std : : string errorMessage = " " ;
if ( ! darkSendSigner . VerifyMessage ( pubkey , winner . vchSig , strMessage , errorMessage ) ) {
return false ;
}
2014-12-31 03:54:00 +01:00
2014-12-09 02:17:57 +01:00
return true ;
}
bool CMasternodePayments : : Sign ( CMasternodePaymentWinner & winner )
{
2015-02-12 19:54:45 +01:00
std : : string strMessage = winner . vin . ToString ( ) . c_str ( ) + boost : : lexical_cast < std : : string > ( winner . nBlockHeight ) + winner . payee . ToString ( ) ;
2014-12-09 02:17:57 +01:00
CKey key2 ;
CPubKey pubkey2 ;
std : : string errorMessage = " " ;
if ( ! darkSendSigner . SetKey ( strMasterPrivKey , errorMessage , key2 , pubkey2 ) )
{
2015-03-05 09:11:56 +01:00
LogPrintf ( " CMasternodePayments::Sign - ERROR: Invalid Masternodeprivkey: '%s' \n " , errorMessage . c_str ( ) ) ;
2015-01-18 16:28:16 +01:00
return false ;
2014-12-09 02:17:57 +01:00
}
if ( ! darkSendSigner . SignMessage ( strMessage , errorMessage , winner . vchSig , key2 ) ) {
LogPrintf ( " CMasternodePayments::Sign - Sign message failed " ) ;
return false ;
}
if ( ! darkSendSigner . VerifyMessage ( pubkey2 , winner . vchSig , strMessage , errorMessage ) ) {
LogPrintf ( " CMasternodePayments::Sign - Verify message failed " ) ;
return false ;
}
return true ;
}
uint64_t CMasternodePayments : : CalculateScore ( uint256 blockHash , CTxIn & vin )
{
uint256 n1 = blockHash ;
uint256 n2 = HashX11 ( BEGIN ( n1 ) , END ( n1 ) ) ;
uint256 n3 = HashX11 ( BEGIN ( vin . prevout . hash ) , END ( vin . prevout . hash ) ) ;
uint256 n4 = n3 > n2 ? ( n3 - n2 ) : ( n2 - n3 ) ;
//printf(" -- CMasternodePayments CalculateScore() n2 = %d \n", n2.Get64());
//printf(" -- CMasternodePayments CalculateScore() n3 = %d \n", n3.Get64());
//printf(" -- CMasternodePayments CalculateScore() n4 = %d \n", n4.Get64());
2015-02-12 19:54:45 +01:00
2014-12-09 02:17:57 +01:00
return n4 . Get64 ( ) ;
}
bool CMasternodePayments : : GetBlockPayee ( int nBlockHeight , CScript & payee )
{
BOOST_FOREACH ( CMasternodePaymentWinner & winner , vWinning ) {
if ( winner . nBlockHeight = = nBlockHeight ) {
2015-02-03 18:17:30 +01:00
payee = winner . payee ;
return true ;
2014-12-09 02:17:57 +01:00
}
}
return false ;
}
bool CMasternodePayments : : GetWinningMasternode ( int nBlockHeight , CTxIn & vinOut )
{
BOOST_FOREACH ( CMasternodePaymentWinner & winner , vWinning ) {
if ( winner . nBlockHeight = = nBlockHeight ) {
vinOut = winner . vin ;
return true ;
}
}
return false ;
}
bool CMasternodePayments : : AddWinningMasternode ( CMasternodePaymentWinner & winnerIn )
{
uint256 blockHash = 0 ;
2015-02-09 21:21:12 +01:00
if ( ! GetBlockHash ( blockHash , winnerIn . nBlockHeight - 576 ) ) {
2014-12-09 02:17:57 +01:00
return false ;
}
winnerIn . score = CalculateScore ( blockHash , winnerIn . vin ) ;
bool foundBlock = false ;
BOOST_FOREACH ( CMasternodePaymentWinner & winner , vWinning ) {
if ( winner . nBlockHeight = = winnerIn . nBlockHeight ) {
foundBlock = true ;
if ( winner . score < winnerIn . score ) {
winner . score = winnerIn . score ;
winner . vin = winnerIn . vin ;
2015-02-03 18:17:30 +01:00
winner . payee = winnerIn . payee ;
2014-12-09 02:17:57 +01:00
winner . vchSig = winnerIn . vchSig ;
2015-02-09 21:36:45 +01:00
2015-03-26 21:46:19 +01:00
mapSeenMasternodeVotes . insert ( make_pair ( winnerIn . GetHash ( ) , winnerIn ) ) ;
2014-12-09 02:17:57 +01:00
return true ;
}
}
}
// if it's not in the vector
if ( ! foundBlock ) {
2015-02-09 21:22:31 +01:00
vWinning . push_back ( winnerIn ) ;
mapSeenMasternodeVotes . insert ( make_pair ( winnerIn . GetHash ( ) , winnerIn ) ) ;
2015-02-12 19:54:45 +01:00
2015-02-09 21:22:31 +01:00
return true ;
2014-12-09 02:17:57 +01:00
}
return false ;
}
void CMasternodePayments : : CleanPaymentList ( )
{
2015-03-26 21:46:19 +01:00
LOCK ( cs_masternodepayments ) ;
2014-12-09 02:17:57 +01:00
if ( chainActive . Tip ( ) = = NULL ) return ;
2015-02-23 21:01:21 +01:00
int nLimit = std : : max ( ( ( int ) mnodeman . size ( ) ) * 2 , 1000 ) ;
2014-12-31 04:17:53 +01:00
2014-12-09 02:17:57 +01:00
vector < CMasternodePaymentWinner > : : iterator it ;
for ( it = vWinning . begin ( ) ; it < vWinning . end ( ) ; it + + ) {
2014-12-31 04:17:53 +01:00
if ( chainActive . Tip ( ) - > nHeight - ( * it ) . nBlockHeight > nLimit ) {
2015-03-05 09:11:56 +01:00
if ( fDebug ) LogPrintf ( " CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d \n " , ( * it ) . nBlockHeight ) ;
2014-12-09 02:17:57 +01:00
vWinning . erase ( it ) ;
break ;
}
}
}
bool CMasternodePayments : : ProcessBlock ( int nBlockHeight )
{
2015-03-26 21:46:19 +01:00
LOCK ( cs_masternodepayments ) ;
2015-03-26 15:29:56 +01:00
if ( nBlockHeight < nLastBlockHeight ) return false ; ;
2015-01-20 11:02:11 +01:00
if ( ! enabled ) return false ;
2015-02-16 20:37:24 +01:00
CMasternodePaymentWinner newWinner ;
2015-03-16 21:57:07 +01:00
int nMinimumAge = mnodeman . CountEnabled ( ) ;
2015-03-22 04:10:34 +01:00
2015-03-16 20:01:11 +01:00
uint256 hash ;
if ( ! GetBlockHash ( hash , nBlockHeight - 10 ) ) return false ;
2015-03-23 15:13:20 +01:00
unsigned int nHash ;
2015-03-16 23:25:15 +01:00
memcpy ( & nHash , & hash , 2 ) ;
2015-03-16 20:01:11 +01:00
2015-03-26 21:46:19 +01:00
LogPrintf ( " ProcessBlock Start nHeight %d. \n " , nBlockHeight ) ;
2014-12-31 04:17:53 +01:00
std : : vector < CTxIn > vecLastPayments ;
2015-02-16 20:37:24 +01:00
BOOST_REVERSE_FOREACH ( CMasternodePaymentWinner & winner , vWinning )
{
//if we already have the same vin - we have one full payment cycle, break
if ( vecLastPayments . size ( ) > 0
& & std : : find ( vecLastPayments . begin ( ) , vecLastPayments . end ( ) , winner . vin ) ! = vecLastPayments . end ( ) ) break ;
2014-12-31 04:17:53 +01:00
vecLastPayments . push_back ( winner . vin ) ;
}
2015-03-01 16:38:53 +01:00
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
2015-03-19 16:04:14 +01:00
CMasternode * pmn = mnodeman . FindOldestNotInVec ( vecLastPayments , nMinimumAge , nMinimumAge * 2.5 * 60 ) ;
if ( pmn ! = NULL )
2015-02-16 20:37:24 +01:00
{
newWinner . score = 0 ;
newWinner . nBlockHeight = nBlockHeight ;
2015-02-25 12:54:03 +01:00
newWinner . vin = pmn - > vin ;
2015-03-16 20:01:11 +01:00
2015-03-23 15:13:20 +01:00
if ( pmn - > donationPercentage > 0 & & ( nHash % 100 ) < = pmn - > donationPercentage ) {
2015-03-16 23:25:15 +01:00
newWinner . payee = pmn - > donationAddress ;
2015-03-16 22:09:23 +01:00
} else {
newWinner . payee . SetDestination ( pmn - > pubkey . GetID ( ) ) ;
2015-03-16 20:01:11 +01:00
}
2014-12-09 02:17:57 +01:00
}
2015-02-16 20:37:24 +01:00
//if we can't find new MN to get paid, pick first active MN counting back from the end of vecLastPayments list
2015-03-16 21:57:07 +01:00
if ( newWinner . nBlockHeight = = 0 & & nMinimumAge > 0 )
2015-02-16 20:37:24 +01:00
{
2015-02-23 21:01:21 +01:00
BOOST_REVERSE_FOREACH ( CTxIn & vinLP , vecLastPayments )
2015-02-16 20:37:24 +01:00
{
2015-02-25 12:54:03 +01:00
CMasternode * pmn = mnodeman . Find ( vinLP ) ;
if ( pmn ! = NULL )
2015-02-23 21:01:21 +01:00
{
2015-02-25 12:54:03 +01:00
pmn - > Check ( ) ;
if ( ! pmn - > IsEnabled ( ) ) continue ;
2015-02-23 21:01:21 +01:00
newWinner . score = 0 ;
newWinner . nBlockHeight = nBlockHeight ;
2015-02-25 12:54:03 +01:00
newWinner . vin = pmn - > vin ;
2015-03-16 20:01:11 +01:00
2015-03-23 15:13:20 +01:00
if ( pmn - > donationPercentage > 0 & & ( nHash % 100 ) < = pmn - > donationPercentage ) {
2015-03-16 23:25:15 +01:00
newWinner . payee = pmn - > donationAddress ;
2015-03-16 22:09:23 +01:00
} else {
newWinner . payee . SetDestination ( pmn - > pubkey . GetID ( ) ) ;
2015-03-16 20:01:11 +01:00
}
2015-02-23 21:01:21 +01:00
break ; // we found active MN
}
2015-02-16 20:37:24 +01:00
}
2015-02-04 16:24:34 +01:00
}
2014-12-09 02:17:57 +01:00
2015-02-23 21:01:21 +01:00
if ( newWinner . nBlockHeight = = 0 ) return false ;
2015-03-26 21:46:19 +01:00
CTxDestination address1 ;
ExtractDestination ( newWinner . payee , address1 ) ;
CBitcoinAddress address2 ( address1 ) ;
LogPrintf ( " Winner payee %s nHeight %d. \n " , address2 . ToString ( ) . c_str ( ) , newWinner . nBlockHeight ) ;
2015-02-16 20:37:24 +01:00
if ( Sign ( newWinner ) )
{
if ( AddWinningMasternode ( newWinner ) )
{
Relay ( newWinner ) ;
2015-03-26 15:29:56 +01:00
nLastBlockHeight = nBlockHeight ;
2014-12-09 02:17:57 +01:00
return true ;
}
}
return false ;
}
void CMasternodePayments : : Relay ( CMasternodePaymentWinner & winner )
{
2015-02-09 21:22:31 +01:00
CInv inv ( MSG_MASTERNODE_WINNER , winner . GetHash ( ) ) ;
vector < CInv > vInv ;
vInv . push_back ( inv ) ;
2014-12-09 02:17:57 +01:00
LOCK ( cs_vNodes ) ;
BOOST_FOREACH ( CNode * pnode , vNodes ) {
2015-02-09 21:22:31 +01:00
pnode - > PushMessage ( " inv " , vInv ) ;
2014-12-09 02:17:57 +01:00
}
}
void CMasternodePayments : : Sync ( CNode * node )
{
2015-03-26 21:46:19 +01:00
LOCK ( cs_masternodepayments ) ;
2014-12-09 02:17:57 +01:00
BOOST_FOREACH ( CMasternodePaymentWinner & winner , vWinning )
if ( winner . nBlockHeight > = chainActive . Tip ( ) - > nHeight - 10 & & winner . nBlockHeight < = chainActive . Tip ( ) - > nHeight + 20 )
2015-03-16 21:57:07 +01:00
node - > PushMessage ( " mnw " , winner ) ;
2014-12-09 02:17:57 +01:00
}
bool CMasternodePayments : : SetPrivKey ( std : : string strPrivKey )
{
CMasternodePaymentWinner winner ;
// Test signing successful, proceed
strMasterPrivKey = strPrivKey ;
Sign ( winner ) ;
if ( CheckSignature ( winner ) ) {
2015-03-05 09:11:56 +01:00
LogPrintf ( " CMasternodePayments::SetPrivKey - Successfully initialized as Masternode payments master \n " ) ;
2015-01-20 11:02:11 +01:00
enabled = true ;
2014-12-09 02:17:57 +01:00
return true ;
} else {
return false ;
}
}