163 lines
5.1 KiB
C++
163 lines
5.1 KiB
C++
// Copyright (c) 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 "chainparams.h"
|
|
#include "clientversion.h"
|
|
#include "consensus/validation.h"
|
|
#include "hash.h"
|
|
#include "primitives/block.h"
|
|
#include "primitives/transaction.h"
|
|
#include "validation.h"
|
|
|
|
#include "cbtx.h"
|
|
#include "deterministicmns.h"
|
|
#include "specialtx.h"
|
|
|
|
#include "llmq/quorums_commitment.h"
|
|
#include "llmq/quorums_blockprocessor.h"
|
|
|
|
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
|
|
{
|
|
if (tx.nVersion != 3 || tx.nType == TRANSACTION_NORMAL)
|
|
return true;
|
|
|
|
if (pindexPrev && pindexPrev->nHeight + 1 < Params().GetConsensus().DIP0003Height) {
|
|
return state.DoS(10, false, REJECT_INVALID, "bad-tx-type");
|
|
}
|
|
|
|
switch (tx.nType) {
|
|
case TRANSACTION_PROVIDER_REGISTER:
|
|
return CheckProRegTx(tx, pindexPrev, state);
|
|
case TRANSACTION_PROVIDER_UPDATE_SERVICE:
|
|
return CheckProUpServTx(tx, pindexPrev, state);
|
|
case TRANSACTION_PROVIDER_UPDATE_REGISTRAR:
|
|
return CheckProUpRegTx(tx, pindexPrev, state);
|
|
case TRANSACTION_PROVIDER_UPDATE_REVOKE:
|
|
return CheckProUpRevTx(tx, pindexPrev, state);
|
|
case TRANSACTION_COINBASE:
|
|
return CheckCbTx(tx, pindexPrev, state);
|
|
case TRANSACTION_QUORUM_COMMITMENT:
|
|
return llmq::CheckLLMQCommitment(tx, pindexPrev, state);
|
|
}
|
|
|
|
return state.DoS(10, false, REJECT_INVALID, "bad-tx-type-check");
|
|
}
|
|
|
|
bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValidationState& state)
|
|
{
|
|
if (tx.nVersion != 3 || tx.nType == TRANSACTION_NORMAL) {
|
|
return true;
|
|
}
|
|
|
|
switch (tx.nType) {
|
|
case TRANSACTION_PROVIDER_REGISTER:
|
|
case TRANSACTION_PROVIDER_UPDATE_SERVICE:
|
|
case TRANSACTION_PROVIDER_UPDATE_REGISTRAR:
|
|
case TRANSACTION_PROVIDER_UPDATE_REVOKE:
|
|
return true; // handled in batches per block
|
|
case TRANSACTION_COINBASE:
|
|
return true; // nothing to do
|
|
case TRANSACTION_QUORUM_COMMITMENT:
|
|
return true; // handled per block
|
|
}
|
|
|
|
return state.DoS(100, false, REJECT_INVALID, "bad-tx-type-proc");
|
|
}
|
|
|
|
bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
|
|
{
|
|
if (tx.nVersion != 3 || tx.nType == TRANSACTION_NORMAL) {
|
|
return true;
|
|
}
|
|
|
|
switch (tx.nType) {
|
|
case TRANSACTION_PROVIDER_REGISTER:
|
|
case TRANSACTION_PROVIDER_UPDATE_SERVICE:
|
|
case TRANSACTION_PROVIDER_UPDATE_REGISTRAR:
|
|
case TRANSACTION_PROVIDER_UPDATE_REVOKE:
|
|
return true; // handled in batches per block
|
|
case TRANSACTION_COINBASE:
|
|
return true; // nothing to do
|
|
case TRANSACTION_QUORUM_COMMITMENT:
|
|
return true; // handled per block
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state, bool fJustCheck, bool fCheckCbTxMerleRoots)
|
|
{
|
|
static int64_t nTimeLoop = 0;
|
|
static int64_t nTimeQuorum = 0;
|
|
static int64_t nTimeDMN = 0;
|
|
static int64_t nTimeMerkle = 0;
|
|
|
|
int64_t nTime1 = GetTimeMicros();
|
|
|
|
for (int i = 0; i < (int)block.vtx.size(); i++) {
|
|
const CTransaction& tx = *block.vtx[i];
|
|
if (!CheckSpecialTx(tx, pindex->pprev, state)) {
|
|
return false;
|
|
}
|
|
if (!ProcessSpecialTx(tx, pindex, state)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
int64_t nTime2 = GetTimeMicros(); nTimeLoop += nTime2 - nTime1;
|
|
LogPrint("bench", " - Loop: %.2fms [%.2fs]\n", 0.001 * (nTime2 - nTime1), nTimeLoop * 0.000001);
|
|
|
|
if (!llmq::quorumBlockProcessor->ProcessBlock(block, pindex, state)) {
|
|
return false;
|
|
}
|
|
|
|
int64_t nTime3 = GetTimeMicros(); nTimeQuorum += nTime3 - nTime2;
|
|
LogPrint("bench", " - quorumBlockProcessor: %.2fms [%.2fs]\n", 0.001 * (nTime3 - nTime2), nTimeQuorum * 0.000001);
|
|
|
|
if (!deterministicMNManager->ProcessBlock(block, pindex, state, fJustCheck)) {
|
|
return false;
|
|
}
|
|
|
|
int64_t nTime4 = GetTimeMicros(); nTimeDMN += nTime4 - nTime3;
|
|
LogPrint("bench", " - deterministicMNManager: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeDMN * 0.000001);
|
|
|
|
if (fCheckCbTxMerleRoots && !CheckCbTxMerkleRoots(block, pindex, state)) {
|
|
return false;
|
|
}
|
|
|
|
int64_t nTime5 = GetTimeMicros(); nTimeMerkle += nTime5 - nTime4;
|
|
LogPrint("bench", " - CheckCbTxMerkleRoots: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeMerkle * 0.000001);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex)
|
|
{
|
|
for (int i = (int)block.vtx.size() - 1; i >= 0; --i) {
|
|
const CTransaction& tx = *block.vtx[i];
|
|
if (!UndoSpecialTx(tx, pindex)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!deterministicMNManager->UndoBlock(block, pindex)) {
|
|
return false;
|
|
}
|
|
|
|
if (!llmq::quorumBlockProcessor->UndoBlock(block, pindex)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
uint256 CalcTxInputsHash(const CTransaction& tx)
|
|
{
|
|
CHashWriter hw(CLIENT_VERSION, SER_GETHASH);
|
|
for (const auto& in : tx.vin) {
|
|
hw << in.prevout;
|
|
}
|
|
return hw.GetHash();
|
|
}
|