src/masternode-payments.cpp
/**
* IsBlockValueValid
*
*   Determine if coinbase outgoing created money is the correct value
*
*   Why is this needed?
*   - In Martkist some blocks are superblocks, which output much higher amounts of coins
*   - Otherblocks are 10% lower in outgoing value, so in total, no extra coins are created
*   - When non-superblocks are detected, the normal schedule should be maintained
*/
IsBlockValueValid
Determine if coinbase outgoing created money is the correct value


IsBlockValueValid Determine if coinbase outgoing created money is the correct value
bool IsBlockValueValid(const CBlock& block, int nBlockHeight, const CAmount &blockReward, const CAmount &nFee, std::string& strErrorRet)
{
	const CAmount &blockRewardWithFee = blockReward + nFee;
    strErrorRet = "";
	bool isBlockRewardValueMet = (block.vtx[0]->GetValueOut() <= blockRewardWithFee);
	if (fDebug) LogPrintf("block.vtx[0].GetValueOut() %lld <= blockReward %lld\n", block.vtx[0]->GetValueOut(), blockRewardWithFee);
	CAmount nSuperblockMaxValue = blockRewardWithFee + 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) {
        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;
        }
		else {
			CAmount nTotalRewardWithMasternodes;
			GetBlockSubsidy(nBlockHeight, Params().GetConsensus(), nTotalRewardWithMasternodes, false, true, 1);
			if (block.vtx[0]->GetValueOut() > (nTotalRewardWithMasternodes+nFee)) {
				strErrorRet = strprintf("IsBlockValueValid: coinbase amount exceeds block subsidy schedule");
				return false;
			}
		}
        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(), blockRewardWithFee);
        }
        return isBlockRewardValueMet;
    }
    if(sporkManager.IsSporkActive(SPORK_9_SUPERBLOCKS_ENABLED)) {
        if(CSuperblockManager::IsSuperblockTriggered(nBlockHeight)) {
            if(CSuperblockManager::IsValid(*block.vtx[0], nBlockHeight, blockRewardWithFee)) {
                LogPrint("gobject", "IsBlockValueValid -- Valid superblock at height %d: %s", nBlockHeight, block.vtx[0]->ToString());
                return true;
            }
            LogPrintf("IsBlockValueValid -- ERROR: Invalid superblock detected at height %d: %s", nBlockHeight, block.vtx[0]->ToString());
            strErrorRet = strprintf("invalid superblock detected at height %d", nBlockHeight);
            return false;
        }
		else {
			CAmount nTotalRewardWithMasternodes;
			GetBlockSubsidy(nBlockHeight, Params().GetConsensus(), nTotalRewardWithMasternodes, false, true, 1);
			if (block.vtx[0]->GetValueOut() > (nTotalRewardWithMasternodes + nFee)) {
				strErrorRet = strprintf("IsBlockValueValid: coinbase amount exceeds block subsidy schedule");
				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(), blockRewardWithFee);
        }
    } else {
        LogPrint("gobject", "IsBlockValueValid -- Superblocks are disabled, no superblocks allowed\n");
        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(), blockRewardWithFee);
        }
    }
    return isBlockRewardValueMet;
}
bool IsBlockValueValid ( const CBlock & block , int nBlockHeight , const CAmount & blockReward , const CAmount & nFee , std :: string & strErrorRet ) { const CAmount & blockRewardWithFee = blockReward + nFee ; strErrorRet = " " ; bool isBlockRewardValueMet = ( block . vtx [ 0 ] -> GetValueOut ( ) <= blockRewardWithFee ) ; if ( fDebug ) LogPrintf ( " \n " , block . vtx [ 0 ] -> GetValueOut ( ) , blockRewardWithFee ) ; CAmount nSuperblockMaxValue = blockRewardWithFee + CSuperblock :: GetPaymentsLimit ( nBlockHeight ) ; bool isSuperblockMaxValueMet = ( block . vtx [ 0 ] -> GetValueOut ( ) <= nSuperblockMaxValue ) ; LogPrint ( " " , " \n " , block . vtx [ 0 ] -> GetValueOut ( ) , nSuperblockMaxValue ) ; if ( ! masternodeSync . IsSynced ( ) || fLiteMode ) { if ( CSuperblock :: IsValidBlockHeight ( nBlockHeight ) ) { if ( fDebug ) LogPrintf ( " \n " ) ; if ( ! isSuperblockMaxValueMet ) { strErrorRet = strprintf ( " " , nBlockHeight , block . vtx [ 0 ] -> GetValueOut ( ) , nSuperblockMaxValue ) ; } return isSuperblockMaxValueMet ; } else { CAmount nTotalRewardWithMasternodes ; GetBlockSubsidy ( nBlockHeight , Params ( ) . GetConsensus ( ) , nTotalRewardWithMasternodes , false , true , 1 ) ; if ( block . vtx [ 0 ] -> GetValueOut ( ) > ( nTotalRewardWithMasternodes + nFee ) ) { strErrorRet = strprintf ( " " ) ; return false ; } } if ( ! isBlockRewardValueMet ) { strErrorRet = strprintf ( " " , nBlockHeight , block . vtx [ 0 ] -> GetValueOut ( ) , blockRewardWithFee ) ; } return isBlockRewardValueMet ; } if ( sporkManager . IsSporkActive ( SPORK_9_SUPERBLOCKS_ENABLED ) ) { if ( CSuperblockManager :: IsSuperblockTriggered ( nBlockHeight ) ) { if ( CSuperblockManager :: IsValid ( * block . vtx [ 0 ] , nBlockHeight , blockRewardWithFee ) ) { LogPrint ( " " , " " , nBlockHeight , block . vtx [ 0 ] -> ToString ( ) ) ; return true ; } LogPrintf ( " " , nBlockHeight , block . vtx [ 0 ] -> ToString ( ) ) ; strErrorRet = strprintf ( " " , nBlockHeight ) ; return false ; } else { CAmount nTotalRewardWithMasternodes ; GetBlockSubsidy ( nBlockHeight , Params ( ) . GetConsensus ( ) , nTotalRewardWithMasternodes , false , true , 1 ) ; if ( block . vtx [ 0 ] -> GetValueOut ( ) > ( nTotalRewardWithMasternodes + nFee ) ) { strErrorRet = strprintf ( " " ) ; return false ; } } LogPrint ( " " , " \n " , nBlockHeight ) ; if ( ! isBlockRewardValueMet ) { strErrorRet = strprintf ( " " , nBlockHeight , block . vtx [ 0 ] -> GetValueOut ( ) , blockRewardWithFee ) ; } } else { LogPrint ( " " , " \n " ) ; if ( ! isBlockRewardValueMet ) { strErrorRet = strprintf ( " " , nBlockHeight , block . vtx [ 0 ] -> GetValueOut ( ) , blockRewardWithFee ) ; } } return isBlockRewardValueMet ; }
IsBlockValueValid
Determine if coinbase outgoing created money is the correct value
IsBlockValueValid Determine if coinbase outgoing created money is the correct value
// we are still using budgets, but we have no data about them anymore, // all we know is predefined budget cycle and window // superblocks started // not enough data but at least it must NOT exceed superblock max value // it MUST be a regular block otherwise // we are synced, let's try to check as much data as we can // all checks are done in CSuperblock::IsValid, nothing to do here // triggered but invalid? that's weird // should NOT allow invalid superblocks, when superblocks are enabled // should NOT allow superblocks at all, when superblocks are disabled // it MUST be a regular block