Skip to content

Commit

Permalink
[Refactoring] Pass both coinbase and coinstake to FillBlockPayee
Browse files Browse the repository at this point in the history
this will be needed in the following commits
  • Loading branch information
random-zebra committed May 3, 2021
1 parent 944e793 commit e567f7f
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 61 deletions.
53 changes: 30 additions & 23 deletions src/blockassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,23 @@ int64_t UpdateTime(CBlockHeader* pblock, const Consensus::Params& consensusParam
return nNewTime - nOldTime;
}

static CMutableTransaction NewCoinbase(const int nHeight, const CScript* pScriptPubKey = nullptr)
{
CMutableTransaction txCoinbase;
txCoinbase.vout.emplace_back();
txCoinbase.vout[0].SetEmpty();
if (pScriptPubKey) txCoinbase.vout[0].scriptPubKey = *pScriptPubKey;
txCoinbase.vin.emplace_back();
txCoinbase.vin[0].scriptSig = CScript() << nHeight << OP_0;
return txCoinbase;
}

bool SolveProofOfStake(CBlock* pblock, CBlockIndex* pindexPrev, CWallet* pwallet, std::vector<CStakeableOutput>* availableCoins)
{
boost::this_thread::interruption_point();

assert(pindexPrev);
const int nHeight = pindexPrev->nHeight + 1;
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);

// Sync wallet before create coinstake
Expand All @@ -80,23 +94,21 @@ bool SolveProofOfStake(CBlock* pblock, CBlockIndex* pindexPrev, CWallet* pwallet
LogPrint(BCLog::STAKING, "%s : stake not found\n", __func__);
return false;
}
// Stake found

// Create coinbase tx and add masternode/budget payments
CMutableTransaction txCoinbase = NewCoinbase(nHeight);
FillBlockPayee(txCoinbase, txCoinStake, nHeight, true);

// Sign coinstake
if (!pwallet->SignCoinStake(txCoinStake)) {
const COutPoint& stakeIn = txCoinStake.vin[0].prevout;
return error("Unable to sign coinstake with input %s-%d", stakeIn.hash.ToString(), stakeIn.n);
}
// Stake found
pblock->nTime = nTxNewTime;

CMutableTransaction emptyTx;
emptyTx.vout.emplace_back();
emptyTx.vout[0].SetEmpty();
emptyTx.vin.emplace_back();
emptyTx.vin[0].scriptSig = CScript() << pindexPrev->nHeight + 1 << OP_0;
pblock->vtx.emplace_back(
std::make_shared<const CTransaction>(emptyTx));
// stake
pblock->vtx.emplace_back(
std::make_shared<const CTransaction>(txCoinStake));
pblock->vtx.emplace_back(MakeTransactionRef(txCoinbase));
pblock->vtx.emplace_back(MakeTransactionRef(txCoinStake));
pblock->nTime = nTxNewTime;
return true;
}

