2015-03-18 00:06:58 +01:00
|
|
|
// Copyright (c) 2014-2015 The Dash developers
|
2015-02-24 15:02:22 +01:00
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
#include "masternodeman.h"
|
2015-03-23 13:59:22 +01:00
|
|
|
#include "masternode.h"
|
2015-02-23 21:01:21 +01:00
|
|
|
#include "activemasternode.h"
|
|
|
|
#include "darksend.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "addrman.h"
|
2015-06-25 21:59:11 +02:00
|
|
|
#include "spork.h"
|
2015-02-23 21:01:21 +01:00
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#include <boost/filesystem.hpp>
|
|
|
|
|
|
|
|
/** Masternode manager */
|
|
|
|
CMasternodeMan mnodeman;
|
|
|
|
|
2015-07-30 18:00:28 +02:00
|
|
|
struct CompareLastPaid
|
2015-02-23 21:01:21 +01:00
|
|
|
{
|
|
|
|
bool operator()(const pair<int64_t, CTxIn>& t1,
|
|
|
|
const pair<int64_t, CTxIn>& t2) const
|
|
|
|
{
|
|
|
|
return t1.first < t2.first;
|
|
|
|
}
|
|
|
|
};
|
2015-07-22 05:07:23 +02:00
|
|
|
|
2015-07-30 18:00:28 +02:00
|
|
|
struct CompareScoreTxIn
|
|
|
|
{
|
|
|
|
bool operator()(const pair<int64_t, CTxIn>& t1,
|
|
|
|
const pair<int64_t, CTxIn>& t2) const
|
|
|
|
{
|
|
|
|
return t1.first < t2.first;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CompareScoreMN
|
2015-03-14 19:34:51 +01:00
|
|
|
{
|
|
|
|
bool operator()(const pair<int64_t, CMasternode>& t1,
|
|
|
|
const pair<int64_t, CMasternode>& t2) const
|
|
|
|
{
|
|
|
|
return t1.first < t2.first;
|
|
|
|
}
|
|
|
|
};
|
2015-02-23 21:01:21 +01:00
|
|
|
|
|
|
|
//
|
|
|
|
// CMasternodeDB
|
|
|
|
//
|
|
|
|
|
|
|
|
CMasternodeDB::CMasternodeDB()
|
|
|
|
{
|
2015-03-05 18:39:47 +01:00
|
|
|
pathMN = GetDataDir() / "mncache.dat";
|
2015-03-24 01:21:07 +01:00
|
|
|
strMagicMessage = "MasternodeCache";
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CMasternodeDB::Write(const CMasternodeMan& mnodemanToSave)
|
|
|
|
{
|
2015-03-05 00:46:50 +01:00
|
|
|
int64_t nStart = GetTimeMillis();
|
|
|
|
|
2015-03-24 01:21:07 +01:00
|
|
|
// serialize, checksum data up to that point, then append checksum
|
2015-02-23 21:01:21 +01:00
|
|
|
CDataStream ssMasternodes(SER_DISK, CLIENT_VERSION);
|
2015-03-24 01:21:07 +01:00
|
|
|
ssMasternodes << strMagicMessage; // masternode cache file specific magic message
|
|
|
|
ssMasternodes << FLATDATA(Params().MessageStart()); // network specific magic number
|
2015-02-23 21:01:21 +01:00
|
|
|
ssMasternodes << mnodemanToSave;
|
|
|
|
uint256 hash = Hash(ssMasternodes.begin(), ssMasternodes.end());
|
|
|
|
ssMasternodes << hash;
|
|
|
|
|
|
|
|
// open output file, and associate with CAutoFile
|
|
|
|
FILE *file = fopen(pathMN.string().c_str(), "wb");
|
2015-04-03 00:51:08 +02:00
|
|
|
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
|
|
|
|
if (fileout.IsNull())
|
2015-02-23 21:01:21 +01:00
|
|
|
return error("%s : Failed to open file %s", __func__, pathMN.string());
|
|
|
|
|
|
|
|
// Write and commit header, data
|
|
|
|
try {
|
|
|
|
fileout << ssMasternodes;
|
|
|
|
}
|
|
|
|
catch (std::exception &e) {
|
|
|
|
return error("%s : Serialize or I/O error - %s", __func__, e.what());
|
|
|
|
}
|
2015-04-03 00:51:08 +02:00
|
|
|
// FileCommit(fileout);
|
2015-02-23 21:01:21 +01:00
|
|
|
fileout.fclose();
|
|
|
|
|
2015-03-05 18:39:47 +01:00
|
|
|
LogPrintf("Written info to mncache.dat %dms\n", GetTimeMillis() - nStart);
|
2015-03-05 00:46:50 +01:00
|
|
|
LogPrintf(" %s\n", mnodemanToSave.ToString());
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2015-07-14 07:25:07 +02:00
|
|
|
CMasternodeDB::ReadResult CMasternodeDB::Read(CMasternodeMan& mnodemanToLoad, bool fDryRun)
|
2015-02-23 21:01:21 +01:00
|
|
|
{
|
2015-03-05 00:46:50 +01:00
|
|
|
int64_t nStart = GetTimeMillis();
|
2015-02-23 21:01:21 +01:00
|
|
|
// open input file, and associate with CAutoFile
|
|
|
|
FILE *file = fopen(pathMN.string().c_str(), "rb");
|
2015-04-03 00:51:08 +02:00
|
|
|
CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
|
|
|
|
if (filein.IsNull())
|
2015-03-05 00:46:50 +01:00
|
|
|
{
|
|
|
|
error("%s : Failed to open file %s", __func__, pathMN.string());
|
|
|
|
return FileError;
|
|
|
|
}
|
2015-02-23 21:01:21 +01:00
|
|
|
|
|
|
|
// use file size to size memory buffer
|
|
|
|
int fileSize = boost::filesystem::file_size(pathMN);
|
|
|
|
int dataSize = fileSize - sizeof(uint256);
|
|
|
|
// Don't try to resize to a negative number if file is small
|
|
|
|
if (dataSize < 0)
|
|
|
|
dataSize = 0;
|
|
|
|
vector<unsigned char> vchData;
|
|
|
|
vchData.resize(dataSize);
|
|
|
|
uint256 hashIn;
|
|
|
|
|
|
|
|
// read data and checksum from file
|
|
|
|
try {
|
|
|
|
filein.read((char *)&vchData[0], dataSize);
|
|
|
|
filein >> hashIn;
|
|
|
|
}
|
|
|
|
catch (std::exception &e) {
|
2015-03-05 00:46:50 +01:00
|
|
|
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
|
|
|
return HashReadError;
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
filein.fclose();
|
|
|
|
|
|
|
|
CDataStream ssMasternodes(vchData, SER_DISK, CLIENT_VERSION);
|
|
|
|
|
|
|
|
// verify stored checksum matches input data
|
|
|
|
uint256 hashTmp = Hash(ssMasternodes.begin(), ssMasternodes.end());
|
|
|
|
if (hashIn != hashTmp)
|
2015-03-05 00:46:50 +01:00
|
|
|
{
|
|
|
|
error("%s : Checksum mismatch, data corrupted", __func__);
|
|
|
|
return IncorrectHash;
|
|
|
|
}
|
2015-02-23 21:01:21 +01:00
|
|
|
|
|
|
|
unsigned char pchMsgTmp[4];
|
2015-03-24 01:21:07 +01:00
|
|
|
std::string strMagicMessageTmp;
|
2015-02-23 21:01:21 +01:00
|
|
|
try {
|
2015-03-24 01:21:07 +01:00
|
|
|
// de-serialize file header (masternode cache file specific magic message) and ..
|
|
|
|
|
|
|
|
ssMasternodes >> strMagicMessageTmp;
|
|
|
|
|
|
|
|
// ... verify the message matches predefined one
|
|
|
|
if (strMagicMessage != strMagicMessageTmp)
|
|
|
|
{
|
|
|
|
error("%s : Invalid masternode cache magic message", __func__);
|
|
|
|
return IncorrectMagicMessage;
|
|
|
|
}
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
// de-serialize file header (network specific magic number) and ..
|
|
|
|
ssMasternodes >> FLATDATA(pchMsgTmp);
|
|
|
|
|
|
|
|
// ... verify the network matches ours
|
|
|
|
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp)))
|
2015-03-05 00:46:50 +01:00
|
|
|
{
|
|
|
|
error("%s : Invalid network magic number", __func__);
|
2015-03-24 01:21:07 +01:00
|
|
|
return IncorrectMagicNumber;
|
2015-03-05 00:46:50 +01:00
|
|
|
}
|
2015-03-24 01:21:07 +01:00
|
|
|
// de-serialize data into CMasternodeMan object
|
2015-02-23 21:01:21 +01:00
|
|
|
ssMasternodes >> mnodemanToLoad;
|
|
|
|
}
|
|
|
|
catch (std::exception &e) {
|
|
|
|
mnodemanToLoad.Clear();
|
2015-03-05 00:46:50 +01:00
|
|
|
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
|
|
|
return IncorrectFormat;
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
2015-03-05 18:39:47 +01:00
|
|
|
LogPrintf("Loaded info from mncache.dat %dms\n", GetTimeMillis() - nStart);
|
2015-03-05 00:46:50 +01:00
|
|
|
LogPrintf(" %s\n", mnodemanToLoad.ToString());
|
2015-07-30 18:00:28 +02:00
|
|
|
if(!fDryRun) {
|
|
|
|
LogPrintf("Masternode manager - cleaning....\n");
|
|
|
|
mnodemanToLoad.CheckAndRemove(true);
|
|
|
|
LogPrintf("Masternode manager - result:\n");
|
|
|
|
LogPrintf(" %s\n", mnodemanToLoad.ToString());
|
|
|
|
}
|
2015-03-05 00:46:50 +01:00
|
|
|
|
|
|
|
return Ok;
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void DumpMasternodes()
|
|
|
|
{
|
|
|
|
int64_t nStart = GetTimeMillis();
|
|
|
|
|
|
|
|
CMasternodeDB mndb;
|
2015-03-05 00:46:50 +01:00
|
|
|
CMasternodeMan tempMnodeman;
|
|
|
|
|
2015-03-05 18:39:47 +01:00
|
|
|
LogPrintf("Verifying mncache.dat format...\n");
|
2015-07-14 07:25:07 +02:00
|
|
|
CMasternodeDB::ReadResult readResult = mndb.Read(tempMnodeman, true);
|
2015-07-30 18:00:28 +02:00
|
|
|
// there was an error and it was not an error on file opening => do not proceed
|
2015-03-05 00:46:50 +01:00
|
|
|
if (readResult == CMasternodeDB::FileError)
|
2015-03-05 18:39:47 +01:00
|
|
|
LogPrintf("Missing masternode cache file - mncache.dat, will try to recreate\n");
|
2015-03-05 00:46:50 +01:00
|
|
|
else if (readResult != CMasternodeDB::Ok)
|
|
|
|
{
|
2015-03-24 01:21:07 +01:00
|
|
|
LogPrintf("Error reading mncache.dat: ");
|
|
|
|
if(readResult == CMasternodeDB::IncorrectFormat)
|
|
|
|
LogPrintf("magic is ok but data has invalid format, will try to recreate\n");
|
|
|
|
else
|
|
|
|
{
|
|
|
|
LogPrintf("file format is unknown or invalid, please fix it manually\n");
|
|
|
|
return;
|
|
|
|
}
|
2015-03-05 00:46:50 +01:00
|
|
|
}
|
2015-03-05 18:39:47 +01:00
|
|
|
LogPrintf("Writting info to mncache.dat...\n");
|
2015-02-23 21:01:21 +01:00
|
|
|
mndb.Write(mnodeman);
|
|
|
|
|
2015-03-05 00:46:50 +01:00
|
|
|
LogPrintf("Masternode dump finished %dms\n", GetTimeMillis() - nStart);
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
2015-03-06 18:25:48 +01:00
|
|
|
CMasternodeMan::CMasternodeMan() {
|
|
|
|
nDsqCount = 0;
|
|
|
|
}
|
2015-02-23 21:01:21 +01:00
|
|
|
|
|
|
|
bool CMasternodeMan::Add(CMasternode &mn)
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
|
|
|
|
if (!mn.IsEnabled())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
CMasternode *pmn = Find(mn.vin);
|
2015-02-25 12:54:03 +01:00
|
|
|
if (pmn == NULL)
|
2015-02-23 21:01:21 +01:00
|
|
|
{
|
2015-07-31 17:46:47 +02:00
|
|
|
LogPrint("masnernode", "CMasternodeMan: Adding new Masternode %s - %i now\n", mn.addr.ToString(), size() + 1);
|
2015-02-23 21:01:21 +01:00
|
|
|
vMasternodes.push_back(mn);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-08-07 05:07:40 +02:00
|
|
|
void CMasternodeMan::AskForMN(CNode* pnode, CTxIn &vin)
|
|
|
|
{
|
|
|
|
std::map<COutPoint, int64_t>::iterator i = mWeAskedForMasternodeListEntry.find(vin.prevout);
|
|
|
|
if (i != mWeAskedForMasternodeListEntry.end())
|
|
|
|
{
|
|
|
|
int64_t t = (*i).second;
|
|
|
|
if (GetTime() < t) return; // we've asked recently
|
|
|
|
}
|
|
|
|
|
|
|
|
// ask for the mnb info once from the node that sent mnp
|
|
|
|
|
|
|
|
LogPrintf("CMasternodeMan::AskForMN - Asking node for missing entry, vin: %s\n", vin.ToString());
|
|
|
|
pnode->PushMessage("dseg", vin);
|
|
|
|
int64_t askAgain = GetTime() + MASTERNODE_MIN_MNP_SECONDS;
|
|
|
|
mWeAskedForMasternodeListEntry[vin.prevout] = askAgain;
|
|
|
|
}
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
void CMasternodeMan::Check()
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
|
2015-06-24 18:41:03 +02:00
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
2015-02-23 21:01:21 +01:00
|
|
|
mn.Check();
|
2015-06-24 18:41:03 +02:00
|
|
|
}
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
2015-07-14 07:25:07 +02:00
|
|
|
void CMasternodeMan::CheckAndRemove(bool forceExpiredRemoval)
|
2015-02-23 21:01:21 +01:00
|
|
|
{
|
2015-02-24 11:39:29 +01:00
|
|
|
Check();
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-07-30 15:44:18 +02:00
|
|
|
LOCK(cs);
|
|
|
|
|
2015-07-14 07:25:07 +02:00
|
|
|
//remove inactive and outdated
|
2015-02-24 11:39:29 +01:00
|
|
|
vector<CMasternode>::iterator it = vMasternodes.begin();
|
2015-02-23 21:01:21 +01:00
|
|
|
while(it != vMasternodes.end()){
|
2015-07-14 07:25:07 +02:00
|
|
|
if((*it).activeState == CMasternode::MASTERNODE_REMOVE ||
|
|
|
|
(*it).activeState == CMasternode::MASTERNODE_VIN_SPENT ||
|
|
|
|
(forceExpiredRemoval && (*it).activeState == CMasternode::MASTERNODE_EXPIRED) ||
|
2015-07-20 07:03:36 +02:00
|
|
|
(*it).protocolVersion < masternodePayments.GetMinMasternodePaymentsProto()) {
|
2015-07-31 17:46:47 +02:00
|
|
|
LogPrint("masnernode", "CMasternodeMan: Removing inactive Masternode %s - %i now\n", (*it).addr.ToString(), size() - 1);
|
2015-07-21 01:48:57 +02:00
|
|
|
|
|
|
|
//erase all of the broadcasts we've seen from this vin
|
|
|
|
// -- if we missed a few pings and the node was removed, this will allow is to get it back without them
|
|
|
|
// sending a brand new mnb
|
|
|
|
map<uint256, CMasternodeBroadcast>::iterator it3 = mapSeenMasternodeBroadcast.begin();
|
|
|
|
while(it3 != mapSeenMasternodeBroadcast.end()){
|
|
|
|
if((*it3).second.vin == (*it).vin){
|
2015-08-05 02:54:02 +02:00
|
|
|
masternodeSync.mapSeenSyncMNB.erase((*it3).first);
|
2015-07-21 01:48:57 +02:00
|
|
|
mapSeenMasternodeBroadcast.erase(it3++);
|
|
|
|
} else {
|
|
|
|
++it3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// allow us to ask for this masternode again if we see another ping
|
|
|
|
map<COutPoint, int64_t>::iterator it2 = mWeAskedForMasternodeListEntry.begin();
|
|
|
|
while(it2 != mWeAskedForMasternodeListEntry.end()){
|
|
|
|
if((*it2).first == (*it).vin.prevout){
|
|
|
|
mWeAskedForMasternodeListEntry.erase(it2++);
|
|
|
|
} else {
|
|
|
|
++it2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-27 00:12:43 +01:00
|
|
|
it = vMasternodes.erase(it);
|
2015-02-23 21:01:21 +01:00
|
|
|
} else {
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
2015-02-26 00:21:28 +01:00
|
|
|
|
2015-03-05 09:10:15 +01:00
|
|
|
// check who's asked for the Masternode list
|
2015-02-26 00:21:28 +01:00
|
|
|
map<CNetAddr, int64_t>::iterator it1 = mAskedUsForMasternodeList.begin();
|
|
|
|
while(it1 != mAskedUsForMasternodeList.end()){
|
2015-02-26 15:02:39 +01:00
|
|
|
if((*it1).second < GetTime()) {
|
|
|
|
mAskedUsForMasternodeList.erase(it1++);
|
|
|
|
} else {
|
2015-02-27 00:12:43 +01:00
|
|
|
++it1;
|
2015-02-26 15:02:39 +01:00
|
|
|
}
|
2015-02-26 00:21:28 +01:00
|
|
|
}
|
|
|
|
|
2015-03-05 09:10:15 +01:00
|
|
|
// check who we asked for the Masternode list
|
2015-02-26 00:21:28 +01:00
|
|
|
it1 = mWeAskedForMasternodeList.begin();
|
|
|
|
while(it1 != mWeAskedForMasternodeList.end()){
|
2015-02-26 15:02:39 +01:00
|
|
|
if((*it1).second < GetTime()){
|
|
|
|
mWeAskedForMasternodeList.erase(it1++);
|
|
|
|
} else {
|
2015-02-27 00:12:43 +01:00
|
|
|
++it1;
|
2015-02-26 15:02:39 +01:00
|
|
|
}
|
2015-02-26 00:21:28 +01:00
|
|
|
}
|
|
|
|
|
2015-03-05 09:10:15 +01:00
|
|
|
// check which Masternodes we've asked for
|
2015-02-26 00:21:28 +01:00
|
|
|
map<COutPoint, int64_t>::iterator it2 = mWeAskedForMasternodeListEntry.begin();
|
|
|
|
while(it2 != mWeAskedForMasternodeListEntry.end()){
|
2015-02-26 15:02:39 +01:00
|
|
|
if((*it2).second < GetTime()){
|
|
|
|
mWeAskedForMasternodeListEntry.erase(it2++);
|
|
|
|
} else {
|
2015-02-27 00:12:43 +01:00
|
|
|
++it2;
|
2015-02-26 15:02:39 +01:00
|
|
|
}
|
2015-02-26 00:21:28 +01:00
|
|
|
}
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
2015-03-01 01:04:17 +01:00
|
|
|
void CMasternodeMan::Clear()
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
vMasternodes.clear();
|
|
|
|
mAskedUsForMasternodeList.clear();
|
|
|
|
mWeAskedForMasternodeList.clear();
|
|
|
|
mWeAskedForMasternodeListEntry.clear();
|
2015-03-06 18:25:48 +01:00
|
|
|
nDsqCount = 0;
|
2015-03-01 01:04:17 +01:00
|
|
|
}
|
|
|
|
|
2015-07-19 01:20:48 +02:00
|
|
|
int CMasternodeMan::CountEnabled(int protocolVersion)
|
2015-02-23 21:01:21 +01:00
|
|
|
{
|
|
|
|
int i = 0;
|
2015-07-20 07:03:36 +02:00
|
|
|
protocolVersion = protocolVersion == -1 ? masternodePayments.GetMinMasternodePaymentsProto() : protocolVersion;
|
2015-02-23 21:01:21 +01:00
|
|
|
|
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
2015-02-24 11:39:29 +01:00
|
|
|
mn.Check();
|
2015-02-26 00:21:28 +01:00
|
|
|
if(mn.protocolVersion < protocolVersion || !mn.IsEnabled()) continue;
|
|
|
|
i++;
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2015-02-26 00:21:28 +01:00
|
|
|
void CMasternodeMan::DsegUpdate(CNode* pnode)
|
|
|
|
{
|
2015-02-27 00:12:43 +01:00
|
|
|
LOCK(cs);
|
|
|
|
|
2015-07-29 10:06:30 +02:00
|
|
|
if(Params().NetworkID() == CBaseChainParams::MAIN) {
|
|
|
|
if(!(pnode->addr.IsRFC1918() || pnode->addr.IsLocal())){
|
|
|
|
std::map<CNetAddr, int64_t>::iterator it = mWeAskedForMasternodeList.find(pnode->addr);
|
|
|
|
if (it != mWeAskedForMasternodeList.end())
|
|
|
|
{
|
|
|
|
if (GetTime() < (*it).second) {
|
|
|
|
LogPrintf("dseg - we already asked %s for the list; skipping...\n", pnode->addr.ToString());
|
|
|
|
return;
|
|
|
|
}
|
2015-07-02 17:07:30 +02:00
|
|
|
}
|
2015-02-26 00:21:28 +01:00
|
|
|
}
|
|
|
|
}
|
2015-07-29 10:06:30 +02:00
|
|
|
|
2015-02-26 00:21:28 +01:00
|
|
|
pnode->PushMessage("dseg", CTxIn());
|
|
|
|
int64_t askAgain = GetTime() + MASTERNODES_DSEG_SECONDS;
|
|
|
|
mWeAskedForMasternodeList[pnode->addr] = askAgain;
|
|
|
|
}
|
|
|
|
|
2015-05-28 19:45:31 +02:00
|
|
|
CMasternode *CMasternodeMan::Find(const CScript &payee)
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
CScript payee2;
|
|
|
|
|
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes)
|
|
|
|
{
|
|
|
|
payee2 = GetScriptForDestination(mn.pubkey.GetID());
|
|
|
|
if(payee2 == payee)
|
|
|
|
return &mn;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-02-26 00:21:28 +01:00
|
|
|
CMasternode *CMasternodeMan::Find(const CTxIn &vin)
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
|
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes)
|
|
|
|
{
|
2015-04-09 21:17:32 +02:00
|
|
|
if(mn.vin.prevout == vin.prevout)
|
2015-02-26 00:21:28 +01:00
|
|
|
return &mn;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-04-07 21:59:30 +02:00
|
|
|
|
|
|
|
CMasternode *CMasternodeMan::Find(const CPubKey &pubKeyMasternode)
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
|
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes)
|
|
|
|
{
|
|
|
|
if(mn.pubkey2 == pubKeyMasternode)
|
|
|
|
return &mn;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2015-07-22 05:07:23 +02:00
|
|
|
//
|
|
|
|
// Deterministically select the oldest/best masternode to pay on the network
|
|
|
|
//
|
2015-08-20 17:36:44 +02:00
|
|
|
CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeight, bool fFilterSigTime, int& nCount)
|
2015-02-26 00:21:28 +01:00
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
|
2015-07-22 05:07:23 +02:00
|
|
|
CMasternode *pBestMasternode = NULL;
|
|
|
|
std::vector<pair<int64_t, CTxIn> > vecMasternodeLastPaid;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Make a vector with all of the last paid times
|
|
|
|
*/
|
2015-03-01 16:38:53 +01:00
|
|
|
|
2015-07-23 16:16:55 +02:00
|
|
|
int nMnCount = CountEnabled();
|
2015-02-26 00:21:28 +01:00
|
|
|
BOOST_FOREACH(CMasternode &mn, vMasternodes)
|
|
|
|
{
|
|
|
|
mn.Check();
|
|
|
|
if(!mn.IsEnabled()) continue;
|
|
|
|
|
2015-06-25 21:59:11 +02:00
|
|
|
// //check protocol version
|
2015-07-08 03:57:32 +02:00
|
|
|
if(mn.protocolVersion < masternodePayments.GetMinMasternodePaymentsProto()) continue;
|
2015-06-25 21:59:11 +02:00
|
|
|
|
2015-07-23 15:45:43 +02:00
|
|
|
//it's in the list (up to 8 entries ahead of current block to allow propagation) -- so let's skip it
|
2015-06-15 02:05:51 +02:00
|
|
|
if(masternodePayments.IsScheduled(mn, nBlockHeight)) continue;
|
2015-05-27 21:47:01 +02:00
|
|
|
|
2015-07-23 16:16:55 +02:00
|
|
|
//it's too new, wait for a cycle
|
2015-07-25 01:10:44 +02:00
|
|
|
if(fFilterSigTime && mn.sigTime + (nMnCount*2.6*60) > GetAdjustedTime()) continue;
|
2015-07-23 16:16:55 +02:00
|
|
|
|
2015-05-30 19:27:51 +02:00
|
|
|
//make sure it has as many confirmations as there are masternodes
|
2015-07-23 16:16:55 +02:00
|
|
|
if(mn.GetMasternodeInputAge() < nMnCount) continue;
|
2015-05-30 19:27:51 +02:00
|
|
|
|
2015-07-22 05:07:23 +02:00
|
|
|
vecMasternodeLastPaid.push_back(make_pair(mn.SecondsSincePayment(), mn.vin));
|
2015-02-26 00:21:28 +01:00
|
|
|
}
|
|
|
|
|
2015-08-20 18:27:34 +02:00
|
|
|
nCount = (int)vecMasternodeLastPaid.size();
|
|
|
|
|
2015-08-20 17:36:44 +02:00
|
|
|
//when the network is in the process of upgrading, don't penalize nodes that recently restarted
|
|
|
|
if(fFilterSigTime && nCount < nMnCount/3) return GetNextMasternodeInQueueForPayment(nBlockHeight, false, nCount);
|
|
|
|
|
2015-07-22 05:07:23 +02:00
|
|
|
// Sort them low to high
|
2015-07-30 18:00:28 +02:00
|
|
|
sort(vecMasternodeLastPaid.rbegin(), vecMasternodeLastPaid.rend(), CompareLastPaid());
|
2015-07-22 05:07:23 +02:00
|
|
|
|
|
|
|
// Look at 1/10 of the oldest nodes (by last payment), calculate their scores and pay the best one
|
2015-07-23 15:45:43 +02:00
|
|
|
// -- This doesn't look at who is being paid in the +8-10 blocks, allowing for double payments very rarely
|
2015-07-30 18:00:28 +02:00
|
|
|
// -- 1/100 payments should be a double payment on mainnet - (1/(3000/10))*2
|
|
|
|
// -- (chance per block * chances before IsScheduled will fire)
|
2015-08-11 21:43:05 +02:00
|
|
|
int nTenthNetwork = CountEnabled()/10;
|
2015-08-20 17:36:44 +02:00
|
|
|
int nCountTenth = 0;
|
2015-07-22 05:07:23 +02:00
|
|
|
uint256 nHigh = 0;
|
|
|
|
BOOST_FOREACH (PAIRTYPE(int64_t, CTxIn)& s, vecMasternodeLastPaid){
|
2015-08-11 21:43:05 +02:00
|
|
|
CMasternode* pmn = Find(s.second);
|
2015-07-22 05:07:23 +02:00
|
|
|
if(!pmn) break;
|
|
|
|
|
|
|
|
uint256 n = pmn->CalculateScore(1, nBlockHeight-100);
|
|
|
|
if(n > nHigh){
|
|
|
|
nHigh = n;
|
|
|
|
pBestMasternode = pmn;
|
|
|
|
}
|
2015-08-20 17:36:44 +02:00
|
|
|
nCountTenth++;
|
2015-08-20 17:50:29 +02:00
|
|
|
if(nCountTenth >= nTenthNetwork) break;
|
2015-07-22 05:07:23 +02:00
|
|
|
}
|
|
|
|
return pBestMasternode;
|
2015-02-26 00:21:28 +01:00
|
|
|
}
|
|
|
|
|
2015-07-29 17:11:43 +02:00
|
|
|
CMasternode *CMasternodeMan::FindRandomNotInVec(std::vector<CTxIn> &vecToExclude, int protocolVersion)
|
2015-02-26 00:21:28 +01:00
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
|
2015-07-29 17:11:43 +02:00
|
|
|
protocolVersion = protocolVersion == -1 ? masternodePayments.GetMinMasternodePaymentsProto() : protocolVersion;
|
|
|
|
|
|
|
|
int nCountEnabled = CountEnabled(protocolVersion);
|
|
|
|
LogPrintf("CMasternodeMan::FindRandomNotInVec - nCountEnabled - vecToExclude.size() %d\n", nCountEnabled - vecToExclude.size());
|
|
|
|
if(nCountEnabled - vecToExclude.size() < 1) return NULL;
|
|
|
|
|
|
|
|
int rand = GetRandInt(nCountEnabled - vecToExclude.size());
|
|
|
|
LogPrintf("CMasternodeMan::FindRandomNotInVec - rand %d\n", rand);
|
|
|
|
bool found;
|
2015-02-26 00:21:28 +01:00
|
|
|
|
2015-07-29 17:11:43 +02:00
|
|
|
BOOST_FOREACH(CMasternode &mn, vMasternodes) {
|
|
|
|
if(mn.protocolVersion < protocolVersion || !mn.IsEnabled()) continue;
|
|
|
|
found = false;
|
|
|
|
BOOST_FOREACH(CTxIn &usedVin, vecToExclude) {
|
|
|
|
if(mn.vin.prevout == usedVin.prevout) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(found) continue;
|
|
|
|
if(--rand < 1) {
|
|
|
|
return &mn;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
2015-02-26 00:21:28 +01:00
|
|
|
}
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
CMasternode* CMasternodeMan::GetCurrentMasterNode(int mod, int64_t nBlockHeight, int minProtocol)
|
|
|
|
{
|
2015-07-24 18:44:46 +02:00
|
|
|
int64_t score = 0;
|
2015-02-23 21:01:21 +01:00
|
|
|
CMasternode* winner = NULL;
|
|
|
|
|
|
|
|
// scan for winner
|
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
|
|
|
mn.Check();
|
|
|
|
if(mn.protocolVersion < minProtocol || !mn.IsEnabled()) continue;
|
|
|
|
|
2015-03-05 09:10:15 +01:00
|
|
|
// calculate the score for each Masternode
|
2015-02-23 21:01:21 +01:00
|
|
|
uint256 n = mn.CalculateScore(mod, nBlockHeight);
|
2015-07-24 18:44:46 +02:00
|
|
|
int64_t n2 = n.GetCompact(false);
|
2015-02-23 21:01:21 +01:00
|
|
|
|
|
|
|
// determine the winner
|
|
|
|
if(n2 > score){
|
|
|
|
score = n2;
|
|
|
|
winner = &mn;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return winner;
|
|
|
|
}
|
|
|
|
|
2015-03-13 10:28:20 +01:00
|
|
|
int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight, int minProtocol, bool fOnlyActive)
|
2015-02-23 21:01:21 +01:00
|
|
|
{
|
2015-07-24 18:44:46 +02:00
|
|
|
std::vector<pair<int64_t, CTxIn> > vecMasternodeScores;
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-03-23 13:59:22 +01:00
|
|
|
//make sure we know about this block
|
|
|
|
uint256 hash = 0;
|
|
|
|
if(!GetBlockHash(hash, nBlockHeight)) return -1;
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
// scan for winner
|
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
|
|
|
if(mn.protocolVersion < minProtocol) continue;
|
2015-03-24 03:02:22 +01:00
|
|
|
if(fOnlyActive) {
|
|
|
|
mn.Check();
|
|
|
|
if(!mn.IsEnabled()) continue;
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
uint256 n = mn.CalculateScore(1, nBlockHeight);
|
2015-07-24 18:44:46 +02:00
|
|
|
int64_t n2 = n.GetCompact(false);
|
2015-02-23 21:01:21 +01:00
|
|
|
|
|
|
|
vecMasternodeScores.push_back(make_pair(n2, mn.vin));
|
|
|
|
}
|
|
|
|
|
2015-07-30 18:00:28 +02:00
|
|
|
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreTxIn());
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-03-02 00:09:33 +01:00
|
|
|
int rank = 0;
|
2015-07-24 18:44:46 +02:00
|
|
|
BOOST_FOREACH (PAIRTYPE(int64_t, CTxIn)& s, vecMasternodeScores){
|
2015-02-23 21:01:21 +01:00
|
|
|
rank++;
|
2015-06-15 02:05:51 +02:00
|
|
|
if(s.second.prevout == vin.prevout) {
|
2015-02-23 21:01:21 +01:00
|
|
|
return rank;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2015-03-14 19:34:51 +01:00
|
|
|
std::vector<pair<int, CMasternode> > CMasternodeMan::GetMasternodeRanks(int64_t nBlockHeight, int minProtocol)
|
|
|
|
{
|
2015-07-24 18:44:46 +02:00
|
|
|
std::vector<pair<int64_t, CMasternode> > vecMasternodeScores;
|
2015-03-14 19:34:51 +01:00
|
|
|
std::vector<pair<int, CMasternode> > vecMasternodeRanks;
|
|
|
|
|
2015-03-23 13:59:22 +01:00
|
|
|
//make sure we know about this block
|
|
|
|
uint256 hash = 0;
|
|
|
|
if(!GetBlockHash(hash, nBlockHeight)) return vecMasternodeRanks;
|
|
|
|
|
2015-03-14 19:34:51 +01:00
|
|
|
// scan for winner
|
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
|
|
|
|
|
|
|
mn.Check();
|
|
|
|
|
|
|
|
if(mn.protocolVersion < minProtocol) continue;
|
|
|
|
if(!mn.IsEnabled()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint256 n = mn.CalculateScore(1, nBlockHeight);
|
2015-07-24 18:44:46 +02:00
|
|
|
int64_t n2 = n.GetCompact(false);
|
2015-03-14 19:34:51 +01:00
|
|
|
|
|
|
|
vecMasternodeScores.push_back(make_pair(n2, mn));
|
|
|
|
}
|
|
|
|
|
2015-07-30 18:00:28 +02:00
|
|
|
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreMN());
|
2015-03-14 19:34:51 +01:00
|
|
|
|
|
|
|
int rank = 0;
|
2015-07-24 18:44:46 +02:00
|
|
|
BOOST_FOREACH (PAIRTYPE(int64_t, CMasternode)& s, vecMasternodeScores){
|
2015-03-14 19:34:51 +01:00
|
|
|
rank++;
|
|
|
|
vecMasternodeRanks.push_back(make_pair(rank, s.second));
|
|
|
|
}
|
|
|
|
|
|
|
|
return vecMasternodeRanks;
|
|
|
|
}
|
|
|
|
|
2015-03-13 10:28:20 +01:00
|
|
|
CMasternode* CMasternodeMan::GetMasternodeByRank(int nRank, int64_t nBlockHeight, int minProtocol, bool fOnlyActive)
|
2015-03-02 00:09:33 +01:00
|
|
|
{
|
2015-07-24 18:44:46 +02:00
|
|
|
std::vector<pair<int64_t, CTxIn> > vecMasternodeScores;
|
2015-03-02 00:09:33 +01:00
|
|
|
|
|
|
|
// scan for winner
|
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
|
|
|
|
|
|
|
if(mn.protocolVersion < minProtocol) continue;
|
2015-03-24 03:02:22 +01:00
|
|
|
if(fOnlyActive) {
|
|
|
|
mn.Check();
|
|
|
|
if(!mn.IsEnabled()) continue;
|
2015-03-02 00:09:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
uint256 n = mn.CalculateScore(1, nBlockHeight);
|
2015-07-24 18:44:46 +02:00
|
|
|
int64_t n2 = n.GetCompact(false);
|
2015-03-02 00:09:33 +01:00
|
|
|
|
|
|
|
vecMasternodeScores.push_back(make_pair(n2, mn.vin));
|
|
|
|
}
|
|
|
|
|
2015-07-30 18:00:28 +02:00
|
|
|
sort(vecMasternodeScores.rbegin(), vecMasternodeScores.rend(), CompareScoreTxIn());
|
2015-03-02 00:09:33 +01:00
|
|
|
|
|
|
|
int rank = 0;
|
2015-07-24 18:44:46 +02:00
|
|
|
BOOST_FOREACH (PAIRTYPE(int64_t, CTxIn)& s, vecMasternodeScores){
|
2015-03-02 00:09:33 +01:00
|
|
|
rank++;
|
|
|
|
if(rank == nRank) {
|
|
|
|
return Find(s.second);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CMasternodeMan::ProcessMasternodeConnections()
|
|
|
|
{
|
2015-03-24 03:03:34 +01:00
|
|
|
//we don't care about this for regtest
|
2015-04-03 00:51:08 +02:00
|
|
|
if(Params().NetworkID() == CBaseChainParams::REGTEST) return;
|
2015-03-06 23:17:51 +01:00
|
|
|
|
2015-08-11 08:00:46 +02:00
|
|
|
LOCK(cs_vNodes);
|
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes) {
|
2015-03-02 00:09:33 +01:00
|
|
|
if(pnode->fDarkSendMaster){
|
2015-08-11 08:00:46 +02:00
|
|
|
if(darkSendPool.pSubmittedToMasternode != NULL && pnode->addr == darkSendPool.pSubmittedToMasternode->addr) continue;
|
2015-07-31 17:46:47 +02:00
|
|
|
LogPrintf("Closing Masternode connection %s \n", pnode->addr.ToString());
|
2015-07-30 15:44:18 +02:00
|
|
|
pnode->fDisconnect = true;
|
2015-03-02 00:09:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
void CMasternodeMan::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
|
|
|
{
|
|
|
|
|
2015-03-05 09:10:15 +01:00
|
|
|
if(fLiteMode) return; //disable all Darksend/Masternode related functionality
|
2015-08-07 06:48:55 +02:00
|
|
|
if(!masternodeSync.IsBlockchainSynced()) return;
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-03-31 23:21:59 +02:00
|
|
|
LOCK(cs_process_message);
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-04-17 17:10:38 +02:00
|
|
|
if (strCommand == "mnb") { //Masternode Broadcast
|
|
|
|
CMasternodeBroadcast mnb;
|
2015-07-14 07:25:07 +02:00
|
|
|
vRecv >> mnb;
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-08-11 21:43:05 +02:00
|
|
|
if(mapSeenMasternodeBroadcast.count(mnb.GetHash())) { //seen
|
2015-08-05 02:54:02 +02:00
|
|
|
masternodeSync.AddedMasternodeList(mnb.GetHash());
|
2015-07-24 20:35:11 +02:00
|
|
|
return;
|
|
|
|
}
|
2015-08-11 21:43:05 +02:00
|
|
|
mapSeenMasternodeBroadcast.insert(make_pair(mnb.GetHash(), mnb));
|
2015-04-22 16:33:44 +02:00
|
|
|
|
2015-04-17 17:10:38 +02:00
|
|
|
int nDoS = 0;
|
2015-07-14 07:25:07 +02:00
|
|
|
if(!mnb.CheckAndUpdate(nDoS)){
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-04-17 17:10:38 +02:00
|
|
|
if(nDoS > 0)
|
|
|
|
Misbehaving(pfrom->GetId(), nDoS);
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-04-17 17:10:38 +02:00
|
|
|
//failed
|
2015-02-23 21:01:21 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-05 09:10:15 +01:00
|
|
|
// make sure the vout that was signed is related to the transaction that spawned the Masternode
|
|
|
|
// - this is expensive, so it's only done once per Masternode
|
2015-04-17 17:10:38 +02:00
|
|
|
if(!darkSendSigner.IsVinAssociatedWithPubkey(mnb.vin, mnb.pubkey)) {
|
2015-05-04 17:04:09 +02:00
|
|
|
LogPrintf("mnb - Got mismatched pubkey and vin\n");
|
2015-04-17 17:10:38 +02:00
|
|
|
Misbehaving(pfrom->GetId(), 33);
|
2015-02-23 21:01:21 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// make sure it's still unspent
|
|
|
|
// - this is checked later by .check() in many places and by ThreadCheckDarkSendPool()
|
2015-07-14 07:25:07 +02:00
|
|
|
if(mnb.CheckInputsAndAdd(nDoS)) {
|
2015-02-23 21:01:21 +01:00
|
|
|
// use this as a peer
|
2015-04-17 17:10:38 +02:00
|
|
|
addrman.Add(CAddress(mnb.addr), pfrom->addr, 2*60*60);
|
2015-08-05 02:54:02 +02:00
|
|
|
masternodeSync.AddedMasternodeList(mnb.GetHash());
|
2015-02-23 21:01:21 +01:00
|
|
|
} else {
|
2015-07-14 07:25:07 +02:00
|
|
|
LogPrintf("mnb - Rejected Masternode entry %s\n", mnb.addr.ToString());
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-04-17 17:10:38 +02:00
|
|
|
if (nDoS > 0)
|
|
|
|
Misbehaving(pfrom->GetId(), nDoS);
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-17 17:10:38 +02:00
|
|
|
else if (strCommand == "mnp") { //Masternode Ping
|
|
|
|
CMasternodePing mnp;
|
|
|
|
vRecv >> mnp;
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-07-31 17:46:47 +02:00
|
|
|
LogPrint("masnernode", "mnp - Masternode ping, vin: %s\n", mnp.vin.ToString());
|
2015-07-14 07:25:07 +02:00
|
|
|
|
2015-08-11 21:43:05 +02:00
|
|
|
if(mapSeenMasternodePing.count(mnp.GetHash())) return; //seen
|
|
|
|
mapSeenMasternodePing.insert(make_pair(mnp.GetHash(), mnp));
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-04-17 17:10:38 +02:00
|
|
|
int nDoS = 0;
|
2015-07-14 07:25:07 +02:00
|
|
|
if(mnp.CheckAndUpdate(nDoS)) return;
|
|
|
|
|
|
|
|
if(nDoS > 0) {
|
2015-08-07 05:07:40 +02:00
|
|
|
// if anything significant failed, mark that node
|
2015-07-14 07:25:07 +02:00
|
|
|
Misbehaving(pfrom->GetId(), nDoS);
|
2015-08-07 05:07:40 +02:00
|
|
|
} else {
|
|
|
|
// if nothing significant failed, search existing Masternode list
|
2015-08-11 21:43:05 +02:00
|
|
|
CMasternode* pmn = Find(mnp.vin);
|
2015-08-07 05:07:40 +02:00
|
|
|
// if it's known, don't ask for the mnb, just return
|
|
|
|
if(pmn != NULL) return;
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
2015-08-07 05:07:40 +02:00
|
|
|
// something significant is broken or mn is unknown,
|
|
|
|
// we might have to ask for a masternode entry once
|
|
|
|
AskForMN(pfrom, mnp.vin);
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-03-05 09:10:15 +01:00
|
|
|
} else if (strCommand == "dseg") { //Get Masternode list or specific entry
|
2015-02-23 21:01:21 +01:00
|
|
|
|
|
|
|
CTxIn vin;
|
|
|
|
vRecv >> vin;
|
|
|
|
|
|
|
|
if(vin == CTxIn()) { //only should ask for this once
|
|
|
|
//local network
|
2015-07-02 17:07:30 +02:00
|
|
|
bool isLocal = (pfrom->addr.IsRFC1918() || pfrom->addr.IsLocal());
|
|
|
|
|
|
|
|
if(!isLocal && Params().NetworkID() == CBaseChainParams::MAIN) {
|
2015-02-26 00:21:28 +01:00
|
|
|
std::map<CNetAddr, int64_t>::iterator i = mAskedUsForMasternodeList.find(pfrom->addr);
|
2015-04-03 00:51:08 +02:00
|
|
|
if (i != mAskedUsForMasternodeList.end()){
|
2015-02-23 21:01:21 +01:00
|
|
|
int64_t t = (*i).second;
|
|
|
|
if (GetTime() < t) {
|
|
|
|
Misbehaving(pfrom->GetId(), 34);
|
|
|
|
LogPrintf("dseg - peer already asked me for the list\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2015-02-26 00:21:28 +01:00
|
|
|
int64_t askAgain = GetTime() + MASTERNODES_DSEG_SECONDS;
|
|
|
|
mAskedUsForMasternodeList[pfrom->addr] = askAgain;
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
} //else, asking for a specific node which is ok
|
|
|
|
|
2015-07-29 06:16:11 +02:00
|
|
|
|
2015-07-26 04:27:40 +02:00
|
|
|
std::vector<CInv> vInv;
|
2015-02-23 21:01:21 +01:00
|
|
|
int i = 0;
|
|
|
|
BOOST_FOREACH(CMasternode& mn, vMasternodes) {
|
|
|
|
if(mn.addr.IsRFC1918()) continue; //local network
|
|
|
|
|
2015-04-03 00:51:08 +02:00
|
|
|
if(mn.IsEnabled()) {
|
2015-07-31 17:46:47 +02:00
|
|
|
LogPrint("masnernode", "dseg - Sending Masternode entry - %s \n", mn.addr.ToString());
|
2015-07-26 06:13:17 +02:00
|
|
|
if(vin == CTxIn() || vin == mn.vin){
|
2015-07-25 21:07:30 +02:00
|
|
|
CInv inv(MSG_MASTERNODE_ANNOUNCE, CMasternodeBroadcast(mn).GetHash());
|
2015-07-26 04:27:40 +02:00
|
|
|
vInv.push_back(inv);
|
2015-05-04 17:04:09 +02:00
|
|
|
|
2015-07-26 06:13:17 +02:00
|
|
|
if(vin == mn.vin) {
|
2015-07-31 17:46:47 +02:00
|
|
|
LogPrintf("dseg - Sent 1 Masternode entries to %s\n", pfrom->addr.ToString());
|
2015-07-26 06:13:17 +02:00
|
|
|
break;
|
|
|
|
}
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
2015-07-14 07:25:07 +02:00
|
|
|
i++;
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
}
|
2015-07-29 06:16:11 +02:00
|
|
|
|
|
|
|
if(vin == CTxIn()) pfrom->PushMessage("ssc", MASTERNODE_SYNC_LIST, (int)vInv.size());
|
2015-07-26 04:27:40 +02:00
|
|
|
if(vInv.size() > 0) pfrom->PushMessage("inv", vInv);
|
2015-02-23 21:01:21 +01:00
|
|
|
|
2015-08-14 18:15:50 +02:00
|
|
|
if(vin == CTxIn()) LogPrintf("dseg - Sent %d Masternode entries to %s\n", i, pfrom->addr.ToString());
|
2015-08-09 15:06:54 +02:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* IT'S SAFE TO REMOVE THIS IN FURTHER VERSIONS
|
|
|
|
* AFTER MIGRATION TO V12 IS DONE
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Light version for OLD MASSTERNODES - fake pings, no self-activation
|
|
|
|
else if (strCommand == "dsee") { //DarkSend Election Entry
|
|
|
|
|
|
|
|
if(IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return;
|
2015-08-09 02:01:07 +02:00
|
|
|
|
|
|
|
CTxIn vin;
|
|
|
|
CService addr;
|
|
|
|
CPubKey pubkey;
|
|
|
|
CPubKey pubkey2;
|
|
|
|
vector<unsigned char> vchSig;
|
|
|
|
int64_t sigTime;
|
|
|
|
int count;
|
|
|
|
int current;
|
|
|
|
int64_t lastUpdated;
|
|
|
|
int protocolVersion;
|
|
|
|
CScript donationAddress;
|
|
|
|
int donationPercentage;
|
|
|
|
std::string strMessage;
|
|
|
|
|
|
|
|
vRecv >> vin >> addr >> vchSig >> sigTime >> pubkey >> pubkey2 >> count >> current >> lastUpdated >> protocolVersion >> donationAddress >> donationPercentage;
|
|
|
|
|
|
|
|
// make sure signature isn't in the future (past is OK)
|
|
|
|
if (sigTime > GetAdjustedTime() + 60 * 60) {
|
|
|
|
LogPrintf("dsee - Signature rejected, too far into the future %s\n", vin.ToString().c_str());
|
2015-08-14 05:18:08 +02:00
|
|
|
Misbehaving(pfrom->GetId(), 1);
|
2015-08-09 02:01:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool isLocal = addr.IsRFC1918() || addr.IsLocal();
|
|
|
|
if(Params().NetworkID() == CBaseChainParams::REGTEST) isLocal = false;
|
|
|
|
|
|
|
|
std::string vchPubKey(pubkey.begin(), pubkey.end());
|
|
|
|
std::string vchPubKey2(pubkey2.begin(), pubkey2.end());
|
|
|
|
|
|
|
|
strMessage = addr.ToString() + boost::lexical_cast<std::string>(sigTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(protocolVersion) + donationAddress.ToString() + boost::lexical_cast<std::string>(donationPercentage);
|
|
|
|
|
|
|
|
if(protocolVersion < masternodePayments.GetMinMasternodePaymentsProto()) {
|
|
|
|
LogPrintf("dsee - ignoring outdated Masternode %s protocol version %d < %d\n", vin.ToString().c_str(), protocolVersion, masternodePayments.GetMinMasternodePaymentsProto());
|
2015-08-14 05:18:08 +02:00
|
|
|
Misbehaving(pfrom->GetId(), 1);
|
2015-08-09 02:01:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CScript pubkeyScript;
|
|
|
|
pubkeyScript = GetScriptForDestination(pubkey.GetID());
|
|
|
|
|
|
|
|
if(pubkeyScript.size() != 25) {
|
|
|
|
LogPrintf("dsee - pubkey the wrong size\n");
|
2015-08-14 05:18:08 +02:00
|
|
|
Misbehaving(pfrom->GetId(), 100);
|
2015-08-09 02:01:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
CScript pubkeyScript2;
|
|
|
|
pubkeyScript2 = GetScriptForDestination(pubkey2.GetID());
|
|
|
|
|
|
|
|
if(pubkeyScript2.size() != 25) {
|
|
|
|
LogPrintf("dsee - pubkey2 the wrong size\n");
|
2015-08-14 05:18:08 +02:00
|
|
|
Misbehaving(pfrom->GetId(), 100);
|
2015-08-09 02:01:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!vin.scriptSig.empty()) {
|
|
|
|
LogPrintf("dsee - Ignore Not Empty ScriptSig %s\n",vin.ToString());
|
2015-08-14 05:18:08 +02:00
|
|
|
Misbehaving(pfrom->GetId(), 100);
|
2015-08-09 02:01:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string errorMessage = "";
|
|
|
|
if(!darkSendSigner.VerifyMessage(pubkey, vchSig, strMessage, errorMessage)){
|
|
|
|
LogPrintf("dsee - Got bad Masternode address signature\n");
|
|
|
|
Misbehaving(pfrom->GetId(), 100);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Params().NetworkID() == CBaseChainParams::MAIN){
|
|
|
|
if(addr.GetPort() != 9999) return;
|
|
|
|
} else if(addr.GetPort() == 9999) return;
|
|
|
|
|
|
|
|
//search existing Masternode list, this is where we update existing Masternodes with new dsee broadcasts
|
|
|
|
CMasternode* pmn = this->Find(vin);
|
|
|
|
if(pmn != NULL)
|
|
|
|
{
|
|
|
|
// count == -1 when it's a new entry
|
|
|
|
// e.g. We don't want the entry relayed/time updated when we're syncing the list
|
|
|
|
// mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below,
|
|
|
|
// after that they just need to match
|
2015-08-14 07:08:32 +02:00
|
|
|
if(count == -1 && pmn->pubkey == pubkey && (GetAdjustedTime() - pmn->nLastDsee > MASTERNODE_MIN_MNB_SECONDS)){
|
2015-08-12 14:27:58 +02:00
|
|
|
if(pmn->protocolVersion > GETHEADERS_VERSION && sigTime - pmn->lastPing.sigTime < MASTERNODE_MIN_MNB_SECONDS) return;
|
2015-08-14 07:08:32 +02:00
|
|
|
if(pmn->nLastDsee < sigTime){ //take the newest entry
|
2015-08-09 02:01:07 +02:00
|
|
|
LogPrintf("dsee - Got updated entry for %s\n", addr.ToString().c_str());
|
2015-08-10 12:16:49 +02:00
|
|
|
if(pmn->protocolVersion < GETHEADERS_VERSION) {
|
2015-08-10 01:47:35 +02:00
|
|
|
pmn->pubkey2 = pubkey2;
|
|
|
|
pmn->sigTime = sigTime;
|
|
|
|
pmn->sig = vchSig;
|
|
|
|
pmn->protocolVersion = protocolVersion;
|
|
|
|
pmn->addr = addr;
|
|
|
|
//fake ping
|
|
|
|
pmn->lastPing = CMasternodePing(vin);
|
|
|
|
}
|
2015-08-14 07:08:32 +02:00
|
|
|
pmn->nLastDsee = sigTime;
|
2015-08-09 02:01:07 +02:00
|
|
|
pmn->Check();
|
|
|
|
if(pmn->IsEnabled()) {
|
|
|
|
TRY_LOCK(cs_vNodes, lockNodes);
|
|
|
|
if(!lockNodes) return;
|
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes)
|
|
|
|
if(pnode->nVersion >= masternodePayments.GetMinMasternodePaymentsProto())
|
|
|
|
pnode->PushMessage("dsee", vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion, donationAddress, donationPercentage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-12 16:29:43 +02:00
|
|
|
static std::map<COutPoint, CPubKey> mapSeenDsee;
|
|
|
|
if(mapSeenDsee.count(vin.prevout) && mapSeenDsee[vin.prevout] == pubkey) {
|
|
|
|
LogPrint("mastenrode", "dsee - already seen this vin %s\n", vin.prevout.ToString());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mapSeenDsee.insert(make_pair(vin.prevout, pubkey));
|
2015-08-09 02:01:07 +02:00
|
|
|
// make sure the vout that was signed is related to the transaction that spawned the Masternode
|
|
|
|
// - this is expensive, so it's only done once per Masternode
|
|
|
|
if(!darkSendSigner.IsVinAssociatedWithPubkey(vin, pubkey)) {
|
|
|
|
LogPrintf("dsee - Got mismatched pubkey and vin\n");
|
|
|
|
Misbehaving(pfrom->GetId(), 100);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-12 14:27:58 +02:00
|
|
|
|
|
|
|
LogPrint("masternode", "dsee - Got NEW OLD Masternode entry %s\n", addr.ToString().c_str());
|
2015-08-09 02:01:07 +02:00
|
|
|
|
|
|
|
// make sure it's still unspent
|
|
|
|
// - this is checked later by .check() in many places and by ThreadCheckDarkSendPool()
|
|
|
|
|
|
|
|
CValidationState state;
|
|
|
|
CMutableTransaction tx = CMutableTransaction();
|
|
|
|
CTxOut vout = CTxOut(999.99*COIN, darkSendPool.collateralPubKey);
|
|
|
|
tx.vin.push_back(vin);
|
|
|
|
tx.vout.push_back(vout);
|
2015-08-10 00:32:09 +02:00
|
|
|
|
|
|
|
bool fAcceptable = false;
|
|
|
|
{
|
|
|
|
TRY_LOCK(cs_main, lockMain);
|
|
|
|
if(!lockMain) return;
|
|
|
|
fAcceptable = AcceptableInputs(mempool, state, CTransaction(tx), false, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(fAcceptable){
|
2015-08-09 02:01:07 +02:00
|
|
|
if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){
|
|
|
|
LogPrintf("dsee - Input must have least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS);
|
|
|
|
Misbehaving(pfrom->GetId(), 20);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// verify that sig time is legit in past
|
|
|
|
// should be at least not earlier than block when 1000 DASH tx got MASTERNODE_MIN_CONFIRMATIONS
|
|
|
|
uint256 hashBlock = 0;
|
|
|
|
CTransaction tx2;
|
|
|
|
GetTransaction(vin.prevout.hash, tx2, hashBlock, true);
|
|
|
|
BlockMap::iterator mi = mapBlockIndex.find(hashBlock);
|
|
|
|
if (mi != mapBlockIndex.end() && (*mi).second)
|
|
|
|
{
|
|
|
|
CBlockIndex* pMNIndex = (*mi).second; // block for 1000 DASH tx -> 1 confirmation
|
|
|
|
CBlockIndex* pConfIndex = chainActive[pMNIndex->nHeight + MASTERNODE_MIN_CONFIRMATIONS - 1]; // block where tx got MASTERNODE_MIN_CONFIRMATIONS
|
|
|
|
if(pConfIndex->GetBlockTime() > sigTime)
|
|
|
|
{
|
|
|
|
LogPrintf("mnb - Bad sigTime %d for Masternode %20s %105s (%i conf block is at %d)\n",
|
|
|
|
sigTime, addr.ToString(), vin.ToString(), MASTERNODE_MIN_CONFIRMATIONS, pConfIndex->GetBlockTime());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// use this as a peer
|
|
|
|
addrman.Add(CAddress(addr), pfrom->addr, 2*60*60);
|
|
|
|
|
2015-08-10 01:47:35 +02:00
|
|
|
// add Masternode
|
2015-08-09 02:01:07 +02:00
|
|
|
CMasternode mn = CMasternode();
|
|
|
|
mn.addr = addr;
|
|
|
|
mn.vin = vin;
|
|
|
|
mn.pubkey = pubkey;
|
|
|
|
mn.sig = vchSig;
|
|
|
|
mn.sigTime = sigTime;
|
|
|
|
mn.pubkey2 = pubkey2;
|
|
|
|
mn.protocolVersion = protocolVersion;
|
|
|
|
// fake ping
|
|
|
|
mn.lastPing = CMasternodePing(vin);
|
|
|
|
mn.Check(true);
|
2015-08-10 01:47:35 +02:00
|
|
|
// add v11 masternodes, v12 should be added by mnb only
|
2015-08-12 03:48:43 +02:00
|
|
|
if(protocolVersion < GETHEADERS_VERSION) {
|
2015-08-12 14:27:58 +02:00
|
|
|
LogPrint("masternode", "dsee - Accepted OLD Masternode entry %i %i\n", count, current);
|
2015-08-12 03:48:43 +02:00
|
|
|
Add(mn);
|
|
|
|
}
|
2015-08-09 02:01:07 +02:00
|
|
|
if(mn.IsEnabled()) {
|
|
|
|
TRY_LOCK(cs_vNodes, lockNodes);
|
|
|
|
if(!lockNodes) return;
|
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes)
|
|
|
|
if(pnode->nVersion >= masternodePayments.GetMinMasternodePaymentsProto())
|
|
|
|
pnode->PushMessage("dsee", vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion, donationAddress, donationPercentage);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
LogPrintf("dsee - Rejected Masternode entry %s\n", addr.ToString().c_str());
|
|
|
|
|
|
|
|
int nDoS = 0;
|
|
|
|
if (state.IsInvalid(nDoS))
|
|
|
|
{
|
|
|
|
LogPrintf("dsee - %s from %s %s was not accepted into the memory pool\n", tx.GetHash().ToString().c_str(),
|
|
|
|
pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str());
|
|
|
|
if (nDoS > 0)
|
|
|
|
Misbehaving(pfrom->GetId(), nDoS);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (strCommand == "dseep") { //DarkSend Election Entry Ping
|
|
|
|
|
2015-08-09 15:06:54 +02:00
|
|
|
if(IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES)) return;
|
|
|
|
|
2015-08-09 02:01:07 +02:00
|
|
|
CTxIn vin;
|
|
|
|
vector<unsigned char> vchSig;
|
|
|
|
int64_t sigTime;
|
|
|
|
bool stop;
|
|
|
|
vRecv >> vin >> vchSig >> sigTime >> stop;
|
|
|
|
|
|
|
|
//LogPrintf("dseep - Received: vin: %s sigTime: %lld stop: %s\n", vin.ToString().c_str(), sigTime, stop ? "true" : "false");
|
|
|
|
|
|
|
|
if (sigTime > GetAdjustedTime() + 60 * 60) {
|
|
|
|
LogPrintf("dseep - Signature rejected, too far into the future %s\n", vin.ToString().c_str());
|
2015-08-14 05:18:08 +02:00
|
|
|
Misbehaving(pfrom->GetId(), 1);
|
2015-08-09 02:01:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sigTime <= GetAdjustedTime() - 60 * 60) {
|
|
|
|
LogPrintf("dseep - Signature rejected, too far into the past %s - %d %d \n", vin.ToString().c_str(), sigTime, GetAdjustedTime());
|
2015-08-14 05:18:08 +02:00
|
|
|
Misbehaving(pfrom->GetId(), 1);
|
2015-08-09 02:01:07 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-14 03:14:08 +02:00
|
|
|
std::map<COutPoint, int64_t>::iterator i = mWeAskedForMasternodeListEntry.find(vin.prevout);
|
|
|
|
if (i != mWeAskedForMasternodeListEntry.end())
|
|
|
|
{
|
|
|
|
int64_t t = (*i).second;
|
|
|
|
if (GetTime() < t) return; // we've asked recently
|
|
|
|
}
|
|
|
|
|
2015-08-09 02:01:07 +02:00
|
|
|
// see if we have this Masternode
|
|
|
|
CMasternode* pmn = this->Find(vin);
|
|
|
|
if(pmn != NULL && pmn->protocolVersion >= masternodePayments.GetMinMasternodePaymentsProto())
|
|
|
|
{
|
|
|
|
// LogPrintf("dseep - Found corresponding mn for vin: %s\n", vin.ToString().c_str());
|
|
|
|
// take this only if it's newer
|
2015-08-14 03:14:08 +02:00
|
|
|
if(sigTime - pmn->nLastDseep > MASTERNODE_MIN_MNP_SECONDS)
|
2015-08-09 02:01:07 +02:00
|
|
|
{
|
|
|
|
std::string strMessage = pmn->addr.ToString() + boost::lexical_cast<std::string>(sigTime) + boost::lexical_cast<std::string>(stop);
|
|
|
|
|
|
|
|
std::string errorMessage = "";
|
|
|
|
if(!darkSendSigner.VerifyMessage(pmn->pubkey2, vchSig, strMessage, errorMessage))
|
|
|
|
{
|
|
|
|
LogPrintf("dseep - Got bad Masternode address signature %s \n", vin.ToString().c_str());
|
|
|
|
//Misbehaving(pfrom->GetId(), 100);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-10 01:47:35 +02:00
|
|
|
// fake ping for v11 masternodes, ignore for v12
|
2015-08-10 12:16:49 +02:00
|
|
|
if(pmn->protocolVersion < GETHEADERS_VERSION) pmn->lastPing = CMasternodePing(vin);
|
2015-08-14 03:14:08 +02:00
|
|
|
pmn->nLastDseep = sigTime;
|
2015-08-09 02:01:07 +02:00
|
|
|
pmn->Check();
|
|
|
|
if(pmn->IsEnabled()) {
|
|
|
|
TRY_LOCK(cs_vNodes, lockNodes);
|
|
|
|
if(!lockNodes) return;
|
2015-08-14 03:14:08 +02:00
|
|
|
LogPrint("masternode", "dseep - relaying %s \n", vin.ToString().c_str());
|
2015-08-09 02:01:07 +02:00
|
|
|
BOOST_FOREACH(CNode* pnode, vNodes)
|
|
|
|
if(pnode->nVersion >= masternodePayments.GetMinMasternodePaymentsProto())
|
|
|
|
pnode->PushMessage("dseep", vin, vchSig, sigTime, stop);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-14 03:14:08 +02:00
|
|
|
LogPrint("masternode", "dseep - Couldn't find Masternode entry %s %s\n", vin.ToString(), pfrom->addr.ToString());
|
2015-08-09 02:01:07 +02:00
|
|
|
|
|
|
|
AskForMN(pfrom, vin);
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
|
|
|
|
2015-08-09 15:06:54 +02:00
|
|
|
/*
|
|
|
|
* END OF "REMOVE"
|
|
|
|
*/
|
|
|
|
|
2015-02-23 21:01:21 +01:00
|
|
|
}
|
2015-03-01 00:56:52 +01:00
|
|
|
|
2015-04-08 04:07:25 +02:00
|
|
|
void CMasternodeMan::Remove(CTxIn vin)
|
|
|
|
{
|
|
|
|
LOCK(cs);
|
|
|
|
|
|
|
|
vector<CMasternode>::iterator it = vMasternodes.begin();
|
|
|
|
while(it != vMasternodes.end()){
|
|
|
|
if((*it).vin == vin){
|
2015-07-31 17:46:47 +02:00
|
|
|
LogPrint("masnernode", "CMasternodeMan: Removing Masternode %s - %i now\n", (*it).addr.ToString(), size() - 1);
|
2015-04-08 04:07:25 +02:00
|
|
|
vMasternodes.erase(it);
|
|
|
|
break;
|
|
|
|
}
|
2015-05-04 17:04:09 +02:00
|
|
|
++it;
|
2015-04-08 04:07:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-05 00:46:50 +01:00
|
|
|
std::string CMasternodeMan::ToString() const
|
2015-03-01 00:56:52 +01:00
|
|
|
{
|
|
|
|
std::ostringstream info;
|
|
|
|
|
2015-03-05 09:10:15 +01:00
|
|
|
info << "Masternodes: " << (int)vMasternodes.size() <<
|
|
|
|
", peers who asked us for Masternode list: " << (int)mAskedUsForMasternodeList.size() <<
|
|
|
|
", peers we asked for Masternode list: " << (int)mWeAskedForMasternodeList.size() <<
|
2015-03-06 18:25:48 +01:00
|
|
|
", entries in Masternode list we asked for: " << (int)mWeAskedForMasternodeListEntry.size() <<
|
|
|
|
", nDsqCount: " << (int)nDsqCount;
|
2015-03-01 00:56:52 +01:00
|
|
|
|
|
|
|
return info.str();
|
|
|
|
}
|