2016-02-02 16:28:56 +01:00
|
|
|
// 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.
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
|
|
|
|
#include "sync.h"
|
|
|
|
#include "net.h"
|
|
|
|
#include "key.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "base58.h"
|
2016-02-02 16:28:56 +01:00
|
|
|
#include "darksend.h"
|
2015-02-09 21:54:51 +01:00
|
|
|
#include "protocol.h"
|
|
|
|
#include "spork.h"
|
2015-02-12 05:05:09 +01:00
|
|
|
#include "main.h"
|
2016-04-15 04:54:11 +02:00
|
|
|
#include "governance.h"
|
2016-02-02 16:28:56 +01:00
|
|
|
#include "consensus/validation.h"
|
2015-02-09 21:54:51 +01:00
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace boost;
|
|
|
|
|
|
|
|
class CSporkMessage;
|
|
|
|
class CSporkManager;
|
|
|
|
|
2015-02-26 15:02:39 +01:00
|
|
|
CSporkManager sporkManager;
|
|
|
|
|
2015-02-09 21:54:51 +01:00
|
|
|
std::map<uint256, CSporkMessage> mapSporks;
|
|
|
|
std::map<int, CSporkMessage> mapSporksActive;
|
2015-02-26 15:02:39 +01:00
|
|
|
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
void ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
|
|
|
{
|
|
|
|
if(fLiteMode) return; //disable all darksend/masternode related functionality
|
|
|
|
|
2016-02-17 23:18:57 +01:00
|
|
|
if (strCommand == NetMsgType::SPORK)
|
2015-02-09 21:54:51 +01:00
|
|
|
{
|
|
|
|
//LogPrintf("ProcessSpork::spork\n");
|
|
|
|
CDataStream vMsg(vRecv);
|
|
|
|
CSporkMessage spork;
|
|
|
|
vRecv >> spork;
|
|
|
|
|
2016-03-02 21:57:24 +01:00
|
|
|
LOCK(cs_main);
|
2015-02-09 21:54:51 +01:00
|
|
|
if(chainActive.Tip() == NULL) return;
|
|
|
|
|
|
|
|
uint256 hash = spork.GetHash();
|
2015-04-07 17:17:50 +02:00
|
|
|
if(mapSporksActive.count(spork.nSporkID)) {
|
2015-02-09 21:54:51 +01:00
|
|
|
if(mapSporksActive[spork.nSporkID].nTimeSigned >= spork.nTimeSigned){
|
2015-07-31 17:46:47 +02:00
|
|
|
if(fDebug) LogPrintf("spork - seen %s block %d \n", hash.ToString(), chainActive.Tip()->nHeight);
|
2015-02-09 21:54:51 +01:00
|
|
|
return;
|
|
|
|
} else {
|
2015-07-31 17:46:47 +02:00
|
|
|
if(fDebug) LogPrintf("spork - got updated spork %s block %d \n", hash.ToString(), chainActive.Tip()->nHeight);
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-31 17:46:47 +02:00
|
|
|
LogPrintf("spork - new %s ID %d Time %d bestHeight %d\n", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Tip()->nHeight);
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
if(!sporkManager.CheckSignature(spork)){
|
|
|
|
LogPrintf("spork - invalid signature\n");
|
|
|
|
Misbehaving(pfrom->GetId(), 100);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-02-11 21:39:33 +01:00
|
|
|
mapSporks[hash] = spork;
|
2015-02-09 21:54:51 +01:00
|
|
|
mapSporksActive[spork.nSporkID] = spork;
|
|
|
|
sporkManager.Relay(spork);
|
|
|
|
|
2015-02-12 05:05:09 +01:00
|
|
|
//does a task if needed
|
|
|
|
ExecuteSpork(spork.nSporkID, spork.nValue);
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
2016-02-17 23:18:57 +01:00
|
|
|
if (strCommand == NetMsgType::GETSPORKS)
|
2015-02-09 21:54:51 +01:00
|
|
|
{
|
|
|
|
std::map<int, CSporkMessage>::iterator it = mapSporksActive.begin();
|
|
|
|
|
|
|
|
while(it != mapSporksActive.end()) {
|
2016-02-17 23:18:57 +01:00
|
|
|
pfrom->PushMessage(NetMsgType::SPORK, it->second);
|
2015-02-09 21:54:51 +01:00
|
|
|
it++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// grab the spork, otherwise say it's off
|
|
|
|
bool IsSporkActive(int nSporkID)
|
|
|
|
{
|
2015-06-25 21:59:11 +02:00
|
|
|
int64_t r = -1;
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
if(mapSporksActive.count(nSporkID)){
|
2015-02-11 15:47:21 +01:00
|
|
|
r = mapSporksActive[nSporkID].nValue;
|
2015-02-09 21:54:51 +01:00
|
|
|
} else {
|
|
|
|
if(nSporkID == SPORK_2_INSTANTX) r = SPORK_2_INSTANTX_DEFAULT;
|
|
|
|
if(nSporkID == SPORK_3_INSTANTX_BLOCK_FILTERING) r = SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT;
|
2015-02-11 15:47:21 +01:00
|
|
|
if(nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT;
|
2015-06-25 17:17:53 +02:00
|
|
|
if(nSporkID == SPORK_7_MASTERNODE_SCANNING) r = SPORK_7_MASTERNODE_SCANNING_DEFAULT;
|
|
|
|
if(nSporkID == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) r = SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT;
|
|
|
|
if(nSporkID == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) r = SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT;
|
2015-07-27 17:27:58 +02:00
|
|
|
if(nSporkID == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) r = SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT;
|
2015-07-08 19:25:47 +02:00
|
|
|
if(nSporkID == SPORK_11_RESET_BUDGET) r = SPORK_11_RESET_BUDGET_DEFAULT;
|
2015-07-16 20:06:45 +02:00
|
|
|
if(nSporkID == SPORK_12_RECONSIDER_BLOCKS) r = SPORK_12_RECONSIDER_BLOCKS_DEFAULT;
|
2015-07-17 05:03:42 +02:00
|
|
|
if(nSporkID == SPORK_13_ENABLE_SUPERBLOCKS) r = SPORK_13_ENABLE_SUPERBLOCKS_DEFAULT;
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2015-06-25 21:59:11 +02:00
|
|
|
if(r == -1) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID);
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
2015-06-25 21:59:11 +02:00
|
|
|
if(r == -1) r = 4070908800; //return 2099-1-1 by default
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
return r < GetTime();
|
|
|
|
}
|
|
|
|
|
2015-02-11 15:47:21 +01:00
|
|
|
// grab the value of the spork on the network, or the default
|
2015-08-14 21:57:41 +02:00
|
|
|
int64_t GetSporkValue(int nSporkID)
|
2015-02-11 15:47:21 +01:00
|
|
|
{
|
2015-08-15 15:34:38 +02:00
|
|
|
int64_t r = -1;
|
2015-02-11 15:47:21 +01:00
|
|
|
|
|
|
|
if(mapSporksActive.count(nSporkID)){
|
|
|
|
r = mapSporksActive[nSporkID].nValue;
|
|
|
|
} else {
|
|
|
|
if(nSporkID == SPORK_2_INSTANTX) r = SPORK_2_INSTANTX_DEFAULT;
|
|
|
|
if(nSporkID == SPORK_3_INSTANTX_BLOCK_FILTERING) r = SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT;
|
|
|
|
if(nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT;
|
2015-05-30 19:27:51 +02:00
|
|
|
if(nSporkID == SPORK_7_MASTERNODE_SCANNING) r = SPORK_7_MASTERNODE_SCANNING_DEFAULT;
|
|
|
|
if(nSporkID == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) r = SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT;
|
|
|
|
if(nSporkID == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) r = SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT;
|
2015-07-27 17:27:58 +02:00
|
|
|
if(nSporkID == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) r = SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT;
|
2015-07-08 19:25:47 +02:00
|
|
|
if(nSporkID == SPORK_11_RESET_BUDGET) r = SPORK_11_RESET_BUDGET_DEFAULT;
|
2015-07-16 20:06:45 +02:00
|
|
|
if(nSporkID == SPORK_12_RECONSIDER_BLOCKS) r = SPORK_12_RECONSIDER_BLOCKS_DEFAULT;
|
2015-07-17 05:03:42 +02:00
|
|
|
if(nSporkID == SPORK_13_ENABLE_SUPERBLOCKS) r = SPORK_13_ENABLE_SUPERBLOCKS_DEFAULT;
|
2015-02-11 15:47:21 +01:00
|
|
|
|
2015-08-15 15:34:38 +02:00
|
|
|
if(r == -1) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID);
|
2015-02-11 15:47:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2015-02-12 05:05:09 +01:00
|
|
|
void ExecuteSpork(int nSporkID, int nValue)
|
|
|
|
{
|
2016-04-15 04:54:11 +02:00
|
|
|
// if(nSporkID == SPORK_11_RESET_BUDGET && nValue == 1){
|
|
|
|
// budget.Clear();
|
|
|
|
// }
|
2015-07-16 20:06:45 +02:00
|
|
|
|
|
|
|
//correct fork via spork technology
|
|
|
|
if(nSporkID == SPORK_12_RECONSIDER_BLOCKS && nValue > 0) {
|
2015-08-03 01:08:37 +02:00
|
|
|
LogPrintf("Spork::ExecuteSpork -- Reconsider Last %d Blocks\n", nValue);
|
2015-07-16 20:06:45 +02:00
|
|
|
|
2015-08-03 01:08:37 +02:00
|
|
|
ReprocessBlocks(nValue);
|
|
|
|
}
|
|
|
|
}
|
2015-08-02 23:59:28 +02:00
|
|
|
|
2015-08-03 01:08:37 +02:00
|
|
|
void ReprocessBlocks(int nBlocks)
|
2015-08-05 02:58:41 +02:00
|
|
|
{
|
|
|
|
std::map<uint256, int64_t>::iterator it = mapRejectedBlocks.begin();
|
|
|
|
while(it != mapRejectedBlocks.end()){
|
|
|
|
//use a window twice as large as is usual for the nBlocks we want to reset
|
|
|
|
if((*it).second > GetTime() - (nBlocks*60*5)) {
|
|
|
|
BlockMap::iterator mi = mapBlockIndex.find((*it).first);
|
|
|
|
if (mi != mapBlockIndex.end() && (*mi).second) {
|
|
|
|
LOCK(cs_main);
|
|
|
|
|
|
|
|
CBlockIndex* pindex = (*mi).second;
|
|
|
|
LogPrintf("ReprocessBlocks - %s\n", (*it).first.ToString());
|
|
|
|
|
|
|
|
CValidationState state;
|
|
|
|
ReconsiderBlock(state, pindex);
|
|
|
|
}
|
2015-08-01 10:51:30 +02:00
|
|
|
}
|
2015-08-05 02:58:41 +02:00
|
|
|
++it;
|
2015-08-03 01:08:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CValidationState state;
|
|
|
|
{
|
|
|
|
LOCK(cs_main);
|
|
|
|
DisconnectBlocksAndReprocess(nBlocks);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (state.IsValid()) {
|
2016-02-02 16:28:56 +01:00
|
|
|
ActivateBestChain(state, Params());
|
2015-07-08 19:25:47 +02:00
|
|
|
}
|
2015-02-12 05:05:09 +01:00
|
|
|
}
|
|
|
|
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
bool CSporkManager::CheckSignature(CSporkMessage& spork)
|
|
|
|
{
|
|
|
|
//note: need to investigate why this is failing
|
2015-02-11 15:47:21 +01:00
|
|
|
std::string strMessage = boost::lexical_cast<std::string>(spork.nSporkID) + boost::lexical_cast<std::string>(spork.nValue) + boost::lexical_cast<std::string>(spork.nTimeSigned);
|
2015-04-03 00:51:08 +02:00
|
|
|
CPubKey pubkey(ParseHex(Params().SporkKey()));
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
std::string errorMessage = "";
|
|
|
|
if(!darkSendSigner.VerifyMessage(pubkey, spork.vchSig, strMessage, errorMessage)){
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CSporkManager::Sign(CSporkMessage& spork)
|
|
|
|
{
|
2015-02-11 15:47:21 +01:00
|
|
|
std::string strMessage = boost::lexical_cast<std::string>(spork.nSporkID) + boost::lexical_cast<std::string>(spork.nValue) + boost::lexical_cast<std::string>(spork.nTimeSigned);
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
CKey key2;
|
|
|
|
CPubKey pubkey2;
|
|
|
|
std::string errorMessage = "";
|
|
|
|
|
|
|
|
if(!darkSendSigner.SetKey(strMasterPrivKey, errorMessage, key2, pubkey2))
|
|
|
|
{
|
2015-07-31 17:46:47 +02:00
|
|
|
LogPrintf("CMasternodePayments::Sign - ERROR: Invalid masternodeprivkey: '%s'\n", errorMessage);
|
2015-02-09 21:54:51 +01:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!darkSendSigner.SignMessage(strMessage, errorMessage, spork.vchSig, key2)) {
|
|
|
|
LogPrintf("CMasternodePayments::Sign - Sign message failed");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!darkSendSigner.VerifyMessage(pubkey2, spork.vchSig, strMessage, errorMessage)) {
|
|
|
|
LogPrintf("CMasternodePayments::Sign - Verify message failed");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-02-11 15:47:21 +01:00
|
|
|
bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue)
|
2015-02-09 21:54:51 +01:00
|
|
|
{
|
|
|
|
|
|
|
|
CSporkMessage msg;
|
|
|
|
msg.nSporkID = nSporkID;
|
2015-02-11 15:47:21 +01:00
|
|
|
msg.nValue = nValue;
|
2015-02-09 21:54:51 +01:00
|
|
|
msg.nTimeSigned = GetTime();
|
|
|
|
|
|
|
|
if(Sign(msg)){
|
|
|
|
Relay(msg);
|
|
|
|
mapSporks[msg.GetHash()] = msg;
|
2015-02-11 15:47:21 +01:00
|
|
|
mapSporksActive[nSporkID] = msg;
|
2015-02-09 21:54:51 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CSporkManager::Relay(CSporkMessage& msg)
|
|
|
|
{
|
|
|
|
CInv inv(MSG_SPORK, msg.GetHash());
|
2015-07-08 02:37:23 +02:00
|
|
|
RelayInv(inv);
|
2015-02-09 21:54:51 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CSporkManager::SetPrivKey(std::string strPrivKey)
|
|
|
|
{
|
|
|
|
CSporkMessage msg;
|
|
|
|
|
|
|
|
// Test signing successful, proceed
|
|
|
|
strMasterPrivKey = strPrivKey;
|
|
|
|
|
|
|
|
Sign(msg);
|
|
|
|
|
|
|
|
if(CheckSignature(msg)){
|
|
|
|
LogPrintf("CSporkManager::SetPrivKey - Successfully initialized as spork signer\n");
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
2015-02-11 15:47:21 +01:00
|
|
|
if(strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE;
|
2015-03-13 10:28:20 +01:00
|
|
|
if(strName == "SPORK_7_MASTERNODE_SCANNING") return SPORK_7_MASTERNODE_SCANNING;
|
2015-05-30 19:27:51 +02:00
|
|
|
if(strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT;
|
|
|
|
if(strName == "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") return SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT;
|
2015-07-27 17:27:58 +02:00
|
|
|
if(strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES;
|
2015-07-08 19:25:47 +02:00
|
|
|
if(strName == "SPORK_11_RESET_BUDGET") return SPORK_11_RESET_BUDGET;
|
2015-07-16 20:06:45 +02:00
|
|
|
if(strName == "SPORK_12_RECONSIDER_BLOCKS") return SPORK_12_RECONSIDER_BLOCKS;
|
2015-07-17 05:03:42 +02:00
|
|
|
if(strName == "SPORK_13_ENABLE_SUPERBLOCKS") return SPORK_13_ENABLE_SUPERBLOCKS;
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string CSporkManager::GetSporkNameByID(int id)
|
|
|
|
{
|
|
|
|
if(id == SPORK_2_INSTANTX) return "SPORK_2_INSTANTX";
|
|
|
|
if(id == SPORK_3_INSTANTX_BLOCK_FILTERING) return "SPORK_3_INSTANTX_BLOCK_FILTERING";
|
2015-02-11 15:47:21 +01:00
|
|
|
if(id == SPORK_5_MAX_VALUE) return "SPORK_5_MAX_VALUE";
|
2015-03-13 10:28:20 +01:00
|
|
|
if(id == SPORK_7_MASTERNODE_SCANNING) return "SPORK_7_MASTERNODE_SCANNING";
|
2015-05-30 19:27:51 +02:00
|
|
|
if(id == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT";
|
|
|
|
if(id == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) return "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT";
|
2015-07-27 17:27:58 +02:00
|
|
|
if(id == SPORK_10_MASTERNODE_PAY_UPDATED_NODES) return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES";
|
2015-07-08 19:25:47 +02:00
|
|
|
if(id == SPORK_11_RESET_BUDGET) return "SPORK_11_RESET_BUDGET";
|
2015-07-16 20:06:45 +02:00
|
|
|
if(id == SPORK_12_RECONSIDER_BLOCKS) return "SPORK_12_RECONSIDER_BLOCKS";
|
2015-07-17 05:03:42 +02:00
|
|
|
if(id == SPORK_13_ENABLE_SUPERBLOCKS) return "SPORK_13_ENABLE_SUPERBLOCKS";
|
2015-02-09 21:54:51 +01:00
|
|
|
|
|
|
|
return "Unknown";
|
2015-04-03 00:51:08 +02:00
|
|
|
}
|