Dash Core  0.12.2.1
P2P Digital Currency
spork.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2017 The Dash Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "chainparams.h"
6 #include "validation.h"
7 #include "messagesigner.h"
8 #include "net_processing.h"
9 #include "spork.h"
10 
11 #include <boost/lexical_cast.hpp>
12 
13 class CSporkMessage;
15 
17 
18 std::map<uint256, CSporkMessage> mapSporks;
19 
20 void CSporkManager::ProcessSpork(CNode* pfrom, std::string& strCommand, CDataStream& vRecv, CConnman& connman)
21 {
22  if(fLiteMode) return; // disable all Dash specific functionality
23 
24  if (strCommand == NetMsgType::SPORK) {
25 
27  vRecv >> spork;
28 
29  uint256 hash = spork.GetHash();
30 
31  std::string strLogMsg;
32  {
33  LOCK(cs_main);
34  pfrom->setAskFor.erase(hash);
35  if(!chainActive.Tip()) return;
36  strLogMsg = strprintf("SPORK -- hash: %s id: %d value: %10d bestHeight: %d peer=%d", hash.ToString(), spork.nSporkID, spork.nValue, chainActive.Height(), pfrom->id);
37  }
38 
39  if(mapSporksActive.count(spork.nSporkID)) {
40  if (mapSporksActive[spork.nSporkID].nTimeSigned >= spork.nTimeSigned) {
41  LogPrint("spork", "%s seen\n", strLogMsg);
42  return;
43  } else {
44  LogPrintf("%s updated\n", strLogMsg);
45  }
46  } else {
47  LogPrintf("%s new\n", strLogMsg);
48  }
49 
50  if(!spork.CheckSignature()) {
51  LogPrintf("CSporkManager::ProcessSpork -- invalid signature\n");
52  Misbehaving(pfrom->GetId(), 100);
53  return;
54  }
55 
56  mapSporks[hash] = spork;
57  mapSporksActive[spork.nSporkID] = spork;
58  spork.Relay(connman);
59 
60  //does a task if needed
61  ExecuteSpork(spork.nSporkID, spork.nValue);
62 
63  } else if (strCommand == NetMsgType::GETSPORKS) {
64 
65  std::map<int, CSporkMessage>::iterator it = mapSporksActive.begin();
66 
67  while(it != mapSporksActive.end()) {
68  connman.PushMessage(pfrom, NetMsgType::SPORK, it->second);
69  it++;
70  }
71  }
72 
73 }
74 
75 void CSporkManager::ExecuteSpork(int nSporkID, int nValue)
76 {
77  //correct fork via spork technology
78  if(nSporkID == SPORK_12_RECONSIDER_BLOCKS && nValue > 0) {
79  // allow to reprocess 24h of blocks max, which should be enough to resolve any issues
80  int64_t nMaxBlocks = 576;
81  // this potentially can be a heavy operation, so only allow this to be executed once per 10 minutes
82  int64_t nTimeout = 10 * 60;
83 
84  static int64_t nTimeExecuted = 0; // i.e. it was never executed before
85 
86  if(GetTime() - nTimeExecuted < nTimeout) {
87  LogPrint("spork", "CSporkManager::ExecuteSpork -- ERROR: Trying to reconsider blocks, too soon - %d/%d\n", GetTime() - nTimeExecuted, nTimeout);
88  return;
89  }
90 
91  if(nValue > nMaxBlocks) {
92  LogPrintf("CSporkManager::ExecuteSpork -- ERROR: Trying to reconsider too many blocks %d/%d\n", nValue, nMaxBlocks);
93  return;
94  }
95 
96 
97  LogPrintf("CSporkManager::ExecuteSpork -- Reconsider Last %d Blocks\n", nValue);
98 
99  ReprocessBlocks(nValue);
100  nTimeExecuted = GetTime();
101  }
102 }
103 
104 bool CSporkManager::UpdateSpork(int nSporkID, int64_t nValue, CConnman& connman)
105 {
106 
107  CSporkMessage spork = CSporkMessage(nSporkID, nValue, GetAdjustedTime());
108 
109  if(spork.Sign(strMasterPrivKey)) {
110  spork.Relay(connman);
111  mapSporks[spork.GetHash()] = spork;
112  mapSporksActive[nSporkID] = spork;
113  return true;
114  }
115 
116  return false;
117 }
118 
119 // grab the spork, otherwise say it's off
121 {
122  int64_t r = -1;
123 
124  if(mapSporksActive.count(nSporkID)){
125  r = mapSporksActive[nSporkID].nValue;
126  } else {
127  switch (nSporkID) {
137  default:
138  LogPrint("spork", "CSporkManager::IsSporkActive -- Unknown Spork ID %d\n", nSporkID);
139  r = 4070908800ULL; // 2099-1-1 i.e. off by default
140  break;
141  }
142  }
143 
144  return r < GetAdjustedTime();
145 }
146 
147 // grab the value of the spork on the network, or the default
148 int64_t CSporkManager::GetSporkValue(int nSporkID)
149 {
150  if (mapSporksActive.count(nSporkID))
151  return mapSporksActive[nSporkID].nValue;
152 
153  switch (nSporkID) {
163  default:
164  LogPrint("spork", "CSporkManager::GetSporkValue -- Unknown Spork ID %d\n", nSporkID);
165  return -1;
166  }
167 
168 }
169 
170 int CSporkManager::GetSporkIDByName(std::string strName)
171 {
172  if (strName == "SPORK_2_INSTANTSEND_ENABLED") return SPORK_2_INSTANTSEND_ENABLED;
173  if (strName == "SPORK_3_INSTANTSEND_BLOCK_FILTERING") return SPORK_3_INSTANTSEND_BLOCK_FILTERING;
174  if (strName == "SPORK_5_INSTANTSEND_MAX_VALUE") return SPORK_5_INSTANTSEND_MAX_VALUE;
175  if (strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT;
176  if (strName == "SPORK_9_SUPERBLOCKS_ENABLED") return SPORK_9_SUPERBLOCKS_ENABLED;
177  if (strName == "SPORK_10_MASTERNODE_PAY_UPDATED_NODES") return SPORK_10_MASTERNODE_PAY_UPDATED_NODES;
178  if (strName == "SPORK_12_RECONSIDER_BLOCKS") return SPORK_12_RECONSIDER_BLOCKS;
179  if (strName == "SPORK_13_OLD_SUPERBLOCK_FLAG") return SPORK_13_OLD_SUPERBLOCK_FLAG;
180  if (strName == "SPORK_14_REQUIRE_SENTINEL_FLAG") return SPORK_14_REQUIRE_SENTINEL_FLAG;
181 
182  LogPrint("spork", "CSporkManager::GetSporkIDByName -- Unknown Spork name '%s'\n", strName);
183  return -1;
184 }
185 
186 std::string CSporkManager::GetSporkNameByID(int nSporkID)
187 {
188  switch (nSporkID) {
189  case SPORK_2_INSTANTSEND_ENABLED: return "SPORK_2_INSTANTSEND_ENABLED";
190  case SPORK_3_INSTANTSEND_BLOCK_FILTERING: return "SPORK_3_INSTANTSEND_BLOCK_FILTERING";
191  case SPORK_5_INSTANTSEND_MAX_VALUE: return "SPORK_5_INSTANTSEND_MAX_VALUE";
192  case SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT: return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT";
193  case SPORK_9_SUPERBLOCKS_ENABLED: return "SPORK_9_SUPERBLOCKS_ENABLED";
194  case SPORK_10_MASTERNODE_PAY_UPDATED_NODES: return "SPORK_10_MASTERNODE_PAY_UPDATED_NODES";
195  case SPORK_12_RECONSIDER_BLOCKS: return "SPORK_12_RECONSIDER_BLOCKS";
196  case SPORK_13_OLD_SUPERBLOCK_FLAG: return "SPORK_13_OLD_SUPERBLOCK_FLAG";
197  case SPORK_14_REQUIRE_SENTINEL_FLAG: return "SPORK_14_REQUIRE_SENTINEL_FLAG";
198  default:
199  LogPrint("spork", "CSporkManager::GetSporkNameByID -- Unknown Spork ID %d\n", nSporkID);
200  return "Unknown";
201  }
202 }
203 
204 bool CSporkManager::SetPrivKey(std::string strPrivKey)
205 {
207 
208  spork.Sign(strPrivKey);
209 
210  if(spork.CheckSignature()){
211  // Test signing successful, proceed
212  LogPrintf("CSporkManager::SetPrivKey -- Successfully initialized as spork signer\n");
213  strMasterPrivKey = strPrivKey;
214  return true;
215  } else {
216  return false;
217  }
218 }
219 
220 bool CSporkMessage::Sign(std::string strSignKey)
221 {
222  CKey key;
223  CPubKey pubkey;
224  std::string strError = "";
225  std::string strMessage = boost::lexical_cast<std::string>(nSporkID) + boost::lexical_cast<std::string>(nValue) + boost::lexical_cast<std::string>(nTimeSigned);
226 
227  if(!CMessageSigner::GetKeysFromSecret(strSignKey, key, pubkey)) {
228  LogPrintf("CSporkMessage::Sign -- GetKeysFromSecret() failed, invalid spork key %s\n", strSignKey);
229  return false;
230  }
231 
232  if(!CMessageSigner::SignMessage(strMessage, vchSig, key)) {
233  LogPrintf("CSporkMessage::Sign -- SignMessage() failed\n");
234  return false;
235  }
236 
237  if(!CMessageSigner::VerifyMessage(pubkey, vchSig, strMessage, strError)) {
238  LogPrintf("CSporkMessage::Sign -- VerifyMessage() failed, error: %s\n", strError);
239  return false;
240  }
241 
242  return true;
243 }
244 
246 {
247  //note: need to investigate why this is failing
248  std::string strError = "";
249  std::string strMessage = boost::lexical_cast<std::string>(nSporkID) + boost::lexical_cast<std::string>(nValue) + boost::lexical_cast<std::string>(nTimeSigned);
250  CPubKey pubkey(ParseHex(Params().SporkPubKey()));
251 
252  if(!CMessageSigner::VerifyMessage(pubkey, vchSig, strMessage, strError)) {
253  LogPrintf("CSporkMessage::CheckSignature -- VerifyMessage() failed, error: %s\n", strError);
254  return false;
255  }
256 
257  return true;
258 }
259 
261 {
262  CInv inv(MSG_SPORK, GetHash());
263  connman.RelayInv(inv);
264 }
void ProcessSpork(CNode *pfrom, std::string &strCommand, CDataStream &vRecv, CConnman &connman)
Definition: spork.cpp:20
static const int64_t SPORK_14_REQUIRE_SENTINEL_FLAG_DEFAULT
Definition: spork.h:40
UniValue spork(const UniValue &params, bool fHelp)
Definition: misc.cpp:225
static const int64_t SPORK_9_SUPERBLOCKS_ENABLED_DEFAULT
Definition: spork.h:36
static const int64_t SPORK_5_INSTANTSEND_MAX_VALUE_DEFAULT
Definition: spork.h:34
static const int SPORK_10_MASTERNODE_PAY_UPDATED_NODES
Definition: spork.h:27
std::set< uint256 > setAskFor
Definition: net.h:743
static const int SPORK_3_INSTANTSEND_BLOCK_FILTERING
Definition: spork.h:23
#define strprintf
Definition: tinyformat.h:1011
static const int SPORK_5_INSTANTSEND_MAX_VALUE
Definition: spork.h:24
int nSporkID
Definition: spork.h:56
CCriticalSection cs_main
Definition: validation.cpp:62
std::vector< unsigned char > vchSig
Definition: spork.h:53
static const int SPORK_9_SUPERBLOCKS_ENABLED
Definition: spork.h:26
bool CheckSignature()
Definition: spork.cpp:245
Definition: net.h:108
NodeId id
Definition: net.h:718
void RelayInv(CInv &inv, const int minProtoVersion=MIN_PEER_PROTO_VERSION)
Definition: net.cpp:2528
int GetSporkIDByName(std::string strName)
Definition: spork.cpp:170
std::string GetSporkNameByID(int nSporkID)
Definition: spork.cpp:186
int64_t nTimeSigned
Definition: spork.h:58
int64_t nValue
Definition: spork.h:57
NodeId GetId() const
Definition: net.h:790
bool fLiteMode
Definition: util.cpp:109
static bool GetKeysFromSecret(const std::string strSecret, CKey &keyRet, CPubKey &pubkeyRet)
Set the private/public key values, returns true if successful.
void Misbehaving(NodeId pnode, int howmuch)
#define LogPrintf(...)
Definition: util.h:98
Definition: net.h:661
static int LogPrint(const char *category, const char *format)
Definition: util.h:126
std::map< int, CSporkMessage > mapSporksActive
Definition: spork.h:103
static const int SPORK_13_OLD_SUPERBLOCK_FLAG
Definition: spork.h:29
#define LOCK(cs)
Definition: sync.h:168
std::string strMasterPrivKey
Definition: spork.h:102
uint256 GetHash() const
Definition: spork.h:83
const char * GETSPORKS
Definition: protocol.cpp:42
static const int SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT
Definition: spork.h:25
bool Sign(std::string strSignKey)
Definition: spork.cpp:220
int Height() const
Definition: chain.h:397
vector< unsigned char > ParseHex(const char *psz)
void Relay(CConnman &connman)
Definition: spork.cpp:260
static bool VerifyMessage(const CPubKey pubkey, const std::vector< unsigned char > &vchSig, const std::string strMessage, std::string &strErrorRet)
Verify the message signature, returns true if succcessful.
CChain chainActive
Definition: validation.cpp:65
std::string ToString() const
Definition: uint256.cpp:65
const char * SPORK
Definition: protocol.cpp:41
static const int SPORK_12_RECONSIDER_BLOCKS
Definition: spork.h:28
bool UpdateSpork(int nSporkID, int64_t nValue, CConnman &connman)
Definition: spork.cpp:104
CSporkManager sporkManager
Definition: spork.cpp:14
static const int SPORK_14_REQUIRE_SENTINEL_FLAG
Definition: spork.h:30
static const int64_t SPORK_13_OLD_SUPERBLOCK_FLAG_DEFAULT
Definition: spork.h:39
static const int64_t SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT
Definition: spork.h:35
const CChainParams & Params()
int64_t GetAdjustedTime()
Definition: timedata.cpp:33
static const int64_t SPORK_3_INSTANTSEND_BLOCK_FILTERING_DEFAULT
Definition: spork.h:33
Definition: protocol.h:314
void ExecuteSpork(int nSporkID, int nValue)
Definition: spork.cpp:75
CBlockIndex * Tip() const
Definition: chain.h:366
static const int64_t SPORK_2_INSTANTSEND_ENABLED_DEFAULT
Definition: spork.h:32
bool SetPrivKey(std::string strPrivKey)
Definition: spork.cpp:204
Definition: pubkey.h:37
static bool SignMessage(const std::string strMessage, std::vector< unsigned char > &vchSigRet, const CKey key)
Sign the message, returns true if successful.
bool IsSporkActive(int nSporkID)
Definition: spork.cpp:120
static const int64_t SPORK_12_RECONSIDER_BLOCKS_DEFAULT
Definition: spork.h:38
int64_t GetTime()
For unit testing.
Definition: utiltime.cpp:20
int64_t GetSporkValue(int nSporkID)
Definition: spork.cpp:148
Definition: key.h:35
static const int SPORK_2_INSTANTSEND_ENABLED
Definition: spork.h:22
std::map< uint256, CSporkMessage > mapSporks
Definition: spork.cpp:18
void PushMessage(CNode *pnode, const std::string &sCommand, Args &&... args)
Definition: net.h:199
static const int64_t SPORK_10_MASTERNODE_PAY_UPDATED_NODES_DEFAULT
Definition: spork.h:37
void ReprocessBlocks(int nBlocks)