2014-12-09 02:17:57 +01:00
# include "core.h"
# include "protocol.h"
# include "activemasternode.h"
# include <boost/lexical_cast.hpp>
//
// Bootup the masternode, look for a 1000DRK input and register on the network
//
2014-12-06 20:41:53 +01:00
void CActiveMasternode : : ManageStatus ( )
2014-12-09 02:17:57 +01:00
{
2014-12-06 20:41:53 +01:00
std : : string errorMessage ;
LogPrintf ( " CActiveMasternode::ManageStatus() - Begin \n " ) ;
if ( ! fMasterNode ) return ;
2014-12-09 02:17:57 +01:00
//need correct adjusted time to send ping
bool fIsInitialDownload = IsInitialBlockDownload ( ) ;
if ( fIsInitialDownload ) {
2014-12-06 20:41:53 +01:00
status = MASTERNODE_SYNC_IN_PROCESS ;
LogPrintf ( " CActiveMasternode::ManageStatus() - Sync in progress. Must wait until sync is complete to start masternode. \n " ) ;
2014-12-09 02:17:57 +01:00
return ;
}
2014-12-06 20:41:53 +01:00
if ( status = = MASTERNODE_INPUT_TOO_NEW | | status = = MASTERNODE_NOT_CAPABLE | | status = = MASTERNODE_SYNC_IN_PROCESS ) {
status = MASTERNODE_NOT_PROCESSED ;
2014-12-09 02:17:57 +01:00
}
2014-12-06 20:41:53 +01:00
if ( status = = MASTERNODE_NOT_PROCESSED ) {
2014-12-09 02:17:57 +01:00
if ( strMasterNodeAddr . empty ( ) ) {
2014-12-06 20:41:53 +01:00
if ( ! GetLocal ( service ) ) {
notCapableReason = " Can't detect external address. Please use the masternodeaddr configuration option. " ;
status = MASTERNODE_NOT_CAPABLE ;
LogPrintf ( " CActiveMasternode::ManageStatus() - not capable: %s \n " , notCapableReason . c_str ( ) ) ;
2014-12-09 02:17:57 +01:00
return ;
}
} else {
2014-12-06 20:41:53 +01:00
service = CService ( strMasterNodeAddr ) ;
2014-12-09 02:17:57 +01:00
}
2014-12-06 20:41:53 +01:00
if ( ( Params ( ) . NetworkID ( ) = = CChainParams : : TESTNET & & service . GetPort ( ) ! = 19999 ) | | ( ! ( Params ( ) . NetworkID ( ) = = CChainParams : : TESTNET ) & & service . GetPort ( ) ! = 9999 ) ) {
notCapableReason = " Invalid port: " + boost : : lexical_cast < string > ( service . GetPort ( ) ) + " -only 9999 or 19999 are supported. " ;
status = MASTERNODE_NOT_CAPABLE ;
LogPrintf ( " CActiveMasternode::ManageStatus() - not capable: %s \n " , notCapableReason . c_str ( ) ) ;
2014-12-09 02:17:57 +01:00
return ;
}
2014-12-06 20:41:53 +01:00
LogPrintf ( " CActiveMasternode::ManageStatus() - Checking inbound connection to '%s' \n " , service . ToString ( ) . c_str ( ) ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( ! ConnectNode ( ( CAddress ) service , service . ToString ( ) . c_str ( ) ) ) {
notCapableReason = " Could not connect to " + service . ToString ( ) ;
status = MASTERNODE_NOT_CAPABLE ;
LogPrintf ( " CActiveMasternode::ManageStatus() - not capable: %s \n " , notCapableReason . c_str ( ) ) ;
2014-12-09 02:17:57 +01:00
return ;
}
if ( pwalletMain - > IsLocked ( ) ) {
2014-12-06 20:41:53 +01:00
notCapableReason = " Wallet is locked. " ;
status = MASTERNODE_NOT_CAPABLE ;
LogPrintf ( " CActiveMasternode::ManageStatus() - not capable: %s \n " , notCapableReason . c_str ( ) ) ;
2014-12-09 02:17:57 +01:00
return ;
}
2014-12-06 20:41:53 +01:00
// Set defaults
status = MASTERNODE_NOT_CAPABLE ;
notCapableReason = " Unknown. " ;
2014-12-09 02:17:57 +01:00
// Choose coins to use
2014-12-06 20:41:53 +01:00
CPubKey pubKeyCollateralAddress ;
CKey keyCollateralAddress ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( GetMasterNodeVin ( vin , pubKeyCollateralAddress , keyCollateralAddress ) ) {
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( GetInputAge ( vin ) < MASTERNODE_MIN_CONFIRMATIONS ) {
LogPrintf ( " CActiveMasternode::ManageStatus() - Input must have least %d confirmations - %d confirmations \n " , MASTERNODE_MIN_CONFIRMATIONS , GetInputAge ( vin ) ) ;
status = MASTERNODE_INPUT_TOO_NEW ;
2014-12-09 02:17:57 +01:00
return ;
}
2014-12-06 20:41:53 +01:00
LogPrintf ( " CActiveMasternode::ManageStatus() - Is capable master node! \n " ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
status = MASTERNODE_IS_CAPABLE ;
notCapableReason = " " ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
pwalletMain - > LockCoin ( vin . prevout ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
// send to all nodes
CPubKey pubKeyMasternode ;
CKey keyMasternode ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( ! darkSendSigner . SetKey ( strMasterNodePrivKey , errorMessage , keyMasternode , pubKeyMasternode ) )
{
LogPrintf ( " Register::ManageStatus() - Error upon calling SetKey: %s \n " , errorMessage . c_str ( ) ) ;
return ;
2014-12-09 02:17:57 +01:00
}
2014-12-06 20:41:53 +01:00
if ( ! Register ( vin , service , keyCollateralAddress , pubKeyCollateralAddress , keyMasternode , pubKeyMasternode , errorMessage ) ) {
LogPrintf ( " CActiveMasternode::ManageStatus() - Error on Register: %s " , errorMessage . c_str ( ) ) ;
2014-12-09 02:17:57 +01:00
}
return ;
2014-12-06 20:41:53 +01:00
} else {
LogPrintf ( " CActiveMasternode::ManageStatus() - Could not find suitable coins! \n " ) ;
2014-12-09 02:17:57 +01:00
}
}
2014-12-06 20:41:53 +01:00
//send to all peers
if ( ! Dseep ( errorMessage ) ) {
LogPrintf ( " CActiveMasternode::ManageStatus() - Error on Ping: %s " , errorMessage . c_str ( ) ) ;
}
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
// Send stop dseep to network for remote masternode
bool CActiveMasternode : : StopMasterNode ( std : : string strService , std : : string strKeyMasternode , std : : string & errorMessage ) {
CTxIn vin ;
CKey keyMasternode ;
CPubKey pubKeyMasternode ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( ! darkSendSigner . SetKey ( strKeyMasternode , errorMessage , keyMasternode , pubKeyMasternode ) ) {
LogPrintf ( " CActiveMasternode::StopMasterNode() - Error: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
return StopMasterNode ( vin , CService ( strService ) , keyMasternode , pubKeyMasternode , errorMessage ) ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
// Send stop dseep to network for main masternode
bool CActiveMasternode : : StopMasterNode ( std : : string & errorMessage ) {
if ( status ! = MASTERNODE_IS_CAPABLE & & status ! = MASTERNODE_REMOTELY_ENABLED ) {
errorMessage = " masternode is not in a running status " ;
LogPrintf ( " CActiveMasternode::StopMasterNode() - Error: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
status = MASTERNODE_STOPPED ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
CPubKey pubKeyMasternode ;
CKey keyMasternode ;
if ( ! darkSendSigner . SetKey ( strMasterNodePrivKey , errorMessage , keyMasternode , pubKeyMasternode ) )
{
LogPrintf ( " Register::ManageStatus() - Error upon calling SetKey: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
2014-12-09 02:17:57 +01:00
}
2014-12-06 20:41:53 +01:00
return StopMasterNode ( vin , service , keyMasternode , pubKeyMasternode , errorMessage ) ;
}
// Send stop dseep to network for any masternode
bool CActiveMasternode : : StopMasterNode ( CTxIn vin , CService service , CKey keyMasternode , CPubKey pubKeyMasternode , std : : string & errorMessage ) {
pwalletMain - > UnlockCoin ( vin . prevout ) ;
return Dseep ( vin , service , keyMasternode , pubKeyMasternode , errorMessage , true ) ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
bool CActiveMasternode : : Dseep ( std : : string & errorMessage ) {
if ( status ! = MASTERNODE_IS_CAPABLE & & status ! = MASTERNODE_REMOTELY_ENABLED ) {
errorMessage = " masternode is not in a running status " ;
LogPrintf ( " CActiveMasternode::Dseep() - Error: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
CPubKey pubKeyMasternode ;
CKey keyMasternode ;
if ( ! darkSendSigner . SetKey ( strMasterNodePrivKey , errorMessage , keyMasternode , pubKeyMasternode ) )
2014-12-09 02:17:57 +01:00
{
2014-12-06 20:41:53 +01:00
LogPrintf ( " Register::ManageStatus() - Error upon calling SetKey: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
2014-12-09 02:17:57 +01:00
}
2014-12-06 20:41:53 +01:00
return Dseep ( vin , service , keyMasternode , pubKeyMasternode , errorMessage , false ) ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
bool CActiveMasternode : : Dseep ( CTxIn vin , CService service , CKey keyMasternode , CPubKey pubKeyMasternode , std : : string & retErrorMessage , bool stop ) {
2014-12-09 02:17:57 +01:00
std : : string errorMessage ;
2014-12-06 20:41:53 +01:00
std : : vector < unsigned char > vchMasterNodeSignature ;
std : : string strMasterNodeSignMessage ;
int64_t masterNodeSignatureTime = GetAdjustedTime ( ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
std : : string strMessage = service . ToString ( ) + boost : : lexical_cast < std : : string > ( masterNodeSignatureTime ) + boost : : lexical_cast < std : : string > ( stop ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( ! darkSendSigner . SignMessage ( strMessage , errorMessage , vchMasterNodeSignature , keyMasternode ) ) {
retErrorMessage = " sign message failed: " + errorMessage ;
LogPrintf ( " CActiveMasternode::Dseep() - Error: %s \n " , retErrorMessage . c_str ( ) ) ;
return false ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( ! darkSendSigner . VerifyMessage ( pubKeyMasternode , vchMasterNodeSignature , strMessage , errorMessage ) ) {
retErrorMessage = " Verify message failed: " + errorMessage ;
LogPrintf ( " CActiveMasternode::Dseep() - Error: %s \n " , retErrorMessage . c_str ( ) ) ;
2014-12-09 02:17:57 +01:00
return false ;
}
2014-12-06 20:41:53 +01:00
// Update Last Seen timestamp in masternode list
bool found = false ;
BOOST_FOREACH ( CMasterNode & mn , darkSendMasterNodes ) {
//LogPrintf(" -- %s\n", mn.vin.ToString().c_str());
if ( mn . vin = = vin ) {
found = true ;
mn . UpdateLastSeen ( ) ;
2014-12-09 02:17:57 +01:00
}
}
2014-12-06 20:41:53 +01:00
if ( ! found ) {
// Seems like we are trying to send a ping while the masternode is not registered in the network
retErrorMessage = " Darksend Masternode List doesn't include our masternode, Shutting down masternode pinging service! " + vin . ToString ( ) ;
LogPrintf ( " CActiveMasternode::Dseep() - Error: %s \n " , retErrorMessage . c_str ( ) ) ;
status = MASTERNODE_NOT_CAPABLE ;
notCapableReason = retErrorMessage ;
2014-12-09 02:17:57 +01:00
return false ;
}
2014-12-06 20:41:53 +01:00
//send to all peers
LogPrintf ( " CActiveMasternode::Dseep() - SendDarkSendElectionEntryPing vin = %s \n " , vin . ToString ( ) . c_str ( ) ) ;
SendDarkSendElectionEntryPing ( vin , vchMasterNodeSignature , masterNodeSignatureTime , stop ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
return true ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
bool CActiveMasternode : : Register ( std : : string strService , std : : string strKeyMasternode , std : : string txHash , std : : string strOutputIndex , std : : string & errorMessage ) {
CTxIn vin ;
CPubKey pubKeyCollateralAddress ;
CKey keyCollateralAddress ;
CPubKey pubKeyMasternode ;
CKey keyMasternode ;
if ( ! darkSendSigner . SetKey ( strKeyMasternode , errorMessage , keyMasternode , pubKeyMasternode ) )
{
LogPrintf ( " CActiveMasternode::Register() - Error upon calling SetKey: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
2014-12-09 02:17:57 +01:00
}
2014-12-06 20:41:53 +01:00
if ( ! GetMasterNodeVin ( vin , pubKeyCollateralAddress , keyCollateralAddress , txHash , strOutputIndex ) ) {
errorMessage = " could not allocate vin " ;
LogPrintf ( " Register::Register() - Error: %s \n " , errorMessage . c_str ( ) ) ;
return false ;
}
return Register ( vin , CService ( strService ) , keyCollateralAddress , pubKeyCollateralAddress , keyMasternode , pubKeyMasternode , errorMessage ) ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
bool CActiveMasternode : : Register ( CTxIn vin , CService service , CKey keyCollateralAddress , CPubKey pubKeyCollateralAddress , CKey keyMasternode , CPubKey pubKeyMasternode , std : : string & retErrorMessage ) {
std : : string errorMessage ;
std : : vector < unsigned char > vchMasterNodeSignature ;
std : : string strMasterNodeSignMessage ;
int64_t masterNodeSignatureTime = GetAdjustedTime ( ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
std : : string vchPubKey ( pubKeyCollateralAddress . begin ( ) , pubKeyCollateralAddress . end ( ) ) ;
std : : string vchPubKey2 ( pubKeyMasternode . begin ( ) , pubKeyMasternode . end ( ) ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
std : : string strMessage = service . ToString ( ) + boost : : lexical_cast < std : : string > ( masterNodeSignatureTime ) + vchPubKey + vchPubKey2 + boost : : lexical_cast < std : : string > ( PROTOCOL_VERSION ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( ! darkSendSigner . SignMessage ( strMessage , errorMessage , vchMasterNodeSignature , keyCollateralAddress ) ) {
retErrorMessage = " sign message failed: " + errorMessage ;
LogPrintf ( " CActiveMasternode::Register() - Error: %s \n " , retErrorMessage . c_str ( ) ) ;
return false ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( ! darkSendSigner . VerifyMessage ( pubKeyCollateralAddress , vchMasterNodeSignature , strMessage , errorMessage ) ) {
retErrorMessage = " Verify message failed: " + errorMessage ;
LogPrintf ( " CActiveMasternode::Register() - Error: %s \n " , retErrorMessage . c_str ( ) ) ;
return false ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
bool found = false ;
BOOST_FOREACH ( CMasterNode & mn , darkSendMasterNodes )
if ( mn . vin = = vin )
found = true ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
if ( ! found ) {
LogPrintf ( " CActiveMasternode::Register() - Adding to masternode list service: %s - vin: %s \n " , service . ToString ( ) . c_str ( ) , vin . ToString ( ) . c_str ( ) ) ;
CMasterNode mn ( service , vin , pubKeyCollateralAddress , vchMasterNodeSignature , masterNodeSignatureTime , pubKeyMasternode , PROTOCOL_VERSION ) ;
mn . UpdateLastSeen ( masterNodeSignatureTime ) ;
darkSendMasterNodes . push_back ( mn ) ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
//send to all peers
LogPrintf ( " CActiveMasternode::Register() - SendDarkSendElectionEntry vin = %s \n " , vin . ToString ( ) . c_str ( ) ) ;
SendDarkSendElectionEntry ( vin , service , vchMasterNodeSignature , masterNodeSignatureTime , pubKeyCollateralAddress , pubKeyMasternode , - 1 , - 1 , masterNodeSignatureTime , PROTOCOL_VERSION ) ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
return true ;
}
bool CActiveMasternode : : GetMasterNodeVin ( CTxIn & vin , CPubKey & pubkey , CKey & secretKey ) {
return GetMasterNodeVin ( vin , pubkey , secretKey , " " , " " ) ;
}
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
bool CActiveMasternode : : GetMasterNodeVin ( CTxIn & vin , CPubKey & pubkey , CKey & secretKey , std : : string strTxHash , std : : string strOutputIndex ) {
CScript pubScript ;
// Find possible candidates
vector < COutput > possibleCoins = SelectCoinsMasternode ( ) ;
COutput * selectedOutput ;
// Find the vin
if ( ! strTxHash . empty ( ) ) {
// Let's find it
uint256 txHash ( strTxHash ) ;
2014-12-16 18:45:43 +01:00
int outputIndex = 0 ;
outputIndex = boost : : lexical_cast < int > ( outputIndex ) ;
2014-12-06 20:41:53 +01:00
bool found = false ;
BOOST_FOREACH ( COutput & out , possibleCoins ) {
2014-12-16 18:45:43 +01:00
if ( out . tx - > GetHash ( ) = = txHash & & out . i = = outputIndex )
{
2014-12-06 20:41:53 +01:00
selectedOutput = & out ;
found = true ;
break ;
}
}
if ( ! found ) {
LogPrintf ( " CActiveMasternode::GetMasterNodeVin - Could not locate valid vin \n " ) ;
return false ;
}
} else {
// No output specified, Select the first one
if ( possibleCoins . size ( ) > 0 ) {
selectedOutput = & possibleCoins [ 0 ] ;
} else {
LogPrintf ( " CActiveMasternode::GetMasterNodeVin - Could not locate specified vin from possible list \n " ) ;
return false ;
}
2014-12-09 02:17:57 +01:00
}
2014-12-06 20:41:53 +01:00
// At this point we have a selected output, retrieve the associated info
return GetVinFromOutput ( * selectedOutput , vin , pubkey , secretKey ) ;
2014-12-09 02:17:57 +01:00
}
2014-12-06 20:41:53 +01:00
// Extract masternode vin information from output
bool CActiveMasternode : : GetVinFromOutput ( COutput out , CTxIn & vin , CPubKey & pubkey , CKey & secretKey ) {
2014-12-09 02:17:57 +01:00
CScript pubScript ;
2014-12-06 20:41:53 +01:00
vin = CTxIn ( out . tx - > GetHash ( ) , out . i ) ;
pubScript = out . tx - > vout [ out . i ] . scriptPubKey ; // the inputs PubKey
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
CTxDestination address1 ;
2014-12-09 02:17:57 +01:00
ExtractDestination ( pubScript , address1 ) ;
CBitcoinAddress address2 ( address1 ) ;
CKeyID keyID ;
if ( ! address2 . GetKeyID ( keyID ) ) {
LogPrintf ( " CActiveMasternode::GetMasterNodeVin - Address does not refer to a key \n " ) ;
return false ;
}
if ( ! pwalletMain - > GetKey ( keyID , secretKey ) ) {
LogPrintf ( " CActiveMasternode::GetMasterNodeVin - Private key for address is not known \n " ) ;
return false ;
}
pubkey = secretKey . GetPubKey ( ) ;
return true ;
}
2014-12-06 20:41:53 +01:00
// get all possible outputs for running masternode
vector < COutput > CActiveMasternode : : SelectCoinsMasternode ( )
{
CCoinControl * coinControl = NULL ;
vector < COutput > vCoins ;
vector < COutput > filteredCoins ;
// Retrieve all possible outputs
pwalletMain - > AvailableCoins ( vCoins , true , coinControl , ALL_COINS ) ;
// Filter
BOOST_FOREACH ( const COutput & out , vCoins )
{
if ( out . tx - > vout [ out . i ] . nValue = = 1000 * COIN ) { //exactly
filteredCoins . push_back ( out ) ;
}
}
return filteredCoins ;
}
/* select coins with specified transaction hash and output index */
/*
bool CActiveMasternode : : SelectCoinsMasternode ( CTxIn & vin , int64 & nValueIn , CScript & pubScript , std : : string strTxHash , std : : string strOutputIndex )
{
CWalletTx ctx ;
// Convert configuration strings
uint256 txHash ;
int outputIndex ;
txHash . SetHex ( strTxHash ) ;
std : : istringstream ( strOutputIndex ) > > outputIndex ;
if ( pwalletMain - > GetTransaction ( txHash , ctx ) ) {
if ( ctx . vout [ outputIndex ] . nValue = = 1000 * COIN ) { //exactly
vin = CTxIn ( ctx . GetHash ( ) , outputIndex ) ;
pubScript = ctx . vout [ outputIndex ] . scriptPubKey ; // the inputs PubKey
nValueIn = ctx . vout [ outputIndex ] . nValue ;
return true ;
}
}
return false ;
}
*/
2014-12-09 02:17:57 +01:00
// when starting a masternode, this can enable to run as a hot wallet with no funds
2014-12-06 20:41:53 +01:00
bool CActiveMasternode : : EnableHotColdMasterNode ( CTxIn & newVin , CService & newService )
2014-12-09 02:17:57 +01:00
{
if ( ! fMasterNode ) return false ;
2014-12-06 20:41:53 +01:00
status = MASTERNODE_REMOTELY_ENABLED ;
2014-12-09 02:17:57 +01:00
2014-12-06 20:41:53 +01:00
//The values below are needed for signing dseep messages going forward
this - > vin = newVin ;
this - > service = newService ;
2014-12-09 02:17:57 +01:00
LogPrintf ( " CActiveMasternode::EnableHotColdMasterNode() - Enabled! You may shut down the cold daemon. \n " ) ;
return true ;
}