22 #include <boost/thread/thread.hpp>
24 #define MN_WINNER_MINIMUM_AGE 8000
34 const std::pair<int64_t, T>& t2)
const
36 return t1.first < t2.first;
44 static const int MASTERNODE_DB_VERSION_BIP155 = 2;
55 const auto& params =
Params();
60 ssMasternodes << MASTERNODE_DB_VERSION_BIP155;
62 ssMasternodes << params.MessageStart();
63 ssMasternodes << mnodemanToSave;
65 ssMasternodes << hash;
71 return error(
"%s : Failed to open file %s", __func__,
pathMN.string());
75 fileout << ssMasternodes;
76 }
catch (
const std::exception& e) {
77 return error(
"%s : Serialize or I/O error - %s", __func__, e.what());
95 error(
"%s : Failed to open file %s", __func__,
pathMN.string());
100 int fileSize = fs::file_size(
pathMN);
101 int dataSize = fileSize -
sizeof(
uint256);
105 std::vector<unsigned char> vchData;
106 vchData.resize(dataSize);
111 filein.
read((
char*)vchData.data(), dataSize);
113 }
catch (
const std::exception& e) {
114 error(
"%s : Deserialize or I/O error - %s", __func__, e.what());
119 const auto& params =
Params();
125 if (hashIn != hashTmp) {
126 error(
"%s : Checksum mismatch, data corrupted", __func__);
131 std::string strMagicMessageTmp;
134 ssMasternodes >> version;
135 ssMasternodes >> strMagicMessageTmp;
139 error(
"%s : Invalid masternode cache magic message", __func__);
144 std::vector<unsigned char> pchMsgTmp(4);
145 ssMasternodes >>
MakeSpan(pchMsgTmp);
148 if (memcmp(pchMsgTmp.data(), params.MessageStart(), pchMsgTmp.size()) != 0) {
149 error(
"%s : Invalid network magic number", __func__);
153 if (version == MASTERNODE_DB_VERSION_BIP155) {
158 ssMasternodes >> mnodemanToLoad;
160 }
catch (
const std::exception& e) {
161 mnodemanToLoad.
Clear();
162 error(
"%s : Deserialize or I/O error - %s", __func__, e.what());
226 int64_t t = (*i).second;
253 auto activeState = mn->GetActiveState();
264 if (it3->second.vin.prevout == it->first) {
275 if (it2->first == it->first) {
285 if (itPing->second.GetVin().prevout == it->first) {
303 if ((*it1).second <
GetTime()) {
313 if ((*it1).second <
GetTime()) {
323 if ((*it2).second <
GetTime()) {
366 static void CountNetwork(
const CService& addr,
int& ipv4,
int& ipv6,
int& onion)
401 if (mn->protocolVersion < nMinProtocol || !mn->IsEnabled()) {
418 CountNetwork(dmn->pdmnState->addr, info.
ipv4, info.
ipv6, info.
onion);
419 if (!dmn->IsPoSeBanned()) {
431 int count_enabled = 0;
438 if (mn->protocolVersion < protocolVersion || !mn->IsEnabled())
continue;
447 return count_enabled;
462 if (
GetTime() < (*it).second) {
496 if (mn->pubKeyMasternode == pubKeyMasternode)
510 for (
const auto& tx : vtx) {
511 for (
const auto& in : tx->vin) {
514 it->second->SetSpent();
520 static bool canScheduleMN(
bool fFilterSigTime,
const MasternodeRef& mn,
int minProtocol,
521 int nMnCount,
int nBlockHeight)
524 if (mn->protocolVersion < minProtocol)
return false;
530 if (fFilterSigTime && mn->sigTime + (nMnCount * 2.6 * 60) >
GetAdjustedTime())
return false;
533 if (
pcoinsTip->GetCoinDepthAtHeight(mn->vin.prevout, nBlockHeight) < nMnCount)
return false;
545 LogPrintf(
"%s: ERROR - called after legacy system disabled\n", __func__);
551 if (!BlockReading)
return nullptr;
554 std::vector<std::pair<int64_t, MasternodeRef> > vecMasternodeLastPaid;
564 if (!it.second->IsEnabled())
continue;
565 if (canScheduleMN(fFilterSigTime, it.second, minProtocol, count_enabled, nBlockHeight)) {
566 vecMasternodeLastPaid.emplace_back(
SecondsSincePayment(it.second, count_enabled, BlockReading), it.second);
575 if (canScheduleMN(fFilterSigTime, mn, minProtocol, count_enabled, nBlockHeight)) {
576 vecMasternodeLastPaid.emplace_back(
SecondsSincePayment(mn, count_enabled, BlockReading), mn);
581 nCount = (int)vecMasternodeLastPaid.size();
587 sort(vecMasternodeLastPaid.rbegin(), vecMasternodeLastPaid.rend(),
CompareScoreMN());
593 int nTenthNetwork = count_enabled / 10;
597 for (
const auto& s: vecMasternodeLastPaid) {
604 pBestMasternode = pmn;
607 if (nCountTenth >= nTenthNetwork)
break;
609 return pBestMasternode;
621 if (mn->protocolVersion < minProtocol || !mn->IsEnabled())
continue;
623 const int64_t n = mn->CalculateScore(hash).GetCompact(
false);
637 const int64_t n = mn->CalculateScore(hash).GetCompact(
false);
651 std::vector<std::pair<MasternodeRef, int>> ret;
653 if (nChainHeight < 0)
return ret;
655 for (
int nHeight = nChainHeight - nLast; nHeight < nChainHeight + 20; nHeight++) {
659 ret.emplace_back(winner, nHeight);
673 std::vector<std::pair<int64_t, CTxIn> > vecMasternodeScores;
678 if (!mn->IsEnabled()) {
681 if (mn->protocolVersion < minProtocol) {
689 vecMasternodeScores.emplace_back(mn->CalculateScore(hash).GetCompact(
false), mn->vin);
698 vecMasternodeScores.emplace_back(mn->CalculateScore(hash).GetCompact(
false), mn->vin);
702 sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(),
CompareScoreMN());
705 for (std::pair<int64_t, CTxIn> & s : vecMasternodeScores) {
707 if (s.second.prevout == vin.
prevout) {
717 std::vector<std::pair<int64_t, MasternodeRef>> vecMasternodeScores;
726 const uint32_t score = mn->IsEnabled() ? mn->CalculateScore(hash).GetCompact(
false) : 9999;
728 vecMasternodeScores.emplace_back(score, mn);
736 const uint32_t score = dmn->IsPoSeBanned() ? 9999 : mn->CalculateScore(hash).GetCompact(
false);
738 vecMasternodeScores.emplace_back(score, mn);
741 sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(),
CompareScoreMN());
742 return vecMasternodeScores;
755 if (pmn !=
nullptr) {
764 if (collateralUtxo.
IsSpent()) {
770 if (collateralUtxo.
out.
nValue != consensus.nMNCollateralAmt) {
785 const int utxoHeight = (int) collateralUtxo.
nHeight;
786 int collateralUtxoDepth = nChainHeight - utxoHeight + 1;
787 if (collateralUtxoDepth < consensus.MasternodeCollateralMinConf()) {
788 LogPrint(
BCLog::MASTERNODE,
"mnb - Input must have at least %d confirmations\n", consensus.MasternodeCollateralMinConf());
875 if (pmn !=
nullptr)
return 0;
916 int64_t t = (*itAskedUsMNList).second;
918 LogPrintf(
"CMasternodeMan::ProcessMessage() : dseg - peer already asked me for the list\n");
931 if (mn->addr.IsRFC1918())
continue;
932 if (mn->IsEnabled()) {
950 return dosScore == 0;
1038 if (pmn ==
nullptr) {
1049 int64_t month = 60 * 60 * 24 * 30;
1050 if (sec < month)
return sec;
1063 if (BlockReading ==
nullptr)
return false;
1065 const CScript& mnpayee = mn->GetPayeeScript();
1075 int max_depth = count_enabled * 1.25;
1076 for (
int n = 0; n < max_depth; n++) {
1081 if (it->second.HasPayeeWithVotes(mnpayee, 2))
1082 return BlockReading->
nTime + nOffset;
1084 BlockReading = BlockReading->
pprev;
1086 if (BlockReading ==
nullptr || BlockReading->
nHeight <= 0) {
1096 std::ostringstream info;
1122 if (nHeight > nCurrentHeight) {
1124 __func__, nHeight, nCurrentHeight);
1128 if (nHeight > nCurrentHeight - (
int) CACHED_BLOCK_HASHES) {
1142 return error(
"%s: Called with null hash\n", __func__);
1144 if (depth < 0 || (
unsigned) depth >= CACHED_BLOCK_HASHES) {
1145 return error(
"%s: Invalid depth %d. Cached block hashes: %d\n", __func__, depth, CACHED_BLOCK_HASHES);
1149 int nStopHeight = std::max(0, nCurrentHeight - depth);
1150 for (
int i = nCurrentHeight; i >= nStopHeight; i--) {
1161 LogPrintf(
"Masternodes thread started\n");
1173 if (!itSeenMNB->second.addr.IsValid()) {
1187 boost::this_thread::interruption_point();
1205 }
catch (boost::thread_interrupted&) {
arith_uint256 UintToArith256(const uint256 &a)
const arith_uint256 ARITH_UINT256_ZERO
const CChainParams & Params()
Return the currently selected parameters.
bool EnableHotColdMasterNode(CTxIn &vin, CService &addr)
Enable cold wallet mode (run a Masternode with no funds)
void ManageStatus()
Manage status of main Masternode.
A CService with information about it as peer.
Non-refcounted RAII wrapper for FILE*.
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
void read(char *pch, size_t nSize)
static const std::string MAIN
Chain name strings.
const_iterator end() const
const_iterator begin() const
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
uint256 GetBlockHash() const
int64_t GetBlockTime() const
int nHeight
height of the entry in the chain. The genesis block has height 0
const Consensus::Params & GetConsensus() const
bool IsRegTestNet() const
void ForEachMN(bool onlyValid, Callback &&cb) const
A writer stream (for serialization) that computes a 256-bit hash.
bool CheckAndUpdate(int &nDoS)
Access to the MN database (mncache.dat)
bool Write(const CMasternodeMan &mnodemanToSave)
ReadResult Read(CMasternodeMan &mnodemanToLoad)
std::string strMagicMessage
bool IsAvailableState() const
bool UpdateFromNewBroadcast(CMasternodeBroadcast &mnb)
CPubKey pubKeyCollateralAddress
std::map< uint256, CMasternodeBroadcast > mapSeenMasternodeBroadcast
std::map< CNetAddr, int64_t > mAskedUsForMasternodeList
void UpdateMasternodeList(CMasternodeBroadcast &mnb)
Update masternode list and maps using provided CMasternodeBroadcast.
std::map< CNetAddr, int64_t > mWeAskedForMasternodeList
int CheckAndRemove(bool forceExpiredRemoval=false)
Check all Masternodes and remove inactive. Return the total masternode count.
int CountEnabled(bool only_legacy=false) const
bool CheckInputs(CMasternodeBroadcast &mnb, int nChainHeight, int &nDoS)
void CheckSpentCollaterals(const std::vector< CTransactionRef > &vtx)
Check all transactions in a block, for spent masternode collateral outpoints (marking them as spent)
int ProcessGetMNList(CNode *pfrom, CTxIn &vin)
RecursiveMutex cs_process_message
std::vector< std::pair< int64_t, MasternodeRef > > GetMasternodeRanks(int nBlockHeight) const
std::vector< std::pair< MasternodeRef, int > > GetMnScores(int nLast) const
vector of pairs <masternode winner, height>
void AskForMN(CNode *pnode, const CTxIn &vin)
Ask (source) node for mnb.
void CacheBlockHash(const CBlockIndex *pindex)
uint256 GetHashAtHeight(int nHeight) const
std::map< COutPoint, MasternodeRef > mapMasternodes
MasternodeRef GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int &nCount, const CBlockIndex *pChainTip=nullptr) const
Find an entry in the masternode list that is next to be paid.
bool RequestMnList(CNode *pnode)
int ProcessMNPing(CNode *pfrom, CMasternodePing &mnp)
int GetBestHeight() const
int64_t GetLastPaid(const MasternodeRef &mn, int count_enabled, const CBlockIndex *BlockReading) const
Get the time a masternode was last paid.
CMasternodeMan::MNsInfo getMNsInfo() const
std::string ToString() const
int GetMasternodeRank(const CTxIn &vin, int64_t nBlockHeight) const
bool ProcessMessage(CNode *pfrom, std::string &strCommand, CDataStream &vRecv, int &dosScore)
void Remove(const COutPoint &collateralOut)
bool Add(CMasternode &mn)
Add an entry.
int64_t SecondsSincePayment(const MasternodeRef &mn, int count_enabled, const CBlockIndex *BlockReading) const
CyclingVector< uint256 > cvLastBlockHashes
std::map< COutPoint, int64_t > mWeAskedForMasternodeListEntry
void Clear()
Clear Masternode vector.
int ProcessMNBroadcast(CNode *pfrom, CMasternodeBroadcast &mnb)
bool IsWithinDepth(const uint256 &nHash, int depth) const
std::map< uint256, CMasternodePing > mapSeenMasternodePing
CMasternode * Find(const COutPoint &collateralOut)
Find an entry.
void BroadcastInvMN(CMasternode *mn, CNode *pfrom)
MasternodeRef GetCurrentMasterNode(const uint256 &hash) const
Get the winner for this block hash.
int ProcessMessageInner(CNode *pfrom, std::string &strCommand, CDataStream &vRecv)
void UncacheBlockHash(const CBlockIndex *pindex)
void CleanPaymentList(int mnCount, int nHeight)
std::map< int, CMasternodeBlockPayees > mapMasternodeBlocks
bool IsScheduled(const CMasternode &mn, int nNotBlockHeight)
bool CheckAndUpdate(int &nDos, bool fRequireAvailable=true, bool fCheckSigTimeOnly=false)
enum Network GetNetwork() const
bool IsAddrV1Compatible() const
Check if the current object can be serialized in pre-ADDRv2/BIP155 format.
CSerializedNetMsg Make(int nFlags, std::string sCommand, Args &&... args)
Information about a peer.
int GetSendVersion() const
void PushInventory(const CInv &inv)
An outpoint - a combination of a transaction hash and an index n into its vout.
std::string ToString() const
An encapsulated public key.
CKeyID GetID() const
Get the KeyID of this public key (hash of its serialization)
Serialized script, used inside transaction inputs and outputs.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToString() const
bool IsSporkActive(SporkId nSporkID)
An input of a transaction.
CTxOut out
unspent transaction output
uint32_t nHeight
at which height the containing transaction was included in the active block chain
void Set(int idx, const T &value)
void EraseSeenMNB(const uint256 &hash)
bool IsBlockchainSynced() const
void AddedMasternodeList(const uint256 &hash)
256-bit unsigned big integer.
uint32_t GetCompact(bool fNegative=false) const
std::string ToString() const
std::unique_ptr< CDeterministicMNManager > deterministicMNManager
std::shared_ptr< const CDeterministicMN > CDeterministicMNCPtr
uint256 Hash(const T1 pbegin, const T1 pend)
Compute the 256-bit hash of an object.
std::unique_ptr< CConnman > g_connman
#define LogPrint(category,...)
CMasternodePayments masternodePayments
Object for who's going to get paid on which blocks.
CMasternodeSync masternodeSync
int MasternodeMinPingSeconds()
int MasternodeRemovalSeconds()
int MasternodePingSeconds()
MasternodeRef MakeMasternodeRefForDMN(const CDeterministicMNCPtr &dmn)
std::shared_ptr< CMasternode > MasternodeRef
CMasternodeMan mnodeman
Masternode manager.
CActiveMasternode activeMasternode
Keep track of the active Masternode.
#define MN_WINNER_MINIMUM_AGE
void ThreadCheckMasternodes()
#define MASTERNODES_REQUEST_SECONDS
const char * MNBROADCAST2
The mnbroadcast2 message is used to broadcast masternode startup data to connected peers Supporting B...
const char * GETMNLIST
The dseg message is used to request the Masternode list or an specific entry.
const char * MNBROADCAST
The mnbroadcast message is used to broadcast masternode startup data to connected peers.
const char * MNPING
The mnping message is used to ensure a masternode is still active.
const char * SYNCSTATUSCOUNT
The syncstatuscount message is used to track the layer 2 syncing process.
FILE * fopen(const fs::path &p, const char *mode)
void ThreadRename(std::string &&)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
RecursiveMutex cs_main
Global state.
@ NET_ONION
TOR (v2 or v3)
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
bool LookupHost(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
@ MSG_MASTERNODE_ANNOUNCE
constexpr Span< A > MakeSpan(A(&a)[N])
MakeSpan for arrays:
CSporkManager sporkManager
@ SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a PIVX scriptPubKey for the given CTxDestination.
bool operator()(const std::pair< int64_t, T > &t1, const std::pair< int64_t, T > &t2) const
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
const fs::path & GetDataDir(bool fNetSpecific)
bool error(const char *fmt, const Args &... args)
TierTwoSyncState g_tiertwo_sync_state
#define MASTERNODE_SYNC_LIST
int64_t GetAdjustedTime()
const uint256 UINT256_ZERO
constant uint256 instances
int64_t GetTimeMillis()
Returns the system time (not mockable)
void MilliSleep(int64_t n)
int64_t GetTime()
DEPRECATED Use either GetSystemTimeInSeconds (not mockable) or GetTime<T> (mockable)
int ActiveProtocol()
See whether the protocol update is enforced for connected nodes.
std::unique_ptr< CCoinsViewCache > pcoinsTip
Global variable that points to the active CCoinsView (protected by cs_main)
CBlockIndex * GetChainTip()
Return a reliable pointer (in mapBlockIndex) to the chain's tip index.
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).