Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 37 additions & 25 deletions src/blockassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,33 +66,48 @@ 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);
pblock->nBits = GetNextWorkRequired(pindexPrev, pblock);

// Sync wallet before create coinstake
pwallet->BlockUntilSyncedToCurrentChain();

CMutableTransaction txCoinStake;
int64_t nTxNewTime = 0;
if (!pwallet->CreateCoinStake(*pwallet, pindexPrev, pblock->nBits, txCoinStake, nTxNewTime, availableCoins)) {
if (!pwallet->CreateCoinStake(pindexPrev, pblock->nBits, txCoinStake, nTxNewTime, availableCoins)) {
LogPrint(BCLog::STAKING, "%s : stake not found\n", __func__);
return false;
}
// 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));
// Create coinbase tx and add masternode/budget payments
CMutableTransaction txCoinbase = NewCoinbase(pindexPrev->nHeight + 1);
FillBlockPayee(txCoinbase, txCoinStake, pindexPrev, 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);
}

pblock->vtx.emplace_back(MakeTransactionRef(txCoinbase));
pblock->vtx.emplace_back(MakeTransactionRef(txCoinStake));
pblock->nTime = nTxNewTime;
return true;
}

Expand All @@ -102,23 +117,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, pindexPrev, 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 Expand Up @@ -493,8 +503,10 @@ void IncrementExtraNonce(std::shared_ptr<CBlock>& pblock, const CBlockIndex* pin

int32_t ComputeBlockVersion(const Consensus::Params& consensus, int nHeight)
{
if (NetworkUpgradeActive(nHeight, consensus, Consensus::UPGRADE_V5_0)) {
return CBlockHeader::CURRENT_VERSION; // v9
if (NetworkUpgradeActive(nHeight, consensus, Consensus::UPGRADE_V6_0)) {
return CBlockHeader::CURRENT_VERSION; // v10
} else if (NetworkUpgradeActive(nHeight, consensus, Consensus::UPGRADE_V5_0)) {
return 9;
} else if (consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V4_0)) {
return 7;
} else if (consensus.NetworkUpgradeActive(nHeight, Consensus::UPGRADE_V3_4)) {
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 (block v10)
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
3 changes: 0 additions & 3 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ class CMainParams : public CChainParams
consensus.nCoinbaseMaturity = 100;
consensus.nFutureTimeDriftPoW = 7200;
consensus.nFutureTimeDriftPoS = 180;
consensus.nMasternodeCountDrift = 20; // num of MN we allow the see-saw payments to be off by
consensus.nMaxMoneyOut = 21000000 * COIN;
consensus.nPoolMaxTransactions = 3;
consensus.nProposalEstablishmentTime = 60 * 60 * 24; // must be at least a day old to make it into a budget
Expand Down Expand Up @@ -280,7 +279,6 @@ class CTestNetParams : public CChainParams
consensus.nCoinbaseMaturity = 15;
consensus.nFutureTimeDriftPoW = 7200;
consensus.nFutureTimeDriftPoS = 180;
consensus.nMasternodeCountDrift = 20; // num of MN we allow the see-saw payments to be off by
consensus.nMaxMoneyOut = 21000000 * COIN;
consensus.nPoolMaxTransactions = 3;
consensus.nProposalEstablishmentTime = 60 * 5; // at least 5 min old to make it into a budget
Expand Down Expand Up @@ -402,7 +400,6 @@ class CRegTestParams : public CChainParams
consensus.nCoinbaseMaturity = 100;
consensus.nFutureTimeDriftPoW = 7200;
consensus.nFutureTimeDriftPoS = 180;
consensus.nMasternodeCountDrift = 4; // num of MN we allow the see-saw payments to be off by
consensus.nMaxMoneyOut = 43199500 * COIN;
consensus.nPoolMaxTransactions = 2;
consensus.nProposalEstablishmentTime = 60 * 5; // at least 5 min old to make it into a budget
Expand Down
1 change: 0 additions & 1 deletion src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ struct Params {
int nCoinbaseMaturity;
int nFutureTimeDriftPoW;
int nFutureTimeDriftPoS;
int nMasternodeCountDrift;
CAmount nMaxMoneyOut;
int nPoolMaxTransactions;
int64_t nProposalEstablishmentTime;
Expand Down
4 changes: 4 additions & 0 deletions src/evo/deterministicmns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,10 @@ CDeterministicMNList CDeterministicMNManager::GetListForBlock(const CBlockIndex*
{
LOCK(cs);

if (!IsDIP3Enforced(pindex->nHeight)) {
return {};
}

CDeterministicMNList snapshot;
std::list<const CBlockIndex*> listDiffIndexes;

Expand Down
17 changes: 3 additions & 14 deletions src/kernel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,8 @@ bool CStakeKernel::CheckKernelHash(bool fSkipLog) const
*/

// helper function for CheckProofOfStake and GetStakeKernelHash
bool LoadStakeInput(const CBlock& block, const CBlockIndex* pindexPrev, std::unique_ptr<CStakeInput>& stake)
static bool LoadStakeInput(const CBlock& block, std::unique_ptr<CStakeInput>& stake)
{
// If previous index is not provided, look for it in the blockmap
if (!pindexPrev) {
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
if (mi != mapBlockIndex.end() && (*mi).second) pindexPrev = (*mi).second;
else return error("%s : couldn't find previous block", __func__);
} else {
// check that is the actual parent block
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
return error("%s : previous block mismatch", __func__);
}

// Check that this is a PoS block
if (!block.IsProofOfStake())
return error("called on non PoS block");
Expand Down Expand Up @@ -153,7 +142,7 @@ bool CheckProofOfStake(const CBlock& block, std::string& strError, const CBlockI
const int nHeight = pindexPrev->nHeight + 1;
// Initialize stake input
std::unique_ptr<CStakeInput> stakeInput;
if (!LoadStakeInput(block, pindexPrev, stakeInput)) {
if (!LoadStakeInput(block, stakeInput)) {
strError = "stake input initialization failed";
return false;
}
Expand Down Expand Up @@ -207,7 +196,7 @@ bool GetStakeKernelHash(uint256& hashRet, const CBlock& block, const CBlockIndex
{
// Initialize stake input
std::unique_ptr<CStakeInput> stakeInput;
if (!LoadStakeInput(block, pindexPrev, stakeInput))
if (!LoadStakeInput(block, stakeInput))
return error("%s : stake input initialization failed", __func__);

CStakeKernel stakeKernel(pindexPrev, stakeInput.get(), block.nBits, block.nTime);
Expand Down
Loading