// Copyright (c) 2014-2016 The Dash Core developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "darksend.h" #include "main.h" #include "spork.h" #include class CSporkMessage; class CSporkManager; CSporkManager sporkManager; std::map mapSporks; void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if(fLiteMode) return; // disable all Dash specific functionality if (strCommand == NetMsgType::SPORK) { // LogPrintf("CSporkManager::ProcessSpork\n"); CDataStream vMsg(vRecv); CSporkMessage spork; vRecv >> spork; LOCK(cs_main); if(chainActive.Tip() == NULL) return; uint256 hash = spork.GetHash(); if(mapSporksActive.count(spork.nSporkID)) { if (mapSporksActive[spork.nSporkID].nTimeSigned >= spork.nTimeSigned) { if(fDebug) LogPrintf("CSporkManager::ProcessSpork -- seen %s block %d\n", hash.ToString(), chainActive.Tip()->nHeight); return; } else { if(fDebug) LogPrintf("CSporkManager::ProcessSpork -- got updated spork %s block %d\n", hash.ToString(), chainActive.Tip()->nHeight); } } LogPrintf("spork -- hash: %s id: %d value: %10d bestHeight: %d new\n", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Tip()->nHeight); if(!spork.CheckSignature()) { LogPrintf("CSporkManager::ProcessSpork -- invalid signature\n"); Misbehaving(pfrom->GetId(), 100); return; } mapSporks[hash] = spork; mapSporksActive[spork.nSporkID] = spork; spork.Relay(); //does a task if needed ExecuteSpork(spork.nSporkID, spork.nValue); } else if (strCommand == NetMsgType::GETSPORKS) { std::map::iterator it = mapSporksActive.begin(); while(it != mapSporksActive.end()) { pfrom->PushMessage(NetMsgType::SPORK, it->second); it++; } } } void CSporkManager::ExecuteSpork(int nSporkID, int nValue) { //correct fork via spork technology if(nSporkID == SPORK_12_RECONSIDER_BLOCKS && nValue > 0) { LogPrintf("CSporkManager::ExecuteSpork -- Reconsider Last %d Blocks\n", nValue); ReprocessBlocks(nValue); } } bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue) { CSporkMessage spork = CSporkMessage(nSporkID, nValue, GetTime()); if(spork.Sign(strMasterPrivKey)) { spork.Relay(); mapSporks[spork.GetHash()] = spork; mapSporksActive[nSporkID] = spork; return true; } return false; } // grab the spork, otherwise say it's off bool CSporkManager::IsSporkActive(int nSporkID) { int64_t r = -1; if(mapSporksActive.count(nSporkID)){ r = mapSporksActive[nSporkID].nValue; } else { switch (nSporkID) { case SPORK_2_INSTANTX: r = SPORK_2_INSTANTX_DEFAULT; break; case SPORK_3_INSTANTX_BLOCK_FILTERING: r = SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT; break; case SPORK_5_MAX_VALUE: r = SPORK_5_MAX_VALUE_DEFAULT; break; case SPORK_7_MASTERNODE_SCANNING: r = SPORK_7_MASTERNODE_SCANNING_DEFAULT; break; case SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT: r = SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT; break; case SPORK_9_SUPERBLOCKS_ENABLED: r = SPORK_9_SUPERBLOCKS_ENABLED_DEFAULT; break; case SPORK_10_MASTERNODE_PAY_UPDATED_NODES: r = SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT; break; case SPORK_12_RECONSIDER_BLOCKS: r = SPORK_12_RECONSIDER_BLOCKS_DEFAULT; break; case SPORK_13_OLD_SUPERBLOCK_FLAG: r = SPORK_13_OLD_SUPERBLOCK_FLAG_DEFAULT; break; default: LogPrintf("CSporkManager::IsSporkActive -- Unknown Spork %d\n", nSporkID); r = 4070908800; // 2099-1-1 i.e. off by default break; } } return r < GetTime(); } // grab the value of the spork on the network, or the default int64_t CSporkManager::GetSporkValue(int nSporkID) { if (mapSporksActive.count(nSporkID)) return mapSporksActive[nSporkID].nValue; switch (nSporkID) { case SPORK_2_INSTANTX: return SPORK_2_INSTANTX_DEFAULT; case SPORK_3_INSTANTX_BLOCK_FILTERING: return SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT; case SPORK_5_MAX_VALUE: return SPORK_5_MAX_VALUE_DEFAULT; case SPORK_7_MASTERNODE_SCANNING: return SPORK_7_MASTERNODE_SCANNING_DEFAULT; case SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT: return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT; case SPORK_9_SUPERBLOCKS_ENABLED: return SPORK_9_SUPERBLOCKS_ENABLED_DEFAULT; case SPORK_10_MASTERNODE_PAY_UPDATED_NODES: return SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT; case SPORK_12_RECONSIDER_BLOCKS: return SPORK_12_RECONSIDER_BLOCKS_DEFAULT; case SPORK_13_OLD_SUPERBLOCK_FLAG: return SPORK_13_OLD_SUPERBLOCK_FLAG_DEFAULT; default: LogPrintf("CSporkManager::GetSporkValue -- Unknown Spork ID %d\n", nSporkID); return -1; } } int CSporkManager::GetSporkIDByName(std::string strName) { if (strName == "SPORK_2_INSTANTX") return SPORK_2_INSTANTX; if (strName == "SPORK_3_INSTANTX_BLOCK_FILTERING") return SPORK_3_INSTANTX_BLOCK_FILTERING; if (strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE; if (strName == "SPORK_7_MASTERNODE_SCANNING") return SPORK_7_MASTERNODE_SCANNING; if (strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT; if (strName == "SPORK_9_SUPERBLOCKS_ENABLED") return SPORK_9_SUPERBLOCKS_ENABLED; if (strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES; if (strName == "SPORK_12_RECONSIDER_BLOCKS") return SPORK_12_RECONSIDER_BLOCKS; if (strName == "SPORK_13_OLD_SUPERBLOCK_FLAG") return SPORK_13_OLD_SUPERBLOCK_FLAG; LogPrintf("CSporkManager::GetSporkIDByName -- Unknown Spork name '%s'\n", strName); return -1; } std::string CSporkManager::GetSporkNameByID(int nSporkID) { switch (nSporkID) { case SPORK_2_INSTANTX: return "SPORK_2_INSTANTX_DEFAULT"; case SPORK_3_INSTANTX_BLOCK_FILTERING: return "SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT"; case SPORK_5_MAX_VALUE: return "SPORK_5_MAX_VALUE_DEFAULT"; case SPORK_7_MASTERNODE_SCANNING: return "SPORK_7_MASTERNODE_SCANNING_DEFAULT"; case SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT: return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT"; case SPORK_9_SUPERBLOCKS_ENABLED: return "SPORK_9_SUPERBLOCKS_ENABLED"; case SPORK_10_MASTERNODE_PAY_UPDATED_NODES: return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT"; case SPORK_12_RECONSIDER_BLOCKS: return "SPORK_12_RECONSIDER_BLOCKS_DEFAULT"; case SPORK_13_OLD_SUPERBLOCK_FLAG: return "SPORK_13_OLD_SUPERBLOCK_FLAG"; default: LogPrintf("CSporkManager::GetSporkNameByID -- Unknown Spork ID %d\n", nSporkID); return "Unknown"; } } bool CSporkManager::SetPrivKey(std::string strPrivKey) { CSporkMessage spork; spork.Sign(strMasterPrivKey); if(spork.CheckSignature()){ // Test signing successful, proceed LogPrintf("CSporkManager::SetPrivKey -- Successfully initialized as spork signer\n"); strMasterPrivKey = strPrivKey; return true; } else { return false; } } bool CSporkMessage::Sign(std::string strSignKey) { CKey key; CPubKey pubkey; std::string strError = ""; std::string strMessage = boost::lexical_cast(nSporkID) + boost::lexical_cast(nValue) + boost::lexical_cast(nTimeSigned); if(!darkSendSigner.GetKeysFromSecret(strSignKey, key, pubkey)) { LogPrintf("CSporkMessage::Sign -- GetKeysFromSecret() failed, invalid spork key %s\n", strSignKey); return false; } if(!darkSendSigner.SignMessage(strMessage, vchSig, key)) { LogPrintf("CSporkMessage::Sign -- SignMessage() failed\n"); return false; } if(!darkSendSigner.VerifyMessage(pubkey, vchSig, strMessage, strError)) { LogPrintf("CSporkMessage::Sign -- VerifyMessage() failed, error: %s\n", strError); return false; } return true; } bool CSporkMessage::CheckSignature() { //note: need to investigate why this is failing std::string strError = ""; std::string strMessage = boost::lexical_cast(nSporkID) + boost::lexical_cast(nValue) + boost::lexical_cast(nTimeSigned); CPubKey pubkey(ParseHex(Params().SporkPubKey())); if(!darkSendSigner.VerifyMessage(pubkey, vchSig, strMessage, strError)) { LogPrintf("CSporkMessage::CheckSignature -- VerifyMessage() failed, error: %s\n", strError); return false; } return true; } void CSporkMessage::Relay() { CInv inv(MSG_SPORK, GetHash()); RelayInv(inv); }