2016-12-20 14:26:45 +01:00
// Copyright (c) 2014-2017 The Dash Core developers
2016-04-08 19:47:00 +02:00
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2016-04-14 00:41:40 +02:00
# include "core_io.h"
# include "main.h"
# include "init.h"
# include "flat-database.h"
# include "governance.h"
# include "masternode.h"
2016-04-15 04:54:11 +02:00
# include "governance.h"
2016-04-14 00:41:40 +02:00
# include "darksend.h"
# include "masternodeman.h"
# include "masternode-sync.h"
# include "util.h"
# include "addrman.h"
# include <boost/lexical_cast.hpp>
2016-08-17 09:08:25 +02:00
2016-09-08 13:40:19 +02:00
std : : string CGovernanceVoting : : ConvertOutcomeToString ( vote_outcome_enum_t nOutcome )
2016-08-17 09:08:25 +02:00
{
switch ( nOutcome )
{
case VOTE_OUTCOME_NONE :
return " NONE " ; break ;
case VOTE_OUTCOME_YES :
return " YES " ; break ;
case VOTE_OUTCOME_NO :
return " NO " ; break ;
case VOTE_OUTCOME_ABSTAIN :
return " ABSTAIN " ; break ;
}
return " error " ;
}
2016-09-08 13:40:19 +02:00
std : : string CGovernanceVoting : : ConvertSignalToString ( vote_signal_enum_t nSignal )
2016-08-17 09:08:25 +02:00
{
2016-09-08 13:40:19 +02:00
string strReturn = " NONE " ;
2016-08-17 09:08:25 +02:00
switch ( nSignal )
{
case VOTE_SIGNAL_NONE :
2016-09-08 13:40:19 +02:00
strReturn = " NONE " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_FUNDING :
2016-09-08 13:40:19 +02:00
strReturn = " FUNDING " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_VALID :
2016-09-08 13:40:19 +02:00
strReturn = " VALID " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_DELETE :
2016-09-08 13:40:19 +02:00
strReturn = " DELETE " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_ENDORSED :
2016-09-08 13:40:19 +02:00
strReturn = " ENDORSED " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP1 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP1 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP2 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP2 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP3 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP3 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP4 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP4 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP5 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP5 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP6 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP6 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP7 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP7 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP8 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP8 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP9 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP9 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP10 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP10 " ;
break ;
2016-08-17 09:08:25 +02:00
case VOTE_SIGNAL_NOOP11 :
2016-09-08 13:40:19 +02:00
strReturn = " NOOP11 " ;
break ;
case VOTE_SIGNAL_CUSTOM1 :
strReturn = " CUSTOM1 " ;
break ;
case VOTE_SIGNAL_CUSTOM2 :
strReturn = " CUSTOM2 " ;
break ;
case VOTE_SIGNAL_CUSTOM3 :
strReturn = " CUSTOM3 " ;
break ;
case VOTE_SIGNAL_CUSTOM4 :
strReturn = " CUSTOM4 " ;
break ;
case VOTE_SIGNAL_CUSTOM5 :
strReturn = " CUSTOM5 " ;
break ;
case VOTE_SIGNAL_CUSTOM6 :
strReturn = " CUSTOM6 " ;
break ;
case VOTE_SIGNAL_CUSTOM7 :
strReturn = " CUSTOM7 " ;
break ;
case VOTE_SIGNAL_CUSTOM8 :
strReturn = " CUSTOM8 " ;
break ;
case VOTE_SIGNAL_CUSTOM9 :
strReturn = " CUSTOM9 " ;
break ;
case VOTE_SIGNAL_CUSTOM10 :
strReturn = " CUSTOM10 " ;
break ;
case VOTE_SIGNAL_CUSTOM11 :
strReturn = " CUSTOM11 " ;
break ;
case VOTE_SIGNAL_CUSTOM12 :
strReturn = " CUSTOM12 " ;
break ;
case VOTE_SIGNAL_CUSTOM13 :
strReturn = " CUSTOM13 " ;
break ;
case VOTE_SIGNAL_CUSTOM14 :
strReturn = " CUSTOM14 " ;
break ;
case VOTE_SIGNAL_CUSTOM15 :
strReturn = " CUSTOM15 " ;
break ;
case VOTE_SIGNAL_CUSTOM16 :
strReturn = " CUSTOM16 " ;
break ;
case VOTE_SIGNAL_CUSTOM17 :
strReturn = " CUSTOM17 " ;
break ;
case VOTE_SIGNAL_CUSTOM18 :
strReturn = " CUSTOM18 " ;
break ;
case VOTE_SIGNAL_CUSTOM19 :
strReturn = " CUSTOM19 " ;
break ;
case VOTE_SIGNAL_CUSTOM20 :
strReturn = " CUSTOM20 " ;
break ;
2016-08-17 09:08:25 +02:00
}
2016-09-08 13:40:19 +02:00
return strReturn ;
2016-08-17 09:08:25 +02:00
}
2016-09-08 13:40:19 +02:00
vote_outcome_enum_t CGovernanceVoting : : ConvertVoteOutcome ( std : : string strVoteOutcome )
2016-08-17 09:08:25 +02:00
{
2016-09-08 13:40:19 +02:00
vote_outcome_enum_t eVote = VOTE_OUTCOME_NONE ;
if ( strVoteOutcome = = " yes " ) {
eVote = VOTE_OUTCOME_YES ;
}
else if ( strVoteOutcome = = " no " ) {
eVote = VOTE_OUTCOME_NO ;
}
else if ( strVoteOutcome = = " abstain " ) {
eVote = VOTE_OUTCOME_ABSTAIN ;
}
return eVote ;
2016-08-17 09:08:25 +02:00
}
2016-09-08 13:40:19 +02:00
vote_signal_enum_t CGovernanceVoting : : ConvertVoteSignal ( std : : string strVoteSignal )
2016-08-17 09:08:25 +02:00
{
2016-09-08 13:40:19 +02:00
vote_signal_enum_t eSignal = VOTE_SIGNAL_NONE ;
if ( strVoteSignal = = " funding " ) {
eSignal = VOTE_SIGNAL_FUNDING ;
}
else if ( strVoteSignal = = " valid " ) {
eSignal = VOTE_SIGNAL_VALID ;
}
if ( strVoteSignal = = " delete " ) {
eSignal = VOTE_SIGNAL_DELETE ;
}
if ( strVoteSignal = = " endorsed " ) {
eSignal = VOTE_SIGNAL_ENDORSED ;
}
if ( eSignal ! = VOTE_SIGNAL_NONE ) {
return eSignal ;
}
2016-08-17 09:08:25 +02:00
// ID FIVE THROUGH CUSTOM_START ARE TO BE USED BY GOVERNANCE ENGINE / TRIGGER SYSTEM
// convert custom sentinel outcomes to integer and store
try {
2016-09-12 09:40:00 +02:00
int i = boost : : lexical_cast < int > ( strVoteSignal ) ;
2016-09-08 13:40:19 +02:00
if ( i < VOTE_SIGNAL_CUSTOM1 | | i > VOTE_SIGNAL_CUSTOM20 ) {
eSignal = VOTE_SIGNAL_NONE ;
}
else {
eSignal = vote_signal_enum_t ( i ) ;
}
2016-08-17 09:08:25 +02:00
}
catch ( std : : exception const & e )
{
2016-09-12 09:40:00 +02:00
std : : ostringstream ostr ;
ostr < < " CGovernanceVote::ConvertVoteSignal: error : " < < e . what ( ) < < std : : endl ;
2016-09-08 13:40:19 +02:00
LogPrintf ( ostr . str ( ) . c_str ( ) ) ;
2016-08-17 09:08:25 +02:00
}
2016-09-08 13:40:19 +02:00
return eSignal ;
2016-08-17 09:08:25 +02:00
}
2016-05-23 19:53:05 +02:00
CGovernanceVote : : CGovernanceVote ( )
2016-09-08 13:40:19 +02:00
: fValid ( true ) ,
fSynced ( false ) ,
nVoteSignal ( int ( VOTE_SIGNAL_NONE ) ) ,
vinMasternode ( ) ,
nParentHash ( ) ,
nVoteOutcome ( int ( VOTE_OUTCOME_NONE ) ) ,
nTime ( 0 ) ,
vchSig ( )
{ }
CGovernanceVote : : CGovernanceVote ( CTxIn vinMasternodeIn , uint256 nParentHashIn , vote_signal_enum_t eVoteSignalIn , vote_outcome_enum_t eVoteOutcomeIn )
: fValid ( true ) ,
fSynced ( false ) ,
nVoteSignal ( eVoteSignalIn ) ,
vinMasternode ( vinMasternodeIn ) ,
nParentHash ( nParentHashIn ) ,
nVoteOutcome ( eVoteOutcomeIn ) ,
nTime ( GetAdjustedTime ( ) ) ,
vchSig ( )
{ }
2016-04-08 19:47:00 +02:00
2016-11-13 18:52:34 +01:00
void CGovernanceVote : : Relay ( ) const
2016-04-08 19:47:00 +02:00
{
2016-08-05 18:25:03 +02:00
CInv inv ( MSG_GOVERNANCE_OBJECT_VOTE , GetHash ( ) ) ;
2016-09-28 22:03:54 +02:00
RelayInv ( inv , PROTOCOL_VERSION ) ;
2016-04-08 19:47:00 +02:00
}
2016-05-23 19:53:05 +02:00
bool CGovernanceVote : : Sign ( CKey & keyMasternode , CPubKey & pubKeyMasternode )
2016-04-08 19:47:00 +02:00
{
// Choose coins to use
CPubKey pubKeyCollateralAddress ;
CKey keyCollateralAddress ;
2016-08-19 13:50:04 +02:00
std : : string strError ;
2016-04-26 19:45:06 +02:00
std : : string strMessage = vinMasternode . prevout . ToStringShort ( ) + " | " + nParentHash . ToString ( ) + " | " +
2016-05-23 19:53:05 +02:00
boost : : lexical_cast < std : : string > ( nVoteSignal ) + " | " + boost : : lexical_cast < std : : string > ( nVoteOutcome ) + " | " + boost : : lexical_cast < std : : string > ( nTime ) ;
2016-04-08 19:47:00 +02:00
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . SignMessage ( strMessage , vchSig , keyMasternode ) ) {
LogPrintf ( " CGovernanceVote::Sign -- SignMessage() failed \n " ) ;
2016-04-26 19:45:06 +02:00
return false ;
}
2016-04-08 19:47:00 +02:00
2016-08-19 13:50:04 +02:00
if ( ! darkSendSigner . VerifyMessage ( pubKeyMasternode , vchSig , strMessage , strError ) ) {
LogPrintf ( " CGovernanceVote::Sign -- VerifyMessage() failed, error: %s \n " , strError ) ;
2016-04-26 19:45:06 +02:00
return false ;
}
2016-04-08 19:47:00 +02:00
return true ;
}
2016-11-13 18:52:34 +01:00
bool CGovernanceVote : : IsValid ( bool fSignatureCheck ) const
2016-04-08 19:47:00 +02:00
{
2016-11-13 18:52:34 +01:00
if ( nTime > GetTime ( ) + ( 60 * 60 ) ) {
2016-09-12 09:40:00 +02:00
LogPrint ( " gobject " , " CGovernanceVote::IsValid -- vote is too far ahead of current time - %s - nTime %lli - Max Time %lli \n " , GetHash ( ) . ToString ( ) , nTime , GetTime ( ) + ( 60 * 60 ) ) ;
2016-04-08 19:47:00 +02:00
return false ;
}
2016-04-26 06:08:36 +02:00
// support up to 50 actions (implemented in sentinel)
2016-11-13 18:52:34 +01:00
if ( nVoteSignal > MAX_SUPPORTED_VOTE_SIGNAL )
2016-04-26 06:08:36 +02:00
{
2016-09-12 09:40:00 +02:00
LogPrint ( " gobject " , " CGovernanceVote::IsValid -- Client attempted to vote on invalid signal(%d) - %s \n " , nVoteSignal , GetHash ( ) . ToString ( ) ) ;
2016-04-26 06:08:36 +02:00
return false ;
}
2016-04-14 00:41:40 +02:00
2016-04-26 06:08:36 +02:00
// 0=none, 1=yes, 2=no, 3=abstain. Beyond that reject votes
if ( nVoteOutcome > 3 )
{
2016-09-12 09:40:00 +02:00
LogPrint ( " gobject " , " CGovernanceVote::IsValid -- Client attempted to vote on invalid outcome(%d) - %s \n " , nVoteSignal , GetHash ( ) . ToString ( ) ) ;
return false ;
2016-04-26 06:08:36 +02:00
}
2016-10-17 20:54:28 +02:00
masternode_info_t infoMn = mnodeman . GetMasternodeInfo ( vinMasternode ) ;
if ( ! infoMn . fInfoValid ) {
2016-09-12 09:40:00 +02:00
LogPrint ( " gobject " , " CGovernanceVote::IsValid -- Unknown Masternode - %s \n " , vinMasternode . prevout . ToStringShort ( ) ) ;
2016-04-26 19:45:06 +02:00
return false ;
}
2016-04-08 19:47:00 +02:00
if ( ! fSignatureCheck ) return true ;
2016-08-19 13:50:04 +02:00
std : : string strError ;
2016-04-26 19:45:06 +02:00
std : : string strMessage = vinMasternode . prevout . ToStringShort ( ) + " | " + nParentHash . ToString ( ) + " | " +
2016-05-23 19:53:05 +02:00
boost : : lexical_cast < std : : string > ( nVoteSignal ) + " | " + boost : : lexical_cast < std : : string > ( nVoteOutcome ) + " | " + boost : : lexical_cast < std : : string > ( nTime ) ;
2016-04-08 19:47:00 +02:00
2016-10-17 20:54:28 +02:00
if ( ! darkSendSigner . VerifyMessage ( infoMn . pubKeyMasternode , vchSig , strMessage , strError ) ) {
2016-08-19 13:50:04 +02:00
LogPrintf ( " CGovernanceVote::IsValid -- VerifyMessage() failed, error: %s \n " , strError ) ;
2016-04-26 19:45:06 +02:00
return false ;
}
2016-04-08 19:47:00 +02:00
return true ;
2016-08-17 09:08:25 +02:00
}
2016-11-13 18:52:34 +01:00
bool operator = = ( const CGovernanceVote & vote1 , const CGovernanceVote & vote2 )
{
bool fResult = ( ( vote1 . vinMasternode = = vote2 . vinMasternode ) & &
( vote1 . nParentHash = = vote2 . nParentHash ) & &
( vote1 . nVoteOutcome = = vote2 . nVoteOutcome ) & &
( vote1 . nVoteSignal = = vote2 . nVoteSignal ) & &
( vote1 . nTime = = vote2 . nTime ) ) ;
return fResult ;
}
bool operator < ( const CGovernanceVote & vote1 , const CGovernanceVote & vote2 )
{
bool fResult = ( vote1 . vinMasternode < vote2 . vinMasternode ) ;
if ( ! fResult ) {
return false ;
}
fResult = ( vote1 . vinMasternode = = vote2 . vinMasternode ) ;
fResult = fResult & & ( vote1 . nParentHash < vote2 . nParentHash ) ;
if ( ! fResult ) {
return false ;
}
fResult = fResult & & ( vote1 . nParentHash = = vote2 . nParentHash ) ;
fResult = fResult & & ( vote1 . nVoteOutcome < vote2 . nVoteOutcome ) ;
if ( ! fResult ) {
return false ;
}
fResult = fResult & & ( vote1 . nVoteOutcome = = vote2 . nVoteOutcome ) ;
fResult = fResult & & ( vote1 . nVoteSignal = = vote2 . nVoteSignal ) ;
if ( ! fResult ) {
return false ;
}
fResult = fResult & & ( vote1 . nVoteSignal = = vote2 . nVoteSignal ) ;
fResult = fResult & & ( vote1 . nTime < vote2 . nTime ) ;
return fResult ;
}