2014-12-09 02:17:57 +01:00
|
|
|
|
2015-03-13 10:28:20 +01:00
|
|
|
// Copyright (c) 2014-2015 The Dash developers
|
2014-12-09 02:17:57 +01:00
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#ifndef MASTERNODE_H
|
|
|
|
#define MASTERNODE_H
|
|
|
|
|
|
|
|
#include "sync.h"
|
|
|
|
#include "net.h"
|
|
|
|
#include "key.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "base58.h"
|
|
|
|
#include "main.h"
|
2015-04-03 00:51:08 +02:00
|
|
|
#include "timedata.h"
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
#define MASTERNODE_MIN_CONFIRMATIONS 15
|
2015-07-20 19:44:27 +02:00
|
|
|
#define MASTERNODE_MIN_MNP_SECONDS (10*60)
|
2015-06-23 17:40:08 +02:00
|
|
|
#define MASTERNODE_MIN_MNB_SECONDS (5*60)
|
2015-07-20 19:44:27 +02:00
|
|
|
#define MASTERNODE_PING_SECONDS (5*60)
|
2014-12-09 02:17:57 +01:00
|
|
|
#define MASTERNODE_EXPIRATION_SECONDS (65*60)
|
2015-07-04 16:49:49 +02:00
|
|
|
#define MASTERNODE_REMOVAL_SECONDS (75*60)
|
2015-08-08 12:36:30 +02:00
|
|
|
#define MASTERNODE_CHECK_SECONDS 5
|
2014-12-09 02:17:57 +01:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
class CMasternode;
|
2015-04-17 17:10:38 +02:00
|
|
|
class CMasternodeBroadcast;
|
|
|
|
class CMasternodePing;
|
2015-02-05 23:56:59 +01:00
|
|
|
extern map<int64_t, uint256> mapCacheBlockHashes;
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-03-23 13:59:22 +01:00
|
|
|
bool GetBlockHash(uint256& hash, int nBlockHeight);
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-07-14 07:25:07 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// The Masternode Ping Class : Contains a different serialize method for sending pings from masternodes throughout the network
|
|
|
|
//
|
|
|
|
|
|
|
|
class CMasternodePing
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
CTxIn vin;
|
|
|
|
uint256 blockHash;
|
|
|
|
int64_t sigTime; //mnb message times
|
|
|
|
std::vector<unsigned char> vchSig;
|
|
|
|
//removed stop
|
|
|
|
|
|
|
|
CMasternodePing();
|
|
|
|
CMasternodePing(CTxIn& newVin);
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
|
|
|
READWRITE(vin);
|
|
|
|
READWRITE(blockHash);
|
|
|
|
READWRITE(sigTime);
|
|
|
|
READWRITE(vchSig);
|
|
|
|
}
|
|
|
|
|
2015-07-20 19:38:02 +02:00
|
|
|
bool CheckAndUpdate(int& nDos, bool fRequireEnabled = true);
|
2015-07-14 07:25:07 +02:00
|
|
|
bool Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode);
|
|
|
|
void Relay();
|
|
|
|
|
|
|
|
uint256 GetHash(){
|
|
|
|
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
|
|
|
ss << vin;
|
|
|
|
ss << sigTime;
|
|
|
|
return ss.GetHash();
|
|
|
|
}
|
|
|
|
|
|
|
|
void swap(CMasternodePing& first, CMasternodePing& second) // nothrow
|
|
|
|
{
|
|
|
|
// enable ADL (not necessary in our case, but good practice)
|
|
|
|
using std::swap;
|
|
|
|
|
|
|
|
// by swapping the members of two classes,
|
|
|
|
// the two classes are effectively swapped
|
|
|
|
swap(first.vin, second.vin);
|
|
|
|
swap(first.blockHash, second.blockHash);
|
|
|
|
swap(first.sigTime, second.sigTime);
|
|
|
|
swap(first.vchSig, second.vchSig);
|
|
|
|
}
|
|
|
|
|
|
|
|
CMasternodePing& operator=(CMasternodePing from)
|
|
|
|
{
|
|
|
|
swap(*this, from);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
friend bool operator==(const CMasternodePing& a, const CMasternodePing& b)
|
|
|
|
{
|
|
|
|
return a.vin == b.vin && a.blockHash == b.blockHash;
|
|
|
|
}
|
|
|
|
friend bool operator!=(const CMasternodePing& a, const CMasternodePing& b)
|
|
|
|
{
|
|
|
|
return !(a == b);
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2014-12-31 03:54:00 +01:00
|
|
|
//
|
2015-03-05 09:10:15 +01:00
|
|
|
// The Masternode Class. For managing the Darksend process. It contains the input of the 1000DRK, signature to prove
|
2014-12-09 02:17:57 +01:00
|
|
|
// it's the one who own that ip address and code for calculating the payment election.
|
2014-12-31 03:54:00 +01:00
|
|
|
//
|
2015-02-23 21:01:21 +01:00
|
|
|
class CMasternode
|
2014-12-09 02:17:57 +01:00
|
|
|
{
|
2015-02-23 21:01:21 +01:00
|
|
|
private:
|
|
|
|
// critical section to protect the inner data structures
|
|
|
|
mutable CCriticalSection cs;
|
2015-08-08 12:36:30 +02:00
|
|
|
int64_t lastTimeChecked;
|
2014-12-09 02:17:57 +01:00
|
|
|
public:
|
2015-03-24 02:59:12 +01:00
|
|
|
enum state {
|
|
|
|
MASTERNODE_ENABLED = 1,
|
|
|
|
MASTERNODE_EXPIRED = 2,
|
|
|
|
MASTERNODE_VIN_SPENT = 3,
|
|
|
|
MASTERNODE_REMOVE = 4,
|
|
|
|
MASTERNODE_POS_ERROR = 5
|
|
|
|
};
|
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
CTxIn vin;
|
2015-02-23 21:01:21 +01:00
|
|
|
CService addr;
|
2014-12-09 02:17:57 +01:00
|
|
|
CPubKey pubkey;
|
|
|
|
CPubKey pubkey2;
|
|
|
|
std::vector<unsigned char> sig;
|
2015-02-23 21:01:21 +01:00
|
|
|
int activeState;
|
2015-07-14 07:25:07 +02:00
|
|
|
int64_t sigTime; //mnb message time
|
2014-12-09 02:17:57 +01:00
|
|
|
int cacheInputAge;
|
|
|
|
int cacheInputAgeBlock;
|
|
|
|
bool unitTest;
|
|
|
|
bool allowFreeTx;
|
|
|
|
int protocolVersion;
|
2015-03-24 02:52:27 +01:00
|
|
|
int64_t nLastDsq; //the dsq count from the last dsq broadcast of this node
|
|
|
|
int nScanningErrorCount;
|
|
|
|
int nLastScanningErrorBlockHeight;
|
2015-07-14 07:25:07 +02:00
|
|
|
CMasternodePing lastPing;
|
|
|
|
|
2015-08-14 07:08:32 +02:00
|
|
|
int64_t nLastDsee;// temporary, do not save. Remove after migration to v12
|
2015-08-14 03:14:08 +02:00
|
|
|
int64_t nLastDseep;// temporary, do not save. Remove after migration to v12
|
2015-07-14 07:25:07 +02:00
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
CMasternode();
|
|
|
|
CMasternode(const CMasternode& other);
|
2015-07-14 07:25:07 +02:00
|
|
|
CMasternode(const CMasternodeBroadcast& mnb);
|
2015-04-17 17:10:38 +02:00
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
void swap(CMasternode& first, CMasternode& second) // nothrow
|
2014-12-09 02:17:57 +01:00
|
|
|
{
|
2015-02-23 21:01:21 +01:00
|
|
|
// enable ADL (not necessary in our case, but good practice)
|
|
|
|
using std::swap;
|
|
|
|
|
|
|
|
// by swapping the members of two classes,
|
|
|
|
// the two classes are effectively swapped
|
|
|
|
swap(first.vin, second.vin);
|
|
|
|
swap(first.addr, second.addr);
|
|
|
|
swap(first.pubkey, second.pubkey);
|
|
|
|
swap(first.pubkey2, second.pubkey2);
|
|
|
|
swap(first.sig, second.sig);
|
|
|
|
swap(first.activeState, second.activeState);
|
2015-03-01 16:38:53 +01:00
|
|
|
swap(first.sigTime, second.sigTime);
|
2015-07-14 07:25:07 +02:00
|
|
|
swap(first.lastPing, second.lastPing);
|
2015-02-23 21:01:21 +01:00
|
|
|
swap(first.cacheInputAge, second.cacheInputAge);
|
|
|
|
swap(first.cacheInputAgeBlock, second.cacheInputAgeBlock);
|
2015-03-24 02:52:27 +01:00
|
|
|
swap(first.unitTest, second.unitTest);
|
2015-02-23 21:01:21 +01:00
|
|
|
swap(first.allowFreeTx, second.allowFreeTx);
|
|
|
|
swap(first.protocolVersion, second.protocolVersion);
|
|
|
|
swap(first.nLastDsq, second.nLastDsq);
|
2015-03-24 02:52:27 +01:00
|
|
|
swap(first.nScanningErrorCount, second.nScanningErrorCount);
|
|
|
|
swap(first.nLastScanningErrorBlockHeight, second.nLastScanningErrorBlockHeight);
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
CMasternode& operator=(CMasternode from)
|
|
|
|
{
|
|
|
|
swap(*this, from);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
friend bool operator==(const CMasternode& a, const CMasternode& b)
|
|
|
|
{
|
|
|
|
return a.vin == b.vin;
|
|
|
|
}
|
|
|
|
friend bool operator!=(const CMasternode& a, const CMasternode& b)
|
|
|
|
{
|
|
|
|
return !(a.vin == b.vin);
|
2014-12-09 02:17:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
uint256 CalculateScore(int mod=1, int64_t nBlockHeight=0);
|
|
|
|
|
2015-04-03 00:51:08 +02:00
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
|
|
|
LOCK(cs);
|
2015-04-17 17:10:38 +02:00
|
|
|
|
2015-04-03 00:51:08 +02:00
|
|
|
READWRITE(vin);
|
|
|
|
READWRITE(addr);
|
|
|
|
READWRITE(pubkey);
|
|
|
|
READWRITE(pubkey2);
|
|
|
|
READWRITE(sig);
|
|
|
|
READWRITE(sigTime);
|
2015-04-17 17:10:38 +02:00
|
|
|
READWRITE(protocolVersion);
|
|
|
|
READWRITE(activeState);
|
2015-07-14 07:25:07 +02:00
|
|
|
READWRITE(lastPing);
|
2015-04-03 00:51:08 +02:00
|
|
|
READWRITE(cacheInputAge);
|
|
|
|
READWRITE(cacheInputAgeBlock);
|
|
|
|
READWRITE(unitTest);
|
|
|
|
READWRITE(allowFreeTx);
|
|
|
|
READWRITE(nLastDsq);
|
|
|
|
READWRITE(nScanningErrorCount);
|
|
|
|
READWRITE(nLastScanningErrorBlockHeight);
|
2015-04-16 16:08:06 +02:00
|
|
|
}
|
|
|
|
|
2015-06-17 22:00:02 +02:00
|
|
|
int64_t SecondsSincePayment();
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-08-12 03:39:22 +02:00
|
|
|
bool UpdateFromNewBroadcast(CMasternodeBroadcast& mnb);
|
2015-04-17 17:10:38 +02:00
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
inline uint64_t SliceHash(uint256& hash, int slice)
|
|
|
|
{
|
|
|
|
uint64_t n = 0;
|
|
|
|
memcpy(&n, &hash+slice*64, 64);
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
2015-08-08 12:36:30 +02:00
|
|
|
void Check(bool forceCheck = false);
|
2014-12-09 02:17:57 +01:00
|
|
|
|
2015-07-14 07:25:07 +02:00
|
|
|
bool IsBroadcastedWithin(int seconds)
|
2014-12-09 02:17:57 +01:00
|
|
|
{
|
2015-07-14 07:25:07 +02:00
|
|
|
return (GetAdjustedTime() - sigTime) < seconds;
|
|
|
|
}
|
2014-12-31 03:54:00 +01:00
|
|
|
|
2015-07-14 07:25:07 +02:00
|
|
|
bool IsPingedWithin(int seconds, int64_t now = -1)
|
|
|
|
{
|
|
|
|
now == -1 ? now = GetAdjustedTime() : now;
|
2015-07-19 17:49:46 +02:00
|
|
|
|
2015-07-14 07:25:07 +02:00
|
|
|
return (lastPing == CMasternodePing())
|
|
|
|
? false
|
|
|
|
: now - lastPing.sigTime < seconds;
|
2014-12-09 02:17:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void Disable()
|
|
|
|
{
|
2015-07-14 07:25:07 +02:00
|
|
|
sigTime = 0;
|
|
|
|
lastPing = CMasternodePing();
|
2014-12-09 02:17:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool IsEnabled()
|
|
|
|
{
|
2015-02-23 21:01:21 +01:00
|
|
|
return activeState == MASTERNODE_ENABLED;
|
2014-12-09 02:17:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int GetMasternodeInputAge()
|
|
|
|
{
|
|
|
|
if(chainActive.Tip() == NULL) return 0;
|
|
|
|
|
|
|
|
if(cacheInputAge == 0){
|
|
|
|
cacheInputAge = GetInputAge(vin);
|
|
|
|
cacheInputAgeBlock = chainActive.Tip()->nHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
return cacheInputAge+(chainActive.Tip()->nHeight-cacheInputAgeBlock);
|
|
|
|
}
|
2015-03-13 10:28:20 +01:00
|
|
|
|
2015-03-31 03:14:44 +02:00
|
|
|
std::string Status() {
|
|
|
|
std::string strStatus = "ACTIVE";
|
|
|
|
|
|
|
|
if(activeState == CMasternode::MASTERNODE_ENABLED) strStatus = "ENABLED";
|
|
|
|
if(activeState == CMasternode::MASTERNODE_EXPIRED) strStatus = "EXPIRED";
|
|
|
|
if(activeState == CMasternode::MASTERNODE_VIN_SPENT) strStatus = "VIN_SPENT";
|
|
|
|
if(activeState == CMasternode::MASTERNODE_REMOVE) strStatus = "REMOVE";
|
|
|
|
if(activeState == CMasternode::MASTERNODE_POS_ERROR) strStatus = "POS_ERROR";
|
|
|
|
|
|
|
|
return strStatus;
|
|
|
|
}
|
|
|
|
|
2015-06-23 18:38:28 +02:00
|
|
|
int64_t GetLastPaid();
|
|
|
|
|
2014-12-09 02:17:57 +01:00
|
|
|
};
|
|
|
|
|
2015-04-17 17:10:38 +02:00
|
|
|
|
|
|
|
//
|
|
|
|
// The Masternode Broadcast Class : Contains a different serialize method for sending masternodes through the network
|
|
|
|
//
|
|
|
|
|
|
|
|
class CMasternodeBroadcast : public CMasternode
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CMasternodeBroadcast();
|
2015-06-23 18:38:28 +02:00
|
|
|
CMasternodeBroadcast(CService newAddr, CTxIn newVin, CPubKey newPubkey, CPubKey newPubkey2, int protocolVersionIn);
|
2015-07-14 07:25:07 +02:00
|
|
|
CMasternodeBroadcast(const CMasternode& mn);
|
2015-04-17 17:10:38 +02:00
|
|
|
|
2015-07-14 07:25:07 +02:00
|
|
|
bool CheckAndUpdate(int& nDoS);
|
|
|
|
bool CheckInputsAndAdd(int& nDos);
|
2015-04-17 17:10:38 +02:00
|
|
|
bool Sign(CKey& keyCollateralAddress);
|
2015-07-14 07:25:07 +02:00
|
|
|
void Relay();
|
2015-04-17 17:10:38 +02:00
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) {
|
|
|
|
READWRITE(vin);
|
|
|
|
READWRITE(addr);
|
|
|
|
READWRITE(pubkey);
|
|
|
|
READWRITE(pubkey2);
|
|
|
|
READWRITE(sig);
|
|
|
|
READWRITE(sigTime);
|
|
|
|
READWRITE(protocolVersion);
|
2015-07-14 07:25:07 +02:00
|
|
|
READWRITE(lastPing);
|
2015-08-12 00:43:05 +02:00
|
|
|
READWRITE(nLastDsq);
|
2015-04-17 17:10:38 +02:00
|
|
|
}
|
2015-06-24 01:44:31 +02:00
|
|
|
|
2015-04-22 16:33:44 +02:00
|
|
|
uint256 GetHash(){
|
2015-06-09 15:22:31 +02:00
|
|
|
CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION);
|
|
|
|
ss << sigTime;
|
|
|
|
ss << pubkey;
|
|
|
|
return ss.GetHash();
|
2015-04-22 16:33:44 +02:00
|
|
|
}
|
2015-04-17 17:10:38 +02:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2015-06-09 03:36:33 +02:00
|
|
|
#endif
|