2015-04-22 16:33:44 +02:00
// Copyright (c) 2014-2015 The Dash developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# include "masternode-budget.h"
# include "masternode.h"
# include "darksend.h"
# include "masternodeman.h"
# include "util.h"
# include "addrman.h"
# include <boost/filesystem.hpp>
# include <boost/lexical_cast.hpp>
CBudgetManager budget ;
CCriticalSection cs_budget ;
2015-05-27 18:28:55 +02:00
std : : map < uint256 , CBudgetProposalBroadcast > mapSeenMasternodeBudgetProposals ;
std : : map < uint256 , CBudgetVote > mapSeenMasternodeBudgetVotes ;
2015-07-02 18:41:33 +02:00
std : : map < uint256 , CBudgetVote > mapOrphanMasternodeBudgetVotes ;
2015-05-27 18:28:55 +02:00
std : : map < uint256 , CFinalizedBudgetBroadcast > mapSeenFinalizedBudgets ;
std : : map < uint256 , CFinalizedBudgetVote > mapSeenFinalizedBudgetVotes ;
2015-07-02 18:41:33 +02:00
std : : map < uint256 , CFinalizedBudgetVote > mapOrphanFinalizedBudgetVotes ;
std : : map < uint256 , int64_t > askedForSourceProposalOrBudget ;
2015-06-01 21:06:03 +02:00
int nSubmittedFinalBudget ;
2015-05-04 17:04:09 +02:00
2015-05-26 16:56:51 +02:00
int GetBudgetPaymentCycleBlocks ( ) {
if ( Params ( ) . NetworkID ( ) = = CBaseChainParams : : MAIN ) return 16616 ; //(60*24*30)/2.6
//for testing purposes
return 50 ;
}
2015-07-10 00:08:26 +02:00
bool IsBudgetCollateralValid ( uint256 nTxCollateralHash , std : : string & strError )
2015-07-02 18:41:33 +02:00
{
2015-07-10 00:08:26 +02:00
return true ;
2015-07-02 18:41:33 +02:00
2015-07-10 00:08:26 +02:00
CTransaction txCollateral ;
uint256 hash ;
if ( ! GetTransaction ( nTxCollateralHash , txCollateral , hash , true ) ) {
LogPrintf ( " CBudgetProposalBroadcast::FeeTXValid - Can't find collateral tx %s \n " , txCollateral . ToString ( ) . c_str ( ) ) ;
return false ;
2015-07-06 22:23:09 +02:00
}
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
if ( txCollateral . vout . size ( ) < 1 ) return false ;
if ( txCollateral . nLockTime ! = 0 ) return false ;
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
int64_t nValueIn = 0 ;
int64_t nValueOut = 0 ;
bool missingTx = false ;
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
BOOST_FOREACH ( const CTxOut o , txCollateral . vout ) {
nValueOut + = o . nValue ;
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
if ( ! o . scriptPubKey . IsNormalPaymentScript ( ) ) {
LogPrintf ( " CBudgetProposalBroadcast::FeeTXValid - Invalid Script %s \n " , txCollateral . ToString ( ) . c_str ( ) ) ;
return false ;
}
2015-07-04 16:49:49 +02:00
}
2015-07-10 00:08:26 +02:00
bool foundOpReturn = false ;
BOOST_FOREACH ( const CTxIn i , txCollateral . vin ) {
CTransaction tx2 ;
uint256 hash ;
if ( GetTransaction ( i . prevout . hash , tx2 , hash , true ) ) {
if ( tx2 . vout . size ( ) > i . prevout . n ) {
nValueIn + = tx2 . vout [ i . prevout . n ] . nValue ;
2015-07-04 16:49:49 +02:00
}
2015-07-10 00:08:26 +02:00
} else {
missingTx = true ;
2015-07-04 16:49:49 +02:00
}
}
2015-07-10 00:08:26 +02:00
if ( ! foundOpReturn ) {
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
}
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
if ( missingTx ) {
if ( fDebug ) LogPrintf ( " CBudgetProposalBroadcast::FeeTXValid - Unknown inputs in collateral transaction - %s \n " , txCollateral . ToString ( ) . c_str ( ) ) ;
return false ;
}
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
//collateral transactions are required to pay out BUDGET_FEE_TX as a fee to the miners
if ( nValueIn - nValueOut < BUDGET_FEE_TX ) {
if ( fDebug ) LogPrintf ( " CBudgetProposalBroadcast::FeeTXValid - did not include enough fees in transaction %d \n %s \n " , nValueOut - nValueIn , txCollateral . ToString ( ) . c_str ( ) ) ;
return false ;
}
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
if ( fDebug ) LogPrintf ( " CBudgetProposalBroadcast::FeeTXValid %s \n " , txCollateral . ToString ( ) . c_str ( ) ) ;
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
CValidationState state ;
if ( ! AcceptableInputs ( mempool , state , txCollateral , true , NULL ) ) {
if ( fDebug ) LogPrintf ( " CBudgetProposalBroadcast::FeeTXValid - didn't pass IsAcceptable \n " ) ;
return false ;
2015-07-04 16:49:49 +02:00
}
2015-07-10 00:08:26 +02:00
return true ;
return true ;
2015-07-04 16:49:49 +02:00
}
2015-07-10 00:08:26 +02:00
void CBudgetManager : : CheckOrphanVotes ( )
2015-07-04 16:49:49 +02:00
{
2015-07-10 00:08:26 +02:00
std : : map < uint256 , CBudgetVote > : : iterator it1 = mapOrphanMasternodeBudgetVotes . begin ( ) ;
while ( it1 ! = mapOrphanMasternodeBudgetVotes . end ( ) ) {
if ( budget . UpdateProposal ( ( ( * it1 ) . second ) , NULL ) ) {
LogPrintf ( " CheckOrphanVotes: Proposal/Budget is known, activating and removing orphan vote \n " ) ;
mapOrphanMasternodeBudgetVotes . erase ( it1 + + ) ;
} else {
+ + it1 ;
2015-07-04 16:49:49 +02:00
}
}
2015-07-10 00:08:26 +02:00
std : : map < uint256 , CFinalizedBudgetVote > : : iterator it2 = mapOrphanFinalizedBudgetVotes . begin ( ) ;
while ( it2 ! = mapOrphanFinalizedBudgetVotes . end ( ) ) {
if ( budget . UpdateFinalizedBudget ( ( ( * it2 ) . second ) , NULL ) ) {
LogPrintf ( " CheckOrphanVotes: Proposal/Budget is known, activating and removing orphan vote \n " ) ;
mapOrphanFinalizedBudgetVotes . erase ( it2 + + ) ;
} else {
+ + it2 ;
2015-07-04 16:49:49 +02:00
}
}
}
2015-07-08 04:35:58 +02:00
void CBudgetManager : : SubmitFinalBudget ( )
2015-06-03 18:10:11 +02:00
{
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( ! pindexPrev ) return ;
2015-07-12 19:34:21 +02:00
2015-06-03 18:10:11 +02:00
int nBlockStart = pindexPrev - > nHeight - ( pindexPrev - > nHeight % GetBudgetPaymentCycleBlocks ( ) ) + GetBudgetPaymentCycleBlocks ( ) ;
if ( nSubmittedFinalBudget > = nBlockStart ) return ;
if ( nBlockStart - pindexPrev - > nHeight > 100 ) return ;
2015-07-08 04:35:58 +02:00
std : : vector < CBudgetProposal * > vBudgetProposals = budget . GetBudget ( ) ;
2015-06-03 18:10:11 +02:00
std : : string strBudgetName = " main " ;
2015-07-08 04:35:58 +02:00
std : : vector < CTxBudgetPayment > vecTxBudgetPayments ;
2015-06-03 18:10:11 +02:00
2015-07-08 04:35:58 +02:00
for ( unsigned int i = 0 ; i < vBudgetProposals . size ( ) ; i + + ) {
2015-06-03 18:10:11 +02:00
CTxBudgetPayment out ;
2015-07-08 04:35:58 +02:00
out . nProposalHash = vBudgetProposals [ i ] - > GetHash ( ) ;
out . payee = vBudgetProposals [ i ] - > GetPayee ( ) ;
out . nAmount = vBudgetProposals [ i ] - > GetAmount ( ) ;
vecTxBudgetPayments . push_back ( out ) ;
2015-06-03 18:10:11 +02:00
}
2015-07-08 04:35:58 +02:00
if ( vecTxBudgetPayments . size ( ) < 1 ) {
2015-06-16 19:04:35 +02:00
LogPrintf ( " SubmitFinalBudget - Found No Proposals For Period \n " ) ;
return ;
}
2015-06-03 18:10:11 +02:00
nSubmittedFinalBudget = nBlockStart ;
CPubKey pubKeyMasternode ;
CKey keyMasternode ;
std : : string errorMessage ;
if ( ! darkSendSigner . SetKey ( strMasterNodePrivKey , errorMessage , keyMasternode , pubKeyMasternode ) ) {
2015-06-16 19:04:35 +02:00
LogPrintf ( " SubmitFinalBudget - Error upon calling SetKey \n " ) ;
2015-07-12 19:34:21 +02:00
return ;
2015-06-03 18:10:11 +02:00
}
2015-07-12 19:34:21 +02:00
CFinalizedBudgetBroadcast tempBudget ( strBudgetName , nBlockStart , vecTxBudgetPayments , 0 ) ;
2015-07-10 00:08:26 +02:00
//create fee tx
2015-07-12 19:34:21 +02:00
CTransaction tx ;
if ( ! pwalletMain - > GetBudgetSystemCollateralTX ( tx , tempBudget . GetHash ( ) , true ) ) {
LogPrintf ( " SubmitFinalBudget - Can't make collateral transaction \n " ) ;
return ;
}
2015-07-10 00:08:26 +02:00
2015-06-03 18:10:11 +02:00
//create the proposal incase we're the first to make it
2015-07-12 19:34:21 +02:00
CFinalizedBudgetBroadcast finalizedBudgetBroadcast ( strBudgetName , nBlockStart , vecTxBudgetPayments , tx . GetHash ( ) ) ;
2015-06-03 18:10:11 +02:00
2015-07-08 04:35:58 +02:00
if ( ! finalizedBudgetBroadcast . IsValid ( ) ) {
LogPrintf ( " SubmitFinalBudget - Invalid finalized budget broadcast (are all the hashes correct?) \n " ) ;
2015-07-12 19:34:21 +02:00
return ;
2015-06-03 18:10:11 +02:00
}
2015-07-08 04:35:58 +02:00
mapSeenFinalizedBudgets . insert ( make_pair ( finalizedBudgetBroadcast . GetHash ( ) , finalizedBudgetBroadcast ) ) ;
finalizedBudgetBroadcast . Relay ( ) ;
budget . AddFinalizedBudget ( finalizedBudgetBroadcast ) ;
2015-06-03 18:10:11 +02:00
2015-07-08 04:35:58 +02:00
CFinalizedBudgetVote vote ( activeMasternode . vin , finalizedBudgetBroadcast . GetHash ( ) ) ;
2015-06-03 18:10:11 +02:00
if ( ! vote . Sign ( keyMasternode , pubKeyMasternode ) ) {
2015-06-16 19:04:35 +02:00
LogPrintf ( " SubmitFinalBudget - Failure to sign. \n " ) ;
2015-07-12 19:34:21 +02:00
return ;
2015-06-03 18:10:11 +02:00
}
mapSeenFinalizedBudgetVotes . insert ( make_pair ( vote . GetHash ( ) , vote ) ) ;
vote . Relay ( ) ;
2015-07-02 18:41:33 +02:00
budget . UpdateFinalizedBudget ( vote , NULL ) ;
2015-06-03 18:10:11 +02:00
}
2015-04-22 16:33:44 +02:00
//
// CBudgetDB
//
CBudgetDB : : CBudgetDB ( )
{
pathDB = GetDataDir ( ) / " budget.dat " ;
strMagicMessage = " MasternodeBudget " ;
}
2015-06-23 18:38:28 +02:00
bool CBudgetDB : : Write ( const CBudgetManager & objToSave )
2015-04-22 16:33:44 +02:00
{
int64_t nStart = GetTimeMillis ( ) ;
// serialize, checksum data up to that point, then append checksum
2015-06-23 18:38:28 +02:00
CDataStream ssObj ( SER_DISK , CLIENT_VERSION ) ;
ssObj < < strMagicMessage ; // masternode cache file specific magic message
ssObj < < FLATDATA ( Params ( ) . MessageStart ( ) ) ; // network specific magic number
ssObj < < objToSave ;
uint256 hash = Hash ( ssObj . begin ( ) , ssObj . end ( ) ) ;
ssObj < < hash ;
2015-04-22 16:33:44 +02:00
// open output file, and associate with CAutoFile
FILE * file = fopen ( pathDB . string ( ) . c_str ( ) , " wb " ) ;
CAutoFile fileout ( file , SER_DISK , CLIENT_VERSION ) ;
if ( fileout . IsNull ( ) )
return error ( " %s : Failed to open file %s " , __func__ , pathDB . string ( ) ) ;
// Write and commit header, data
try {
2015-06-23 18:38:28 +02:00
fileout < < ssObj ;
2015-04-22 16:33:44 +02:00
}
catch ( std : : exception & e ) {
return error ( " %s : Serialize or I/O error - %s " , __func__ , e . what ( ) ) ;
}
fileout . fclose ( ) ;
2015-05-04 17:04:09 +02:00
LogPrintf ( " Written info to budget.dat %dms \n " , GetTimeMillis ( ) - nStart ) ;
2015-04-22 16:33:44 +02:00
return true ;
}
2015-06-23 18:38:28 +02:00
CBudgetDB : : ReadResult CBudgetDB : : Read ( CBudgetManager & objToLoad )
2015-04-22 16:33:44 +02:00
{
2015-06-10 04:46:24 +02:00
2015-04-22 16:33:44 +02:00
int64_t nStart = GetTimeMillis ( ) ;
// open input file, and associate with CAutoFile
FILE * file = fopen ( pathDB . string ( ) . c_str ( ) , " rb " ) ;
CAutoFile filein ( file , SER_DISK , CLIENT_VERSION ) ;
if ( filein . IsNull ( ) )
{
error ( " %s : Failed to open file %s " , __func__ , pathDB . string ( ) ) ;
return FileError ;
}
// use file size to size memory buffer
int fileSize = boost : : filesystem : : file_size ( pathDB ) ;
int dataSize = fileSize - sizeof ( uint256 ) ;
// Don't try to resize to a negative number if file is small
if ( dataSize < 0 )
dataSize = 0 ;
vector < unsigned char > vchData ;
vchData . resize ( dataSize ) ;
uint256 hashIn ;
// read data and checksum from file
try {
filein . read ( ( char * ) & vchData [ 0 ] , dataSize ) ;
filein > > hashIn ;
}
catch ( std : : exception & e ) {
error ( " %s : Deserialize or I/O error - %s " , __func__ , e . what ( ) ) ;
return HashReadError ;
}
filein . fclose ( ) ;
2015-06-23 18:38:28 +02:00
CDataStream ssObj ( vchData , SER_DISK , CLIENT_VERSION ) ;
2015-04-22 16:33:44 +02:00
// verify stored checksum matches input data
2015-06-23 18:38:28 +02:00
uint256 hashTmp = Hash ( ssObj . begin ( ) , ssObj . end ( ) ) ;
2015-04-22 16:33:44 +02:00
if ( hashIn ! = hashTmp )
{
error ( " %s : Checksum mismatch, data corrupted " , __func__ ) ;
return IncorrectHash ;
}
2015-07-06 22:23:09 +02:00
2015-04-22 16:33:44 +02:00
unsigned char pchMsgTmp [ 4 ] ;
std : : string strMagicMessageTmp ;
try {
// de-serialize file header (masternode cache file specific magic message) and ..
2015-06-23 18:38:28 +02:00
ssObj > > strMagicMessageTmp ;
2015-04-22 16:33:44 +02:00
// ... verify the message matches predefined one
if ( strMagicMessage ! = strMagicMessageTmp )
{
error ( " %s : Invalid masternode cache magic message " , __func__ ) ;
return IncorrectMagicMessage ;
}
// de-serialize file header (network specific magic number) and ..
2015-06-23 18:38:28 +02:00
ssObj > > FLATDATA ( pchMsgTmp ) ;
2015-04-22 16:33:44 +02:00
// ... verify the network matches ours
if ( memcmp ( pchMsgTmp , Params ( ) . MessageStart ( ) , sizeof ( pchMsgTmp ) ) )
{
error ( " %s : Invalid network magic number " , __func__ ) ;
return IncorrectMagicNumber ;
}
// de-serialize data into CBudgetManager object
2015-06-23 18:38:28 +02:00
ssObj > > objToLoad ;
2015-04-22 16:33:44 +02:00
}
catch ( std : : exception & e ) {
2015-06-23 18:38:28 +02:00
objToLoad . Clear ( ) ;
2015-04-22 16:33:44 +02:00
error ( " %s : Deserialize or I/O error - %s " , __func__ , e . what ( ) ) ;
return IncorrectFormat ;
}
2015-06-23 18:38:28 +02:00
objToLoad . CheckAndRemove ( ) ; // clean out expired
2015-05-04 17:04:09 +02:00
LogPrintf ( " Loaded info from budget.dat %dms \n " , GetTimeMillis ( ) - nStart ) ;
2015-06-23 18:38:28 +02:00
LogPrintf ( " %s \n " , objToLoad . ToString ( ) ) ;
2015-04-22 16:33:44 +02:00
return Ok ;
}
void DumpBudgets ( )
{
int64_t nStart = GetTimeMillis ( ) ;
CBudgetDB mndb ;
2015-07-08 19:17:16 +02:00
2015-05-04 17:04:09 +02:00
LogPrintf ( " Writting info to budget.dat... \n " ) ;
2015-04-22 16:33:44 +02:00
mndb . Write ( budget ) ;
2015-06-23 18:38:28 +02:00
LogPrintf ( " Budget dump finished %dms \n " , GetTimeMillis ( ) - nStart ) ;
2015-04-22 16:33:44 +02:00
}
2015-07-08 04:35:58 +02:00
void CBudgetManager : : AddFinalizedBudget ( CFinalizedBudget & finalizedBudget )
2015-05-04 11:31:31 +02:00
{
2015-06-03 18:10:11 +02:00
LOCK ( cs ) ;
2015-07-08 04:35:58 +02:00
if ( ! finalizedBudget . IsValid ( ) ) return ;
2015-07-10 00:08:26 +02:00
if ( mapFinalizedBudgets . count ( finalizedBudget . GetHash ( ) ) ) {
2015-07-04 16:49:49 +02:00
return ;
}
2015-05-04 17:04:09 +02:00
2015-07-08 04:35:58 +02:00
mapFinalizedBudgets . insert ( make_pair ( finalizedBudget . GetHash ( ) , finalizedBudget ) ) ;
2015-05-04 11:31:31 +02:00
}
2015-07-08 04:35:58 +02:00
void CBudgetManager : : AddProposal ( CBudgetProposal & budgetProposal )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
LOCK ( cs ) ;
2015-07-08 04:35:58 +02:00
std : : string strError = " " ;
if ( ! budgetProposal . IsValid ( strError ) ) {
LogPrintf ( " mprop - invalid budget proposal - %s \n " , strError . c_str ( ) ) ;
return ;
}
2015-07-10 00:08:26 +02:00
if ( mapProposals . count ( budgetProposal . GetHash ( ) ) ) {
2015-07-04 16:49:49 +02:00
return ;
}
2015-05-04 17:04:09 +02:00
2015-07-08 04:35:58 +02:00
mapProposals . insert ( make_pair ( budgetProposal . GetHash ( ) , budgetProposal ) ) ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
void CBudgetManager : : CheckAndRemove ( )
2015-04-22 16:33:44 +02:00
{
2015-06-16 19:04:35 +02:00
std : : string strError = " " ;
2015-06-03 18:10:11 +02:00
std : : map < uint256 , CFinalizedBudget > : : iterator it = mapFinalizedBudgets . begin ( ) ;
while ( it ! = mapFinalizedBudgets . end ( ) )
{
2015-07-08 04:35:58 +02:00
CFinalizedBudget * pfinalizedBudget = & ( ( * it ) . second ) ;
if ( ! pfinalizedBudget - > IsValid ( ) ) {
2015-06-10 08:49:08 +02:00
mapFinalizedBudgets . erase ( it + + ) ;
2015-06-03 18:10:11 +02:00
} else {
2015-07-08 04:35:58 +02:00
pfinalizedBudget - > AutoCheck ( ) ;
2015-06-10 08:49:08 +02:00
+ + it ;
2015-06-03 18:10:11 +02:00
}
}
2015-04-22 16:33:44 +02:00
2015-06-03 18:10:11 +02:00
std : : map < uint256 , CBudgetProposal > : : iterator it2 = mapProposals . begin ( ) ;
while ( it2 ! = mapProposals . end ( ) )
{
2015-07-08 04:35:58 +02:00
CBudgetProposal * pbudgetProposal = & ( ( * it2 ) . second ) ;
if ( ! pbudgetProposal - > IsValid ( strError ) ) {
2015-06-10 08:49:08 +02:00
mapProposals . erase ( it2 + + ) ;
2015-06-03 18:10:11 +02:00
} else {
2015-06-10 08:49:08 +02:00
+ + it2 ;
2015-06-03 18:10:11 +02:00
}
2015-04-22 16:33:44 +02:00
}
}
2015-05-30 19:27:51 +02:00
void CBudgetManager : : FillBlockPayee ( CMutableTransaction & txNew , int64_t nFees )
2015-06-03 18:10:11 +02:00
{
2015-05-30 19:27:51 +02:00
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( ! pindexPrev ) return ;
int nHighestCount = 0 ;
CScript payee ;
int64_t nAmount = 0 ;
// ------- Grab The Highest Count
2015-06-03 18:10:11 +02:00
2015-05-30 19:27:51 +02:00
std : : map < uint256 , CFinalizedBudget > : : iterator it = mapFinalizedBudgets . begin ( ) ;
while ( it ! = mapFinalizedBudgets . end ( ) )
2015-06-03 18:10:11 +02:00
{
2015-07-08 04:35:58 +02:00
CFinalizedBudget * pfinalizedBudget = & ( ( * it ) . second ) ;
if ( pfinalizedBudget - > GetVoteCount ( ) > nHighestCount ) {
if ( pindexPrev - > nHeight + 1 > = pfinalizedBudget - > GetBlockStart ( ) & & pindexPrev - > nHeight + 1 < = pfinalizedBudget - > GetBlockEnd ( ) ) {
if ( pfinalizedBudget - > GetPayeeAndAmount ( pindexPrev - > nHeight + 1 , payee , nAmount ) ) {
nHighestCount = pfinalizedBudget - > GetVoteCount ( ) ;
2015-05-30 19:27:51 +02:00
}
}
}
it + + ;
}
CAmount blockValue = GetBlockValue ( pindexPrev - > nBits , pindexPrev - > nHeight , nFees ) ;
//miners get the full amount on these blocks
txNew . vout [ 0 ] . nValue = blockValue ;
2015-06-03 18:10:11 +02:00
2015-05-30 19:27:51 +02:00
if ( nHighestCount > 0 ) {
txNew . vout . resize ( 2 ) ;
//these are super blocks, so their value can be much larger than normal
txNew . vout [ 1 ] . scriptPubKey = payee ;
txNew . vout [ 1 ] . nValue = nAmount ;
CTxDestination address1 ;
ExtractDestination ( payee , address1 ) ;
CBitcoinAddress address2 ( address1 ) ;
LogPrintf ( " Budget payment to %s for %lld \n " , address2 . ToString ( ) . c_str ( ) , nAmount ) ;
}
}
2015-06-03 18:10:11 +02:00
CFinalizedBudget * CBudgetManager : : FindFinalizedBudget ( uint256 nHash )
2015-05-30 19:27:51 +02:00
{
2015-06-03 18:10:11 +02:00
if ( mapFinalizedBudgets . count ( nHash ) )
return & mapFinalizedBudgets [ nHash ] ;
2015-05-30 22:12:12 +02:00
2015-06-03 18:10:11 +02:00
return NULL ;
2015-05-30 19:27:51 +02:00
}
2015-06-03 18:10:11 +02:00
CBudgetProposal * CBudgetManager : : FindProposal ( const std : : string & strProposalName )
2015-04-22 16:33:44 +02:00
{
2015-06-03 18:10:11 +02:00
//find the prop with the highest yes count
2015-04-22 16:33:44 +02:00
2015-07-07 00:06:09 +02:00
int nYesCount = - 99999 ;
2015-07-08 04:35:58 +02:00
CBudgetProposal * pbudgetProposal = NULL ;
2015-06-03 18:10:11 +02:00
std : : map < uint256 , CBudgetProposal > : : iterator it = mapProposals . begin ( ) ;
while ( it ! = mapProposals . end ( ) ) {
if ( ( * it ) . second . strProposalName = = strProposalName & & ( * it ) . second . GetYeas ( ) > nYesCount ) {
2015-07-08 04:35:58 +02:00
pbudgetProposal = & ( ( * it ) . second ) ;
nYesCount = pbudgetProposal - > GetYeas ( ) ;
2015-06-03 18:10:11 +02:00
}
+ + it ;
}
2015-07-07 00:06:09 +02:00
if ( nYesCount = = - 99999 ) return NULL ;
2015-06-03 18:10:11 +02:00
2015-07-08 04:35:58 +02:00
return pbudgetProposal ;
2015-06-03 18:10:11 +02:00
}
CBudgetProposal * CBudgetManager : : FindProposal ( uint256 nHash )
{
if ( mapProposals . count ( nHash ) )
return & mapProposals [ nHash ] ;
return NULL ;
}
bool CBudgetManager : : IsBudgetPaymentBlock ( int nBlockHeight ) {
std : : map < uint256 , CFinalizedBudget > : : iterator it = mapFinalizedBudgets . begin ( ) ;
while ( it ! = mapFinalizedBudgets . end ( ) )
{
2015-07-08 04:35:58 +02:00
CFinalizedBudget * pfinalizedBudget = & ( ( * it ) . second ) ;
if ( nBlockHeight > = pfinalizedBudget - > GetBlockStart ( ) & & nBlockHeight < = pfinalizedBudget - > GetBlockEnd ( ) ) {
2015-06-03 18:10:11 +02:00
return true ;
}
it + + ;
}
return false ;
}
bool CBudgetManager : : IsTransactionValid ( const CTransaction & txNew , int nBlockHeight )
{
int nHighestCount = 0 ;
std : : vector < CFinalizedBudget * > ret ;
// ------- Grab The Highest Count
std : : map < uint256 , CFinalizedBudget > : : iterator it = mapFinalizedBudgets . begin ( ) ;
while ( it ! = mapFinalizedBudgets . end ( ) )
{
2015-07-08 04:35:58 +02:00
CFinalizedBudget * pfinalizedBudget = & ( ( * it ) . second ) ;
if ( pfinalizedBudget - > GetVoteCount ( ) > nHighestCount ) {
if ( nBlockHeight > = pfinalizedBudget - > GetBlockStart ( ) & & nBlockHeight < = pfinalizedBudget - > GetBlockEnd ( ) ) {
nHighestCount = pfinalizedBudget - > GetVoteCount ( ) ;
2015-06-03 18:10:11 +02:00
}
}
it + + ;
}
if ( nHighestCount < mnodeman . CountEnabled ( ) / 20 ) return true ;
// check the highest finalized budgets (+/- 10% to assist in consensus)
std : : map < uint256 , CFinalizedBudget > : : iterator it2 = mapFinalizedBudgets . begin ( ) ;
while ( it2 ! = mapFinalizedBudgets . end ( ) )
{
2015-07-08 04:35:58 +02:00
CFinalizedBudget * pfinalizedBudget = & ( ( * it2 ) . second ) ;
2015-06-03 18:10:11 +02:00
2015-07-08 04:35:58 +02:00
if ( pfinalizedBudget - > GetVoteCount ( ) > nHighestCount - ( mnodeman . CountEnabled ( ) / 10 ) ) {
if ( nBlockHeight > = pfinalizedBudget - > GetBlockStart ( ) & & nBlockHeight < = pfinalizedBudget - > GetBlockEnd ( ) ) {
if ( pfinalizedBudget - > IsTransactionValid ( txNew , nBlockHeight ) ) {
2015-06-03 18:10:11 +02:00
return true ;
}
}
}
it2 + + ;
}
//we looked through all of the known budgets
return false ;
}
2015-07-03 19:54:10 +02:00
std : : vector < CBudgetProposal * > CBudgetManager : : GetAllProposals ( )
{
2015-07-08 04:35:58 +02:00
std : : vector < CBudgetProposal * > vBudgetProposalRet ;
2015-07-03 19:54:10 +02:00
std : : map < uint256 , CBudgetProposal > : : iterator it2 = mapProposals . begin ( ) ;
while ( it2 ! = mapProposals . end ( ) )
{
2015-07-05 02:02:14 +02:00
( * it2 ) . second . CleanAndRemove ( ) ;
2015-07-05 00:49:42 +02:00
2015-07-08 04:35:58 +02:00
CBudgetProposal * pbudgetProposal = & ( ( * it2 ) . second ) ;
vBudgetProposalRet . push_back ( pbudgetProposal ) ;
2015-07-03 19:54:10 +02:00
it2 + + ;
}
2015-07-08 04:35:58 +02:00
return vBudgetProposalRet ;
2015-07-03 19:54:10 +02:00
}
2015-06-03 18:10:11 +02:00
//Need to review this function
std : : vector < CBudgetProposal * > CBudgetManager : : GetBudget ( )
{
// ------- Sort budgets by Yes Count
std : : map < uint256 , int > mapList ;
std : : map < uint256 , CBudgetProposal > : : iterator it = mapProposals . begin ( ) ;
while ( it ! = mapProposals . end ( ) ) {
2015-07-05 00:49:42 +02:00
( * it ) . second . CleanAndRemove ( ) ;
2015-06-03 18:10:11 +02:00
mapList . insert ( make_pair ( ( * it ) . second . GetHash ( ) , ( * it ) . second . GetYeas ( ) ) ) ;
+ + it ;
}
//sort the map and grab the highest count item
std : : vector < std : : pair < uint256 , int > > vecList ( mapList . begin ( ) , mapList . end ( ) ) ;
std : : sort ( vecList . begin ( ) , vecList . end ( ) ) ;
// ------- Grab The Budgets In Order
2015-07-08 04:35:58 +02:00
std : : vector < CBudgetProposal * > vBudgetProposalRet ;
2015-06-03 18:10:11 +02:00
int64_t nBudgetAllocated = 0 ;
2015-06-10 04:46:24 +02:00
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
2015-07-08 04:35:58 +02:00
if ( pindexPrev = = NULL ) return vBudgetProposalRet ;
2015-06-10 04:46:24 +02:00
int nBlockStart = pindexPrev - > nHeight - ( pindexPrev - > nHeight % GetBudgetPaymentCycleBlocks ( ) ) + GetBudgetPaymentCycleBlocks ( ) ;
2015-06-16 19:04:35 +02:00
int nBlockEnd = nBlockStart + GetBudgetPaymentCycleBlocks ( ) - 1 ;
2015-06-10 04:46:24 +02:00
int64_t nTotalBudget = GetTotalBudget ( nBlockStart ) ;
2015-06-03 18:10:11 +02:00
std : : map < uint256 , CBudgetProposal > : : iterator it2 = mapProposals . begin ( ) ;
while ( it2 ! = mapProposals . end ( ) )
{
2015-07-08 04:35:58 +02:00
CBudgetProposal * pbudgetProposal = & ( ( * it2 ) . second ) ;
2015-06-03 18:10:11 +02:00
2015-06-16 19:04:35 +02:00
//prop start/end should be inside this period
2015-07-08 04:35:58 +02:00
if ( pbudgetProposal - > nBlockStart < = nBlockStart & & pbudgetProposal - > nBlockEnd > = nBlockEnd & & pbudgetProposal - > GetYeas ( ) - pbudgetProposal - > GetNays ( ) > mnodeman . CountEnabled ( ) / 10 )
2015-06-16 19:04:35 +02:00
{
if ( nTotalBudget = = nBudgetAllocated ) {
2015-07-08 04:35:58 +02:00
pbudgetProposal - > SetAllotted ( 0 ) ;
} else if ( pbudgetProposal - > GetAmount ( ) + nBudgetAllocated < = nTotalBudget ) {
pbudgetProposal - > SetAllotted ( pbudgetProposal - > GetAmount ( ) ) ;
nBudgetAllocated + = pbudgetProposal - > GetAmount ( ) ;
2015-06-16 19:04:35 +02:00
} else {
//couldn't pay for the entire budget, so it'll be partially paid.
2015-07-08 04:35:58 +02:00
pbudgetProposal - > SetAllotted ( nTotalBudget - nBudgetAllocated ) ;
2015-06-16 19:04:35 +02:00
nBudgetAllocated = nTotalBudget ;
}
2015-07-06 22:23:09 +02:00
2015-07-08 04:35:58 +02:00
vBudgetProposalRet . push_back ( pbudgetProposal ) ;
2015-06-03 18:10:11 +02:00
}
it2 + + ;
}
2015-07-08 04:35:58 +02:00
return vBudgetProposalRet ;
2015-06-03 18:10:11 +02:00
}
std : : vector < CFinalizedBudget * > CBudgetManager : : GetFinalizedBudgets ( )
{
2015-07-08 04:35:58 +02:00
std : : vector < CFinalizedBudget * > vFinalizedBudgetRet ;
2015-06-03 18:10:11 +02:00
// ------- Grab The Budgets In Order
std : : map < uint256 , CFinalizedBudget > : : iterator it2 = mapFinalizedBudgets . begin ( ) ;
while ( it2 ! = mapFinalizedBudgets . end ( ) )
{
2015-07-08 04:35:58 +02:00
CFinalizedBudget * pfinalizedBudget = & ( ( * it2 ) . second ) ;
2015-06-03 18:10:11 +02:00
2015-07-08 04:35:58 +02:00
vFinalizedBudgetRet . push_back ( pfinalizedBudget ) ;
2015-06-03 18:10:11 +02:00
it2 + + ;
}
2015-07-08 04:35:58 +02:00
return vFinalizedBudgetRet ;
2015-06-03 18:10:11 +02:00
}
std : : string CBudgetManager : : GetRequiredPaymentsString ( int64_t nBlockHeight )
{
std : : string ret = " unknown-budget " ;
std : : map < uint256 , CFinalizedBudget > : : iterator it = mapFinalizedBudgets . begin ( ) ;
while ( it ! = mapFinalizedBudgets . end ( ) )
{
2015-07-08 04:35:58 +02:00
CFinalizedBudget * pfinalizedBudget = & ( ( * it ) . second ) ;
if ( nBlockHeight > = pfinalizedBudget - > GetBlockStart ( ) & & nBlockHeight < = pfinalizedBudget - > GetBlockEnd ( ) ) {
2015-06-03 18:10:11 +02:00
CTxBudgetPayment payment ;
2015-07-08 04:35:58 +02:00
if ( pfinalizedBudget - > GetProposalByBlock ( nBlockHeight , payment ) ) {
2015-06-03 18:10:11 +02:00
if ( ret = = " unknown-budget " ) {
ret = payment . nProposalHash . ToString ( ) . c_str ( ) ;
} else {
ret + = " , " ;
ret + = payment . nProposalHash . ToString ( ) . c_str ( ) ;
}
} else {
LogPrintf ( " CBudgetManager::GetRequiredPaymentsString - Couldn't find budget payment for block %lld \n " , nBlockHeight ) ;
}
}
it + + ;
}
return ret ;
}
2015-06-10 04:46:24 +02:00
int64_t CBudgetManager : : GetTotalBudget ( int nHeight )
2015-06-03 18:10:11 +02:00
{
if ( chainActive . Tip ( ) = = NULL ) return 0 ;
2015-06-10 04:46:24 +02:00
//get min block value and calculate from that
int64_t nSubsidy = 5 * COIN ;
if ( Params ( ) . NetworkID ( ) = = CBaseChainParams : : TESTNET ) {
for ( int i = 46200 ; i < = nHeight ; i + = 210240 ) nSubsidy - = nSubsidy / 14 ;
} else {
// yearly decline of production by 7.1% per year, projected 21.3M coins max by year 2050.
for ( int i = 210240 ; i < = nHeight ; i + = 210240 ) nSubsidy - = nSubsidy / 14 ;
}
return ( ( nSubsidy / 100 ) * 10 ) * 576 * 30 ;
2015-06-03 18:10:11 +02:00
}
void CBudgetManager : : NewBlock ( )
{
budget . CheckAndRemove ( ) ;
if ( strBudgetMode = = " suggest " ) { //suggest the budget we see
SubmitFinalBudget ( ) ;
}
//this function should be called 1/6 blocks, allowing up to 100 votes per day on all proposals
if ( chainActive . Height ( ) % 6 ! = 0 ) return ;
2015-07-04 16:49:49 +02:00
2015-06-03 18:10:11 +02:00
mnodeman . DecrementVotedTimes ( ) ;
2015-07-04 16:49:49 +02:00
//remove invalid votes once in a while (we have to check the signatures and validity of every vote, somewhat CPU intensive)
std : : map < uint256 , CBudgetProposal > : : iterator it = mapProposals . begin ( ) ;
while ( it ! = mapProposals . end ( ) ) {
( * it ) . second . CleanAndRemove ( ) ;
+ + it ;
}
std : : map < uint256 , CFinalizedBudget > : : iterator it2 = mapFinalizedBudgets . begin ( ) ;
while ( it2 ! = mapFinalizedBudgets . end ( ) ) {
( * it2 ) . second . CleanAndRemove ( ) ;
+ + it2 ;
}
2015-06-03 18:10:11 +02:00
}
void CBudgetManager : : ProcessMessage ( CNode * pfrom , std : : string & strCommand , CDataStream & vRecv )
{
// lite mode is not supported
if ( IsInitialBlockDownload ( ) ) return ;
LOCK ( cs_budget ) ;
2015-04-22 16:33:44 +02:00
if ( strCommand = = " mnvs " ) { //Masternode vote sync
2015-07-12 19:34:21 +02:00
uint256 nProp ;
vRecv > > nProp ;
2015-07-06 22:23:09 +02:00
bool IsLocal = pfrom - > addr . IsRFC1918 ( ) | | pfrom - > addr . IsLocal ( ) ;
2015-07-12 19:34:21 +02:00
if ( ! IsLocal & & nProp = = 0 ) {
2015-07-02 17:07:30 +02:00
if ( pfrom - > HasFulfilledRequest ( " mnvs " ) ) {
LogPrintf ( " mnvs - peer already asked me for the list \n " ) ;
Misbehaving ( pfrom - > GetId ( ) , 20 ) ;
return ;
}
2015-07-12 19:34:21 +02:00
pfrom - > FulfilledRequest ( " mnvs " ) ;
2015-04-22 16:33:44 +02:00
}
2015-07-02 18:41:33 +02:00
budget . Sync ( pfrom , nProp ) ;
2015-07-06 23:00:00 +02:00
LogPrintf ( " mnvs - Sent Masternode votes to %s \n " , pfrom - > addr . ToString ( ) ) ;
2015-04-22 16:33:44 +02:00
}
2015-05-04 17:04:09 +02:00
if ( strCommand = = " mprop " ) { //Masternode Proposal
2015-07-08 04:35:58 +02:00
CBudgetProposalBroadcast budgetProposalBroadcast ;
vRecv > > budgetProposalBroadcast ;
2015-07-06 22:23:09 +02:00
2015-07-08 04:35:58 +02:00
if ( mapSeenMasternodeBudgetProposals . count ( budgetProposalBroadcast . GetHash ( ) ) ) {
2015-07-10 00:08:26 +02:00
return ;
2015-05-04 17:04:09 +02:00
}
2015-06-16 19:04:35 +02:00
//set time we first saw this prop
2015-07-08 04:35:58 +02:00
budgetProposalBroadcast . nTime = GetAdjustedTime ( ) ;
2015-06-16 19:04:35 +02:00
2015-07-10 00:08:26 +02:00
std : : string strError = " " ;
if ( ! IsBudgetCollateralValid ( budgetProposalBroadcast . nFeeTXHash , strError ) ) {
LogPrintf ( " Proposal FeeTX is not valid - %s - %s \n " , budgetProposalBroadcast . nFeeTXHash . ToString ( ) , strError ) ;
2015-05-04 17:04:09 +02:00
return ;
}
2015-07-08 04:35:58 +02:00
if ( ! budgetProposalBroadcast . IsValid ( strError ) ) {
2015-07-10 00:08:26 +02:00
LogPrintf ( " mprop - invalid budget proposal - %s \n " , strError ) ;
2015-06-03 18:10:11 +02:00
return ;
2015-05-04 17:04:09 +02:00
}
2015-07-08 04:35:58 +02:00
mapSeenMasternodeBudgetProposals . insert ( make_pair ( budgetProposalBroadcast . GetHash ( ) , budgetProposalBroadcast ) ) ;
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
CBudgetProposal budgetProposal ( budgetProposalBroadcast ) ;
budget . AddProposal ( budgetProposal ) ;
budgetProposalBroadcast . Relay ( ) ;
2015-07-02 18:41:33 +02:00
2015-07-10 00:08:26 +02:00
//We might have active votes for this proposal that are valid now
CheckOrphanVotes ( ) ;
2015-05-04 17:04:09 +02:00
}
2015-04-22 16:33:44 +02:00
if ( strCommand = = " mvote " ) { //Masternode Vote
CBudgetVote vote ;
vRecv > > vote ;
2015-05-04 17:04:09 +02:00
2015-05-27 18:28:55 +02:00
if ( mapSeenMasternodeBudgetVotes . count ( vote . GetHash ( ) ) ) {
2015-05-04 17:04:09 +02:00
return ;
}
2015-07-06 23:00:00 +02:00
CMasternode * pmn = mnodeman . Find ( vote . vin ) ;
if ( pmn = = NULL ) {
if ( fDebug ) LogPrintf ( " mvote - unknown masternode - vin: %s \n " , vote . vin . ToString ( ) ) ;
2015-05-04 17:04:09 +02:00
return ;
2015-04-22 16:33:44 +02:00
}
2015-07-06 23:00:00 +02:00
if ( ! vote . SignatureValid ( ) ) {
LogPrintf ( " mvote - signature invalid \n " ) ;
Misbehaving ( pfrom - > GetId ( ) , 20 ) ;
2015-06-03 18:10:11 +02:00
return ;
2015-04-22 16:33:44 +02:00
}
2015-05-27 18:28:55 +02:00
mapSeenMasternodeBudgetVotes . insert ( make_pair ( vote . GetHash ( ) , vote ) ) ;
2015-07-10 00:08:26 +02:00
if ( pmn - > nVotedTimes < 100 ) {
2015-07-02 18:41:33 +02:00
budget . UpdateProposal ( vote , pfrom ) ;
2015-06-03 18:10:11 +02:00
vote . Relay ( ) ;
if ( ! IsSyncingMasternodeAssets ( ) ) pmn - > nVotedTimes + + ;
2015-04-22 16:33:44 +02:00
} else {
2015-07-06 23:00:00 +02:00
LogPrintf ( " mvote - masternode can't vote again - vin: %s \n " , pmn - > vin . ToString ( ) ) ;
2015-06-03 18:10:11 +02:00
return ;
2015-04-22 16:33:44 +02:00
}
}
2015-05-04 17:04:09 +02:00
if ( strCommand = = " fbs " ) { //Finalized Budget Suggestion
2015-07-08 04:35:58 +02:00
CFinalizedBudgetBroadcast finalizedBudgetBroadcast ;
vRecv > > finalizedBudgetBroadcast ;
2015-05-04 17:04:09 +02:00
2015-07-08 04:35:58 +02:00
if ( mapSeenFinalizedBudgets . count ( finalizedBudgetBroadcast . GetHash ( ) ) ) {
2015-05-04 17:04:09 +02:00
return ;
}
2015-07-10 00:08:26 +02:00
std : : string strError = " " ;
if ( ! IsBudgetCollateralValid ( finalizedBudgetBroadcast . nFeeTXHash , strError ) ) {
LogPrintf ( " Finalized Budget FeeTX is not valid - %s - %s \n " , finalizedBudgetBroadcast . nFeeTXHash . ToString ( ) , strError ) ;
2015-05-04 17:04:09 +02:00
return ;
}
2015-07-08 04:35:58 +02:00
if ( ! finalizedBudgetBroadcast . IsValid ( ) ) {
2015-07-06 23:00:00 +02:00
LogPrintf ( " fbs - invalid finalized budget \n " ) ;
2015-06-03 18:10:11 +02:00
return ;
2015-05-04 17:04:09 +02:00
}
2015-07-08 04:35:58 +02:00
mapSeenFinalizedBudgets . insert ( make_pair ( finalizedBudgetBroadcast . GetHash ( ) , finalizedBudgetBroadcast ) ) ;
2015-07-04 16:49:49 +02:00
2015-07-10 00:08:26 +02:00
CFinalizedBudget finalizedBudget ( finalizedBudgetBroadcast ) ;
budget . AddFinalizedBudget ( finalizedBudget ) ;
finalizedBudgetBroadcast . Relay ( ) ;
2015-07-02 18:41:33 +02:00
2015-07-10 00:08:26 +02:00
//we might have active votes for this budget that are now valid
CheckOrphanVotes ( ) ;
2015-05-04 17:04:09 +02:00
}
if ( strCommand = = " fbvote " ) { //Finalized Budget Vote
CFinalizedBudgetVote vote ;
vRecv > > vote ;
2015-05-27 18:28:55 +02:00
if ( mapSeenFinalizedBudgetVotes . count ( vote . GetHash ( ) ) ) {
2015-05-04 17:04:09 +02:00
return ;
}
2015-07-06 23:00:00 +02:00
CMasternode * pmn = mnodeman . Find ( vote . vin ) ;
if ( pmn = = NULL ) {
if ( fDebug ) LogPrintf ( " fbvote - unknown masternode - vin: %s \n " , vote . vin . ToString ( ) ) ;
2015-05-04 17:04:09 +02:00
return ;
}
2015-07-06 23:00:00 +02:00
if ( ! vote . SignatureValid ( ) ) {
LogPrintf ( " fbvote - signature invalid \n " ) ;
Misbehaving ( pfrom - > GetId ( ) , 20 ) ;
2015-06-03 18:10:11 +02:00
return ;
2015-05-04 17:04:09 +02:00
}
2015-05-27 18:28:55 +02:00
mapSeenFinalizedBudgetVotes . insert ( make_pair ( vote . GetHash ( ) , vote ) ) ;
2015-07-10 00:08:26 +02:00
if ( pmn - > nVotedTimes < 100 ) {
2015-07-02 18:41:33 +02:00
budget . UpdateFinalizedBudget ( vote , pfrom ) ;
2015-05-04 17:04:09 +02:00
vote . Relay ( ) ;
if ( ! IsSyncingMasternodeAssets ( ) ) pmn - > nVotedTimes + + ;
} else {
2015-07-06 23:00:00 +02:00
LogPrintf ( " fbvote - masternode can't vote again - vin: %s \n " , pmn - > vin . ToString ( ) ) ;
2015-05-04 17:04:09 +02:00
return ;
}
}
2015-04-22 16:33:44 +02:00
}
2015-06-03 18:10:11 +02:00
bool CBudgetManager : : PropExists ( uint256 nHash )
2015-04-22 16:33:44 +02:00
{
2015-06-03 18:10:11 +02:00
if ( mapProposals . count ( nHash ) ) return true ;
return false ;
2015-04-22 16:33:44 +02:00
}
2015-07-02 18:41:33 +02:00
void CBudgetManager : : Sync ( CNode * pfrom , uint256 nProp )
2015-04-22 16:33:44 +02:00
{
2015-07-06 22:23:09 +02:00
/*
2015-07-02 17:07:30 +02:00
Sync with a client on the network
- -
2015-07-06 22:23:09 +02:00
This code checks each of the hash maps for all known budget proposals and finalized budget proposals , then checks them against the
budget object to see if they ' re OK . If all checks pass , we ' ll send it to the peer .
2015-07-02 17:07:30 +02:00
*/
std : : map < uint256 , CBudgetProposalBroadcast > : : iterator it1 = mapSeenMasternodeBudgetProposals . begin ( ) ;
while ( it1 ! = mapSeenMasternodeBudgetProposals . end ( ) ) {
2015-07-08 04:35:58 +02:00
CBudgetProposal * pbudgetProposal = budget . FindProposal ( ( * it1 ) . first ) ;
if ( pbudgetProposal & & ( nProp = = 0 | | ( * it1 ) . first = = nProp ) ) {
2015-07-02 17:07:30 +02:00
pfrom - > PushMessage ( " mprop " , ( ( * it1 ) . second ) ) ;
}
it1 + + ;
}
std : : map < uint256 , CBudgetVote > : : iterator it2 = mapSeenMasternodeBudgetVotes . begin ( ) ;
while ( it2 ! = mapSeenMasternodeBudgetVotes . end ( ) ) {
2015-07-08 04:35:58 +02:00
CBudgetProposal * pbudgetProposal = budget . FindProposal ( ( * it2 ) . second . nProposalHash ) ;
if ( pbudgetProposal & & ( nProp = = 0 | | ( * it1 ) . first = = nProp ) ) {
2015-07-02 17:07:30 +02:00
pfrom - > PushMessage ( " mvote " , ( ( * it2 ) . second ) ) ;
}
it2 + + ;
}
std : : map < uint256 , CFinalizedBudgetBroadcast > : : iterator it3 = mapSeenFinalizedBudgets . begin ( ) ;
while ( it3 ! = mapSeenFinalizedBudgets . end ( ) ) {
2015-07-08 04:35:58 +02:00
CFinalizedBudget * pfinalizedBudget = budget . FindFinalizedBudget ( ( * it3 ) . first ) ;
if ( pfinalizedBudget & & ( nProp = = 0 | | ( * it1 ) . first = = nProp ) ) {
2015-07-02 17:07:30 +02:00
pfrom - > PushMessage ( " fbs " , ( ( * it3 ) . second ) ) ;
}
it3 + + ;
2015-06-03 18:10:11 +02:00
}
2015-04-22 16:33:44 +02:00
2015-07-02 17:07:30 +02:00
std : : map < uint256 , CFinalizedBudgetVote > : : iterator it4 = mapSeenFinalizedBudgetVotes . begin ( ) ;
while ( it4 ! = mapSeenFinalizedBudgetVotes . end ( ) ) {
2015-07-08 04:35:58 +02:00
CFinalizedBudget * pfinalizedBudget = budget . FindFinalizedBudget ( ( * it4 ) . second . nBudgetHash ) ;
if ( pfinalizedBudget & & ( nProp = = 0 | | ( * it1 ) . first = = nProp ) ) {
2015-07-02 17:07:30 +02:00
pfrom - > PushMessage ( " fbvote " , ( ( * it4 ) . second ) ) ;
}
it4 + + ;
}
2015-05-04 17:04:09 +02:00
}
2015-04-22 16:33:44 +02:00
2015-07-02 18:41:33 +02:00
bool CBudgetManager : : UpdateProposal ( CBudgetVote & vote , CNode * pfrom )
2015-05-04 17:04:09 +02:00
{
LOCK ( cs ) ;
2015-07-02 18:41:33 +02:00
2015-05-04 17:04:09 +02:00
if ( ! mapProposals . count ( vote . nProposalHash ) ) {
2015-07-02 18:41:33 +02:00
if ( pfrom ) {
LogPrintf ( " Unknown proposal %d, Asking for source proposal \n " , vote . nProposalHash . ToString ( ) . c_str ( ) ) ;
mapOrphanMasternodeBudgetVotes [ vote . nProposalHash ] = vote ;
if ( ! askedForSourceProposalOrBudget . count ( vote . nProposalHash ) ) {
pfrom - > PushMessage ( " mnvs " , vote . nProposalHash ) ;
askedForSourceProposalOrBudget [ vote . nProposalHash ] = GetTime ( ) ;
}
}
return false ;
2015-04-30 19:11:34 +02:00
}
2015-04-22 16:33:44 +02:00
2015-07-02 18:41:33 +02:00
2015-06-03 18:10:11 +02:00
mapProposals [ vote . nProposalHash ] . AddOrUpdateVote ( vote ) ;
2015-07-02 18:41:33 +02:00
return true ;
2015-04-22 16:33:44 +02:00
}
2015-07-02 18:41:33 +02:00
bool CBudgetManager : : UpdateFinalizedBudget ( CFinalizedBudgetVote & vote , CNode * pfrom )
2015-04-22 16:33:44 +02:00
{
2015-04-30 19:11:34 +02:00
LOCK ( cs ) ;
2015-04-22 16:33:44 +02:00
2015-06-03 18:10:11 +02:00
if ( ! mapFinalizedBudgets . count ( vote . nBudgetHash ) ) {
2015-07-02 18:41:33 +02:00
if ( pfrom ) {
LogPrintf ( " Unknown Finalized Proposal %s, Asking for source proposal \n " , vote . nBudgetHash . ToString ( ) . c_str ( ) ) ;
mapOrphanFinalizedBudgetVotes [ vote . nBudgetHash ] = vote ;
if ( ! askedForSourceProposalOrBudget . count ( vote . nBudgetHash ) ) {
pfrom - > PushMessage ( " mnvs " , vote . nBudgetHash ) ;
askedForSourceProposalOrBudget [ vote . nBudgetHash ] = GetTime ( ) ;
}
}
return false ;
2015-06-01 21:06:03 +02:00
}
2015-06-03 18:10:11 +02:00
mapFinalizedBudgets [ vote . nBudgetHash ] . AddOrUpdateVote ( vote ) ;
2015-07-02 18:41:33 +02:00
return true ;
2015-04-22 16:33:44 +02:00
}
2015-06-03 18:10:11 +02:00
CBudgetProposal : : CBudgetProposal ( )
2015-04-22 16:33:44 +02:00
{
2015-06-03 18:10:11 +02:00
strProposalName = " unknown " ;
nBlockStart = 0 ;
nBlockEnd = 0 ;
nAmount = 0 ;
2015-06-16 19:04:35 +02:00
nTime = 0 ;
2015-06-03 18:10:11 +02:00
}
2015-07-10 00:08:26 +02:00
CBudgetProposal : : CBudgetProposal ( std : : string strProposalNameIn , std : : string strURLIn , int nBlockStartIn , int nBlockEndIn , CScript addressIn , CAmount nAmountIn , uint256 nFeeTXHashIn )
2015-06-03 18:10:11 +02:00
{
strProposalName = strProposalNameIn ;
strURL = strURLIn ;
2015-07-04 16:49:49 +02:00
nBlockStart = nBlockStartIn ;
nBlockEnd = nBlockEndIn ;
address = addressIn ;
nAmount = nAmountIn ;
2015-06-16 19:04:35 +02:00
nTime = 0 ;
2015-07-10 00:08:26 +02:00
nFeeTXHash = nFeeTXHashIn ;
2015-06-03 18:10:11 +02:00
}
CBudgetProposal : : CBudgetProposal ( const CBudgetProposal & other )
{
strProposalName = other . strProposalName ;
strURL = other . strURL ;
nBlockStart = other . nBlockStart ;
nBlockEnd = other . nBlockEnd ;
address = other . address ;
nAmount = other . nAmount ;
2015-06-16 19:04:35 +02:00
nTime = other . nTime ;
2015-07-10 00:08:26 +02:00
nFeeTXHash = other . nFeeTXHash ;
mapVotes = other . mapVotes ;
2015-06-03 18:10:11 +02:00
}
2015-06-16 19:04:35 +02:00
bool CBudgetProposal : : IsValid ( std : : string & strError )
2015-06-03 18:10:11 +02:00
{
2015-07-08 17:55:52 +02:00
if ( GetYeas ( ) - GetNays ( ) < - ( mnodeman . CountEnabled ( ) / 10 ) ) {
2015-07-04 16:49:49 +02:00
strError = " Active removal " ;
return false ;
}
2015-07-12 16:45:58 +02:00
if ( nBlockStart < 0 ) {
strError = " Invalid Proposal " ;
return false ;
}
if ( address = = CScript ( ) ) {
strError = " Invalid Payment Address " ;
return false ;
}
2015-06-16 19:04:35 +02:00
//if proposal doesn't gain traction within 2 weeks, remove it
// nTime not being saved correctly
// if(nTime + (60*60*24*2) < GetAdjustedTime()) {
2015-07-04 16:49:49 +02:00
// if(GetYeas()-GetNays() < (mnodeman.CountEnabled()/10)) {
2015-06-16 19:04:35 +02:00
// strError = "Not enough support";
// return false;
// }
// }
2015-06-03 18:10:11 +02:00
2015-06-10 04:46:24 +02:00
//can only pay out 10% of the possible coins (min value of coins)
if ( nAmount > budget . GetTotalBudget ( nBlockStart ) ) {
2015-06-16 19:04:35 +02:00
strError = " Payment more than max " ;
2015-06-10 04:46:24 +02:00
return false ;
}
2015-07-06 22:23:09 +02:00
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( pindexPrev = = NULL ) { strError = " Tip is NULL " ; return true ; }
if ( GetBlockEnd ( ) < pindexPrev - > nHeight - GetBudgetPaymentCycleBlocks ( ) / 2 ) return false ;
2015-06-03 18:10:11 +02:00
return true ;
}
void CBudgetProposal : : AddOrUpdateVote ( CBudgetVote & vote )
{
LOCK ( cs ) ;
uint256 hash = vote . vin . prevout . GetHash ( ) ;
mapVotes [ hash ] = vote ;
}
2015-07-04 16:49:49 +02:00
// If masternode voted for a proposal, but is now invalid -- remove the vote
void CBudgetProposal : : CleanAndRemove ( )
{
std : : map < uint256 , CBudgetVote > : : iterator it = mapVotes . begin ( ) ;
while ( it ! = mapVotes . end ( ) ) {
2015-07-06 22:23:09 +02:00
if ( ( * it ) . second . SignatureValid ( ) )
2015-07-04 16:49:49 +02:00
{
+ + it ;
} else {
mapSeenMasternodeBudgetVotes . erase ( ( * it ) . first ) ;
mapVotes . erase ( it + + ) ;
}
}
}
2015-06-03 18:10:11 +02:00
double CBudgetProposal : : GetRatio ( )
{
int yeas = 0 ;
int nays = 0 ;
2015-04-22 16:33:44 +02:00
2015-05-04 17:04:09 +02:00
std : : map < uint256 , CBudgetVote > : : iterator it = mapVotes . begin ( ) ;
2015-04-22 16:33:44 +02:00
2015-05-04 17:04:09 +02:00
while ( it ! = mapVotes . end ( ) ) {
if ( ( * it ) . second . nVote = = VOTE_YES ) yeas + + ;
if ( ( * it ) . second . nVote = = VOTE_NO ) nays + + ;
+ + it ;
}
2015-04-22 16:33:44 +02:00
2015-05-04 17:04:09 +02:00
if ( yeas + nays = = 0 ) return 0.0f ;
2015-04-30 19:11:34 +02:00
2015-05-04 17:04:09 +02:00
return ( ( double ) ( yeas ) / ( double ) ( yeas + nays ) ) ;
2015-04-22 16:33:44 +02:00
}
2015-05-04 17:04:09 +02:00
int CBudgetProposal : : GetYeas ( )
2015-04-22 16:33:44 +02:00
{
2015-06-03 18:10:11 +02:00
int ret = 0 ;
2015-04-30 19:11:34 +02:00
std : : map < uint256 , CBudgetVote > : : iterator it = mapVotes . begin ( ) ;
2015-05-04 17:04:09 +02:00
while ( it ! = mapVotes . end ( ) ) {
if ( ( * it ) . second . nVote = = VOTE_YES ) ret + + ;
+ + it ;
2015-04-30 19:11:34 +02:00
}
2015-05-04 17:04:09 +02:00
return ret ;
2015-04-22 16:33:44 +02:00
}
2015-05-04 17:04:09 +02:00
int CBudgetProposal : : GetNays ( )
2015-04-22 16:33:44 +02:00
{
2015-06-03 18:10:11 +02:00
int ret = 0 ;
2015-04-22 16:33:44 +02:00
2015-05-04 17:04:09 +02:00
std : : map < uint256 , CBudgetVote > : : iterator it = mapVotes . begin ( ) ;
while ( it ! = mapVotes . end ( ) ) {
if ( ( * it ) . second . nVote = = VOTE_NO ) ret + + ;
+ + it ;
2015-04-30 19:11:34 +02:00
}
2015-04-22 16:33:44 +02:00
2015-05-04 17:04:09 +02:00
return ret ;
2015-04-22 16:33:44 +02:00
}
2015-05-04 17:04:09 +02:00
int CBudgetProposal : : GetAbstains ( )
2015-04-22 16:33:44 +02:00
{
2015-06-03 18:10:11 +02:00
int ret = 0 ;
2015-04-22 16:33:44 +02:00
2015-04-30 19:11:34 +02:00
std : : map < uint256 , CBudgetVote > : : iterator it = mapVotes . begin ( ) ;
2015-05-04 17:04:09 +02:00
while ( it ! = mapVotes . end ( ) ) {
if ( ( * it ) . second . nVote = = VOTE_ABSTAIN ) ret + + ;
+ + it ;
2015-04-30 19:11:34 +02:00
}
2015-04-22 16:33:44 +02:00
2015-05-04 17:04:09 +02:00
return ret ;
2015-04-22 16:33:44 +02:00
}
2015-05-04 17:04:09 +02:00
int CBudgetProposal : : GetBlockStartCycle ( )
2015-04-22 16:33:44 +02:00
{
2015-05-04 17:04:09 +02:00
//end block is half way through the next cycle (so the proposal will be removed much after the payment is sent)
2015-04-22 16:33:44 +02:00
2015-05-26 16:56:51 +02:00
return ( nBlockStart - ( nBlockStart % GetBudgetPaymentCycleBlocks ( ) ) ) ;
2015-04-22 16:33:44 +02:00
}
2015-05-04 17:04:09 +02:00
int CBudgetProposal : : GetBlockCurrentCycle ( )
2015-04-22 16:33:44 +02:00
{
2015-05-04 17:04:09 +02:00
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( pindexPrev = = NULL ) return - 1 ;
2015-04-30 19:11:34 +02:00
2015-05-04 17:04:09 +02:00
if ( pindexPrev - > nHeight > = GetBlockEndCycle ( ) ) return - 1 ;
2015-04-22 16:33:44 +02:00
2015-05-26 16:56:51 +02:00
return ( pindexPrev - > nHeight - ( pindexPrev - > nHeight % GetBudgetPaymentCycleBlocks ( ) ) ) ;
2015-04-22 16:33:44 +02:00
}
2015-05-04 17:04:09 +02:00
int CBudgetProposal : : GetBlockEndCycle ( )
2015-04-22 16:33:44 +02:00
{
2015-05-04 17:04:09 +02:00
//end block is half way through the next cycle (so the proposal will be removed much after the payment is sent)
2015-04-22 16:33:44 +02:00
2015-05-26 16:56:51 +02:00
return nBlockEnd - ( GetBudgetPaymentCycleBlocks ( ) / 2 ) ;
2015-04-22 16:33:44 +02:00
}
2015-05-27 19:11:00 +02:00
int CBudgetProposal : : GetTotalPaymentCount ( )
2015-04-22 16:33:44 +02:00
{
2015-05-26 16:56:51 +02:00
return ( GetBlockEndCycle ( ) - GetBlockStartCycle ( ) ) / GetBudgetPaymentCycleBlocks ( ) ;
2015-04-22 16:33:44 +02:00
}
2015-05-27 19:11:00 +02:00
int CBudgetProposal : : GetRemainingPaymentCount ( )
2015-04-22 16:33:44 +02:00
{
2015-05-26 16:56:51 +02:00
return ( GetBlockEndCycle ( ) - GetBlockCurrentCycle ( ) ) / GetBudgetPaymentCycleBlocks ( ) ;
2015-04-22 16:33:44 +02:00
}
2015-05-04 17:04:09 +02:00
CBudgetProposalBroadcast : : CBudgetProposalBroadcast ( )
{
strProposalName = " unknown " ;
2015-07-04 16:49:49 +02:00
strURL = " " ;
2015-05-04 17:04:09 +02:00
nBlockStart = 0 ;
nBlockEnd = 0 ;
nAmount = 0 ;
2015-06-16 19:04:35 +02:00
nTime = 0 ;
2015-07-10 00:08:26 +02:00
nFeeTXHash = 0 ;
2015-05-04 17:04:09 +02:00
}
CBudgetProposalBroadcast : : CBudgetProposalBroadcast ( const CBudgetProposal & other )
{
strProposalName = other . strProposalName ;
2015-07-04 16:49:49 +02:00
strURL = other . strURL ;
2015-05-04 17:04:09 +02:00
nBlockStart = other . nBlockStart ;
nBlockEnd = other . nBlockEnd ;
address = other . address ;
nAmount = other . nAmount ;
2015-07-10 00:08:26 +02:00
nFeeTXHash = other . nFeeTXHash ;
2015-05-04 17:04:09 +02:00
}
2015-07-10 00:08:26 +02:00
CBudgetProposalBroadcast : : CBudgetProposalBroadcast ( std : : string strProposalNameIn , std : : string strURLIn , int nPaymentCount , CScript addressIn , CAmount nAmountIn , int nBlockStartIn , uint256 nFeeTXHashIn )
2015-06-03 18:10:11 +02:00
{
strProposalName = strProposalNameIn ;
strURL = strURLIn ;
nBlockStart = nBlockStartIn ;
int nCycleStart = ( nBlockStart - ( nBlockStart % GetBudgetPaymentCycleBlocks ( ) ) ) ;
//calculate the end of the cycle for this vote, add half a cycle (vote will be deleted after that block)
nBlockEnd = nCycleStart + ( GetBudgetPaymentCycleBlocks ( ) * nPaymentCount ) + GetBudgetPaymentCycleBlocks ( ) / 2 ;
address = addressIn ;
nAmount = nAmountIn ;
2015-07-08 19:17:16 +02:00
2015-07-10 00:08:26 +02:00
nFeeTXHash = nFeeTXHashIn ;
2015-05-04 17:04:09 +02:00
}
void CBudgetProposalBroadcast : : Relay ( )
{
CInv inv ( MSG_BUDGET_PROPOSAL , GetHash ( ) ) ;
2015-07-08 02:37:23 +02:00
RelayInv ( inv , MIN_BUDGET_PEER_PROTO_VERSION ) ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
CBudgetVote : : CBudgetVote ( )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
vin = CTxIn ( ) ;
nProposalHash = 0 ;
nVote = VOTE_ABSTAIN ;
nTime = 0 ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
CBudgetVote : : CBudgetVote ( CTxIn vinIn , uint256 nProposalHashIn , int nVoteIn )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
vin = vinIn ;
nProposalHash = nProposalHashIn ;
nVote = nVoteIn ;
nTime = GetAdjustedTime ( ) ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
void CBudgetVote : : Relay ( )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
CInv inv ( MSG_BUDGET_VOTE , GetHash ( ) ) ;
2015-07-08 02:37:23 +02:00
RelayInv ( inv , MIN_BUDGET_PEER_PROTO_VERSION ) ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
bool CBudgetVote : : Sign ( CKey & keyMasternode , CPubKey & pubKeyMasternode )
2015-05-04 17:04:09 +02:00
{
// Choose coins to use
CPubKey pubKeyCollateralAddress ;
CKey keyCollateralAddress ;
std : : string errorMessage ;
2015-06-03 18:10:11 +02:00
std : : string strMessage = vin . prevout . ToStringShort ( ) + nProposalHash . ToString ( ) + boost : : lexical_cast < std : : string > ( nVote ) + boost : : lexical_cast < std : : string > ( nTime ) ;
2015-05-04 17:04:09 +02:00
if ( ! darkSendSigner . SignMessage ( strMessage , errorMessage , vchSig , keyMasternode ) )
return ( " Error upon calling SignMessage " ) ;
if ( ! darkSendSigner . VerifyMessage ( pubKeyMasternode , vchSig , strMessage , errorMessage ) )
return ( " Error upon calling VerifyMessage " ) ;
return true ;
}
2015-06-03 18:10:11 +02:00
bool CBudgetVote : : SignatureValid ( )
2015-05-04 17:04:09 +02:00
{
std : : string errorMessage ;
2015-06-03 18:10:11 +02:00
std : : string strMessage = vin . prevout . ToStringShort ( ) + nProposalHash . ToString ( ) + boost : : lexical_cast < std : : string > ( nVote ) + boost : : lexical_cast < std : : string > ( nTime ) ;
2015-05-04 17:04:09 +02:00
CMasternode * pmn = mnodeman . Find ( vin ) ;
if ( pmn = = NULL )
{
2015-07-06 23:00:00 +02:00
LogPrintf ( " CBudgetVote::SignatureValid() - Unknown Masternode - %s \n " , vin . ToString ( ) . c_str ( ) ) ;
2015-05-04 17:04:09 +02:00
return false ;
}
if ( ! darkSendSigner . VerifyMessage ( pmn - > pubkey2 , vchSig , strMessage , errorMessage ) ) {
2015-06-03 18:10:11 +02:00
LogPrintf ( " CBudgetVote::SignatureValid() - Verify message failed \n " ) ;
2015-05-04 17:04:09 +02:00
return false ;
}
return true ;
}
2015-06-03 18:10:11 +02:00
CFinalizedBudget : : CFinalizedBudget ( )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
strBudgetName = " " ;
nBlockStart = 0 ;
vecProposals . clear ( ) ;
mapVotes . clear ( ) ;
2015-07-10 00:08:26 +02:00
nFeeTXHash = 0 ;
2015-06-03 18:10:11 +02:00
}
2015-05-04 17:04:09 +02:00
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
CFinalizedBudget : : CFinalizedBudget ( const CFinalizedBudget & other )
{
strBudgetName = other . strBudgetName ;
nBlockStart = other . nBlockStart ;
vecProposals = other . vecProposals ;
mapVotes = other . mapVotes ;
2015-07-10 00:08:26 +02:00
nFeeTXHash = other . nFeeTXHash ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
void CFinalizedBudget : : AddOrUpdateVote ( CFinalizedBudgetVote & vote )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
LOCK ( cs ) ;
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
uint256 hash = vote . vin . prevout . GetHash ( ) ;
mapVotes [ hash ] = vote ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
//evaluate if we should vote for this. Masternode only
void CFinalizedBudget : : AutoCheck ( )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
if ( ! fMasterNode | | fAutoChecked ) return ;
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
if ( Params ( ) . NetworkID ( ) = = CBaseChainParams : : MAIN ) {
if ( rand ( ) % 100 > 5 ) return ; //do this 1 in 20 blocks -- spread out the voting activity on mainnet
}
fAutoChecked = true ; //we only need to check this once
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
if ( strBudgetMode = = " auto " ) //only vote for exact matches
{
std : : vector < CBudgetProposal * > props1 = budget . GetBudget ( ) ;
2015-05-04 17:04:09 +02:00
2015-07-05 09:37:52 +02:00
if ( props1 . size ( ) = = 0 ) {
LogPrintf ( " CFinalizedBudget::AutoCheck - Can't get Budget, aborting \n " ) ;
return ;
}
2015-06-03 18:10:11 +02:00
for ( unsigned int i = 0 ; i < vecProposals . size ( ) ; i + + ) {
if ( i > props1 . size ( ) - 1 ) {
LogPrintf ( " CFinalizedBudget::AutoCheck - Vector size mismatch, aborting \n " ) ;
return ;
}
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
if ( vecProposals [ i ] . nProposalHash ! = props1 [ i ] - > GetHash ( ) ) {
LogPrintf ( " CFinalizedBudget::AutoCheck - item #%d doesn't match %s %s \n " , i , vecProposals [ i ] . nProposalHash . ToString ( ) . c_str ( ) , props1 [ i ] - > GetHash ( ) . ToString ( ) . c_str ( ) ) ;
return ;
}
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
if ( vecProposals [ i ] . payee ! = props1 [ i ] - > GetPayee ( ) ) {
LogPrintf ( " CFinalizedBudget::AutoCheck - item #%d payee doesn't match %s %s \n " , i , vecProposals [ i ] . payee . ToString ( ) . c_str ( ) , props1 [ i ] - > GetPayee ( ) . ToString ( ) . c_str ( ) ) ;
return ;
}
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
if ( vecProposals [ i ] . nAmount ! = props1 [ i ] - > GetAmount ( ) ) {
LogPrintf ( " CFinalizedBudget::AutoCheck - item #%d payee doesn't match %s %s \n " , i , vecProposals [ i ] . payee . ToString ( ) . c_str ( ) , props1 [ i ] - > GetPayee ( ) . ToString ( ) . c_str ( ) ) ;
return ;
}
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
LogPrintf ( " CFinalizedBudget::AutoCheck - Finalized Budget Matches! Submitting Vote. \n " ) ;
SubmitVote ( ) ;
}
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
}
}
2015-07-04 16:49:49 +02:00
// If masternode voted for a proposal, but is now invalid -- remove the vote
void CFinalizedBudget : : CleanAndRemove ( )
{
std : : map < uint256 , CFinalizedBudgetVote > : : iterator it = mapVotes . begin ( ) ;
while ( it ! = mapVotes . end ( ) ) {
2015-07-06 22:23:09 +02:00
if ( ( * it ) . second . SignatureValid ( ) )
2015-07-04 16:49:49 +02:00
{
+ + it ;
} else {
mapSeenFinalizedBudgetVotes . erase ( ( * it ) . first ) ;
mapVotes . erase ( it + + ) ;
}
}
}
2015-05-04 17:04:09 +02:00
2015-06-10 04:46:24 +02:00
int64_t CFinalizedBudget : : GetTotalPayout ( )
{
int64_t ret = 0 ;
for ( unsigned int i = 0 ; i < vecProposals . size ( ) ; i + + ) {
ret + = vecProposals [ i ] . nAmount ;
}
return ret ;
}
2015-06-03 18:10:11 +02:00
std : : string CFinalizedBudget : : GetProposals ( ) {
2015-07-03 00:34:11 +02:00
std : : string ret = " " ;
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
BOOST_FOREACH ( CTxBudgetPayment & payment , vecProposals ) {
2015-07-08 04:35:58 +02:00
CBudgetProposal * pbudgetProposal = budget . FindProposal ( payment . nProposalHash ) ;
2015-06-03 18:10:11 +02:00
std : : string token = payment . nProposalHash . ToString ( ) ;
2015-07-08 04:35:58 +02:00
if ( pbudgetProposal ) token = pbudgetProposal - > GetName ( ) ;
2015-06-03 18:10:11 +02:00
if ( ret = = " " ) { ret = token ; }
2015-07-03 02:51:31 +02:00
else { ret + = " , " + token ; }
2015-06-03 18:10:11 +02:00
}
return ret ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
std : : string CFinalizedBudget : : GetStatus ( )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
std : : string retBadHashes = " " ;
std : : string retBadPayeeOrAmount = " " ;
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
for ( int nBlockHeight = GetBlockStart ( ) ; nBlockHeight < = GetBlockEnd ( ) ; nBlockHeight + + )
{
CTxBudgetPayment prop1 ;
if ( ! GetProposalByBlock ( nBlockHeight , prop1 ) ) {
LogPrintf ( " CFinalizedBudget::GetStatus - Couldn't find budget payment for block %lld \n " , nBlockHeight ) ;
continue ;
}
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
CBudgetProposal * prop2 = budget . FindProposal ( prop1 . nProposalHash ) ;
if ( ! prop2 ) {
if ( retBadHashes = = " " ) {
retBadHashes = " Unknown proposal hash! Check this proposal before voting " + prop1 . nProposalHash . ToString ( ) ;
} else {
retBadHashes + = " , " + prop1 . nProposalHash . ToString ( ) ;
}
} else {
if ( prop2 - > GetPayee ( ) ! = prop1 . payee | | prop2 - > GetAmount ( ) ! = prop1 . nAmount )
{
if ( retBadPayeeOrAmount = = " " ) {
retBadPayeeOrAmount = " Budget payee/nAmount doesn't match our proposal! " + prop1 . nProposalHash . ToString ( ) ;
} else {
retBadPayeeOrAmount + = " , " + prop1 . nProposalHash . ToString ( ) ;
}
}
}
}
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
if ( retBadHashes = = " " & & retBadPayeeOrAmount = = " " ) return " OK " ;
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
return retBadHashes + retBadPayeeOrAmount ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
bool CFinalizedBudget : : IsValid ( )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
//must be the correct block for payment to happen (once a month)
if ( nBlockStart % GetBudgetPaymentCycleBlocks ( ) ! = 0 ) return false ;
if ( GetBlockEnd ( ) - nBlockStart > 100 ) return false ;
if ( vecProposals . size ( ) > 100 ) return false ;
2015-07-04 16:49:49 +02:00
if ( strBudgetName = = " " ) return false ;
if ( nBlockStart = = 0 ) return false ;
2015-07-12 19:34:21 +02:00
if ( nFeeTXHash = = 0 ) return false ;
2015-06-03 18:10:11 +02:00
2015-06-10 04:46:24 +02:00
//can only pay out 10% of the possible coins (min value of coins)
if ( GetTotalPayout ( ) > budget . GetTotalBudget ( nBlockStart ) ) return false ;
2015-06-03 18:10:11 +02:00
//TODO: if N cycles old, invalid, invalid
2015-07-04 16:49:49 +02:00
CBlockIndex * pindexPrev = chainActive . Tip ( ) ;
if ( pindexPrev = = NULL ) return true ;
if ( nBlockStart < pindexPrev - > nHeight ) return false ;
2015-07-06 22:23:09 +02:00
if ( GetBlockEnd ( ) < pindexPrev - > nHeight - GetBudgetPaymentCycleBlocks ( ) / 2 ) return false ;
2015-07-04 16:49:49 +02:00
2015-06-03 18:10:11 +02:00
return true ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
bool CFinalizedBudget : : IsTransactionValid ( const CTransaction & txNew , int nBlockHeight )
2015-05-04 17:04:09 +02:00
{
2015-07-08 19:17:16 +02:00
// TODO:
// BOOST_FOREACH(CMasternodePayee& payee, vecPayments)
// {
// bool found = false;
// BOOST_FOREACH(CTxOut out, txNew.vout)
// {
// if(payee.scriptPubKey == out.scriptPubKey && payee.nValue == out.nValue)
// found = true;
// }
2015-05-04 17:04:09 +02:00
2015-07-08 19:17:16 +02:00
// if(payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED && !found){
2015-05-04 17:04:09 +02:00
2015-07-08 19:17:16 +02:00
// CTxDestination address1;
// ExtractDestination(payee.scriptPubKey, address1);
// CBitcoinAddress address2(address1);
2015-05-04 17:04:09 +02:00
2015-07-08 19:17:16 +02:00
// LogPrintf("CFinalizedBudget::IsTransactionValid - Missing required payment - %s:%d\n", address2.ToString().c_str(), payee.nValue);
// return false;
// }
// }
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
return true ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
void CFinalizedBudget : : SubmitVote ( )
2015-05-04 17:04:09 +02:00
{
2015-06-03 18:10:11 +02:00
CPubKey pubKeyMasternode ;
CKey keyMasternode ;
std : : string errorMessage ;
if ( ! darkSendSigner . SetKey ( strMasterNodePrivKey , errorMessage , keyMasternode , pubKeyMasternode ) ) {
LogPrintf ( " CFinalizedBudget::SubmitVote - Error upon calling SetKey \n " ) ;
return ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
CFinalizedBudgetVote vote ( activeMasternode . vin , GetHash ( ) ) ;
if ( ! vote . Sign ( keyMasternode , pubKeyMasternode ) ) {
LogPrintf ( " CFinalizedBudget::SubmitVote - Failure to sign. " ) ;
return ;
}
2015-05-04 17:04:09 +02:00
2015-06-03 18:10:11 +02:00
mapSeenFinalizedBudgetVotes . insert ( make_pair ( vote . GetHash ( ) , vote ) ) ;
vote . Relay ( ) ;
2015-07-02 18:41:33 +02:00
budget . UpdateFinalizedBudget ( vote , NULL ) ;
2015-05-04 17:04:09 +02:00
}
2015-06-03 18:10:11 +02:00
CFinalizedBudgetBroadcast : : CFinalizedBudgetBroadcast ( )
2015-05-04 17:04:09 +02:00
{
strBudgetName = " " ;
nBlockStart = 0 ;
vecProposals . clear ( ) ;
mapVotes . clear ( ) ;
2015-06-03 18:10:11 +02:00
vchSig . clear ( ) ;
2015-07-10 00:08:26 +02:00
nFeeTXHash = 0 ;
2015-05-04 17:04:09 +02:00
}
CFinalizedBudgetBroadcast : : CFinalizedBudgetBroadcast ( const CFinalizedBudget & other )
{
strBudgetName = other . strBudgetName ;
nBlockStart = other . nBlockStart ;
2015-05-30 22:12:12 +02:00
BOOST_FOREACH ( CTxBudgetPayment out , other . vecProposals ) vecProposals . push_back ( out ) ;
2015-05-04 17:04:09 +02:00
mapVotes = other . mapVotes ;
2015-07-10 00:08:26 +02:00
nFeeTXHash = other . nFeeTXHash ;
2015-05-04 17:04:09 +02:00
}
2015-07-10 00:08:26 +02:00
CFinalizedBudgetBroadcast : : CFinalizedBudgetBroadcast ( std : : string strBudgetNameIn , int nBlockStartIn , std : : vector < CTxBudgetPayment > vecProposalsIn , uint256 nFeeTXHashIn )
2015-05-04 17:04:09 +02:00
{
strBudgetName = strBudgetNameIn ;
nBlockStart = nBlockStartIn ;
2015-05-30 22:12:12 +02:00
BOOST_FOREACH ( CTxBudgetPayment out , vecProposalsIn ) vecProposals . push_back ( out ) ;
2015-05-04 17:04:09 +02:00
mapVotes . clear ( ) ;
2015-07-10 00:08:26 +02:00
nFeeTXHash = nFeeTXHashIn ;
2015-05-26 16:56:51 +02:00
}
2015-06-03 18:10:11 +02:00
void CFinalizedBudgetBroadcast : : Relay ( )
2015-06-01 21:06:03 +02:00
{
2015-06-03 18:10:11 +02:00
CInv inv ( MSG_BUDGET_FINALIZED , GetHash ( ) ) ;
2015-07-08 02:37:23 +02:00
RelayInv ( inv , MIN_BUDGET_PEER_PROTO_VERSION ) ;
2015-06-01 21:06:03 +02:00
}
2015-06-03 18:10:11 +02:00
CFinalizedBudgetVote : : CFinalizedBudgetVote ( )
2015-06-01 21:06:03 +02:00
{
2015-06-03 18:10:11 +02:00
vin = CTxIn ( ) ;
nBudgetHash = 0 ;
nTime = 0 ;
vchSig . clear ( ) ;
}
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
CFinalizedBudgetVote : : CFinalizedBudgetVote ( CTxIn vinIn , uint256 nBudgetHashIn )
{
vin = vinIn ;
nBudgetHash = nBudgetHashIn ;
nTime = GetAdjustedTime ( ) ;
vchSig . clear ( ) ;
}
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
void CFinalizedBudgetVote : : Relay ( )
{
CInv inv ( MSG_BUDGET_FINALIZED_VOTE , GetHash ( ) ) ;
2015-07-08 02:37:23 +02:00
RelayInv ( inv , MIN_BUDGET_PEER_PROTO_VERSION ) ;
2015-06-01 21:06:03 +02:00
}
2015-06-03 18:10:11 +02:00
bool CFinalizedBudgetVote : : Sign ( CKey & keyMasternode , CPubKey & pubKeyMasternode )
2015-06-01 21:06:03 +02:00
{
2015-06-03 18:10:11 +02:00
// Choose coins to use
CPubKey pubKeyCollateralAddress ;
CKey keyCollateralAddress ;
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
std : : string errorMessage ;
std : : string strMessage = vin . prevout . ToStringShort ( ) + nBudgetHash . ToString ( ) + boost : : lexical_cast < std : : string > ( nTime ) ;
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
if ( ! darkSendSigner . SignMessage ( strMessage , errorMessage , vchSig , keyMasternode ) )
return ( " Error upon calling SignMessage " ) ;
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
if ( ! darkSendSigner . VerifyMessage ( pubKeyMasternode , vchSig , strMessage , errorMessage ) )
return ( " Error upon calling VerifyMessage " ) ;
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
return true ;
}
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
bool CFinalizedBudgetVote : : SignatureValid ( )
{
2015-06-01 21:06:03 +02:00
std : : string errorMessage ;
2015-06-03 18:10:11 +02:00
std : : string strMessage = vin . prevout . ToStringShort ( ) + nBudgetHash . ToString ( ) + boost : : lexical_cast < std : : string > ( nTime ) ;
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
CMasternode * pmn = mnodeman . Find ( vin ) ;
2015-06-01 21:06:03 +02:00
2015-06-03 18:10:11 +02:00
if ( pmn = = NULL )
{
LogPrintf ( " CFinalizedBudgetVote::SignatureValid() - Unknown Masternode \n " ) ;
return false ;
2015-06-01 21:06:03 +02:00
}
2015-06-03 18:10:11 +02:00
if ( ! darkSendSigner . VerifyMessage ( pmn - > pubkey2 , vchSig , strMessage , errorMessage ) ) {
LogPrintf ( " CFinalizedBudgetVote::SignatureValid() - Verify message failed \n " ) ;
return false ;
2015-06-01 21:06:03 +02:00
}
2015-06-03 18:10:11 +02:00
return true ;
2015-06-01 21:06:03 +02:00
}