Expand All @@ -106,23 +118,18 @@ bool CreateCoinbaseTx(CBlock* pblock, const CScript& scriptPubKeyIn, CBlockIndex
const int nHeight = pindexPrev->nHeight + 1;

// Create coinbase tx
CMutableTransaction txNew;
txNew.vin.resize(1);
txNew.vin[0].prevout.SetNull();
txNew.vout.resize(1);
txNew.vout[0].scriptPubKey = scriptPubKeyIn;
CMutableTransaction txCoinbase = NewCoinbase(nHeight, &scriptPubKeyIn);

//Masternode and general budget payments
FillBlockPayee(txNew, nHeight, false);
CMutableTransaction txDummy; // POW blocks have no coinstake
FillBlockPayee(txCoinbase, txDummy, nHeight, false);

txNew.vin[0].scriptSig = CScript() << nHeight << OP_0;
// If no payee was detected, then the whole block value goes to the first output.
if (txNew.vout.size() == 1) {
txNew.vout[0].nValue = GetBlockValue(nHeight);
if (txCoinbase.vout.size() == 1) {
txCoinbase.vout[0].nValue = GetBlockValue(nHeight);
}

pblock->vtx.emplace_back(
std::make_shared<const CTransaction>(CTransaction(txNew)));
pblock->vtx.emplace_back(MakeTransactionRef(txCoinbase));
return true;
}

Expand Down
28 changes: 19 additions & 9 deletions src/budget/budgetmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ bool CBudgetManager::GetExpectedPayeeAmount(int chainHeight, CAmount& nAmountRet
return GetPayeeAndAmount(chainHeight, payeeRet, nAmountRet);
}

bool CBudgetManager::FillBlockPayee(CMutableTransaction& txNew, const int nHeight, bool fProofOfStake) const
bool CBudgetManager::FillBlockPayee(CMutableTransaction& txCoinbase, CMutableTransaction& txCoinstake, const int nHeight, bool fProofOfStake) const
{
if (nHeight <= 0) return false;

Expand All @@ -427,19 +427,29 @@ bool CBudgetManager::FillBlockPayee(CMutableTransaction& txNew, const int nHeigh

CAmount blockValue = GetBlockValue(nHeight);

// Starting from PIVX v6.0 masternode and budgets are paid in the coinbase tx of PoS blocks
const bool fPayCoinstake = fProofOfStake &&
!Params().GetConsensus().NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V6_0);

if (fProofOfStake) {
unsigned int i = txNew.vout.size();
txNew.vout.resize(i + 1);
txNew.vout[i].scriptPubKey = payee;
txNew.vout[i].nValue = nAmount;
if (fPayCoinstake) {
unsigned int i = txCoinstake.vout.size();
txCoinstake.vout.resize(i + 1);
txCoinstake.vout[i].scriptPubKey = payee;
txCoinstake.vout[i].nValue = nAmount;
} else {
txCoinbase.vout.resize(1);
txCoinbase.vout[0].scriptPubKey = payee;
txCoinbase.vout[0].nValue = nAmount;
}
} else {
//miners get the full amount on these blocks
txNew.vout[0].nValue = blockValue;
txNew.vout.resize(2);
txCoinbase.vout[0].nValue = blockValue;
txCoinbase.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;
txCoinbase.vout[1].scriptPubKey = payee;
txCoinbase.vout[1].nValue = nAmount;
}

CTxDestination address;
Expand Down
2 changes: 1 addition & 1 deletion src/budget/budgetmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class CBudgetManager
bool UpdateFinalizedBudget(CFinalizedBudgetVote& vote, CNode* pfrom, std::string& strError);
TrxValidationStatus IsTransactionValid(const CTransaction& txNew, const uint256& nBlockHash, int nBlockHeight) const;
std::string GetRequiredPaymentsString(int nBlockHeight);
bool FillBlockPayee(CMutableTransaction& txNew, const int nHeight, bool fProofOfStake) const;
bool FillBlockPayee(CMutableTransaction& txCoinbase, CMutableTransaction& txCoinstake, const int nHeight, bool fProofOfStake) const;

// Only initialized masternodes: sign and submit votes on valid finalized budgets
void VoteOnFinalizedBudgets();
Expand Down
42 changes: 22 additions & 20 deletions src/masternode-payments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,14 +284,15 @@ bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight)
}


void FillBlockPayee(CMutableTransaction& txNew, const int nHeight, bool fProofOfStake)
void FillBlockPayee(CMutableTransaction& txCoinbase, CMutableTransaction& txCoinstake, const int nHeight, bool fProofOfStake)
{
if (nHeight == 0) return;

if (!sporkManager.IsSporkActive(SPORK_13_ENABLE_SUPERBLOCKS) || // if superblocks are not enabled
!g_budgetman.FillBlockPayee(txNew, nHeight, fProofOfStake) ) { // or this is not a superblock,
// ... or this is not a superblock
!g_budgetman.FillBlockPayee(txCoinbase, txCoinstake, nHeight, fProofOfStake) ) {
// ... or there's no budget with enough votes, then pay a masternode
masternodePayments.FillBlockPayee(txNew, nHeight, fProofOfStake);
masternodePayments.FillBlockPayee(txCoinbase, txCoinstake, nHeight, fProofOfStake);
}
}

Expand All @@ -304,15 +305,15 @@ std::string GetRequiredPaymentsString(int nBlockHeight)
}
}

