2016-12-20 14:26:45 +01:00
|
|
|
// Copyright (c) 2014-2017 The Dash Core developers
|
2015-02-09 21:54:51 +01:00
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2016-07-30 13:04:27 +02:00
|
|
|
|
2015-02-09 21:54:51 +01:00
|
|
|
#ifndef SPORK_H
|
|
|
|
#define SPORK_H
|
|
|
|
|
2016-02-02 16:28:56 +01:00
|
|
|
#include "hash.h"
|
2016-07-30 13:04:27 +02:00
|
|
|
#include "net.h"
|
2016-02-02 16:28:56 +01:00
|
|
|
#include "utilstrencodings.h"
|
2018-03-02 14:15:04 +01:00
|
|
|
#include "key.h"
|
2015-04-03 00:51:08 +02:00
|
|
|
|
2016-08-29 21:16:02 +02:00
|
|
|
class CSporkMessage;
|
|
|
|
class CSporkManager;
|
|
|
|
|
2015-05-30 19:27:51 +02:00
|
|
|
/*
|
|
|
|
Don't ever reuse these IDs for other sporks
|
|
|
|
- This would result in old clients getting confused about which spork is for what
|
|
|
|
*/
|
2016-09-01 16:55:25 +02:00
|
|
|
static const int SPORK_2_INSTANTSEND_ENABLED = 10001;
|
|
|
|
static const int SPORK_3_INSTANTSEND_BLOCK_FILTERING = 10002;
|
|
|
|
static const int SPORK_5_INSTANTSEND_MAX_VALUE = 10004;
|
2018-02-15 15:44:22 +01:00
|
|
|
static const int SPORK_6_NEW_SIGS = 10005;
|
2016-08-29 21:16:02 +02:00
|
|
|
static const int SPORK_9_SUPERBLOCKS_ENABLED = 10008;
|
|
|
|
static const int SPORK_12_RECONSIDER_BLOCKS = 10011;
|
2018-09-26 16:17:47 +02:00
|
|
|
static const int SPORK_16_INSTANTSEND_AUTOLOCKS = 10015;
|
2018-11-26 16:53:20 +01:00
|
|
|
static const int SPORK_17_QUORUM_DKG_ENABLED = 10016;
|
2016-08-29 21:16:02 +02:00
|
|
|
|
2018-04-20 12:53:23 +02:00
|
|
|
static const int SPORK_START = SPORK_2_INSTANTSEND_ENABLED;
|
2018-11-26 16:53:20 +01:00
|
|
|
static const int SPORK_END = SPORK_17_QUORUM_DKG_ENABLED;
|
2018-04-20 12:53:23 +02:00
|
|
|
|
2018-04-18 13:50:26 +02:00
|
|
|
extern std::map<int, int64_t> mapSporkDefaults;
|
2015-02-09 21:54:51 +01:00
|
|
|
extern CSporkManager sporkManager;
|
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* Sporks are network parameters used primarily to prevent forking and turn
|
|
|
|
* on/off certain features. They are a soft consensus mechanism.
|
|
|
|
*
|
|
|
|
* We use 2 main classes to manage the spork system.
|
|
|
|
*
|
|
|
|
* SporkMessages - low-level constructs which contain the sporkID, value,
|
|
|
|
* signature and a signature timestamp
|
|
|
|
* SporkManager - a higher-level construct which manages the naming, use of
|
|
|
|
* sporks, signatures and verification, and which sporks are active according
|
|
|
|
* to this node
|
|
|
|
*/
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* CSporkMessage is a low-level class used to encapsulate Spork messages and
|
|
|
|
* serialize them for transmission to other peers. This includes the internal
|
|
|
|
* spork ID, value, spork signature and timestamp for the signature.
|
|
|
|
*/
|
2015-02-09 21:54:51 +01:00
|
|
|
class CSporkMessage
|
|
|
|
{
|
2016-07-30 13:04:27 +02:00
|
|
|
private:
|
2015-02-09 21:54:51 +01:00
|
|
|
std::vector<unsigned char> vchSig;
|
2016-07-30 13:04:27 +02:00
|
|
|
|
|
|
|
public:
|
2015-02-09 21:54:51 +01:00
|
|
|
int nSporkID;
|
2015-02-11 15:47:21 +01:00
|
|
|
int64_t nValue;
|
2015-02-09 21:54:51 +01:00
|
|
|
int64_t nTimeSigned;
|
|
|
|
|
2016-08-29 21:16:02 +02:00
|
|
|
CSporkMessage(int nSporkID, int64_t nValue, int64_t nTimeSigned) :
|
|
|
|
nSporkID(nSporkID),
|
|
|
|
nValue(nValue),
|
|
|
|
nTimeSigned(nTimeSigned)
|
|
|
|
{}
|
2016-07-30 13:04:27 +02:00
|
|
|
|
2016-08-29 21:16:02 +02:00
|
|
|
CSporkMessage() :
|
|
|
|
nSporkID(0),
|
|
|
|
nValue(0),
|
|
|
|
nTimeSigned(0)
|
|
|
|
{}
|
2016-08-15 16:46:46 +02:00
|
|
|
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2015-04-03 00:51:08 +02:00
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
2017-09-19 21:36:55 +02:00
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
2015-02-09 21:54:51 +01:00
|
|
|
READWRITE(nSporkID);
|
2015-02-11 15:47:21 +01:00
|
|
|
READWRITE(nValue);
|
2015-02-09 21:54:51 +01:00
|
|
|
READWRITE(nTimeSigned);
|
2018-09-30 19:01:33 +02:00
|
|
|
READWRITE(vchSig);
|
2015-04-03 00:51:08 +02:00
|
|
|
}
|
2016-08-29 21:16:02 +02:00
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* GetHash returns the double-sha256 hash of the serialized spork message.
|
|
|
|
*/
|
2018-02-16 15:54:53 +01:00
|
|
|
uint256 GetHash() const;
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* GetSignatureHash returns the hash of the serialized spork message
|
|
|
|
* without the signature included. The intent of this method is to get the
|
|
|
|
* hash to be signed.
|
|
|
|
*/
|
2018-02-16 15:54:53 +01:00
|
|
|
uint256 GetSignatureHash() const;
|
2016-08-29 21:16:02 +02:00
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* Sign will sign the spork message with the given key.
|
|
|
|
*/
|
2018-08-22 16:46:27 +02:00
|
|
|
bool Sign(const CKey& key, bool fSporkSixActive);
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* CheckSignature will ensure the spork signature matches the provided public
|
|
|
|
* key hash.
|
|
|
|
*/
|
2018-08-22 16:46:27 +02:00
|
|
|
bool CheckSignature(const CKeyID& pubKeyId, bool fSporkSixActive) const;
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* GetSignerKeyID is used to recover the spork address of the key used to
|
|
|
|
* sign this spork message.
|
|
|
|
*
|
|
|
|
* This method was introduced along with the multi-signer sporks feature,
|
|
|
|
* in order to identify which spork key signed this message.
|
|
|
|
*/
|
2018-09-30 19:01:33 +02:00
|
|
|
bool GetSignerKeyID(CKeyID& retKeyidSporkSigner, bool fSporkSixActive);
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Relay is used to send this spork message to other peers.
|
|
|
|
*/
|
2017-09-07 17:58:38 +02:00
|
|
|
void Relay(CConnman& connman);
|
2015-02-09 21:54:51 +01:00
|
|
|
};
|
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* CSporkManager is a higher-level class which manages the node's spork
|
|
|
|
* messages, rules for which sporks should be considered active/inactive, and
|
|
|
|
* processing for certain sporks (e.g. spork 12).
|
|
|
|
*/
|
2015-02-09 21:54:51 +01:00
|
|
|
class CSporkManager
|
|
|
|
{
|
|
|
|
private:
|
2018-09-26 16:15:02 +02:00
|
|
|
static const std::string SERIALIZATION_VERSION_STRING;
|
|
|
|
|
2018-08-13 22:21:21 +02:00
|
|
|
mutable CCriticalSection cs;
|
|
|
|
std::map<uint256, CSporkMessage> mapSporksByHash;
|
2018-09-30 19:01:33 +02:00
|
|
|
std::map<int, std::map<CKeyID, CSporkMessage> > mapSporksActive;
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2018-09-30 19:01:33 +02:00
|
|
|
std::set<CKeyID> setSporkPubKeyIDs;
|
|
|
|
int nMinSporkKeys;
|
2018-03-02 14:15:04 +01:00
|
|
|
CKey sporkPrivKey;
|
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* SporkValueIsActive is used to get the value agreed upon by the majority
|
|
|
|
* of signed spork messages for a given Spork ID.
|
|
|
|
*/
|
2018-09-30 19:01:33 +02:00
|
|
|
bool SporkValueIsActive(int nSporkID, int64_t& nActiveValueRet) const;
|
2018-10-02 11:02:27 +02:00
|
|
|
|
2015-02-09 21:54:51 +01:00
|
|
|
public:
|
|
|
|
|
2016-07-30 13:04:27 +02:00
|
|
|
CSporkManager() {}
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2018-08-13 22:21:21 +02:00
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
2018-09-26 16:15:02 +02:00
|
|
|
std::string strVersion;
|
|
|
|
if(ser_action.ForRead()) {
|
|
|
|
READWRITE(strVersion);
|
|
|
|
if (strVersion != SERIALIZATION_VERSION_STRING) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
strVersion = SERIALIZATION_VERSION_STRING;
|
|
|
|
READWRITE(strVersion);
|
|
|
|
}
|
2018-09-30 19:01:33 +02:00
|
|
|
// we don't serialize pubkey ids because pubkeys should be
|
|
|
|
// hardcoded or be setted with cmdline or options, should
|
|
|
|
// not reuse pubkeys from previous dashd run
|
2018-08-13 22:21:21 +02:00
|
|
|
READWRITE(mapSporksByHash);
|
|
|
|
READWRITE(mapSporksActive);
|
|
|
|
// we don't serialize private key to prevent its leakage
|
|
|
|
}
|
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* Clear is used to clear all in-memory active spork messages. Since spork
|
|
|
|
* public and private keys are set in init.cpp, we do not clear them here.
|
|
|
|
*
|
|
|
|
* This method was introduced along with the spork cache.
|
|
|
|
*/
|
2018-08-13 22:21:21 +02:00
|
|
|
void Clear();
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* CheckAndRemove is defined to fulfill an interface as part of the on-disk
|
|
|
|
* cache used to cache sporks between runs. If sporks that are restored
|
|
|
|
* from cache do not have valid signatures when compared against the
|
|
|
|
* current spork private keys, they are removed from in-memory storage.
|
|
|
|
*
|
|
|
|
* This method was introduced along with the spork cache.
|
|
|
|
*/
|
2018-09-26 16:15:02 +02:00
|
|
|
void CheckAndRemove();
|
2018-08-13 22:21:21 +02:00
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* ProcessSpork is used to handle the 'getsporks' and 'spork' p2p messages.
|
|
|
|
*
|
|
|
|
* For 'getsporks', it sends active sporks to the requesting peer. For 'spork',
|
|
|
|
* it validates the spork and adds it to the internal spork storage and
|
|
|
|
* performs any necessary processing.
|
|
|
|
*/
|
2017-02-06 14:31:37 +01:00
|
|
|
void ProcessSpork(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* ExecuteSpork is used to perform certain actions based on the spork value.
|
|
|
|
*
|
|
|
|
* Currently only used with Spork 12.
|
|
|
|
*/
|
2016-07-30 13:04:27 +02:00
|
|
|
void ExecuteSpork(int nSporkID, int nValue);
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* UpdateSpork is used by the spork RPC command to set a new spork value, sign
|
|
|
|
* and broadcast the spork message.
|
|
|
|
*/
|
2017-09-07 17:58:38 +02:00
|
|
|
bool UpdateSpork(int nSporkID, int64_t nValue, CConnman& connman);
|
2015-02-09 21:54:51 +01:00
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* IsSporkActive returns a bool for time-based sporks, and should be used
|
|
|
|
* to determine whether the spork can be considered active or not.
|
|
|
|
*
|
|
|
|
* For value-based sporks such as SPORK_5_INSTANTSEND_MAX_VALUE, the spork
|
|
|
|
* value should not be considered a timestamp, but an integer value
|
|
|
|
* instead, and therefore this method doesn't make sense and should not be
|
|
|
|
* used.
|
|
|
|
*/
|
2016-07-30 13:04:27 +02:00
|
|
|
bool IsSporkActive(int nSporkID);
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* GetSporkValue returns the spork value given a Spork ID. If no active spork
|
|
|
|
* message has yet been received by the node, it returns the default value.
|
|
|
|
*/
|
2016-07-30 13:04:27 +02:00
|
|
|
int64_t GetSporkValue(int nSporkID);
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* GetSporkIDByName returns the internal Spork ID given the spork name.
|
|
|
|
*/
|
2018-02-12 13:49:00 +01:00
|
|
|
int GetSporkIDByName(const std::string& strName);
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* GetSporkNameByID returns the spork name as a string, given a Spork ID.
|
|
|
|
*/
|
2016-07-30 13:04:27 +02:00
|
|
|
std::string GetSporkNameByID(int nSporkID);
|
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* GetSporkByHash returns a spork message given a hash of the spork message.
|
|
|
|
*
|
|
|
|
* This is used when a requesting peer sends a MSG_SPORK inventory message with
|
|
|
|
* the hash, to quickly lookup and return the full spork message. We maintain a
|
|
|
|
* hash-based index of sporks for this reason, and this function is the access
|
|
|
|
* point into that index.
|
|
|
|
*/
|
2018-08-13 22:21:21 +02:00
|
|
|
bool GetSporkByHash(const uint256& hash, CSporkMessage &sporkRet);
|
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* SetSporkAddress is used to set a public key ID which will be used to
|
|
|
|
* verify spork signatures.
|
|
|
|
*
|
|
|
|
* This can be called multiple times to add multiple keys to the set of
|
|
|
|
* valid spork signers.
|
|
|
|
*/
|
2018-03-02 14:15:04 +01:00
|
|
|
bool SetSporkAddress(const std::string& strAddress);
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* SetMinSporkKeys is used to set the required spork signer threshold, for
|
|
|
|
* a spork to be considered active.
|
|
|
|
*
|
|
|
|
* This value must be at least a majority of the total number of spork
|
|
|
|
* keys, and for obvious resons cannot be larger than that number.
|
|
|
|
*/
|
2018-09-30 19:01:33 +02:00
|
|
|
bool SetMinSporkKeys(int minSporkKeys);
|
2018-10-02 11:02:27 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* SetPrivKey is used to set a spork key to enable setting / signing of
|
|
|
|
* spork values.
|
|
|
|
*
|
|
|
|
* This will return false if the private key does not match any spork
|
|
|
|
* address in the set of valid spork signers (see SetSporkAddress).
|
|
|
|
*/
|
2018-02-12 13:49:00 +01:00
|
|
|
bool SetPrivKey(const std::string& strPrivKey);
|
2018-08-13 22:21:21 +02:00
|
|
|
|
2018-10-02 11:02:27 +02:00
|
|
|
/**
|
|
|
|
* ToString returns the string representation of the SporkManager.
|
|
|
|
*/
|
2018-08-13 22:21:21 +02:00
|
|
|
std::string ToString() const;
|
2015-02-09 21:54:51 +01:00
|
|
|
};
|
|
|
|
|
2015-04-03 00:51:08 +02:00
|
|
|
#endif
|