d40a5ce31f
* Properly initialize confirmedHash in CSimplifiedMNListEntry * Add consensus params for temporary hard-fork on testnet This hard-fork is required on testnet as we have to fix a few consensus bugs in DIP3/DIP4. It will also be required to introduce LLMQ commitments to testnet. * Add temporary fork-logic for testnet, which sets confirmedHash to null ...before fork activation. Otherwise we'd invalidate all DIP3 blocks on testnet. * Bump nTemporaryTestnetForkHeight to 273000
107 lines
3.4 KiB
C++
107 lines
3.4 KiB
C++
// Copyright (c) 2017-2018 The Dash Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include "cbtx.h"
|
|
#include "deterministicmns.h"
|
|
#include "simplifiedmns.h"
|
|
#include "specialtx.h"
|
|
|
|
#include "chainparams.h"
|
|
#include "univalue.h"
|
|
#include "validation.h"
|
|
|
|
bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
|
|
{
|
|
if (tx.nType != TRANSACTION_COINBASE) {
|
|
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-type");
|
|
}
|
|
|
|
if (!tx.IsCoinBase()) {
|
|
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-invalid");
|
|
}
|
|
|
|
CCbTx cbTx;
|
|
if (!GetTxPayload(tx, cbTx)) {
|
|
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-payload");
|
|
}
|
|
|
|
if (cbTx.nVersion == 0 || cbTx.nVersion > CCbTx::CURRENT_VERSION) {
|
|
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-version");
|
|
}
|
|
|
|
if (pindexPrev && pindexPrev->nHeight + 1 != cbTx.nHeight) {
|
|
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-height");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// This can only be done after the block has been fully processed, as otherwise we won't have the finished MN list
|
|
bool CheckCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindex, CValidationState& state)
|
|
{
|
|
if (block.vtx[0]->nType != TRANSACTION_COINBASE) {
|
|
return true;
|
|
}
|
|
|
|
CCbTx cbTx;
|
|
if (!GetTxPayload(*block.vtx[0], cbTx)) {
|
|
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-payload");
|
|
}
|
|
|
|
if (pindex) {
|
|
uint256 calculatedMerkleRoot;
|
|
if (!CalcCbTxMerkleRootMNList(block, pindex->pprev, calculatedMerkleRoot, state)) {
|
|
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-mnmerkleroot");
|
|
}
|
|
if (calculatedMerkleRoot != cbTx.merkleRootMNList) {
|
|
return state.DoS(100, false, REJECT_INVALID, "bad-cbtx-mnmerkleroot");
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, CValidationState& state)
|
|
{
|
|
LOCK(deterministicMNManager->cs);
|
|
|
|
CDeterministicMNList tmpMNList;
|
|
if (!deterministicMNManager->BuildNewListFromBlock(block, pindexPrev, state, tmpMNList)) {
|
|
return false;
|
|
}
|
|
|
|
CSimplifiedMNList sml(tmpMNList);
|
|
|
|
// BEGIN TEMPORARY CODE
|
|
const auto& consensus = Params().GetConsensus();
|
|
if (consensus.nTemporaryTestnetForkHeight != 0 &&
|
|
pindexPrev->nHeight + 1 >= consensus.nTemporaryTestnetForkDIP3Height &&
|
|
pindexPrev->nHeight + 1 < consensus.nTemporaryTestnetForkHeight &&
|
|
chainActive[consensus.nTemporaryTestnetForkDIP3Height]->GetBlockHash() == consensus.nTemporaryTestnetForkDIP3BlockHash) {
|
|
for (auto& sme : sml.mnList) {
|
|
sme.confirmedHash.SetNull();
|
|
}
|
|
}
|
|
// END TEMPORARY CODE
|
|
|
|
bool mutated = false;
|
|
merkleRootRet = sml.CalcMerkleRoot(&mutated);
|
|
return !mutated;
|
|
}
|
|
|
|
std::string CCbTx::ToString() const
|
|
{
|
|
return strprintf("CCbTx(nHeight=%d, nVersion=%d, merkleRootMNList=%s)",
|
|
nVersion, nHeight, merkleRootMNList.ToString());
|
|
}
|
|
|
|
void CCbTx::ToJson(UniValue& obj) const
|
|
{
|
|
obj.clear();
|
|
obj.setObject();
|
|
obj.push_back(Pair("version", (int)nVersion));
|
|
obj.push_back(Pair("height", (int)nHeight));
|
|
obj.push_back(Pair("merkleRootMNList", merkleRootMNList.ToString()));
|
|
}
|