void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, const int nHeight, bool fProofOfStake)
void CMasternodePayments::FillBlockPayee(CMutableTransaction& txCoinbase, CMutableTransaction& txCoinstake, const int nHeight, bool fProofOfStake) const
{
if (nHeight == 0) return;

bool hasPayment = true;
CScript payee;

//spork
if (!masternodePayments.GetBlockPayee(nHeight, payee)) {
if (!GetBlockPayee(nHeight, payee)) {
//no masternode detected
const CMasternode* winningNode = mnodeman.GetCurrentMasterNode(1);
if (winningNode) {
Expand All @@ -331,33 +332,33 @@ void CMasternodePayments::FillBlockPayee(CMutableTransaction& txNew, const int n
* use vout.size() to align with several different cases.
* An additional output is appended as the masternode payment
*/
unsigned int i = txNew.vout.size();
txNew.vout.resize(i + 1);
txNew.vout[i].scriptPubKey = payee;
txNew.vout[i].nValue = masternodePayment;
unsigned int i = txCoinstake.vout.size();
txCoinstake.vout.resize(i + 1);
txCoinstake.vout[i].scriptPubKey = payee;
txCoinstake.vout[i].nValue = masternodePayment;

//subtract mn payment from the stake reward
if (!txNew.vout[1].IsZerocoinMint()) {
if (!txCoinstake.vout[1].IsZerocoinMint()) {
if (i == 2) {
// Majority of cases; do it quick and move on
txNew.vout[i - 1].nValue -= masternodePayment;
txCoinstake.vout[i - 1].nValue -= masternodePayment;
} else if (i > 2) {
// special case, stake is split between (i-1) outputs
unsigned int outputs = i-1;
CAmount mnPaymentSplit = masternodePayment / outputs;
CAmount mnPaymentRemainder = masternodePayment - (mnPaymentSplit * outputs);
for (unsigned int j=1; j<=outputs; j++) {
txNew.vout[j].nValue -= mnPaymentSplit;
txCoinstake.vout[j].nValue -= mnPaymentSplit;
}
// in case it's not an even division, take the last bit of dust from the last one
txNew.vout[outputs].nValue -= mnPaymentRemainder;
txCoinstake.vout[outputs].nValue -= mnPaymentRemainder;
}
}
} else {
txNew.vout.resize(2);
txNew.vout[1].scriptPubKey = payee;
txNew.vout[1].nValue = masternodePayment;
txNew.vout[0].nValue = GetBlockValue(nHeight) - masternodePayment;
txCoinbase.vout.resize(2);
txCoinbase.vout[1].scriptPubKey = payee;
txCoinbase.vout[1].nValue = masternodePayment;
txCoinbase.vout[0].nValue = GetBlockValue(nHeight) - masternodePayment;
}

CTxDestination address1;
Expand Down Expand Up @@ -454,10 +455,11 @@ void CMasternodePayments::ProcessMessageMasternodePayments(CNode* pfrom, std::st
}
}

bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee)
bool CMasternodePayments::GetBlockPayee(int nBlockHeight, CScript& payee) const
{
if (mapMasternodeBlocks.count(nBlockHeight)) {
return mapMasternodeBlocks[nBlockHeight].GetPayee(payee);
const auto it = mapMasternodeBlocks.find(nBlockHeight);
if (it != mapMasternodeBlocks.end()) {
return it->second.GetPayee(payee);
}

return false;
Expand Down
10 changes: 5 additions & 5 deletions src/masternode-payments.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDa
bool IsBlockPayeeValid(const CBlock& block, int nBlockHeight);
std::string GetRequiredPaymentsString(int nBlockHeight);
bool IsBlockValueValid(int nHeight, CAmount& nExpectedValue, CAmount nMinted);
void FillBlockPayee(CMutableTransaction& txNew, const int nHeight, bool fProofOfStake);
void FillBlockPayee(CMutableTransaction& txCoinbase, CMutableTransaction& txCoinstake, const int nHeight, bool fProofOfStake);

void DumpMasternodePayments();

Expand Down Expand Up @@ -116,12 +116,12 @@ class CMasternodeBlockPayees
vecPayments.push_back(c);
}

bool GetPayee(CScript& payee)
bool GetPayee(CScript& payee) const
{
LOCK(cs_vecPayments);

int nVotes = -1;
for (CMasternodePayee& p : vecPayments) {
for (const CMasternodePayee& p : vecPayments) {
if (p.nVotes > nVotes) {
payee = p.scriptPubKey;
nVotes = p.nVotes;
Expand Down Expand Up @@ -253,7 +253,7 @@ class CMasternodePayments
void Sync(CNode* node, int nCountNeeded);
void CleanPaymentList(int mnCount, int nHeight);

bool GetBlockPayee(int nBlockHeight, CScript& payee);
bool GetBlockPayee(int nBlockHeight, CScript& payee) const;
bool IsTransactionValid(const CTransaction& txNew, int nBlockHeight);
bool IsScheduled(const CMasternode& mn, int nNotBlockHeight);

Expand All @@ -274,7 +274,7 @@ class CMasternodePayments

void ProcessMessageMasternodePayments(CNode* pfrom, std::string& strCommand, CDataStream& vRecv);
std::string GetRequiredPaymentsString(int nBlockHeight);
void FillBlockPayee(CMutableTransaction& txNew, const int nHeight, bool fProofOfStake);
void FillBlockPayee(CMutableTransaction& txCoinbase, CMutableTransaction& txCoinstake, const int nHeight, bool fProofOfStake) const;
std::string ToString() const;

ADD_SERIALIZE_METHODS;
Expand Down
3 changes: 0 additions & 3 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3295,9 +3295,6 @@ bool CWallet::CreateCoinStake(
// Set coinstake input
txNew.vin.emplace_back(stakeInput.GetTxIn());

// Masternode payment
FillBlockPayee(txNew, pindexPrev->nHeight + 1, true);

// Limit size
unsigned int nBytes = ::GetSerializeSize(txNew, SER_NETWORK, PROTOCOL_VERSION);
if (nBytes >= DEFAULT_BLOCK_MAX_SIZE / 5)
Expand Down

0 comments on commit e567f7f

Please sign in to comment.