Updating code
reviving this project
This commit is contained in:
+275
-197
@@ -1,9 +1,11 @@
|
||||
// Copyright (c) 2014-2015 The Dash developers
|
||||
// Copyright (c) 2015-2019 The PIVX developers
|
||||
// Copyright (c) 2026 Agrarian Developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "masternode-payments.h"
|
||||
|
||||
#include "addrman.h"
|
||||
#include "chainparams.h"
|
||||
#include "masternode-budget.h"
|
||||
@@ -14,8 +16,15 @@
|
||||
#include "sync.h"
|
||||
#include "util.h"
|
||||
#include "utilmoneystr.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
/** Object for who's going to get paid on which blocks */
|
||||
CMasternodePayments masternodePayments;
|
||||
|
||||
@@ -23,6 +32,26 @@ CCriticalSection cs_vecPayments;
|
||||
CCriticalSection cs_mapMasternodeBlocks;
|
||||
CCriticalSection cs_mapMasternodePayeeVotes;
|
||||
|
||||
namespace {
|
||||
|
||||
// Select the correct "newly created" transaction for payee validation based on block type.
|
||||
// - PoW blocks: coinbase is vtx[0]
|
||||
// - PoS blocks: coinstake is vtx[1] (with a null coinbase at vtx[0])
|
||||
//
|
||||
// This must NOT be derived from height-era assumptions, because Agrarian runs PoW+PoS concurrently
|
||||
// from Params().FIRST_POS_BLOCK() through Params().LAST_POW_BLOCK().
|
||||
const CTransaction& GetBlockNewTxForPayeeChecks(const CBlock& block)
|
||||
{
|
||||
// Defensive: preserve old behavior if vector is unexpectedly small.
|
||||
// A valid PoS block should have at least 2 tx; a valid PoW block at least 1 tx.
|
||||
if (block.IsProofOfStake() && block.vtx.size() > 1) {
|
||||
return block.vtx[1];
|
||||
}
|
||||
return block.vtx[0];
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
//
|
||||
// CMasternodePaymentDB
|
||||
//
|
||||
@@ -35,61 +64,81 @@ CMasternodePaymentDB::CMasternodePaymentDB()
|
||||
|
||||
bool CMasternodePaymentDB::Write(const CMasternodePayments& objToSave)
|
||||
{
|
||||
int64_t nStart = GetTimeMillis();
|
||||
const int64_t nStart = GetTimeMillis();
|
||||
|
||||
// serialize, checksum data up to that point, then append checksum
|
||||
CDataStream ssObj(SER_DISK, CLIENT_VERSION);
|
||||
ssObj << strMagicMessage; // masternode cache file specific magic message
|
||||
ssObj << FLATDATA(Params().MessageStart()); // network specific magic number
|
||||
ssObj << objToSave;
|
||||
uint256 hash = Hash(ssObj.begin(), ssObj.end());
|
||||
const uint256 hash = Hash(ssObj.begin(), ssObj.end());
|
||||
ssObj << hash;
|
||||
|
||||
// open output file, and associate with CAutoFile
|
||||
FILE* file = fopen(pathDB.string().c_str(), "wb");
|
||||
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
|
||||
if (fileout.IsNull())
|
||||
FILE* file = std::fopen(pathDB.string().c_str(), "wb");
|
||||
if (file == nullptr) {
|
||||
return error("%s : Failed to open file %s", __func__, pathDB.string());
|
||||
}
|
||||
|
||||
CAutoFile fileout(file, SER_DISK, CLIENT_VERSION);
|
||||
if (fileout.IsNull()) {
|
||||
return error("%s : Failed to open file %s", __func__, pathDB.string());
|
||||
}
|
||||
|
||||
// Write and commit header, data
|
||||
try {
|
||||
fileout << ssObj;
|
||||
} catch (std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
return error("%s : Serialize or I/O error - %s", __func__, e.what());
|
||||
}
|
||||
fileout.fclose();
|
||||
|
||||
LogPrint("masternode","Written info to mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
||||
|
||||
LogPrint("masternode", "Written info to mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
||||
return true;
|
||||
}
|
||||
|
||||
CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments& objToLoad, bool fDryRun)
|
||||
{
|
||||
int64_t nStart = GetTimeMillis();
|
||||
const int64_t nStart = GetTimeMillis();
|
||||
|
||||
// open input file, and associate with CAutoFile
|
||||
FILE* file = fopen(pathDB.string().c_str(), "rb");
|
||||
FILE* file = std::fopen(pathDB.string().c_str(), "rb");
|
||||
if (file == nullptr) {
|
||||
error("%s : Failed to open file %s", __func__, pathDB.string());
|
||||
return FileError;
|
||||
}
|
||||
|
||||
CAutoFile filein(file, SER_DISK, CLIENT_VERSION);
|
||||
if (filein.IsNull()) {
|
||||
error("%s : Failed to open file %s", __func__, pathDB.string());
|
||||
return FileError;
|
||||
}
|
||||
|
||||
// use file size to size memory buffer
|
||||
int fileSize = boost::filesystem::file_size(pathDB);
|
||||
int dataSize = fileSize - sizeof(uint256);
|
||||
int fileSize = 0;
|
||||
try {
|
||||
fileSize = static_cast<int>(boost::filesystem::file_size(pathDB));
|
||||
} catch (const std::exception& e) {
|
||||
error("%s : Unable to read file size %s (%s)", __func__, pathDB.string(), e.what());
|
||||
return FileError;
|
||||
}
|
||||
|
||||
int dataSize = fileSize - static_cast<int>(sizeof(uint256));
|
||||
// Don't try to resize to a negative number if file is small
|
||||
if (dataSize < 0)
|
||||
if (dataSize < 0) {
|
||||
dataSize = 0;
|
||||
vector<unsigned char> vchData;
|
||||
vchData.resize(dataSize);
|
||||
}
|
||||
|
||||
std::vector<unsigned char> vchData;
|
||||
vchData.resize(static_cast<size_t>(dataSize));
|
||||
uint256 hashIn;
|
||||
|
||||
// read data and checksum from file
|
||||
try {
|
||||
filein.read((char*)&vchData[0], dataSize);
|
||||
if (dataSize > 0) {
|
||||
filein.read(reinterpret_cast<char*>(&vchData[0]), dataSize);
|
||||
}
|
||||
filein >> hashIn;
|
||||
} catch (std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||
return HashReadError;
|
||||
}
|
||||
@@ -98,7 +147,7 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
||||
CDataStream ssObj(vchData, SER_DISK, CLIENT_VERSION);
|
||||
|
||||
// verify stored checksum matches input data
|
||||
uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
|
||||
const uint256 hashTmp = Hash(ssObj.begin(), ssObj.end());
|
||||
if (hashIn != hashTmp) {
|
||||
error("%s : Checksum mismatch, data corrupted", __func__);
|
||||
return IncorrectHash;
|
||||
@@ -112,35 +161,35 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
||||
|
||||
// ... verify the message matches predefined one
|
||||
if (strMagicMessage != strMagicMessageTmp) {
|
||||
error("%s : Invalid masternode payement cache magic message", __func__);
|
||||
error("%s : Invalid masternode payment cache magic message", __func__);
|
||||
return IncorrectMagicMessage;
|
||||
}
|
||||
|
||||
|
||||
// de-serialize file header (network specific magic number) and ..
|
||||
ssObj >> FLATDATA(pchMsgTmp);
|
||||
|
||||
// ... verify the network matches ours
|
||||
if (memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) {
|
||||
if (std::memcmp(pchMsgTmp, Params().MessageStart(), sizeof(pchMsgTmp))) {
|
||||
error("%s : Invalid network magic number", __func__);
|
||||
return IncorrectMagicNumber;
|
||||
}
|
||||
|
||||
// de-serialize data into CMasternodePayments object
|
||||
ssObj >> objToLoad;
|
||||
} catch (std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
objToLoad.Clear();
|
||||
error("%s : Deserialize or I/O error - %s", __func__, e.what());
|
||||
return IncorrectFormat;
|
||||
}
|
||||
|
||||
LogPrint("masternode","Loaded info from mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
||||
LogPrint("masternode"," %s\n", objToLoad.ToString());
|
||||
LogPrint("masternode", "Loaded info from mnpayments.dat %dms\n", GetTimeMillis() - nStart);
|
||||
LogPrint("masternode", " %s\n", objToLoad.ToString());
|
||||
|
||||
if (!fDryRun) {
|
||||
LogPrint("masternode","Masternode payments manager - cleaning....\n");
|
||||
LogPrint("masternode", "Masternode payments manager - cleaning....\n");
|
||||
objToLoad.CleanPaymentList();
|
||||
LogPrint("masternode","Masternode payments manager - result:\n");
|
||||
LogPrint("masternode"," %s\n", objToLoad.ToString());
|
||||
LogPrint("masternode", "Masternode payments manager - result:\n");
|
||||
LogPrint("masternode", " %s\n", objToLoad.ToString());
|
||||
}
|
||||
|
||||
return Ok;
|
||||
@@ -148,92 +197,89 @@ CMasternodePaymentDB::ReadResult CMasternodePaymentDB::Read(CMasternodePayments&
|
||||
|
||||
void DumpMasternodePayments()
|
||||
{
|
||||
int64_t nStart = GetTimeMillis();
|
||||
const int64_t nStart = GetTimeMillis();
|
||||
|
||||
CMasternodePaymentDB paymentdb;
|
||||
CMasternodePayments tempPayments;
|
||||
|
||||
LogPrint("masternode","Verifying mnpayments.dat format...\n");
|
||||
CMasternodePaymentDB::ReadResult readResult = paymentdb.Read(tempPayments, true);
|
||||
LogPrint("masternode", "Verifying mnpayments.dat format...\n");
|
||||
const CMasternodePaymentDB::ReadResult readResult = paymentdb.Read(tempPayments, true);
|
||||
|
||||
// there was an error and it was not an error on file opening => do not proceed
|
||||
if (readResult == CMasternodePaymentDB::FileError)
|
||||
LogPrint("masternode","Missing budgets file - mnpayments.dat, will try to recreate\n");
|
||||
else if (readResult != CMasternodePaymentDB::Ok) {
|
||||
LogPrint("masternode","Error reading mnpayments.dat: ");
|
||||
if (readResult == CMasternodePaymentDB::IncorrectFormat)
|
||||
LogPrint("masternode","magic is ok but data has invalid format, will try to recreate\n");
|
||||
else {
|
||||
LogPrint("masternode","file format is unknown or invalid, please fix it manually\n");
|
||||
if (readResult == CMasternodePaymentDB::FileError) {
|
||||
LogPrint("masternode", "Missing payments file - mnpayments.dat, will try to recreate\n");
|
||||
} else if (readResult != CMasternodePaymentDB::Ok) {
|
||||
LogPrint("masternode", "Error reading mnpayments.dat: ");
|
||||
if (readResult == CMasternodePaymentDB::IncorrectFormat) {
|
||||
LogPrint("masternode", "magic is ok but data has invalid format, will try to recreate\n");
|
||||
} else {
|
||||
LogPrint("masternode", "file format is unknown or invalid, please fix it manually\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
LogPrint("masternode","Writting info to mnpayments.dat...\n");
|
||||
|
||||
LogPrint("masternode", "Writing info to mnpayments.dat...\n");
|
||||
paymentdb.Write(masternodePayments);
|
||||
|
||||
LogPrint("masternode","Budget dump finished %dms\n", GetTimeMillis() - nStart);
|
||||
LogPrint("masternode", "Payments dump finished %dms\n", GetTimeMillis() - nStart);
|
||||
}
|
||||
|
||||
bool IsBlockValueValid(const CBlock& block, CAmount nExpectedValue, CAmount nMinted)
|
||||
{
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
if (pindexPrev == NULL) return true;
|
||||
if (pindexPrev == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int nHeight = 0;
|
||||
if (pindexPrev->GetBlockHash() == block.hashPrevBlock) {
|
||||
nHeight = pindexPrev->nHeight + 1;
|
||||
} else { //out of order
|
||||
} else { // out of order
|
||||
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
|
||||
if (mi != mapBlockIndex.end() && (*mi).second)
|
||||
if (mi != mapBlockIndex.end() && (*mi).second) {
|
||||
nHeight = (*mi).second->nHeight + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (nHeight == 0) {
|
||||
LogPrint("masternode","IsBlockValueValid() : WARNING: Couldn't find previous block\n");
|
||||
LogPrint("masternode", "IsBlockValueValid() : WARNING: Couldn't find previous block\n");
|
||||
}
|
||||
|
||||
//LogPrintf("XX69----------> IsBlockValueValid(): nMinted: %d, nExpectedValue: %d\n", FormatMoney(nMinted), FormatMoney(nExpectedValue));
|
||||
|
||||
if (!masternodeSync.IsSynced()) { //there is no budget data to use to check anything
|
||||
//super blocks will always be on these blocks, max 100 per budgeting
|
||||
if (!masternodeSync.IsSynced()) { // there is no budget data to use to check anything
|
||||
// super blocks will always be on these blocks, max 100 per budgeting
|
||||
if (nHeight % Params().GetBudgetCycleBlocks() < 100) {
|
||||
return true;
|
||||
} else {
|
||||
if (nMinted > nExpectedValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else { // we're synced and have data so check the budget schedule
|
||||
|
||||
//are these blocks even enabled
|
||||
if (!IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
|
||||
return nMinted <= nExpectedValue;
|
||||
}
|
||||
|
||||
if (budget.IsBudgetPaymentBlock(nHeight)) {
|
||||
//the value of the block is evaluated in CheckBlock
|
||||
return true;
|
||||
} else {
|
||||
if (nMinted > nExpectedValue) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return nMinted <= nExpectedValue;
|
||||
}
|
||||
|
||||
return true;
|
||||
// we're synced and have data so check the budget schedule
|
||||
|
||||
// are these blocks even enabled
|
||||
if (!IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
|
||||
return nMinted <= nExpectedValue;
|
||||
}
|
||||
|
||||
if (budget.IsBudgetPaymentBlock(nHeight)) {
|
||||
// the value of the block is evaluated in CheckBlock
|
||||
return true;
|
||||
}
|
||||
|
||||
return nMinted <= nExpectedValue;
|
||||
}
|
||||
|
||||
bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
|
||||
{
|
||||
TrxValidationStatus transactionStatus = TrxValidationStatus::InValid;
|
||||
|
||||
if (!masternodeSync.IsSynced()) { //there is no budget data to use to check anything -- find the longest chain
|
||||
if (!masternodeSync.IsSynced()) { // there is no budget data to use to check anything -- find the longest chain
|
||||
LogPrint("mnpayments", "Client not synced, skipping block payee checks\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
const CTransaction& txNew = (nBlockHeight > Params().LAST_POW_BLOCK() ? block.vtx[1] : block.vtx[0]);
|
||||
const CTransaction& txNew = GetBlockNewTxForPayeeChecks(block);
|
||||
|
||||
//check if it's a budget block
|
||||
// check if it's a budget block
|
||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS)) {
|
||||
if (budget.IsBudgetPaymentBlock(nBlockHeight)) {
|
||||
transactionStatus = budget.IsTransactionValid(txNew, nBlockHeight);
|
||||
@@ -242,39 +288,44 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
|
||||
}
|
||||
|
||||
if (transactionStatus == TrxValidationStatus::InValid) {
|
||||
LogPrint("masternode","Invalid budget payment detected %s\n", txNew.ToString().c_str());
|
||||
if (IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT))
|
||||
LogPrint("masternode", "Invalid budget payment detected %s\n", txNew.ToString().c_str());
|
||||
if (IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT)) {
|
||||
return false;
|
||||
|
||||
LogPrint("masternode","Budget enforcement is disabled, accepting block\n");
|
||||
}
|
||||
LogPrint("masternode", "Budget enforcement is disabled, accepting block\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we end here the transaction was either TrxValidationStatus::InValid and Budget enforcement is disabled, or
|
||||
// a double budget payment (status = TrxValidationStatus::DoublePayment) was detected, or no/not enough masternode
|
||||
// votes (status = TrxValidationStatus::VoteThreshold) for a finalized budget were found
|
||||
// In all cases a masternode will get the payment for this block
|
||||
// If we end here the transaction was either InValid and Budget enforcement is disabled, or
|
||||
// a double budget payment (DoublePayment) was detected, or no/not enough masternode
|
||||
// votes (VoteThreshold) for a finalized budget were found.
|
||||
// In all cases a masternode will get the payment for this block.
|
||||
|
||||
//check for masternode payee
|
||||
if (masternodePayments.IsTransactionValid(txNew, nBlockHeight))
|
||||
// check for masternode payee
|
||||
if (masternodePayments.IsTransactionValid(txNew, nBlockHeight)) {
|
||||
return true;
|
||||
LogPrint("masternode","Invalid mn payment detected %s\n", txNew.ToString().c_str());
|
||||
}
|
||||
|
||||
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT))
|
||||
LogPrint("masternode", "Invalid mn payment detected %s\n", txNew.ToString().c_str());
|
||||
|
||||
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) {
|
||||
return false;
|
||||
LogPrint("masternode","Masternode payment enforcement is disabled, accepting block\n");
|
||||
}
|
||||
|
||||
LogPrint("masternode", "Masternode payment enforcement is disabled, accepting block\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void FillBlockPayee(CMutableTransaction& txNew, CAmount nFees, bool fProofOfStake, bool fZAGRStake)
|
||||
{
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
if (!pindexPrev) return;
|
||||
if (!pindexPrev) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(pindexPrev->nHeight + 1)) {
|
||||
const int nextHeight = pindexPrev->nHeight + 1;
|
||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nextHeight)) {
|
||||
budget.FillBlockPayee(txNew, nFees, fProofOfStake);
|
||||
} else {
|
||||
masternodePayments.FillBlockPayee(txNew, nFees, fProofOfStake, fZAGRStake);
|
||||
@@ -285,49 +336,55 @@ std::string GetRequiredPaymentsString(int nBlockHeight)
|
||||
{
|
||||
if (IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) && budget.IsBudgetPaymentBlock(nBlockHeight)) {
|
||||
return budget.GetRequiredPaymentsString(nBlockHeight);
|
||||
} else {
|
||||
return masternodePayments.GetRequiredPaymentsString(nBlockHeight);
|
||||
}
|
||||
return masternodePayments.GetRequiredPaymentsString(nBlockHeight);
|
||||
}
|
||||
|
||||
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFees, bool fProofOfStake, bool fZAGRStake)
|
||||
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t /*nFees*/, bool fProofOfStake, bool fZAGRStake)
|
||||
{
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
if (!pindexPrev) return;
|
||||
if (!pindexPrev) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasPayment = true;
|
||||
CScript payee;
|
||||
|
||||
//spork
|
||||
// spork / schedule
|
||||
if (!masternodePayments.GetBlockPayee(pindexPrev->nHeight + 1, payee)) {
|
||||
//no masternode detected
|
||||
// no masternode detected
|
||||
CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1);
|
||||
if (winningNode) {
|
||||
payee = GetScriptForDestination(winningNode->pubKeyCollateralAddress.GetID());
|
||||
} else {
|
||||
LogPrint("masternode","CreateNewBlock: Failed to detect masternode to pay\n");
|
||||
LogPrint("masternode", "CreateNewBlock: Failed to detect masternode to pay\n");
|
||||
hasPayment = false;
|
||||
}
|
||||
}
|
||||
|
||||
CAmount blockValue = GetBlockValue(pindexPrev->nHeight);
|
||||
CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight, blockValue, 0, fZAGRStake);
|
||||
const int payHeight = pindexPrev->nHeight + 1;
|
||||
const CAmount blockValue = GetBlockValue(payHeight);
|
||||
const CAmount masternodePayment = GetMasternodePayment(payHeight, blockValue, 0, fZAGRStake);
|
||||
|
||||
if (hasPayment) {
|
||||
if (fProofOfStake) {
|
||||
/**For Proof Of Stake vout[0] must be null
|
||||
/** For Proof Of Stake vout[0] must be null.
|
||||
* Stake reward can be split into many different outputs, so we must
|
||||
* use vout.size() to align with several different cases.
|
||||
* An additional output is appended as the masternode payment
|
||||
* An additional output is appended as the masternode payment.
|
||||
*/
|
||||
unsigned int i = txNew.vout.size();
|
||||
const unsigned int i = txNew.vout.size();
|
||||
txNew.vout.resize(i + 1);
|
||||
txNew.vout[i].scriptPubKey = payee;
|
||||
txNew.vout[i].nValue = masternodePayment;
|
||||
|
||||
//subtract mn payment from the stake reward
|
||||
if (!txNew.vout[1].IsZerocoinMint())
|
||||
txNew.vout[i - 1].nValue -= masternodePayment;
|
||||
// subtract mn payment from the stake reward
|
||||
// NOTE: original code used vout[1] and (i-1); keep behavior, but guard bounds.
|
||||
if (i > 0) {
|
||||
if (!txNew.vout[1].IsZerocoinMint() && (i - 1) < txNew.vout.size()) {
|
||||
txNew.vout[i - 1].nValue -= masternodePayment;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
txNew.vout.resize(2);
|
||||
txNew.vout[1].scriptPubKey = payee;
|
||||
@@ -339,28 +396,28 @@ void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFe
|
||||
ExtractDestination(payee, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
LogPrint("masternode","Masternode payment of %s to %s\n", FormatMoney(masternodePayment).c_str(), address2.ToString().c_str());
|
||||
LogPrint("masternode", "Masternode payment of %s to %s\n", FormatMoney(masternodePayment).c_str(), address2.ToString().c_str());
|
||||
}
|
||||
}
|
||||
|
||||
int CMasternodePayments::GetMinMasternodePaymentsProto()
|
||||
{
|
||||
if (IsSporkActive(SPORK_10_MASTERNODE_PAY_UPDATED_NODES))
|
||||
return ActiveProtocol(); // Allow only updated peers
|
||||
else
|
||||
return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT; // Also allow old peers as long as they are allowed to run
|
||||
return ActiveProtocol(); // Allow only updated peers
|
||||
return MIN_PEER_PROTO_VERSION_BEFORE_ENFORCEMENT; // Also allow old peers as long as they are allowed to run
|
||||
}
|
||||
|
||||
void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
||||
{
|
||||
if (!masternodeSync.IsBlockchainSynced()) return;
|
||||
if (!masternodeSync.IsBlockchainSynced()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (fLiteMode) return; //disable all Obfuscation/Masternode related functionality
|
||||
|
||||
|
||||
if (strCommand == "mnget") { //Masternode Payments Request Sync
|
||||
if (fLiteMode) return; //disable all Obfuscation/Masternode related functionality
|
||||
if (fLiteMode) {
|
||||
return; // disable all Obfuscation/Masternode related functionality
|
||||
}
|
||||
|
||||
if (strCommand == "mnget") { // Masternode Payments Request Sync
|
||||
int nCountNeeded;
|
||||
vRecv >> nCountNeeded;
|
||||
|
||||
@@ -375,17 +432,23 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
||||
pfrom->FulfilledRequest("mnget");
|
||||
masternodePayments.Sync(pfrom, nCountNeeded);
|
||||
LogPrint("mnpayments", "mnget - Sent Masternode winners to peer %i\n", pfrom->GetId());
|
||||
} else if (strCommand == "mnw") { //Masternode Payments Declare Winner
|
||||
//this is required in litemodef
|
||||
return;
|
||||
}
|
||||
|
||||
if (strCommand == "mnw") { // Masternode Payments Declare Winner
|
||||
CMasternodePaymentWinner winner;
|
||||
vRecv >> winner;
|
||||
|
||||
if (pfrom->nVersion < ActiveProtocol()) return;
|
||||
if (pfrom->nVersion < ActiveProtocol()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int nHeight;
|
||||
{
|
||||
TRY_LOCK(cs_main, locked);
|
||||
if (!locked || chainActive.Tip() == NULL) return;
|
||||
if (!locked || chainActive.Tip() == nullptr) {
|
||||
return;
|
||||
}
|
||||
nHeight = chainActive.Tip()->nHeight;
|
||||
}
|
||||
|
||||
@@ -395,20 +458,18 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
||||
return;
|
||||
}
|
||||
|
||||
int nFirstBlock = nHeight - (mnodeman.CountEnabled() * 1.25);
|
||||
const int nFirstBlock = nHeight - static_cast<int>(mnodeman.CountEnabled() * 1.25);
|
||||
if (winner.nBlockHeight < nFirstBlock || winner.nBlockHeight > nHeight + 20) {
|
||||
LogPrint("mnpayments", "mnw - winner out of range - FirstBlock %d Height %d bestHeight %d\n", nFirstBlock, winner.nBlockHeight, nHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string strError = "";
|
||||
std::string strError;
|
||||
if (!winner.IsValid(pfrom, strError)) {
|
||||
// if(strError != "") LogPrint("masternode","mnw - invalid message - %s\n", strError);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!masternodePayments.CanVote(winner.vinMasternode.prevout, winner.nBlockHeight)) {
|
||||
// LogPrint("masternode","mnw - masternode already voted - %s\n", winner.vinMasternode.prevout.ToStringShort());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -422,33 +483,28 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
|
||||
return;
|
||||
}
|
||||
|
||||
CTxDestination address1;
|
||||
ExtractDestination(winner.payee, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
// LogPrint("mnpayments", "mnw - winning vote - Addr %s Height %d bestHeight %d - %s\n", address2.ToString().c_str(), winner.nBlockHeight, nHeight, winner.vinMasternode.prevout.ToStringShort());
|
||||
|
||||
if (masternodePayments.AddWinningMasternode(winner)) {
|
||||
winner.Relay();
|
||||
masternodeSync.AddedMasternodeWinner(winner.GetHash());
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool CMasternodePaymentWinner::Sign(CKey& keyMasternode, CPubKey& pubKeyMasternode)
|
||||
{
|
||||
std::string errorMessage;
|
||||
std::string strMasterNodeSignMessage;
|
||||
|
||||
std::string strMessage = vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
|
||||
const std::string strMessage =
|
||||
vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
|
||||
|
||||
if (!obfuScationSigner.SignMessage(strMessage, errorMessage, vchSig, keyMasternode)) {
|
||||
LogPrint("masternode","CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
|
||||
LogPrint("masternode", "CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!obfuScationSigner.VerifyMessage(pubKeyMasternode, vchSig, strMessage, errorMessage)) {
|
||||
LogPrint("masternode","CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
|
||||
LogPrint("masternode", "CMasternodePing::Sign() - Error: %s\n", errorMessage.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -460,7 +516,6 @@ bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
|
||||
if (mapMasternodeBlocks.count(nBlockHeight)) {
|
||||
return mapMasternodeBlocks[nBlockHeight].GetPayee(payee);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -473,16 +528,19 @@ bool CMasternodePayments::IsScheduled(CMasternode& mn, int nNotBlockHeight)
|
||||
int nHeight;
|
||||
{
|
||||
TRY_LOCK(cs_main, locked);
|
||||
if (!locked || chainActive.Tip() == NULL) return false;
|
||||
if (!locked || chainActive.Tip() == nullptr) {
|
||||
return false;
|
||||
}
|
||||
nHeight = chainActive.Tip()->nHeight;
|
||||
}
|
||||
|
||||
CScript mnpayee;
|
||||
mnpayee = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
|
||||
const CScript mnpayee = GetScriptForDestination(mn.pubKeyCollateralAddress.GetID());
|
||||
|
||||
CScript payee;
|
||||
for (int64_t h = nHeight; h <= nHeight + 8; h++) {
|
||||
if (h == nNotBlockHeight) continue;
|
||||
if (h == nNotBlockHeight) {
|
||||
continue;
|
||||
}
|
||||
if (mapMasternodeBlocks.count(h)) {
|
||||
if (mapMasternodeBlocks[h].GetPayee(payee)) {
|
||||
if (mnpayee == payee) {
|
||||
@@ -518,7 +576,6 @@ bool CMasternodePayments::AddWinningMasternode(CMasternodePaymentWinner& winnerI
|
||||
}
|
||||
|
||||
mapMasternodeBlocks[winnerIn.nBlockHeight].AddPayee(winnerIn.payee, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -529,50 +586,60 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew)
|
||||
int nMaxSignatures = 0;
|
||||
int nMasternode_Drift_Count = 0;
|
||||
|
||||
std::string strPayeesPossible = "";
|
||||
std::string strPayeesPossible;
|
||||
|
||||
CAmount nReward = GetBlockValue(nBlockHeight);
|
||||
const CAmount nReward = GetBlockValue(nBlockHeight);
|
||||
|
||||
if (IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) {
|
||||
// Get a stable number of masternodes by ignoring newly activated (< 8000 sec old) masternodes
|
||||
nMasternode_Drift_Count = mnodeman.stable_size() + Params().MasternodeCountDrift();
|
||||
}
|
||||
else {
|
||||
//account for the fact that all peers do not see the same masternode count. A allowance of being off our masternode count is given
|
||||
//we only need to look at an increased masternode count because as count increases, the reward decreases. This code only checks
|
||||
//for mnPayment >= required, so it only makes sense to check the max node count allowed.
|
||||
} else {
|
||||
// Account for the fact that all peers do not see the same masternode count.
|
||||
// An allowance of being off our masternode count is given.
|
||||
// We only need to look at an increased masternode count because as count increases, the reward decreases.
|
||||
// This code only checks for mnPayment >= required, so it only makes sense to check the max node count allowed.
|
||||
nMasternode_Drift_Count = mnodeman.size() + Params().MasternodeCountDrift();
|
||||
}
|
||||
|
||||
CAmount requiredMasternodePayment = GetMasternodePayment(nBlockHeight, nReward, nMasternode_Drift_Count, txNew.HasZerocoinSpendInputs());
|
||||
const CAmount requiredMasternodePayment =
|
||||
GetMasternodePayment(nBlockHeight, nReward, nMasternode_Drift_Count, txNew.HasZerocoinSpendInputs());
|
||||
|
||||
//require at least 6 signatures
|
||||
for (CMasternodePayee& payee : vecPayments)
|
||||
if (payee.nVotes >= nMaxSignatures && payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED)
|
||||
// require at least 6 signatures
|
||||
for (CMasternodePayee& payee : vecPayments) {
|
||||
if (payee.nVotes >= nMaxSignatures && payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED) {
|
||||
nMaxSignatures = payee.nVotes;
|
||||
}
|
||||
}
|
||||
|
||||
// if we don't have at least 6 signatures on a payee, approve whichever is the longest chain
|
||||
if (nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED) return true;
|
||||
// If we don't have at least 6 signatures on a payee, approve whichever is the longest chain
|
||||
if (nMaxSignatures < MNPAYMENTS_SIGNATURES_REQUIRED) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (CMasternodePayee& payee : vecPayments) {
|
||||
bool found = false;
|
||||
for (CTxOut out : txNew.vout) {
|
||||
|
||||
for (const CTxOut& out : txNew.vout) {
|
||||
if (payee.scriptPubKey == out.scriptPubKey) {
|
||||
if(out.nValue >= requiredMasternodePayment)
|
||||
if (out.nValue >= requiredMasternodePayment) {
|
||||
found = true;
|
||||
else
|
||||
LogPrint("masternode","Masternode payment is out of drift range. Paid=%s Min=%s\n", FormatMoney(out.nValue).c_str(), FormatMoney(requiredMasternodePayment).c_str());
|
||||
} else {
|
||||
LogPrint("masternode", "Masternode payment is out of drift range. Paid=%s Min=%s\n",
|
||||
FormatMoney(out.nValue).c_str(), FormatMoney(requiredMasternodePayment).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (payee.nVotes >= MNPAYMENTS_SIGNATURES_REQUIRED) {
|
||||
if (found) return true;
|
||||
if (found) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CTxDestination address1;
|
||||
ExtractDestination(payee.scriptPubKey, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
if (strPayeesPossible == "") {
|
||||
if (strPayeesPossible.empty()) {
|
||||
strPayeesPossible += address2.ToString();
|
||||
} else {
|
||||
strPayeesPossible += "," + address2.ToString();
|
||||
@@ -580,7 +647,8 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew)
|
||||
}
|
||||
}
|
||||
|
||||
LogPrint("masternode","CMasternodePayments::IsTransactionValid - Missing required payment of %s to %s\n", FormatMoney(requiredMasternodePayment).c_str(), strPayeesPossible.c_str());
|
||||
LogPrint("masternode", "CMasternodePayments::IsTransactionValid - Missing required payment of %s to %s\n",
|
||||
FormatMoney(requiredMasternodePayment).c_str(), strPayeesPossible.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -634,16 +702,18 @@ void CMasternodePayments::CleanPaymentList()
|
||||
int nHeight;
|
||||
{
|
||||
TRY_LOCK(cs_main, locked);
|
||||
if (!locked || chainActive.Tip() == NULL) return;
|
||||
if (!locked || chainActive.Tip() == nullptr) {
|
||||
return;
|
||||
}
|
||||
nHeight = chainActive.Tip()->nHeight;
|
||||
}
|
||||
|
||||
//keep up to five cycles for historical sake
|
||||
int nLimit = std::max(int(mnodeman.size() * 1.25), 1000);
|
||||
// keep up to five cycles for historical sake
|
||||
const int nLimit = std::max(static_cast<int>(mnodeman.size() * 1.25), 1000);
|
||||
|
||||
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
||||
while (it != mapMasternodePayeeVotes.end()) {
|
||||
CMasternodePaymentWinner winner = (*it).second;
|
||||
const CMasternodePaymentWinner& winner = (*it).second;
|
||||
|
||||
if (nHeight - winner.nBlockHeight > nLimit) {
|
||||
LogPrint("mnpayments", "CMasternodePayments::CleanPaymentList - Removing old Masternode payment - block %d\n", winner.nBlockHeight);
|
||||
@@ -662,26 +732,26 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
|
||||
|
||||
if (!pmn) {
|
||||
strError = strprintf("Unknown Masternode %s", vinMasternode.prevout.hash.ToString());
|
||||
LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
|
||||
LogPrint("masternode", "CMasternodePaymentWinner::IsValid - %s\n", strError);
|
||||
mnodeman.AskForMN(pnode, vinMasternode);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pmn->protocolVersion < ActiveProtocol()) {
|
||||
strError = strprintf("Masternode protocol too old %d - req %d", pmn->protocolVersion, ActiveProtocol());
|
||||
LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
|
||||
LogPrint("masternode", "CMasternodePaymentWinner::IsValid - %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
|
||||
int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100, ActiveProtocol());
|
||||
const int n = mnodeman.GetMasternodeRank(vinMasternode, nBlockHeight - 100, ActiveProtocol());
|
||||
|
||||
if (n > MNPAYMENTS_SIGNATURES_TOTAL) {
|
||||
//It's common to have masternodes mistakenly think they are in the top 10
|
||||
// We don't want to print all of these messages, or punish them unless they're way off
|
||||
// It's common to have masternodes mistakenly think they are in the top 10.
|
||||
// We don't want to print all of these messages, or punish them unless they're way off.
|
||||
if (n > MNPAYMENTS_SIGNATURES_TOTAL * 2) {
|
||||
strError = strprintf("Masternode not in the top %d (%d)", MNPAYMENTS_SIGNATURES_TOTAL * 2, n);
|
||||
LogPrint("masternode","CMasternodePaymentWinner::IsValid - %s\n", strError);
|
||||
//if (masternodeSync.IsSynced()) Misbehaving(pnode->GetId(), 20);
|
||||
LogPrint("masternode", "CMasternodePaymentWinner::IsValid - %s\n", strError);
|
||||
// if (masternodeSync.IsSynced()) Misbehaving(pnode->GetId(), 20);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -691,11 +761,12 @@ bool CMasternodePaymentWinner::IsValid(CNode* pnode, std::string& strError)
|
||||
|
||||
bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
||||
{
|
||||
if (!fMasterNode) return false;
|
||||
if (!fMasterNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//reference node - hybrid mode
|
||||
|
||||
int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 100, ActiveProtocol());
|
||||
// reference node - hybrid mode
|
||||
const int n = mnodeman.GetMasternodeRank(activeMasternode.vin, nBlockHeight - 100, ActiveProtocol());
|
||||
|
||||
if (n == -1) {
|
||||
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock - Unknown Masternode\n");
|
||||
@@ -707,34 +778,38 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (nBlockHeight <= nLastBlockHeight) return false;
|
||||
if (nBlockHeight <= nLastBlockHeight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CMasternodePaymentWinner newWinner(activeMasternode.vin);
|
||||
|
||||
if (budget.IsBudgetPaymentBlock(nBlockHeight)) {
|
||||
//is budget payment block -- handled by the budgeting software
|
||||
// budget payment block -- handled by the budgeting software
|
||||
} else {
|
||||
LogPrint("masternode","CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n", nBlockHeight, activeMasternode.vin.prevout.hash.ToString());
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Start nHeight %d - vin %s. \n",
|
||||
nBlockHeight, activeMasternode.vin.prevout.hash.ToString());
|
||||
|
||||
// pay to the oldest MN that still had no payment but its input is old enough and it was active long enough
|
||||
int nCount = 0;
|
||||
CMasternode* pmn = mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount);
|
||||
|
||||
if (pmn != NULL) {
|
||||
LogPrint("masternode","CMasternodePayments::ProcessBlock() Found by FindOldestNotInVec \n");
|
||||
if (pmn != nullptr) {
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Found by FindOldestNotInVec \n");
|
||||
|
||||
newWinner.nBlockHeight = nBlockHeight;
|
||||
|
||||
CScript payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
|
||||
const CScript payee = GetScriptForDestination(pmn->pubKeyCollateralAddress.GetID());
|
||||
newWinner.AddPayee(payee);
|
||||
|
||||
CTxDestination address1;
|
||||
ExtractDestination(payee, address1);
|
||||
CBitcoinAddress address2(address1);
|
||||
|
||||
LogPrint("masternode","CMasternodePayments::ProcessBlock() Winner payee %s nHeight %d. \n", address2.ToString().c_str(), newWinner.nBlockHeight);
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Winner payee %s nHeight %d. \n",
|
||||
address2.ToString().c_str(), newWinner.nBlockHeight);
|
||||
} else {
|
||||
LogPrint("masternode","CMasternodePayments::ProcessBlock() Failed to find masternode to pay\n");
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() Failed to find masternode to pay\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -743,13 +818,13 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight)
|
||||
CKey keyMasternode;
|
||||
|
||||
if (!obfuScationSigner.SetKey(strMasterNodePrivKey, errorMessage, keyMasternode, pubKeyMasternode)) {
|
||||
LogPrint("masternode","CMasternodePayments::ProcessBlock() - Error upon calling SetKey: %s\n", errorMessage.c_str());
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() - Error upon calling SetKey: %s\n", errorMessage.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
LogPrint("masternode","CMasternodePayments::ProcessBlock() - Signing Winner\n");
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() - Signing Winner\n");
|
||||
if (newWinner.Sign(keyMasternode, pubKeyMasternode)) {
|
||||
LogPrint("masternode","CMasternodePayments::ProcessBlock() - AddWinningMasternode\n");
|
||||
LogPrint("masternode", "CMasternodePayments::ProcessBlock() - AddWinningMasternode\n");
|
||||
|
||||
if (AddWinningMasternode(newWinner)) {
|
||||
newWinner.Relay();
|
||||
@@ -771,12 +846,14 @@ bool CMasternodePaymentWinner::SignatureValid()
|
||||
{
|
||||
CMasternode* pmn = mnodeman.Find(vinMasternode);
|
||||
|
||||
if (pmn != NULL) {
|
||||
std::string strMessage = vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
|
||||
if (pmn != nullptr) {
|
||||
const std::string strMessage =
|
||||
vinMasternode.prevout.ToStringShort() + std::to_string(nBlockHeight) + payee.ToString();
|
||||
|
||||
std::string errorMessage = "";
|
||||
std::string errorMessage;
|
||||
if (!obfuScationSigner.VerifyMessage(pmn->pubKeyMasternode, vchSig, strMessage, errorMessage)) {
|
||||
return error("CMasternodePaymentWinner::SignatureValid() - Got bad Masternode address signature %s\n", vinMasternode.prevout.hash.ToString());
|
||||
return error("CMasternodePaymentWinner::SignatureValid() - Got bad Masternode address signature %s\n",
|
||||
vinMasternode.prevout.hash.ToString());
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -792,36 +869,38 @@ void CMasternodePayments::Sync(CNode* node, int nCountNeeded)
|
||||
int nHeight;
|
||||
{
|
||||
TRY_LOCK(cs_main, locked);
|
||||
if (!locked || chainActive.Tip() == NULL) return;
|
||||
if (!locked || chainActive.Tip() == nullptr) {
|
||||
return;
|
||||
}
|
||||
nHeight = chainActive.Tip()->nHeight;
|
||||
}
|
||||
|
||||
int nCount = (mnodeman.CountEnabled() * 1.25);
|
||||
if (nCountNeeded > nCount) nCountNeeded = nCount;
|
||||
int nCount = static_cast<int>(mnodeman.CountEnabled() * 1.25);
|
||||
if (nCountNeeded > nCount) {
|
||||
nCountNeeded = nCount;
|
||||
}
|
||||
|
||||
int nInvCount = 0;
|
||||
std::map<uint256, CMasternodePaymentWinner>::iterator it = mapMasternodePayeeVotes.begin();
|
||||
while (it != mapMasternodePayeeVotes.end()) {
|
||||
CMasternodePaymentWinner winner = (*it).second;
|
||||
const CMasternodePaymentWinner& winner = (*it).second;
|
||||
if (winner.nBlockHeight >= nHeight - nCountNeeded && winner.nBlockHeight <= nHeight + 20) {
|
||||
node->PushInventory(CInv(MSG_MASTERNODE_WINNER, winner.GetHash()));
|
||||
nInvCount++;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
node->PushMessage("ssc", MASTERNODE_SYNC_MNW, nInvCount);
|
||||
}
|
||||
|
||||
std::string CMasternodePayments::ToString() const
|
||||
{
|
||||
std::ostringstream info;
|
||||
|
||||
info << "Votes: " << (int)mapMasternodePayeeVotes.size() << ", Blocks: " << (int)mapMasternodeBlocks.size();
|
||||
|
||||
return info.str();
|
||||
}
|
||||
|
||||
|
||||
int CMasternodePayments::GetOldestBlock()
|
||||
{
|
||||
LOCK(cs_mapMasternodeBlocks);
|
||||
@@ -833,13 +912,12 @@ int CMasternodePayments::GetOldestBlock()
|
||||
if ((*it).first < nOldestBlock) {
|
||||
nOldestBlock = (*it).first;
|
||||
}
|
||||
it++;
|
||||
++it;
|
||||
}
|
||||
|
||||
return nOldestBlock;
|
||||
}
|
||||
|
||||
|
||||
int CMasternodePayments::GetNewestBlock()
|
||||
{
|
||||
LOCK(cs_mapMasternodeBlocks);
|
||||
@@ -851,7 +929,7 @@ int CMasternodePayments::GetNewestBlock()
|
||||
if ((*it).first > nNewestBlock) {
|
||||
nNewestBlock = (*it).first;
|
||||
}
|
||||
it++;
|
||||
++it;
|
||||
}
|
||||
|
||||
return nNewestBlock;
|
||||
|
||||
Reference in New Issue
Block a user