Complete rewrite of consensus code for mn/budget payments
- Added FindProposal and FindFinalBudget to budgeting class - Added 2 new sporks for Proposals and Budget payment enforcement. This is outside of the decentralized code so we can turn it off if there's a problem. - Detect budget blocks and pay correct amounts in super blocks
This commit is contained in:
parent
bd4a7f2fad
commit
eaf7b940a6
@ -2093,11 +2093,12 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
|||||||
int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
|
int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart;
|
||||||
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001);
|
LogPrint("bench", " - Connect %u transactions: %.2fms (%.3fms/tx, %.3fms/txin) [%.2fs]\n", (unsigned)block.vtx.size(), 0.001 * (nTime1 - nTimeStart), 0.001 * (nTime1 - nTimeStart) / block.vtx.size(), nInputs <= 1 ? 0 : 0.001 * (nTime1 - nTimeStart) / (nInputs-1), nTimeConnect * 0.000001);
|
||||||
|
|
||||||
if (block.vtx[0].GetValueOut() > GetBlockValue(pindex->pprev->nBits, pindex->pprev->nHeight, nFees))
|
if(!IsBlockValueValid(block.vtx[0].GetValueOut(), GetBlockValue(pindex->pprev->nBits, pindex->pprev->nHeight, nFees))){
|
||||||
return state.DoS(100,
|
return state.DoS(100,
|
||||||
error("ConnectBlock() : coinbase pays too much (actual=%d vs limit=%d)",
|
error("ConnectBlock() : coinbase pays too much (actual=%d vs limit=%d)",
|
||||||
block.vtx[0].GetValueOut(), GetBlockValue(pindex->pprev->nBits, pindex->pprev->nHeight, nFees)),
|
block.vtx[0].GetValueOut(), GetBlockValue(pindex->pprev->nBits, pindex->pprev->nHeight, nFees)),
|
||||||
REJECT_INVALID, "bad-cb-amount");
|
REJECT_INVALID, "bad-cb-amount");
|
||||||
|
}
|
||||||
|
|
||||||
if (!control.Wait())
|
if (!control.Wait())
|
||||||
return state.DoS(100, false);
|
return state.DoS(100, false);
|
||||||
|
@ -184,7 +184,7 @@ void DumpBudgets()
|
|||||||
LogPrintf("Masternode dump finished %dms\n", GetTimeMillis() - nStart);
|
LogPrintf("Masternode dump finished %dms\n", GetTimeMillis() - nStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBudgetProposal *CBudgetManager::Find(const std::string &strProposalName)
|
CBudgetProposal *CBudgetManager::FindProposal(const std::string &strProposalName)
|
||||||
{
|
{
|
||||||
//find the prop with the highest yes count
|
//find the prop with the highest yes count
|
||||||
|
|
||||||
@ -330,6 +330,68 @@ void CBudgetVote::Relay()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CBudgetManager::FillBlockPayee(CMutableTransaction& txNew, int64_t nFees)
|
||||||
|
{
|
||||||
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
|
if(!pindexPrev) return;
|
||||||
|
|
||||||
|
int nHighestCount = 0;
|
||||||
|
CScript payee;
|
||||||
|
int64_t nAmount = 0;
|
||||||
|
|
||||||
|
// ------- Grab The Highest Count
|
||||||
|
|
||||||
|
std::map<uint256, CFinalizedBudget>::iterator it = mapFinalizedBudgets.begin();
|
||||||
|
while(it != mapFinalizedBudgets.end())
|
||||||
|
{
|
||||||
|
CFinalizedBudget* prop = &((*it).second);
|
||||||
|
if(prop->GetVoteCount() > nHighestCount){
|
||||||
|
if(pindexPrev->nHeight+1 >= prop->GetBlockStart() && pindexPrev->nHeight+1 <= prop->GetBlockEnd()){
|
||||||
|
if(prop->GetPayeeAndAmount(pindexPrev->nHeight+1, payee, nAmount)){
|
||||||
|
nHighestCount = prop->GetVoteCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmount blockValue = GetBlockValue(pindexPrev->nBits, pindexPrev->nHeight, nFees);
|
||||||
|
|
||||||
|
//miners get the full amount on these blocks
|
||||||
|
txNew.vout[0].nValue = blockValue;
|
||||||
|
|
||||||
|
if(nHighestCount > 0){
|
||||||
|
txNew.vout.resize(2);
|
||||||
|
|
||||||
|
//these are super blocks, so their value can be much larger than normal
|
||||||
|
txNew.vout[1].scriptPubKey = payee;
|
||||||
|
txNew.vout[1].nValue = nAmount;
|
||||||
|
|
||||||
|
CTxDestination address1;
|
||||||
|
ExtractDestination(payee, address1);
|
||||||
|
CBitcoinAddress address2(address1);
|
||||||
|
|
||||||
|
LogPrintf("Budget payment to %s for %lld\n", address2.ToString().c_str(), nAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CFinalizedBudget::GetPayeeAndAmount(int64_t nBlockHeight, CScript& payee, int64_t& nAmount)
|
||||||
|
{
|
||||||
|
uint256 nProp = GetProposalByBlock(nBlockHeight);
|
||||||
|
|
||||||
|
CBudgetProposal* prop = budget.FindProposal(nProp);
|
||||||
|
if(prop){
|
||||||
|
payee = prop->GetPayee();
|
||||||
|
nAmount = prop->GetAmount();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LogPrintf("GetPayeeAndAmount - Couldn't find budget! %s\n", nProp.ToString().c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
void CBudgetManager::ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
||||||
{
|
{
|
||||||
// lite mode is not supported
|
// lite mode is not supported
|
||||||
@ -790,7 +852,7 @@ std::string CFinalizedBudget::GetProposals() {
|
|||||||
std::string ret = "aeu";
|
std::string ret = "aeu";
|
||||||
|
|
||||||
BOOST_FOREACH(uint256& nHash, vecProposals){
|
BOOST_FOREACH(uint256& nHash, vecProposals){
|
||||||
CFinalizedBudget* prop = budget.Find(nHash);
|
CFinalizedBudget* prop = budget.FindFinalizedBudget(nHash);
|
||||||
|
|
||||||
std::string token = nHash.ToString();
|
std::string token = nHash.ToString();
|
||||||
if(prop) token = prop->GetName();
|
if(prop) token = prop->GetName();
|
||||||
@ -801,7 +863,7 @@ std::string CFinalizedBudget::GetProposals() {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CFinalizedBudget *CBudgetManager::Find(uint256 nHash)
|
CFinalizedBudget *CBudgetManager::FindFinalizedBudget(uint256 nHash)
|
||||||
{
|
{
|
||||||
if(mapFinalizedBudgets.count(nHash))
|
if(mapFinalizedBudgets.count(nHash))
|
||||||
return &mapFinalizedBudgets[nHash];
|
return &mapFinalizedBudgets[nHash];
|
||||||
@ -809,6 +871,13 @@ CFinalizedBudget *CBudgetManager::Find(uint256 nHash)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBudgetProposal *CBudgetManager::FindProposal(uint256 nHash)
|
||||||
|
{
|
||||||
|
if(mapProposals.count(nHash))
|
||||||
|
return &mapProposals[nHash];
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
bool CBudgetManager::PropExists(uint256 nHash)
|
bool CBudgetManager::PropExists(uint256 nHash)
|
||||||
{
|
{
|
||||||
@ -950,6 +1019,7 @@ bool CFinalizedBudget::IsValid()
|
|||||||
//must be the correct block for payment to happen (once a month)
|
//must be the correct block for payment to happen (once a month)
|
||||||
if(nBlockStart % GetBudgetPaymentCycleBlocks() != 0) return false;
|
if(nBlockStart % GetBudgetPaymentCycleBlocks() != 0) return false;
|
||||||
if(GetBlockEnd() - nBlockStart > 100) return false;
|
if(GetBlockEnd() - nBlockStart > 100) return false;
|
||||||
|
if(vecProposals.size() > 100) return false;
|
||||||
|
|
||||||
//make sure all prop names exist
|
//make sure all prop names exist
|
||||||
BOOST_FOREACH(uint256 nHash, vecProposals){
|
BOOST_FOREACH(uint256 nHash, vecProposals){
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
// Copyright (c) 2014-2015 The Dash developers
|
// Copyright (c) 2014-2015 The Dash developers
|
||||||
|
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
#ifndef MASTERNODE_BUDGET_H
|
#ifndef MASTERNODE_BUDGET_H
|
||||||
@ -90,8 +90,9 @@ public:
|
|||||||
void Calculate();
|
void Calculate();
|
||||||
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
void ProcessMessage(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
||||||
void NewBlock();
|
void NewBlock();
|
||||||
CBudgetProposal *Find(const std::string &strProposalName);
|
CBudgetProposal *FindProposal(const std::string &strProposalName);
|
||||||
CFinalizedBudget *Find(uint256 nHash);
|
CBudgetProposal *FindProposal(uint256 nHash);
|
||||||
|
CFinalizedBudget *FindFinalizedBudget(uint256 nHash);
|
||||||
std::pair<std::string, std::string> GetVotes(std::string strProposalName);
|
std::pair<std::string, std::string> GetVotes(std::string strProposalName);
|
||||||
|
|
||||||
|
|
||||||
@ -108,6 +109,7 @@ public:
|
|||||||
bool PropExists(uint256 nHash);
|
bool PropExists(uint256 nHash);
|
||||||
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
|
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
|
||||||
std::string GetRequiredPaymentsString(int64_t nBlockHeight);
|
std::string GetRequiredPaymentsString(int64_t nBlockHeight);
|
||||||
|
void FillBlockPayee(CMutableTransaction& txNew, int64_t nFees);
|
||||||
|
|
||||||
void Clear(){
|
void Clear(){
|
||||||
printf("Not implemented\n");
|
printf("Not implemented\n");
|
||||||
@ -177,6 +179,7 @@ public:
|
|||||||
if(i > (int)vecProposals.size()-1) return 0;
|
if(i > (int)vecProposals.size()-1) return 0;
|
||||||
return vecProposals[i];
|
return vecProposals[i];
|
||||||
}
|
}
|
||||||
|
bool GetPayeeAndAmount(int64_t nBlockHeight, CScript& payee, int64_t& nAmount);
|
||||||
|
|
||||||
uint256 GetHash(){
|
uint256 GetHash(){
|
||||||
/*
|
/*
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "darksend.h"
|
#include "darksend.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "sync.h"
|
#include "sync.h"
|
||||||
|
#include "spork.h"
|
||||||
#include "addrman.h"
|
#include "addrman.h"
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
@ -18,12 +19,44 @@ CMasternodePayments masternodePayments;
|
|||||||
map<uint256, CMasternodePaymentWinner> mapMasternodePayeeVotes;
|
map<uint256, CMasternodePaymentWinner> mapMasternodePayeeVotes;
|
||||||
map<uint256, CMasternodeBlockPayees> mapMasternodeBlocks;
|
map<uint256, CMasternodeBlockPayees> mapMasternodeBlocks;
|
||||||
|
|
||||||
|
bool IsBlockValueValid(int64_t nBlockValue, int64_t nExpectedValue){
|
||||||
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
|
if(pindexPrev == NULL) return true;
|
||||||
|
|
||||||
|
//while syncing take the longest chain
|
||||||
|
if (fImporting || fReindex || pindexPrev->nHeight+1 < Checkpoints::GetTotalBlocksEstimate()) {
|
||||||
|
//super blocks will always be on these blocks, max 100 per budgeting
|
||||||
|
if(pindexPrev->nHeight+1 % GetBudgetPaymentCycleBlocks() < 100){
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if(nBlockValue > nExpectedValue) return false;
|
||||||
|
}
|
||||||
|
} else { // we're synced so check the budget schedule
|
||||||
|
if(budget.IsBudgetPaymentBlock(pindexPrev->nHeight+1)){
|
||||||
|
//the value of the block is evaluated in CheckBlock
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if(nBlockValue > nExpectedValue) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsBlockPayeeValid(const CTransaction& txNew, int64_t nBlockHeight)
|
bool IsBlockPayeeValid(const CTransaction& txNew, int64_t nBlockHeight)
|
||||||
{
|
{
|
||||||
//check if it's a budget block
|
//check if it's a budget block
|
||||||
if(budget.IsBudgetPaymentBlock(nBlockHeight)){
|
if(budget.IsBudgetPaymentBlock(nBlockHeight)){
|
||||||
if(budget.IsTransactionValid(txNew, nBlockHeight)){
|
if(budget.IsTransactionValid(txNew, nBlockHeight)){
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
LogPrintf("Invalid budget payment detected %s\n", txNew.ToString().c_str());
|
||||||
|
if(IsSporkActive(SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT)){
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
LogPrintf("Budget enforcement is disabled, accepting block");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,11 +64,32 @@ bool IsBlockPayeeValid(const CTransaction& txNew, int64_t nBlockHeight)
|
|||||||
if(masternodePayments.IsTransactionValid(txNew, nBlockHeight))
|
if(masternodePayments.IsTransactionValid(txNew, nBlockHeight))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
LogPrintf("Invalid mn payment detected %s\n", txNew.ToString().c_str());
|
||||||
|
if(IsSporkActive(SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT)){
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
LogPrintf("Masternode payment enforcement is disabled, accepting block");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void FillBlockPayee(CMutableTransaction& txNew, int64_t nFees)
|
||||||
|
{
|
||||||
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
|
if(!pindexPrev) return;
|
||||||
|
|
||||||
|
if(budget.IsBudgetPaymentBlock(pindexPrev->nHeight+1)){
|
||||||
|
budget.FillBlockPayee(txNew, nFees);
|
||||||
|
} else {
|
||||||
|
masternodePayments.FillBlockPayee(txNew, nFees);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetRequiredPaymentsString(int64_t nBlockHeight)
|
std::string GetRequiredPaymentsString(int64_t nBlockHeight)
|
||||||
{
|
{
|
||||||
if(budget.IsBudgetPaymentBlock(nBlockHeight)){
|
if(budget.IsBudgetPaymentBlock(nBlockHeight)){
|
||||||
@ -45,6 +99,47 @@ std::string GetRequiredPaymentsString(int64_t nBlockHeight)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, int64_t nFees)
|
||||||
|
{
|
||||||
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
|
if(!pindexPrev) return;
|
||||||
|
|
||||||
|
bool hasPayment = true;
|
||||||
|
CScript payee;
|
||||||
|
|
||||||
|
//spork
|
||||||
|
if(!masternodePayments.GetBlockPayee(pindexPrev->nHeight+1, payee)){
|
||||||
|
//no masternode detected
|
||||||
|
CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1);
|
||||||
|
if(winningNode){
|
||||||
|
payee = GetScriptForDestination(winningNode->pubkey.GetID());
|
||||||
|
} else {
|
||||||
|
LogPrintf("CreateNewBlock: Failed to detect masternode to pay\n");
|
||||||
|
hasPayment = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CAmount blockValue = GetBlockValue(pindexPrev->nBits, pindexPrev->nHeight, nFees);
|
||||||
|
CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight+1, blockValue);
|
||||||
|
|
||||||
|
txNew.vout[0].nValue = blockValue;
|
||||||
|
|
||||||
|
if(hasPayment){
|
||||||
|
txNew.vout.resize(2);
|
||||||
|
|
||||||
|
txNew.vout[1].scriptPubKey = payee;
|
||||||
|
txNew.vout[1].nValue = masternodePayment;
|
||||||
|
|
||||||
|
txNew.vout[0].nValue -= masternodePayment;
|
||||||
|
|
||||||
|
CTxDestination address1;
|
||||||
|
ExtractDestination(payee, address1);
|
||||||
|
CBitcoinAddress address2(address1);
|
||||||
|
|
||||||
|
LogPrintf("Masternode payment to %s\n", address2.ToString().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv)
|
||||||
{
|
{
|
||||||
if(IsInitialBlockDownload()) return;
|
if(IsInitialBlockDownload()) return;
|
||||||
@ -304,13 +399,13 @@ bool CMasternodePaymentWinner::IsValid()
|
|||||||
|
|
||||||
if(n == -1)
|
if(n == -1)
|
||||||
{
|
{
|
||||||
if(fDebug) LogPrintf("CMasternodePaymentWinner::IsValid - Unknown Masternode\n");
|
LogPrintf("CMasternodePaymentWinner::IsValid - Unknown Masternode\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(n > MNPAYMENTS_SIGNATURES_TOTAL)
|
if(n > MNPAYMENTS_SIGNATURES_TOTAL)
|
||||||
{
|
{
|
||||||
if(fDebug) LogPrintf("CMasternodePaymentWinner::IsValid - Masternode not in the top %d (%d)\n", MNPAYMENTS_SIGNATURES_TOTAL, n);
|
LogPrintf("CMasternodePaymentWinner::IsValid - Masternode not in the top %d (%d)\n", MNPAYMENTS_SIGNATURES_TOTAL, n);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,8 @@ void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDa
|
|||||||
bool IsReferenceNode(CTxIn& vin);
|
bool IsReferenceNode(CTxIn& vin);
|
||||||
bool IsBlockPayeeValid(const CTransaction& txNew, int64_t nBlockHeight);
|
bool IsBlockPayeeValid(const CTransaction& txNew, int64_t nBlockHeight);
|
||||||
std::string GetRequiredPaymentsString(int64_t nBlockHeight);
|
std::string GetRequiredPaymentsString(int64_t nBlockHeight);
|
||||||
|
bool IsBlockValueValid(int64_t nBlockValue, int64_t nExpectedValue);
|
||||||
|
void FillBlockPayee(CMutableTransaction& txNew, int64_t nFees);
|
||||||
|
|
||||||
class CMasternodePayee : public CTxOut
|
class CMasternodePayee : public CTxOut
|
||||||
{
|
{
|
||||||
@ -194,6 +196,7 @@ public:
|
|||||||
|
|
||||||
void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
|
||||||
std::string GetRequiredPaymentsString(int nBlockHeight);
|
std::string GetRequiredPaymentsString(int nBlockHeight);
|
||||||
|
void FillBlockPayee(CMutableTransaction& txNew, int64_t nFees);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -379,6 +379,9 @@ CMasternode* CMasternodeMan::GetNextMasternodeInQueueForPayment()
|
|||||||
//it's in the list -- so let's skip it
|
//it's in the list -- so let's skip it
|
||||||
if(masternodePayments.IsScheduled(mn)) continue;
|
if(masternodePayments.IsScheduled(mn)) continue;
|
||||||
|
|
||||||
|
//make sure it has as many confirmations as there are masternodes
|
||||||
|
if(mn.GetMasternodeInputAge() < CountEnabled()) continue;
|
||||||
|
|
||||||
if(pOldestMasternode == NULL || pOldestMasternode->SecondsSincePayment() < mn.SecondsSincePayment()){
|
if(pOldestMasternode == NULL || pOldestMasternode->SecondsSincePayment() < mn.SecondsSincePayment()){
|
||||||
pOldestMasternode = &mn;
|
pOldestMasternode = &mn;
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||||||
return NULL;
|
return NULL;
|
||||||
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
||||||
|
|
||||||
int payments = 1;
|
|
||||||
// -regtest only: allow overriding block.nVersion with
|
// -regtest only: allow overriding block.nVersion with
|
||||||
// -blockversion=N to test forking scenarios
|
// -blockversion=N to test forking scenarios
|
||||||
if (Params().MineBlocksOnDemand())
|
if (Params().MineBlocksOnDemand())
|
||||||
@ -127,9 +126,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||||||
unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
|
unsigned int nBlockMinSize = GetArg("-blockminsize", DEFAULT_BLOCK_MIN_SIZE);
|
||||||
nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
|
nBlockMinSize = std::min(nBlockMaxSize, nBlockMinSize);
|
||||||
|
|
||||||
// start masternode payments
|
|
||||||
bool bMasterNodePayment = GetTimeMicros() > Params().StartMasternodePayments();
|
|
||||||
|
|
||||||
// Collect memory pool transactions into the block
|
// Collect memory pool transactions into the block
|
||||||
CAmount nFees = 0;
|
CAmount nFees = 0;
|
||||||
|
|
||||||
@ -139,35 +135,6 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||||||
const int nHeight = pindexPrev->nHeight + 1;
|
const int nHeight = pindexPrev->nHeight + 1;
|
||||||
CCoinsViewCache view(pcoinsTip);
|
CCoinsViewCache view(pcoinsTip);
|
||||||
|
|
||||||
if(bMasterNodePayment) {
|
|
||||||
bool hasPayment = true;
|
|
||||||
//spork
|
|
||||||
if(!masternodePayments.GetBlockPayee(pindexPrev->nHeight+1, pblock->payee)){
|
|
||||||
//no masternode detected
|
|
||||||
CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1);
|
|
||||||
if(winningNode){
|
|
||||||
pblock->payee = GetScriptForDestination(winningNode->pubkey.GetID());
|
|
||||||
} else {
|
|
||||||
LogPrintf("CreateNewBlock: Failed to detect masternode to pay\n");
|
|
||||||
hasPayment = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hasPayment){
|
|
||||||
payments++;
|
|
||||||
txNew.vout.resize(payments);
|
|
||||||
|
|
||||||
txNew.vout[payments-1].scriptPubKey = pblock->payee;
|
|
||||||
txNew.vout[payments-1].nValue = 0;
|
|
||||||
|
|
||||||
CTxDestination address1;
|
|
||||||
ExtractDestination(pblock->payee, address1);
|
|
||||||
CBitcoinAddress address2(address1);
|
|
||||||
|
|
||||||
LogPrintf("Masternode payment to %s\n", address2.ToString().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add our coinbase tx as first transaction
|
// Add our coinbase tx as first transaction
|
||||||
pblock->vtx.push_back(txNew);
|
pblock->vtx.push_back(txNew);
|
||||||
pblocktemplate->vTxFees.push_back(-1); // updated at end
|
pblocktemplate->vTxFees.push_back(-1); // updated at end
|
||||||
@ -351,18 +318,12 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Masternode and general budget payments
|
||||||
|
FillBlockPayee(txNew, nFees);
|
||||||
|
|
||||||
nLastBlockTx = nBlockTx;
|
nLastBlockTx = nBlockTx;
|
||||||
nLastBlockSize = nBlockSize;
|
nLastBlockSize = nBlockSize;
|
||||||
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
|
LogPrintf("CreateNewBlock(): total size %u\n", nBlockSize);
|
||||||
CAmount blockValue = GetBlockValue(pindexPrev->nBits, pindexPrev->nHeight, nFees);
|
|
||||||
CAmount masternodePayment = GetMasternodePayment(pindexPrev->nHeight+1, blockValue);
|
|
||||||
|
|
||||||
//create masternode payment
|
|
||||||
if(payments > 1){
|
|
||||||
txNew.vout[payments-1].nValue = masternodePayment;
|
|
||||||
blockValue -= masternodePayment;
|
|
||||||
}
|
|
||||||
txNew.vout[0].nValue = blockValue;
|
|
||||||
|
|
||||||
// Compute final coinbase transaction.
|
// Compute final coinbase transaction.
|
||||||
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
|
txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
|
||||||
|
@ -248,7 +248,7 @@ Value mnbudget(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
std::string strProposalName = params[1].get_str();
|
std::string strProposalName = params[1].get_str();
|
||||||
|
|
||||||
CBudgetProposal* prop = budget.Find(strProposalName);
|
CBudgetProposal* prop = budget.FindProposal(strProposalName);
|
||||||
|
|
||||||
if(prop == NULL) return "Unknown proposal name";
|
if(prop == NULL) return "Unknown proposal name";
|
||||||
|
|
||||||
@ -283,7 +283,7 @@ Value mnbudget(const Array& params, bool fHelp)
|
|||||||
|
|
||||||
Object obj;
|
Object obj;
|
||||||
|
|
||||||
CBudgetProposal* prop = budget.Find(strProposalName);
|
CBudgetProposal* prop = budget.FindProposal(strProposalName);
|
||||||
|
|
||||||
if(prop == NULL) return "Unknown proposal name";
|
if(prop == NULL) return "Unknown proposal name";
|
||||||
|
|
||||||
|
@ -81,11 +81,12 @@ bool IsSporkActive(int nSporkID)
|
|||||||
if(mapSporksActive.count(nSporkID)){
|
if(mapSporksActive.count(nSporkID)){
|
||||||
r = mapSporksActive[nSporkID].nValue;
|
r = mapSporksActive[nSporkID].nValue;
|
||||||
} else {
|
} else {
|
||||||
if(nSporkID == SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT) r = SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT_DEFAULT;
|
|
||||||
if(nSporkID == SPORK_2_INSTANTX) r = SPORK_2_INSTANTX_DEFAULT;
|
if(nSporkID == SPORK_2_INSTANTX) r = SPORK_2_INSTANTX_DEFAULT;
|
||||||
if(nSporkID == SPORK_3_INSTANTX_BLOCK_FILTERING) r = SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT;
|
if(nSporkID == SPORK_3_INSTANTX_BLOCK_FILTERING) r = SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT;
|
||||||
if(nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT;
|
if(nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT;
|
||||||
if(nSporkID == SPORK_7_MASTERNODE_SCANNING) r = SPORK_7_MASTERNODE_SCANNING;
|
if(nSporkID == SPORK_7_MASTERNODE_SCANNING) r = SPORK_7_MASTERNODE_SCANNING;
|
||||||
|
if(nSporkID == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) r = SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT;
|
||||||
|
if(nSporkID == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) r = SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT;
|
||||||
|
|
||||||
if(r == 0) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID);
|
if(r == 0) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID);
|
||||||
}
|
}
|
||||||
@ -102,11 +103,12 @@ int GetSporkValue(int nSporkID)
|
|||||||
if(mapSporksActive.count(nSporkID)){
|
if(mapSporksActive.count(nSporkID)){
|
||||||
r = mapSporksActive[nSporkID].nValue;
|
r = mapSporksActive[nSporkID].nValue;
|
||||||
} else {
|
} else {
|
||||||
if(nSporkID == SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT) r = SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT_DEFAULT;
|
|
||||||
if(nSporkID == SPORK_2_INSTANTX) r = SPORK_2_INSTANTX_DEFAULT;
|
if(nSporkID == SPORK_2_INSTANTX) r = SPORK_2_INSTANTX_DEFAULT;
|
||||||
if(nSporkID == SPORK_3_INSTANTX_BLOCK_FILTERING) r = SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT;
|
if(nSporkID == SPORK_3_INSTANTX_BLOCK_FILTERING) r = SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT;
|
||||||
if(nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT;
|
if(nSporkID == SPORK_5_MAX_VALUE) r = SPORK_5_MAX_VALUE_DEFAULT;
|
||||||
if(nSporkID == SPORK_7_MASTERNODE_SCANNING) r = SPORK_7_MASTERNODE_SCANNING;
|
if(nSporkID == SPORK_7_MASTERNODE_SCANNING) r = SPORK_7_MASTERNODE_SCANNING_DEFAULT;
|
||||||
|
if(nSporkID == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) r = SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT;
|
||||||
|
if(nSporkID == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) r = SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT;
|
||||||
|
|
||||||
if(r == 0) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID);
|
if(r == 0) LogPrintf("GetSpork::Unknown Spork %d\n", nSporkID);
|
||||||
}
|
}
|
||||||
@ -209,22 +211,24 @@ bool CSporkManager::SetPrivKey(std::string strPrivKey)
|
|||||||
|
|
||||||
int CSporkManager::GetSporkIDByName(std::string strName)
|
int CSporkManager::GetSporkIDByName(std::string strName)
|
||||||
{
|
{
|
||||||
if(strName == "SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT") return SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT;
|
|
||||||
if(strName == "SPORK_2_INSTANTX") return SPORK_2_INSTANTX;
|
if(strName == "SPORK_2_INSTANTX") return SPORK_2_INSTANTX;
|
||||||
if(strName == "SPORK_3_INSTANTX_BLOCK_FILTERING") return SPORK_3_INSTANTX_BLOCK_FILTERING;
|
if(strName == "SPORK_3_INSTANTX_BLOCK_FILTERING") return SPORK_3_INSTANTX_BLOCK_FILTERING;
|
||||||
if(strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE;
|
if(strName == "SPORK_5_MAX_VALUE") return SPORK_5_MAX_VALUE;
|
||||||
if(strName == "SPORK_7_MASTERNODE_SCANNING") return SPORK_7_MASTERNODE_SCANNING;
|
if(strName == "SPORK_7_MASTERNODE_SCANNING") return SPORK_7_MASTERNODE_SCANNING;
|
||||||
|
if(strName == "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT") return SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT;
|
||||||
|
if(strName == "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT") return SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT;
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CSporkManager::GetSporkNameByID(int id)
|
std::string CSporkManager::GetSporkNameByID(int id)
|
||||||
{
|
{
|
||||||
if(id == SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT) return "SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT";
|
|
||||||
if(id == SPORK_2_INSTANTX) return "SPORK_2_INSTANTX";
|
if(id == SPORK_2_INSTANTX) return "SPORK_2_INSTANTX";
|
||||||
if(id == SPORK_3_INSTANTX_BLOCK_FILTERING) return "SPORK_3_INSTANTX_BLOCK_FILTERING";
|
if(id == SPORK_3_INSTANTX_BLOCK_FILTERING) return "SPORK_3_INSTANTX_BLOCK_FILTERING";
|
||||||
if(id == SPORK_5_MAX_VALUE) return "SPORK_5_MAX_VALUE";
|
if(id == SPORK_5_MAX_VALUE) return "SPORK_5_MAX_VALUE";
|
||||||
if(id == SPORK_7_MASTERNODE_SCANNING) return "SPORK_7_MASTERNODE_SCANNING";
|
if(id == SPORK_7_MASTERNODE_SCANNING) return "SPORK_7_MASTERNODE_SCANNING";
|
||||||
|
if(id == SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT) return "SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT";
|
||||||
|
if(id == SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT) return "SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT";
|
||||||
|
|
||||||
return "Unknown";
|
return "Unknown";
|
||||||
}
|
}
|
||||||
|
13
src/spork.h
13
src/spork.h
@ -19,20 +19,23 @@
|
|||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
// Don't ever reuse these IDs for other sporks
|
/*
|
||||||
#define SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT 10000
|
Don't ever reuse these IDs for other sporks
|
||||||
|
- This would result in old clients getting confused about which spork is for what
|
||||||
|
*/
|
||||||
#define SPORK_2_INSTANTX 10001
|
#define SPORK_2_INSTANTX 10001
|
||||||
#define SPORK_3_INSTANTX_BLOCK_FILTERING 10002
|
#define SPORK_3_INSTANTX_BLOCK_FILTERING 10002
|
||||||
#define SPORK_4_NOTUSED 10003
|
|
||||||
#define SPORK_5_MAX_VALUE 10004
|
#define SPORK_5_MAX_VALUE 10004
|
||||||
#define SPORK_6_NOTUSED 10005
|
|
||||||
#define SPORK_7_MASTERNODE_SCANNING 10006
|
#define SPORK_7_MASTERNODE_SCANNING 10006
|
||||||
|
#define SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT 10007
|
||||||
|
#define SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT 10008
|
||||||
|
|
||||||
#define SPORK_1_MASTERNODE_PAYMENTS_ENFORCEMENT_DEFAULT 1424217600 //2015-2-18
|
|
||||||
#define SPORK_2_INSTANTX_DEFAULT 978307200 //2001-1-1
|
#define SPORK_2_INSTANTX_DEFAULT 978307200 //2001-1-1
|
||||||
#define SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT 1424217600 //2015-2-18
|
#define SPORK_3_INSTANTX_BLOCK_FILTERING_DEFAULT 1424217600 //2015-2-18
|
||||||
#define SPORK_5_MAX_VALUE_DEFAULT 1000 //1000 DASH
|
#define SPORK_5_MAX_VALUE_DEFAULT 1000 //1000 DASH
|
||||||
#define SPORK_7_MASTERNODE_SCANNING_DEFAULT 978307200 //2001-1-1
|
#define SPORK_7_MASTERNODE_SCANNING_DEFAULT 978307200 //2001-1-1
|
||||||
|
#define SPORK_8_MASTERNODE_PAYMENT_ENFORCEMENT_DEFAULT 1434326400 //2015-6-15
|
||||||
|
#define SPORK_9_MASTERNODE_BUDGET_ENFORCEMENT_DEFAULT 1434326400 //2015-6-15
|
||||||
|
|
||||||
class CSporkMessage;
|
class CSporkMessage;
|
||||||
class CSporkManager;
|
class CSporkManager;
|
||||||
|
Loading…
Reference in New Issue
Block a user