Refactor MN payee logic in preparation for DIP3 (#2215)

* Refactor block payee filling/validation

1. Move out old budget validation into it's own function (IsOldBudgetBlockValueValid)
2. Refactor IsBlockValueValid to bail out early instead of using deep
   nested if/else blocks. IMHO, I feel that this makes the code much easier
   to read and less error prone.
3. Refactor/rename CreateSuperblock and CMasternodePayments::FillBlockPayee
   to be getters without actually modifying the coinbase TX. The coinbase
   is now only modified from the global FillBlockPayments function. Makes
   later changes in DIP3 easier (allowing superblock and MN rewards in same block)

* Use __func__ for logging in block payee code

* Fix code style nit
This commit is contained in:
Alexander Block 2018-08-12 17:27:09 +02:00 committed by UdjinM6
parent d946f21bd9
commit 4d3518fe04
4 changed files with 186 additions and 154 deletions

View File

@ -366,14 +366,14 @@ bool CSuperblockManager::GetBestSuperblock(CSuperblock_sptr& pSuperblockRet, int
}
/**
* Create Superblock Payments
* Get Superblock Payments
*
* - Create the correct payment structure for a given superblock
* - Returns payments for superblock
*/
void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNewRet, int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet)
bool CSuperblockManager::GetSuperblockPayments(int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet)
{
DBG( std::cout << "CSuperblockManager::CreateSuperblock Start" << std::endl; );
DBG( std::cout << "CSuperblockManager::GetSuperblockPayments Start" << std::endl; );
LOCK(governance.cs);
@ -381,18 +381,18 @@ void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNewRet, int nBl
CSuperblock_sptr pSuperblock;
if(!CSuperblockManager::GetBestSuperblock(pSuperblock, nBlockHeight)) {
LogPrint("gobject", "CSuperblockManager::CreateSuperblock -- Can't find superblock for height %d\n", nBlockHeight);
DBG( std::cout << "CSuperblockManager::CreateSuperblock Failed to get superblock for height, returning" << std::endl; );
return;
LogPrint("gobject", "CSuperblockManager::GetSuperblockPayments -- Can't find superblock for height %d\n", nBlockHeight);
DBG( std::cout << "CSuperblockManager::GetSuperblockPayments Failed to get superblock for height, returning" << std::endl; );
return false;
}
// make sure it's empty, just in case
voutSuperblockRet.clear();
// CONFIGURE SUPERBLOCK OUTPUTS
// GET SUPERBLOCK OUTPUTS
// Superblock payments are appended to the end of the coinbase vout vector
DBG( std::cout << "CSuperblockManager::CreateSuperblock Number payments: " << pSuperblock->CountPayments() << std::endl; );
// Superblock payments will be appended to the end of the coinbase vout vector
DBG( std::cout << "CSuperblockManager::GetSuperblockPayments Number payments: " << pSuperblock->CountPayments() << std::endl; );
// TODO: How many payments can we add before things blow up?
// Consider at least following limits:
@ -400,13 +400,12 @@ void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNewRet, int nBl
// - max "budget" available
for(int i = 0; i < pSuperblock->CountPayments(); i++) {
CGovernancePayment payment;
DBG( std::cout << "CSuperblockManager::CreateSuperblock i = " << i << std::endl; );
DBG( std::cout << "CSuperblockManager::GetSuperblockPayments i = " << i << std::endl; );
if(pSuperblock->GetPayment(i, payment)) {
DBG( std::cout << "CSuperblockManager::CreateSuperblock Payment found " << std::endl; );
DBG( std::cout << "CSuperblockManager::GetSuperblockPayments Payment found " << std::endl; );
// SET COINBASE OUTPUT TO SUPERBLOCK SETTING
CTxOut txout = CTxOut(payment.nAmount, payment.script);
txNewRet.vout.push_back(txout);
voutSuperblockRet.push_back(txout);
// PRINT NICE LOG OUTPUT FOR SUPERBLOCK PAYMENT
@ -417,15 +416,17 @@ void CSuperblockManager::CreateSuperblock(CMutableTransaction& txNewRet, int nBl
// TODO: PRINT NICE N.N DASH OUTPUT
DBG( std::cout << "CSuperblockManager::CreateSuperblock Before LogPrintf call, nAmount = " << payment.nAmount << std::endl; );
DBG( std::cout << "CSuperblockManager::GetSuperblockPayments Before LogPrintf call, nAmount = " << payment.nAmount << std::endl; );
LogPrintf("NEW Superblock : output %d (addr %s, amount %d)\n", i, address2.ToString(), payment.nAmount);
DBG( std::cout << "CSuperblockManager::CreateSuperblock After LogPrintf call " << std::endl; );
DBG( std::cout << "CSuperblockManager::GetSuperblockPayments After LogPrintf call " << std::endl; );
} else {
DBG( std::cout << "CSuperblockManager::CreateSuperblock Payment not found " << std::endl; );
DBG( std::cout << "CSuperblockManager::GetSuperblockPayments Payment not found " << std::endl; );
}
}
DBG( std::cout << "CSuperblockManager::CreateSuperblock End" << std::endl; );
DBG( std::cout << "CSuperblockManager::GetSuperblockPayments End" << std::endl; );
return true;
}
bool CSuperblockManager::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
@ -679,7 +680,7 @@ bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount b
int nOutputs = txNew.vout.size();
int nPayments = CountPayments();
int nMinerPayments = nOutputs - nPayments;
int nMinerAndMasternodePayments = nOutputs - nPayments;
LogPrint("gobject", "CSuperblock::IsValid nOutputs = %d, nPayments = %d, GetDataAsHexString = %s\n",
nOutputs, nPayments, GetGovernanceObject()->GetDataAsHexString());
@ -687,7 +688,7 @@ bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount b
// We require an exact match (including order) between the expected
// superblock payments and the payments actually in the block.
if(nMinerPayments < 0) {
if(nMinerAndMasternodePayments < 0) {
// This means the block cannot have all the superblock payments
// so it is not valid.
// TODO: could that be that we just hit coinbase size limit?
@ -703,7 +704,7 @@ bool CSuperblock::IsValid(const CTransaction& txNew, int nBlockHeight, CAmount b
return false;
}
// miner should not get more than he would usually get
// miner and masternodes should not get more than they would usually get
CAmount nBlockValue = txNew.GetValueOut();
if(nBlockValue > blockReward + nPaymentsTotalAmount) {
LogPrintf("CSuperblock::IsValid -- ERROR: Block invalid, block value limit exceeded: block %lld, limit %lld\n", nBlockValue, blockReward + nPaymentsTotalAmount);

View File

@ -67,7 +67,7 @@ public:
static bool IsSuperblockTriggered(int nBlockHeight);
static void CreateSuperblock(CMutableTransaction& txNewRet, int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet);
static bool GetSuperblockPayments(int nBlockHeight, std::vector<CTxOut>& voutSuperblockRet);
static void ExecuteBestSuperblock(int nBlockHeight);
static std::string GetRequiredPaymentsString(int nBlockHeight);

View File

@ -23,6 +23,45 @@ CCriticalSection cs_vecPayees;
CCriticalSection cs_mapMasternodeBlocks;
CCriticalSection cs_mapMasternodePaymentVotes;
bool IsOldBudgetBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockReward, std::string& strErrorRet) {
const Consensus::Params& consensusParams = Params().GetConsensus();
if (nBlockHeight >= consensusParams.nSuperblockStartBlock) {
// switched to new budget system (superblocks)
return true;
}
bool isBlockRewardValueMet = (block.vtx[0]->GetValueOut() <= blockReward);
// we are still using budgets, but we have no data about them anymore,
// all we know is predefined budget cycle and window
int nOffset = nBlockHeight % consensusParams.nBudgetPaymentsCycleBlocks;
if(nBlockHeight >= consensusParams.nBudgetPaymentsStartBlock &&
nOffset < consensusParams.nBudgetPaymentsWindowBlocks) {
// NOTE: old budget system is disabled since 12.1
if(masternodeSync.IsSynced()) {
// no old budget blocks should be accepted here on mainnet,
// testnet/devnet/regtest should produce regular blocks only
LogPrint("gobject", "%s -- WARNING: Client synced but old budget system is disabled, checking block value against block reward\n", __func__);
if(!isBlockRewardValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, old budgets are disabled",
nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
}
return isBlockRewardValueMet;
}
// when not synced, rely on online nodes (all networks)
LogPrint("gobject", "%s -- WARNING: Skipping old budget block value checks, accepting block\n", __func__);
return true;
}
// LogPrint("gobject", "%s -- Block is not in budget cycle window, checking block value against block reward\n", __func__);
if(!isBlockRewardValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, block is not in old budget cycle window",
nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
}
return isBlockRewardValueMet;
}
/**
* IsBlockValueValid
*
@ -38,105 +77,82 @@ bool IsBlockValueValid(const CBlock& block, int nBlockHeight, CAmount blockRewar
{
strErrorRet = "";
bool isBlockRewardValueMet = (block.vtx[0]->GetValueOut() <= blockReward);
if(fDebug) LogPrintf("block.vtx[0]->GetValueOut() %lld <= blockReward %lld\n", block.vtx[0]->GetValueOut(), blockReward);
// we are still using budgets, but we have no data about them anymore,
// all we know is predefined budget cycle and window
const Consensus::Params& consensusParams = Params().GetConsensus();
if(nBlockHeight < consensusParams.nSuperblockStartBlock) {
int nOffset = nBlockHeight % consensusParams.nBudgetPaymentsCycleBlocks;
if(nBlockHeight >= consensusParams.nBudgetPaymentsStartBlock &&
nOffset < consensusParams.nBudgetPaymentsWindowBlocks) {
// NOTE: old budget system is disabled since 12.1
if(masternodeSync.IsSynced()) {
// no old budget blocks should be accepted here on mainnet,
// testnet/devnet/regtest should produce regular blocks only
LogPrint("gobject", "IsBlockValueValid -- WARNING: Client synced but old budget system is disabled, checking block value against block reward\n");
if(!isBlockRewardValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, old budgets are disabled",
nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
}
return isBlockRewardValueMet;
}
// when not synced, rely on online nodes (all networks)
LogPrint("gobject", "IsBlockValueValid -- WARNING: Skipping old budget block value checks, accepting block\n");
return true;
}
// LogPrint("gobject", "IsBlockValueValid -- Block is not in budget cycle window, checking block value against block reward\n");
if(!isBlockRewardValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, block is not in old budget cycle window",
nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
}
return isBlockRewardValueMet;
if (!IsOldBudgetBlockValueValid(block, nBlockHeight, blockReward, strErrorRet)) {
return false;
}
// superblocks started
bool isBlockRewardValueMet = (block.vtx[0]->GetValueOut() <= blockReward);
if(fDebug) LogPrintf("block.vtx[0]->GetValueOut() %lld <= blockReward %lld\n", block.vtx[0]->GetValueOut(), blockReward);
CAmount nSuperblockMaxValue = blockReward + CSuperblock::GetPaymentsLimit(nBlockHeight);
bool isSuperblockMaxValueMet = (block.vtx[0]->GetValueOut() <= nSuperblockMaxValue);
LogPrint("gobject", "block.vtx[0]->GetValueOut() %lld <= nSuperblockMaxValue %lld\n", block.vtx[0]->GetValueOut(), nSuperblockMaxValue);
if(!masternodeSync.IsSynced() || fLiteMode) {
// not enough data but at least it must NOT exceed superblock max value
if(CSuperblock::IsValidBlockHeight(nBlockHeight)) {
if(fDebug) LogPrintf("IsBlockPayeeValid -- WARNING: Not enough data, checking superblock max bounds only\n");
if(!isSuperblockMaxValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded superblock max value",
nBlockHeight, block.vtx[0]->GetValueOut(), nSuperblockMaxValue);
}
return isSuperblockMaxValueMet;
}
if(!isBlockRewardValueMet) {
if (!CSuperblock::IsValidBlockHeight(nBlockHeight)) {
// can't possibly be a superblock, so lets just check for block reward limits
if (!isBlockRewardValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, only regular blocks are allowed at this height",
nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
}
// it MUST be a regular block otherwise
return isBlockRewardValueMet;
}
// we are synced, let's try to check as much data as we can
// bail out in case superblock limits were exceeded
if (!isSuperblockMaxValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded superblock max value",
nBlockHeight, block.vtx[0]->GetValueOut(), nSuperblockMaxValue);
return false;
}
if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) {
if(CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
if(CSuperblockManager::IsValid(*block.vtx[0], nBlockHeight, blockReward)) {
LogPrint("gobject", "IsBlockValueValid -- Valid superblock at height %d: %s", nBlockHeight, block.vtx[0]->ToString());
// all checks are done in CSuperblock::IsValid, nothing to do here
return true;
}
if(!masternodeSync.IsSynced() || fLiteMode) {
if(fDebug) LogPrintf("%s -- WARNING: Not enough data, checked superblock max bounds only\n", __func__);
// not enough data for full checks but at least we know that the superblock limits were honored.
// We rely on the network to have followed the correct chain in this case
return true;
}
// triggered but invalid? that's weird
LogPrintf("IsBlockValueValid -- ERROR: Invalid superblock detected at height %d: %s", nBlockHeight, block.vtx[0]->ToString());
// should NOT allow invalid superblocks, when superblocks are enabled
strErrorRet = strprintf("invalid superblock detected at height %d", nBlockHeight);
return false;
}
LogPrint("gobject", "IsBlockValueValid -- No triggered superblock detected at height %d\n", nBlockHeight);
if(!isBlockRewardValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, no triggered superblock detected",
nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
}
} else {
// we are synced and possibly on a superblock now
if (!sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) {
// should NOT allow superblocks at all, when superblocks are disabled
LogPrint("gobject", "IsBlockValueValid -- Superblocks are disabled, no superblocks allowed\n");
// revert to block reward limits in this case
LogPrint("gobject", "%s -- Superblocks are disabled, no superblocks allowed\n", __func__);
if(!isBlockRewardValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, superblocks are disabled",
nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
}
return isBlockRewardValueMet;
}
// it MUST be a regular block
return isBlockRewardValueMet;
if (!CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
// we are on a valid superblock height but a superblock was not triggered
// revert to block reward limits in this case
if(!isBlockRewardValueMet) {
strErrorRet = strprintf("coinbase pays too much at height %d (actual=%d vs limit=%d), exceeded block reward, no triggered superblock detected",
nBlockHeight, block.vtx[0]->GetValueOut(), blockReward);
}
return isBlockRewardValueMet;
}
// this actually also checks for correct payees and not only amount
if (!CSuperblockManager::IsValid(*block.vtx[0], nBlockHeight, blockReward)) {
// triggered but invalid? that's weird
LogPrintf("%s -- ERROR: Invalid superblock detected at height %d: %s", __func__, nBlockHeight, block.vtx[0]->ToString());
// should NOT allow invalid superblocks, when superblocks are enabled
strErrorRet = strprintf("invalid superblock detected at height %d", nBlockHeight);
return false;
}
// we got a valid superblock
return true;
}
bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward)
{
if(!masternodeSync.IsSynced() || fLiteMode) {
//there is no budget data to use to check anything, let's just accept the longest chain
if(fDebug) LogPrintf("IsBlockPayeeValid -- WARNING: Not enough data, skipping block payee checks\n");
if(fDebug) LogPrintf("%s -- WARNING: Not enough data, skipping block payee checks\n", __func__);
return true;
}
@ -149,7 +165,7 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc
// NOTE: old budget system is disabled since 12.1 and we should never enter this branch
// anymore when sync is finished (on mainnet). We have no old budget data but these blocks
// have tons of confirmations and can be safely accepted without payee verification
LogPrint("gobject", "IsBlockPayeeValid -- WARNING: Client synced but old budget system is disabled, accepting any payee\n");
LogPrint("gobject", "%s -- WARNING: Client synced but old budget system is disabled, accepting any payee\n", __func__);
return true;
}
@ -159,33 +175,33 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int nBlockHeight, CAmount bloc
if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) {
if(CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
if(CSuperblockManager::IsValid(txNew, nBlockHeight, blockReward)) {
LogPrint("gobject", "IsBlockPayeeValid -- Valid superblock at height %d: %s", nBlockHeight, txNew.ToString());
LogPrint("gobject", "%s -- Valid superblock at height %d: %s", __func__, nBlockHeight, txNew.ToString());
return true;
} else {
LogPrintf("%s -- ERROR: Invalid superblock detected at height %d: %s", __func__, nBlockHeight, txNew.ToString());
// should NOT allow such superblocks, when superblocks are enabled
return false;
}
LogPrintf("IsBlockPayeeValid -- ERROR: Invalid superblock detected at height %d: %s", nBlockHeight, txNew.ToString());
// should NOT allow such superblocks, when superblocks are enabled
return false;
} else {
LogPrint("gobject", "%s -- No triggered superblock detected at height %d\n", __func__, nBlockHeight);
}
// continue validation, should pay MN
LogPrint("gobject", "IsBlockPayeeValid -- No triggered superblock detected at height %d\n", nBlockHeight);
} else {
// should NOT allow superblocks at all, when superblocks are disabled
LogPrint("gobject", "IsBlockPayeeValid -- Superblocks are disabled, no superblocks allowed\n");
LogPrint("gobject", "%s -- Superblocks are disabled, no superblocks allowed\n", __func__);
}
// IF THIS ISN'T A SUPERBLOCK OR SUPERBLOCK IS INVALID, IT SHOULD PAY A MASTERNODE DIRECTLY
if(mnpayments.IsTransactionValid(txNew, nBlockHeight)) {
LogPrint("mnpayments", "IsBlockPayeeValid -- Valid masternode payment at height %d: %s", nBlockHeight, txNew.ToString());
// If this isn't a superblock or spork15 is activated, check for correct masternode payment
if(mnpayments.IsTransactionValid(txNew, nBlockHeight, blockReward)) {
LogPrint("mnpayments", "%s -- Valid masternode payment at height %d: %s", __func__, nBlockHeight, txNew.ToString());
return true;
}
if(sporkManager.IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)) {
LogPrintf("IsBlockPayeeValid -- ERROR: Invalid masternode payment detected at height %d: %s", nBlockHeight, txNew.ToString());
LogPrintf("%s -- ERROR: Invalid masternode payment detected at height %d: %s", __func__, nBlockHeight, txNew.ToString());
return false;
}
LogPrintf("IsBlockPayeeValid -- WARNING: Masternode payment enforcement is disabled, accepting any payee\n");
LogPrintf("%s -- WARNING: Masternode payment enforcement is disabled, accepting any payee\n", __func__);
return true;
}
@ -195,14 +211,33 @@ void FillBlockPayments(CMutableTransaction& txNew, int nBlockHeight, CAmount blo
// (height should be validated inside)
if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED) &&
CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
LogPrint("gobject", "FillBlockPayments -- triggered superblock creation at height %d\n", nBlockHeight);
CSuperblockManager::CreateSuperblock(txNew, nBlockHeight, voutSuperblockRet);
return;
LogPrint("gobject", "%s -- triggered superblock creation at height %d\n", __func__, nBlockHeight);
CSuperblockManager::GetSuperblockPayments(nBlockHeight, voutSuperblockRet);
}
// FILL BLOCK PAYEE WITH MASTERNODE PAYMENT OTHERWISE
mnpayments.FillBlockPayee(txNew, nBlockHeight, blockReward, txoutMasternodeRet);
LogPrint("mnpayments", "FillBlockPayments -- nBlockHeight %d blockReward %lld txoutMasternodeRet %s txNew %s",
// TODO this is a placeholder until DIP3 is merged, which will allow superblock payments and MN reward payments
// in the same block. We set this to false for now, which means that we'll always get into the next if statement
// when a superblock payment is present
bool allowSuperblockAndMNReward = false;
// don't allow payments to superblocks AND masternodes before spork15 activation
if (!voutSuperblockRet.empty() && !allowSuperblockAndMNReward) {
txNew.vout.insert(txNew.vout.end(), voutSuperblockRet.begin(), voutSuperblockRet.end());
return;
}
if (!mnpayments.GetMasternodeTxOut(nBlockHeight, blockReward, txoutMasternodeRet)) {
// no idea whom to pay (MN list empty?), lets hope for the best
return;
}
txNew.vout.emplace_back(txoutMasternodeRet);
txNew.vout.insert(txNew.vout.end(), voutSuperblockRet.begin(), voutSuperblockRet.end());
// subtract MN payment from miner reward
txNew.vout[0].nValue -= txoutMasternodeRet.nValue;
LogPrint("mnpayments", "%s -- nBlockHeight %d blockReward %lld txoutMasternodeRet %s txNew %s", __func__,
nBlockHeight, blockReward, txoutMasternodeRet.ToString(), txNew.ToString());
}
@ -244,10 +279,10 @@ bool CMasternodePayments::UpdateLastVote(const CMasternodePaymentVote& vote)
/**
* FillBlockPayee
*
* Fill Masternode ONLY payment block
* Get masternode payment tx output
*/
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet) const
bool CMasternodePayments::GetMasternodeTxOut(int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet) const
{
// make sure it's not filled yet
txoutMasternodeRet = CTxOut();
@ -260,8 +295,8 @@ void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int nBlockH
masternode_info_t mnInfo;
if(!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) {
// ...and we can't calculate it on our own
LogPrintf("CMasternodePayments::FillBlockPayee -- Failed to detect masternode to pay\n");
return;
LogPrintf("CMasternodePayments::%s -- Failed to detect masternode to pay\n", __func__);
return false;
}
// fill payee with locally calculated winner and hope for the best
payee = GetScriptForDestination(mnInfo.keyIDCollateralAddress);
@ -269,18 +304,15 @@ void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int nBlockH
// GET MASTERNODE PAYMENT VARIABLES SETUP
CAmount masternodePayment = GetMasternodePayment(nBlockHeight, blockReward);
// split reward between miner ...
txNew.vout[0].nValue -= masternodePayment;
// ... and masternode
txoutMasternodeRet = CTxOut(masternodePayment, payee);
txNew.vout.push_back(txoutMasternodeRet);
CTxDestination address1;
ExtractDestination(payee, address1);
CBitcoinAddress address2(address1);
LogPrintf("CMasternodePayments::FillBlockPayee -- Masternode payment %lld to %s\n", masternodePayment, address2.ToString());
LogPrintf("CMasternodePayments::%s -- Masternode payment %lld to %s\n", __func__, masternodePayment, address2.ToString());
return true;
}
int CMasternodePayments::GetMinMasternodePaymentsProto() const {
@ -445,12 +477,12 @@ bool CMasternodePaymentVote::Sign()
uint256 hash = GetSignatureHash();
if(!CHashSigner::SignHash(hash, activeMasternodeInfo.keyMasternode, vchSig)) {
LogPrintf("CMasternodePaymentVote::Sign -- SignHash() failed\n");
LogPrintf("CMasternodePaymentVote::%s -- SignHash() failed\n", __func__);
return false;
}
if (!CHashSigner::VerifyHash(hash, activeMasternodeInfo.keyIDMasternode, vchSig, strError)) {
LogPrintf("CMasternodePaymentVote::Sign -- VerifyHash() failed, error: %s\n", strError);
LogPrintf("CMasternodePaymentVote::%s -- VerifyHash() failed, error: %s\n", __func__, strError);
return false;
}
} else {
@ -459,12 +491,12 @@ bool CMasternodePaymentVote::Sign()
ScriptToAsmStr(payee);
if(!CMessageSigner::SignMessage(strMessage, vchSig, activeMasternodeInfo.keyMasternode)) {
LogPrintf("CMasternodePaymentVote::Sign -- SignMessage() failed\n");
LogPrintf("CMasternodePaymentVote::%s -- SignMessage() failed\n", __func__);
return false;
}
if(!CMessageSigner::VerifyMessage(activeMasternodeInfo.keyIDMasternode, vchSig, strMessage, strError)) {
LogPrintf("CMasternodePaymentVote::Sign -- VerifyMessage() failed, error: %s\n", strError);
LogPrintf("CMasternodePaymentVote::%s -- VerifyMessage() failed, error: %s\n", __func__, strError);
return false;
}
}
@ -518,7 +550,7 @@ bool CMasternodePayments::AddOrUpdatePaymentVote(const CMasternodePaymentVote& v
auto it = mapMasternodeBlocks.emplace(vote.nBlockHeight, CMasternodeBlockPayees(vote.nBlockHeight)).first;
it->second.AddPayee(vote);
LogPrint("mnpayments", "CMasternodePayments::AddOrUpdatePaymentVote -- added, hash=%s\n", nVoteHash.ToString());
LogPrint("mnpayments", "CMasternodePayments::%s -- added, hash=%s\n", __func__, nVoteHash.ToString());
return true;
}
@ -551,7 +583,7 @@ bool CMasternodeBlockPayees::GetBestPayee(CScript& payeeRet) const
LOCK(cs_vecPayees);
if(vecPayees.empty()) {
LogPrint("mnpayments", "CMasternodeBlockPayees::GetBestPayee -- ERROR: couldn't find any payee\n");
LogPrint("mnpayments", "CMasternodeBlockPayees::%s -- ERROR: couldn't find any payee\n", __func__);
return false;
}
@ -576,7 +608,7 @@ bool CMasternodeBlockPayees::HasPayeeWithVotes(const CScript& payeeIn, int nVote
}
}
LogPrint("mnpayments", "CMasternodeBlockPayees::HasPayeeWithVotes -- ERROR: couldn't find any payee with %d+ votes\n", nVotesReq);
LogPrint("mnpayments", "CMasternodeBlockPayees::%s -- ERROR: couldn't find any payee with %d+ votes\n", __func__, nVotesReq);
return false;
}
@ -604,7 +636,7 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew) const
if (payee.GetVoteCount() >= MNPAYMENTS_SIGNATURES_REQUIRED) {
for (const auto& txout : txNew.vout) {
if (payee.GetPayee() == txout.scriptPubKey && nMasternodePayment == txout.nValue) {
LogPrint("mnpayments", "CMasternodeBlockPayees::IsTransactionValid -- Found required payment\n");
LogPrint("mnpayments", "CMasternodeBlockPayees::%s -- Found required payment\n", __func__);
return true;
}
}
@ -621,7 +653,7 @@ bool CMasternodeBlockPayees::IsTransactionValid(const CTransaction& txNew) const
}
}
LogPrintf("CMasternodeBlockPayees::IsTransactionValid -- ERROR: Missing required payment, possible payees: '%s', amount: %f DASH\n", strPayeesPossible, (float)nMasternodePayment/COIN);
LogPrintf("CMasternodeBlockPayees::%s -- ERROR: Missing required payment, possible payees: '%s', amount: %f DASH\n", __func__, strPayeesPossible, (float)nMasternodePayment/COIN);
return false;
}
@ -657,10 +689,9 @@ std::string CMasternodePayments::GetRequiredPaymentsString(int nBlockHeight) con
return it == mapMasternodeBlocks.end() ? "Unknown" : it->second.GetRequiredPaymentsString();
}
bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlockHeight) const
bool CMasternodePayments::IsTransactionValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) const
{
LOCK(cs_mapMasternodeBlocks);
const auto it = mapMasternodeBlocks.find(nBlockHeight);
return it == mapMasternodeBlocks.end() ? true : it->second.IsTransactionValid(txNew);
}
@ -678,14 +709,14 @@ void CMasternodePayments::CheckAndRemove()
CMasternodePaymentVote vote = (*it).second;
if(nCachedBlockHeight - vote.nBlockHeight > nLimit) {
LogPrint("mnpayments", "CMasternodePayments::CheckAndRemove -- Removing old Masternode payment: nBlockHeight=%d\n", vote.nBlockHeight);
LogPrint("mnpayments", "CMasternodePayments::%s -- Removing old Masternode payment: nBlockHeight=%d\n", __func__, vote.nBlockHeight);
mapMasternodePaymentVotes.erase(it++);
mapMasternodeBlocks.erase(vote.nBlockHeight);
} else {
++it;
}
}
LogPrintf("CMasternodePayments::CheckAndRemove -- %s\n", ToString());
LogPrintf("CMasternodePayments::%s -- %s\n", __func__, ToString());
}
bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::string& strError, CConnman& connman) const
@ -723,7 +754,7 @@ bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::s
int nRank;
if(!mnodeman.GetMasternodeRank(masternodeOutpoint, nRank, nBlockHeight - 101, nMinRequiredProtocol)) {
LogPrint("mnpayments", "CMasternodePaymentVote::IsValid -- Can't calculate rank for masternode %s\n",
LogPrint("mnpayments", "CMasternodePaymentVote::%s -- Can't calculate rank for masternode %s\n", __func__,
masternodeOutpoint.ToStringShort());
return false;
}
@ -736,7 +767,7 @@ bool CMasternodePaymentVote::IsValid(CNode* pnode, int nValidationHeight, std::s
if(nRank > MNPAYMENTS_SIGNATURES_TOTAL*2 && nBlockHeight > nValidationHeight) {
LOCK(cs_main);
strError = strprintf("Masternode %s is not in the top %d (%d)", masternodeOutpoint.ToStringShort(), MNPAYMENTS_SIGNATURES_TOTAL*2, nRank);
LogPrintf("CMasternodePaymentVote::IsValid -- Error: %s\n", strError);
LogPrintf("CMasternodePaymentVote::%s -- Error: %s\n", __func__, strError);
Misbehaving(pnode->GetId(), 20);
}
// Still invalid however
@ -760,30 +791,30 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight, CConnman& connman)
int nRank;
if (!mnodeman.GetMasternodeRank(activeMasternodeInfo.outpoint, nRank, nBlockHeight - 101, GetMinMasternodePaymentsProto())) {
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock -- Unknown Masternode\n");
LogPrint("mnpayments", "CMasternodePayments::%s -- Unknown Masternode\n", __func__);
return false;
}
if (nRank > MNPAYMENTS_SIGNATURES_TOTAL) {
LogPrint("mnpayments", "CMasternodePayments::ProcessBlock -- Masternode not in the top %d (%d)\n", MNPAYMENTS_SIGNATURES_TOTAL, nRank);
LogPrint("mnpayments", "CMasternodePayments::%s -- Masternode not in the top %d (%d)\n", __func__, MNPAYMENTS_SIGNATURES_TOTAL, nRank);
return false;
}
// LOCATE THE NEXT MASTERNODE WHICH SHOULD BE PAID
LogPrintf("CMasternodePayments::ProcessBlock -- Start: nBlockHeight=%d, masternode=%s\n", nBlockHeight, activeMasternodeInfo.outpoint.ToStringShort());
LogPrintf("CMasternodePayments::%s -- Start: nBlockHeight=%d, masternode=%s\n", __func__, nBlockHeight, activeMasternodeInfo.outpoint.ToStringShort());
// 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;
masternode_info_t mnInfo;
if (!mnodeman.GetNextMasternodeInQueueForPayment(nBlockHeight, true, nCount, mnInfo)) {
LogPrintf("CMasternodePayments::ProcessBlock -- ERROR: Failed to find masternode to pay\n");
LogPrintf("CMasternodePayments::%s -- ERROR: Failed to find masternode to pay\n", __func__);
return false;
}
LogPrintf("CMasternodePayments::ProcessBlock -- Masternode found by GetNextMasternodeInQueueForPayment(): %s\n", mnInfo.outpoint.ToStringShort());
LogPrintf("CMasternodePayments::%s -- Masternode found by GetNextMasternodeInQueueForPayment(): %s\n", __func__, mnInfo.outpoint.ToStringShort());
CScript payee = GetScriptForDestination(mnInfo.keyIDCollateralAddress);
@ -794,13 +825,13 @@ bool CMasternodePayments::ProcessBlock(int nBlockHeight, CConnman& connman)
ExtractDestination(payee, address1);
CBitcoinAddress address2(address1);
LogPrintf("CMasternodePayments::ProcessBlock -- vote: payee=%s, nBlockHeight=%d\n", address2.ToString(), nBlockHeight);
LogPrintf("CMasternodePayments::%s -- vote: payee=%s, nBlockHeight=%d\n", address2.ToString(), nBlockHeight);
// SIGN MESSAGE TO NETWORK WITH OUR MASTERNODE KEYS
LogPrintf("CMasternodePayments::ProcessBlock -- Signing vote\n");
LogPrintf("CMasternodePayments::%s -- Signing vote\n", __func__);
if (voteNew.Sign()) {
LogPrintf("CMasternodePayments::ProcessBlock -- AddOrUpdatePaymentVote()\n");
LogPrintf("CMasternodePayments::%s -- AddOrUpdatePaymentVote()\n", __func__);
if (AddOrUpdatePaymentVote(voteNew)) {
voteNew.Relay(connman);
@ -817,13 +848,13 @@ void CMasternodePayments::CheckBlockVotes(int nBlockHeight)
CMasternodeMan::rank_pair_vec_t mns;
if (!mnodeman.GetMasternodeRanks(mns, nBlockHeight - 101, GetMinMasternodePaymentsProto())) {
LogPrintf("CMasternodePayments::CheckBlockVotes -- nBlockHeight=%d, GetMasternodeRanks failed\n", nBlockHeight);
LogPrintf("CMasternodePayments::%s -- nBlockHeight=%d, GetMasternodeRanks failed\n", __func__, nBlockHeight);
return;
}
std::string debugStr;
debugStr += strprintf("CMasternodePayments::CheckBlockVotes -- nBlockHeight=%d,\n Expected voting MNs:\n", nBlockHeight);
debugStr += strprintf("CMasternodePayments::%s -- nBlockHeight=%d,\n Expected voting MNs:\n", __func__, nBlockHeight);
LOCK2(cs_mapMasternodeBlocks, cs_mapMasternodePaymentVotes);
@ -885,7 +916,7 @@ void CMasternodePaymentVote::Relay(CConnman& connman) const
{
// Do not relay until fully synced
if(!masternodeSync.IsSynced()) {
LogPrint("mnpayments", "CMasternodePayments::Relay -- won't relay until fully synced\n");
LogPrint("mnpayments", "CMasternodePayments::%s -- won't relay until fully synced\n", __func__);
return;
}
@ -974,7 +1005,7 @@ void CMasternodePayments::Sync(CNode* pnode, CConnman& connman) const
}
}
LogPrintf("CMasternodePayments::Sync -- Sent %d votes to peer=%d\n", nInvCount, pnode->id);
LogPrintf("CMasternodePayments::%s -- Sent %d votes to peer=%d\n", __func__, nInvCount, pnode->id);
CNetMsgMaker msgMaker(pnode->GetSendVersion());
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::SYNCSTATUSCOUNT, MASTERNODE_SYNC_MNW, nInvCount));
}
@ -999,7 +1030,7 @@ void CMasternodePayments::RequestLowDataPaymentBlocks(CNode* pnode, CConnman& co
vToFetch.push_back(CInv(MSG_MASTERNODE_PAYMENT_BLOCK, pindex->GetBlockHash()));
// We should not violate GETDATA rules
if(vToFetch.size() == MAX_INV_SZ) {
LogPrintf("CMasternodePayments::RequestLowDataPaymentBlocks -- asking peer=%d for %d blocks\n", pnode->id, MAX_INV_SZ);
LogPrintf("CMasternodePayments::%s -- asking peer=%d for %d blocks\n", __func__, pnode->id, MAX_INV_SZ);
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
// Start filling new batch
vToFetch.clear();
@ -1045,7 +1076,7 @@ void CMasternodePayments::RequestLowDataPaymentBlocks(CNode* pnode, CConnman& co
}
// We should not violate GETDATA rules
if(vToFetch.size() == MAX_INV_SZ) {
LogPrintf("CMasternodePayments::RequestLowDataPaymentBlocks -- asking peer=%d for %d payment blocks\n", pnode->id, MAX_INV_SZ);
LogPrintf("CMasternodePayments::%s -- asking peer=%d for %d payment blocks\n", __func__, pnode->id, MAX_INV_SZ);
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
// Start filling new batch
vToFetch.clear();
@ -1053,7 +1084,7 @@ void CMasternodePayments::RequestLowDataPaymentBlocks(CNode* pnode, CConnman& co
}
// Ask for the rest of it
if(!vToFetch.empty()) {
LogPrintf("CMasternodePayments::RequestLowDataPaymentBlocks -- asking peer=%d for %d payment blocks\n", pnode->id, vToFetch.size());
LogPrintf("CMasternodePayments::%s -- asking peer=%d for %d payment blocks\n", __func__, pnode->id, vToFetch.size());
connman.PushMessage(pnode, msgMaker.Make(NetMsgType::GETDATA, vToFetch));
}
}
@ -1085,7 +1116,7 @@ void CMasternodePayments::UpdatedBlockTip(const CBlockIndex *pindex, CConnman& c
if(!pindex) return;
nCachedBlockHeight = pindex->nHeight;
LogPrint("mnpayments", "CMasternodePayments::UpdatedBlockTip -- nCachedBlockHeight=%d\n", nCachedBlockHeight);
LogPrint("mnpayments", "CMasternodePayments::%s -- nCachedBlockHeight=%d\n", __func__, nCachedBlockHeight);
int nFutureBlock = nCachedBlockHeight + 10;

View File

@ -214,7 +214,7 @@ public:
void CheckAndRemove();
bool GetBlockPayee(int nBlockHeight, CScript& payeeRet) const;
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight) const;
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight, CAmount blockReward) const;
bool IsScheduled(const masternode_info_t& mnInfo, int nNotBlockHeight) const;
bool UpdateLastVote(const CMasternodePaymentVote& vote);
@ -222,7 +222,7 @@ public:
int GetMinMasternodePaymentsProto() const;
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
std::string GetRequiredPaymentsString(int nBlockHeight) const;
void FillBlockPayee(CMutableTransaction& txNew, int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet) const;
bool GetMasternodeTxOut(int nBlockHeight, CAmount blockReward, CTxOut& txoutMasternodeRet) const;
std::string ToString() const;
int GetBlockCount() const { return mapMasternodeBlocks.size(); }