Merge #15921: validation: Tidy up ValidationState interface

3004d5a12d09d94bfc4dee2a8e8f2291996a4aaf [validation] Remove fMissingInputs from AcceptToMemoryPool() (John Newbery)
c428622a5bb1e37b2e6ab2c52791ac05d9271238 [validation] Remove unused first_invalid parameter from ProcessNewBlockHeaders() (John Newbery)
7204c6434b944f6ad51b3c895837729d3aa56eea [validation] Remove useless ret parameter from Invalid() (John Newbery)
1a37de4b3174d19a6d8691ae07e92b32fdfaef11 [validation] Remove error() calls from Invalid() calls (John Newbery)
067981e49246822421a7bcc720491427e1dba8a3 [validation] Tidy Up ValidationResult class (John Newbery)
a27a2957ed9afbe5a96caa5f0f4cbec730d27460 [validation] Add CValidationState subclasses (John Newbery)

Pull request description:

  Carries out some remaining tidy-ups remaining after PR 15141:

  - split ValidationState into TxValidationState and BlockValidationState (commit from ajtowns)
  - various minor code style tidy-ups to the ValidationState class
  - remove the useless `ret` parameter from `ValidationState::Invalid()`
  - remove the now unused `first_invalid` parameter from `ProcessNewBlockHeaders()`
  - remove the `fMissingInputs` parameter from `AcceptToMemoryPool()`, and deal with missing inputs the same way as other errors by using the `TxValidationState` object.

  Tip for reviewers (thanks ryanofsky!): The first commit ("[validation] Add CValidationState subclasses" ) is huge and can be easier to start reviewing if you revert the rote, mechanical changes:

  Substitute the commit hash of commit "[validation] Add CValidationState subclasses" for <CommitHash> in the commands below.

  ```sh
  git checkout <CommitHash>
  git grep -l ValidationState | xargs sed -i 's/BlockValidationState\|TxValidationState/CValidationState/g'
  git grep -l ValidationResult | xargs sed -i 's/BlockValidationResult\|TxValidationResult/ValidationInvalidReason/g'
  git grep -l MaybePunish | xargs sed -i 's/MaybePunishNode\(ForBlock\|ForTx\)/MaybePunishNode/g'
  git diff HEAD^
  ```

  After that it's possible to easily see the mechanical changes with:

  ```sh
  git log -p -n1 -U0 --word-diff-regex=. <CommitHash>
  ```

ACKs for top commit:
  laanwj:
    ACK 3004d5a12d09d94bfc4dee2a8e8f2291996a4aaf
  amitiuttarwar:
    code review ACK 3004d5a12d09d94bfc4dee2a8e8f2291996a4aaf. Also built & ran tests locally.
  fjahr:
    Code review ACK 3004d5a12d09d94bfc4dee2a8e8f2291996a4aaf . Only nit style change and pure virtual destructor added since my last review.
  ryanofsky:
    Code review ACK 3004d5a12d09d94bfc4dee2a8e8f2291996a4aaf. Just whitespace change and pure virtual destructor added since last review.

Tree-SHA512: 511de1fb380a18bec1944ea82b513b6192df632ee08bb16344a2df3c40811a88f3872f04df24bc93a41643c96c48f376a04551840fd804a961490d6c702c3d36
This commit is contained in:
Wladimir J. van der Laan 2019-10-30 15:27:22 +01:00 committed by PastaPastaPasta
parent 091d813e00
commit eec81f7b33
62 changed files with 707 additions and 651 deletions

View File

@ -40,8 +40,8 @@ static void AssembleBlock(benchmark::Bench& bench)
LOCK(::cs_main); // Required for ::AcceptToMemoryPool.
for (const auto& txr : txs) {
CValidationState state;
bool ret{::AcceptToMemoryPool(::ChainstateActive(), *test_setup.m_node.mempool, state, txr, nullptr /* pfMissingInputs */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
TxValidationState state;
bool ret{::AcceptToMemoryPool(::ChainstateActive(), *test_setup.m_node.mempool, state, txr, false /* bypass_limits */, /* nAbsurdFee */ 0)};
assert(ret);
}
}

View File

@ -42,7 +42,7 @@ static void DeserializeAndCheckBlockTest(benchmark::Bench& bench)
bool rewound = stream.Rewind(benchmark::data::block813851.size());
assert(rewound);
CValidationState validationState;
BlockValidationState validationState;
bool checked = CheckBlock(block, validationState, chainParams->GetConsensus(), block.GetBlockTime());
assert(checked);
});

View File

@ -56,7 +56,7 @@ static void DuplicateInputs(benchmark::Bench& bench)
block.hashMerkleRoot = BlockMerkleRoot(block);
bench.minEpochIterations(10).run([&] {
CValidationState cvstate{};
BlockValidationState cvstate{};
assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false));
assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate");
});

View File

@ -198,13 +198,13 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
if (vtx_missing.size() != tx_missing_offset)
return READ_STATUS_INVALID;
CValidationState state;
BlockValidationState state;
if (!CheckBlock(block, state, Params().GetConsensus())) {
// TODO: We really want to just check merkle tree manually here,
// but that is expensive, and CheckBlock caches a block's
// "checked-status" (in the CBlock?). CBlock should be able to
// check its own merkle root and cache that check.
if (state.GetReason() == ValidationInvalidReason::BLOCK_MUTATED)
if (state.GetResult() == BlockValidationResult::BLOCK_MUTATED)
return READ_STATUS_FAILED; // Possible Short ID collision
return READ_STATUS_CHECKBLOCK_FAILED;
}

View File

@ -351,8 +351,8 @@ bool CCoinJoin::IsCollateralValid(CTxMemPool& mempool, const CTransaction& txCol
{
LOCK(cs_main);
CValidationState validationState;
if (!AcceptToMemoryPool(::ChainstateActive(), mempool, validationState, MakeTransactionRef(txCollateral), /*pfMissingInputs=*/nullptr, /*bypass_limits=*/false, /*nAbsurdFee=*/DEFAULT_MAX_RAW_TX_FEE, /*test_accept=*/true)) {
TxValidationState validationState;
if (!AcceptToMemoryPool(::ChainstateActive(), mempool, validationState, MakeTransactionRef(txCollateral), /*bypass_limits=*/false, /*nAbsurdFee=*/DEFAULT_MAX_RAW_TX_FEE, /*test_accept=*/true)) {
LogPrint(BCLog::COINJOIN, "CCoinJoin::IsCollateralValid -- didn't pass AcceptToMemoryPool()\n");
return false;
}

View File

@ -320,9 +320,9 @@ void CCoinJoinServer::CommitFinalTransaction()
{
// See if the transaction is valid
TRY_LOCK(cs_main, lockMain);
CValidationState validationState;
TxValidationState validationState;
mempool.PrioritiseTransaction(hashTx, 0.1 * COIN);
if (!lockMain || !AcceptToMemoryPool(::ChainstateActive(), mempool, validationState, finalTransaction, nullptr /* pfMissingInputs */, false /* bypass_limits */, DEFAULT_MAX_RAW_TX_FEE /* nAbsurdFee */)) {
if (!lockMain || !AcceptToMemoryPool(::ChainstateActive(), mempool, validationState, finalTransaction, false /* bypass_limits */, DEFAULT_MAX_RAW_TX_FEE /* nAbsurdFee */)) {
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::CommitFinalTransaction -- AcceptToMemoryPool() error: Transaction not valid\n");
WITH_LOCK(cs_coinjoin, SetNull());
// not much we can do in this case, just notify clients
@ -454,8 +454,8 @@ void CCoinJoinServer::ChargeRandomFees() const
void CCoinJoinServer::ConsumeCollateral(const CTransactionRef& txref) const
{
LOCK(cs_main);
CValidationState validationState;
if (!AcceptToMemoryPool(::ChainstateActive(), mempool, validationState, txref, nullptr /* pfMissingInputs */, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
TxValidationState validationState;
if (!AcceptToMemoryPool(::ChainstateActive(), mempool, validationState, txref, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
LogPrint(BCLog::COINJOIN, "%s -- AcceptToMemoryPool failed\n", __func__);
} else {
connman.RelayTransaction(*txref);

View File

@ -10,7 +10,7 @@
#include <primitives/transaction.h>
#include <consensus/validation.h>
bool CheckTransaction(const CTransaction& tx, CValidationState& state)
bool CheckTransaction(const CTransaction& tx, TxValidationState& state)
{
bool allowEmptyTxInOut = false;
if (tx.nType == TRANSACTION_QUORUM_COMMITMENT) {
@ -19,25 +19,25 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
// Basic checks that don't depend on any context
if (!allowEmptyTxInOut && tx.vin.empty())
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vin-empty");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vin-empty");
if (!allowEmptyTxInOut && tx.vout.empty())
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-empty");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-empty");
// Size limits
if (::GetSerializeSize(tx, PROTOCOL_VERSION) > MAX_LEGACY_BLOCK_SIZE)
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-oversize");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-oversize");
if (tx.vExtraPayload.size() > MAX_TX_EXTRA_PAYLOAD)
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-payload-oversize");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-payload-oversize");
// Check for negative or overflow output values (see CVE-2010-5139)
CAmount nValueOut = 0;
for (const auto& txout : tx.vout) {
if (txout.nValue < 0)
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-negative");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-negative");
if (txout.nValue > MAX_MONEY)
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-toolarge");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-toolarge");
nValueOut += txout.nValue;
if (!MoneyRange(nValueOut))
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-txouttotal-toolarge");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-txouttotal-toolarge");
}
// Check for duplicate inputs (see CVE-2018-17144)
@ -48,7 +48,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
std::set<COutPoint> vInOutPoints;
for (const auto& txin : tx.vin) {
if (!vInOutPoints.insert(txin.prevout).second)
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputs-duplicate");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputs-duplicate");
}
if (tx.IsCoinBase()) {
@ -58,11 +58,11 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
minCbSize = 1;
}
if (tx.vin[0].scriptSig.size() < minCbSize || tx.vin[0].scriptSig.size() > 100)
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-length");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cb-length");
} else {
for (const auto& txin : tx.vin)
if (txin.prevout.IsNull())
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-prevout-null");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-prevout-null");
}
return true;

View File

@ -13,9 +13,9 @@
*/
class CTransaction;
class CValidationState;
class TxValidationState;
/** Context-independent validity checks */
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
bool CheckTransaction(const CTransaction& tx, TxValidationState& state);
#endif // BITCOIN_CONSENSUS_TX_CHECK_H

View File

@ -158,11 +158,11 @@ unsigned int GetTransactionSigOpCount(const CTransaction& tx, const CCoinsViewCa
return nSigOps;
}
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
{
// are the actual inputs available?
if (!inputs.HaveInputs(tx)) {
return state.Invalid(ValidationInvalidReason::TX_MISSING_INPUTS, false, "bad-txns-inputs-missingorspent",
return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent",
strprintf("%s: inputs missing/spent", __func__));
}
@ -174,27 +174,27 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
// If prev is coinbase, check that it's matured
if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, "bad-txns-premature-spend-of-coinbase",
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-premature-spend-of-coinbase",
strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
}
// Check for negative or overflow input values
nValueIn += coin.out.nValue;
if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputvalues-outofrange");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputvalues-outofrange");
}
}
const CAmount value_out = tx.GetValueOut();
if (nValueIn < value_out) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-in-belowout",
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-in-belowout",
strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
}
// Tally transaction fees
const CAmount txfee_aux = nValueIn - value_out;
if (!MoneyRange(txfee_aux)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-fee-outofrange");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-fee-outofrange");
}
txfee = txfee_aux;

View File

@ -13,7 +13,7 @@
class CBlockIndex;
class CCoinsViewCache;
class CTransaction;
class CValidationState;
class TxValidationState;
/** Transaction validation functions */
@ -24,7 +24,7 @@ namespace Consensus {
* @param[out] txfee Set to the transaction fee if successful.
* Preconditions: tx.IsCoinBase() is false.
*/
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee);
bool CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee);
} // namespace Consensus
/** Auxiliary functions for transaction validation (ideally should not be exposed) */

View File

@ -8,19 +8,47 @@
#include <string>
/** A "reason" why something was invalid, suitable for determining whether the
* provider of the object should be banned/ignored/disconnected/etc.
/** A "reason" why a transaction was invalid, suitable for determining whether the
* provider of the transaction should be banned/ignored/disconnected/etc.
*/
enum class ValidationInvalidReason {
// txn and blocks:
NONE, //!< not actually invalid
CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
enum class TxValidationResult {
TX_RESULT_UNSET, //!< initial value. Tx has not yet been rejected
TX_CONSENSUS, //!< invalid by consensus rules
/**
* Invalid by a change to consensus rules more recent than some major deployment.
*/
RECENT_CONSENSUS_CHANGE,
// Only blocks (or headers):
CACHED_INVALID, //!< this object was cached as being invalid, but we don't know why
// Only loose txn:
TX_RECENT_CONSENSUS_CHANGE,
TX_NOT_STANDARD, //!< didn't meet our local policy rules
TX_MISSING_INPUTS, //!< transaction was missing some of its inputs
TX_PREMATURE_SPEND, //!< transaction spends a coinbase too early, or violates locktime/sequence locks
TX_BAD_SPECIAL, //!< special transaction violates some rules that are not enough for insta-ban
/**
* Tx already in mempool or conflicts with a tx in the chain
* Currently this is only used if the transaction already exists in the mempool or on chain.
*/
TX_CONFLICT,
TX_CONFLICT_LOCK, //!< conflicts with InstantSend lock
TX_MEMPOOL_POLICY, //!< violated mempool's fee/size/descendant/etc limits
};
/** A "reason" why a block was invalid, suitable for determining whether the
* provider of the block should be banned/ignored/disconnected/etc.
* These are much more granular than the rejection codes, which may be more
* useful for some other use-cases.
*/
enum class BlockValidationResult {
BLOCK_RESULT_UNSET, //!< initial value. Block has not yet been rejected
BLOCK_CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
/**
* Invalid by a change to consensus rules more recent than SegWit.
* Currently unused as there are no such consensus rule changes, and any download
* sources realistically need to support SegWit in order to provide useful data,
* so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
* is uninteresting.
*/
BLOCK_RECENT_CONSENSUS_CHANGE,
BLOCK_CACHED_INVALID, //!< this block was cached as being invalid and we didn't store the reason why
BLOCK_INVALID_HEADER, //!< invalid proof of work or time too old
BLOCK_MUTATED, //!< the block's data didn't match the data committed to by the PoW
BLOCK_MISSING_PREV, //!< We don't have the previous block the checked one is built on
@ -28,92 +56,78 @@ enum class ValidationInvalidReason {
BLOCK_TIME_FUTURE, //!< block timestamp was > 2 hours in the future (or our clock is bad)
BLOCK_CHECKPOINT, //!< the block failed to meet one of our checkpoints
BLOCK_CHAINLOCK, //!< the block conflicts with the ChainLock
// Only loose txn:
TX_NOT_STANDARD, //!< didn't meet our local policy rules
TX_MISSING_INPUTS, //!< a transaction was missing some of its inputs
TX_PREMATURE_SPEND, //!< transaction spends a coinbase too early, or violates locktime/sequence locks
TX_BAD_SPECIAL, //!< special transaction violates some rules that are not enough for insta-ban
/**
* Tx already in mempool or conflicts with a tx in the chain
* TODO: Currently this is only used if the transaction already exists in the mempool or on chain,
* TODO: ATMP's fMissingInputs and a valid CValidationState being used to indicate missing inputs
*/
TX_CONFLICT,
TX_CONFLICT_LOCK, //!< conflicts with InstantSend lock
TX_MEMPOOL_POLICY, //!< violated mempool's fee/size/descendant/etc limits
};
inline bool IsTransactionReason(ValidationInvalidReason r)
{
return r == ValidationInvalidReason::NONE ||
r == ValidationInvalidReason::CONSENSUS ||
r == ValidationInvalidReason::RECENT_CONSENSUS_CHANGE ||
r == ValidationInvalidReason::TX_NOT_STANDARD ||
r == ValidationInvalidReason::TX_PREMATURE_SPEND ||
r == ValidationInvalidReason::TX_MISSING_INPUTS ||
r == ValidationInvalidReason::TX_BAD_SPECIAL ||
r == ValidationInvalidReason::TX_CONFLICT ||
r == ValidationInvalidReason::TX_CONFLICT_LOCK ||
r == ValidationInvalidReason::TX_MEMPOOL_POLICY;
}
inline bool IsBlockReason(ValidationInvalidReason r)
{
return r == ValidationInvalidReason::NONE ||
r == ValidationInvalidReason::CONSENSUS ||
r == ValidationInvalidReason::RECENT_CONSENSUS_CHANGE ||
r == ValidationInvalidReason::CACHED_INVALID ||
r == ValidationInvalidReason::BLOCK_INVALID_HEADER ||
r == ValidationInvalidReason::BLOCK_MUTATED ||
r == ValidationInvalidReason::BLOCK_MISSING_PREV ||
r == ValidationInvalidReason::BLOCK_INVALID_PREV ||
r == ValidationInvalidReason::BLOCK_TIME_FUTURE ||
r == ValidationInvalidReason::BLOCK_CHECKPOINT ||
r == ValidationInvalidReason::BLOCK_CHAINLOCK;
}
/** Capture information about block/transaction validation */
class CValidationState {
/** Base class for capturing information about block/transaction validation. This is subclassed
* by TxValidationState and BlockValidationState for validation information on transactions
* and blocks respectively. */
class ValidationState {
private:
enum mode_state {
MODE_VALID, //!< everything ok
MODE_INVALID, //!< network rule violation (DoS value may be set)
MODE_ERROR, //!< run-time error
} mode;
ValidationInvalidReason m_reason;
std::string strRejectReason;
std::string strDebugMessage;
public:
CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE) {}
bool Invalid(ValidationInvalidReason reasonIn, bool ret = false,
const std::string &strRejectReasonIn="",
const std::string &strDebugMessageIn="") {
m_reason = reasonIn;
strRejectReason = strRejectReasonIn;
strDebugMessage = strDebugMessageIn;
if (mode == MODE_ERROR)
return ret;
mode = MODE_INVALID;
return ret;
} m_mode;
std::string m_reject_reason;
std::string m_debug_message;
protected:
void Invalid(const std::string &reject_reason="",
const std::string &debug_message="")
{
m_reject_reason = reject_reason;
m_debug_message = debug_message;
if (m_mode != MODE_ERROR) m_mode = MODE_INVALID;
}
bool Error(const std::string& strRejectReasonIn) {
if (mode == MODE_VALID)
strRejectReason = strRejectReasonIn;
mode = MODE_ERROR;
public:
// ValidationState is abstract. Have a pure virtual destructor.
virtual ~ValidationState() = 0;
ValidationState() : m_mode(MODE_VALID) {}
bool Error(const std::string& reject_reason)
{
if (m_mode == MODE_VALID)
m_reject_reason = reject_reason;
m_mode = MODE_ERROR;
return false;
}
bool IsValid() const {
return mode == MODE_VALID;
bool IsValid() const { return m_mode == MODE_VALID; }
bool IsInvalid() const { return m_mode == MODE_INVALID; }
bool IsError() const { return m_mode == MODE_ERROR; }
std::string GetRejectReason() const { return m_reject_reason; }
std::string GetDebugMessage() const { return m_debug_message; }
};
inline ValidationState::~ValidationState() {};
class TxValidationState : public ValidationState {
private:
TxValidationResult m_result;
public:
bool Invalid(TxValidationResult result,
const std::string &reject_reason="",
const std::string &debug_message="")
{
m_result = result;
ValidationState::Invalid(reject_reason, debug_message);
return false;
}
bool IsInvalid() const {
return mode == MODE_INVALID;
TxValidationResult GetResult() const { return m_result; }
};
class BlockValidationState : public ValidationState {
private:
BlockValidationResult m_result;
public:
bool Invalid(BlockValidationResult result,
const std::string &reject_reason="",
const std::string &debug_message="") {
m_result = result;
ValidationState::Invalid(reject_reason, debug_message);
return false;
}
bool IsError() const {
return mode == MODE_ERROR;
}
ValidationInvalidReason GetReason() const { return m_reason; }
std::string GetRejectReason() const { return strRejectReason; }
std::string GetDebugMessage() const { return strDebugMessage; }
BlockValidationResult GetResult() const { return m_result; }
};
#endif // BITCOIN_CONSENSUS_VALIDATION_H

View File

@ -15,33 +15,33 @@
#include <chainparams.h>
#include <consensus/merkle.h>
bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state)
{
if (tx.nType != TRANSACTION_COINBASE) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-type");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-type");
}
if (!tx.IsCoinBase()) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-invalid");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-invalid");
}
CCbTx cbTx;
if (!GetTxPayload(tx, cbTx)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-payload");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-payload");
}
if (cbTx.nVersion == 0 || cbTx.nVersion > CCbTx::CURRENT_VERSION) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-version");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-version");
}
if (pindexPrev && pindexPrev->nHeight + 1 != cbTx.nHeight) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-height");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-height");
}
if (pindexPrev) {
bool fDIP0008Active = pindexPrev->nHeight >= Params().GetConsensus().DIP0008Height;
if (fDIP0008Active && cbTx.nVersion < 2) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-version");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-version");
}
}
@ -49,7 +49,7 @@ bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidatio
}
// This can only be done after the block has been fully processed, as otherwise we won't have the finished MN list
bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const llmq::CQuorumBlockProcessor& quorum_block_processor, CValidationState& state, const CCoinsViewCache& view)
bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const llmq::CQuorumBlockProcessor& quorum_block_processor, BlockValidationState& state, const CCoinsViewCache& view)
{
if (block.vtx[0]->nType != TRANSACTION_COINBASE) {
return true;
@ -61,7 +61,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const
CCbTx cbTx;
if (!GetTxPayload(*block.vtx[0], cbTx)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-payload");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cbtx-payload");
}
int64_t nTime2 = GetTimeMicros(); nTimePayload += nTime2 - nTime1;
@ -77,7 +77,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const
return false;
}
if (calculatedMerkleRoot != cbTx.merkleRootMNList) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-mnmerkleroot");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cbtx-mnmerkleroot");
}
int64_t nTime3 = GetTimeMicros(); nTimeMerkleMNL += nTime3 - nTime2;
@ -89,7 +89,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const
return false;
}
if (calculatedMerkleRoot != cbTx.merkleRootQuorums) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-quorummerkleroot");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cbtx-quorummerkleroot");
}
}
@ -101,7 +101,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const
return true;
}
bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, CValidationState& state, const CCoinsViewCache& view)
bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, BlockValidationState& state, const CCoinsViewCache& view)
{
LOCK(deterministicMNManager->cs);
@ -134,7 +134,7 @@ bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev
if (sml == smlCached) {
merkleRootRet = merkleRootCached;
if (mutatedCached) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "mutated-cached-calc-cb-mnmerkleroot");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "mutated-cached-calc-cb-mnmerkleroot");
}
return true;
}
@ -150,13 +150,13 @@ bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev
mutatedCached = mutated;
if (mutated) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "mutated-calc-cb-mnmerkleroot");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "mutated-calc-cb-mnmerkleroot");
}
return true;
} catch (const std::exception& e) {
LogPrintf("%s -- failed: %s\n", __func__, e.what());
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "failed-calc-cb-mnmerkleroot");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "failed-calc-cb-mnmerkleroot");
}
}
@ -223,7 +223,7 @@ auto CalcHashCountFromQCHashes(const QcHashMap& qcHashes)
return hash_count;
}
bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, const llmq::CQuorumBlockProcessor& quorum_block_processor, uint256& merkleRootRet, CValidationState& state)
bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, const llmq::CQuorumBlockProcessor& quorum_block_processor, uint256& merkleRootRet, BlockValidationState& state)
{
static int64_t nTimeMined = 0;
static int64_t nTimeLoop = 0;
@ -233,7 +233,7 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre
auto retVal = CachedGetQcHashesQcIndexedHashes(pindexPrev, quorum_block_processor);
if (!retVal) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "commitment-not-found");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "commitment-not-found");
}
// The returned quorums are in reversed order, so the most recent one is at index 0
auto [qcHashes, qcIndexedHashes] = retVal.value();
@ -249,7 +249,7 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre
if (tx->nVersion == 3 && tx->nType == TRANSACTION_QUORUM_COMMITMENT) {
llmq::CFinalCommitmentTxPayload qc;
if (!GetTxPayload(*tx, qc)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-payload-calc-cbtx-quorummerkleroot");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-payload-calc-cbtx-quorummerkleroot");
}
if (qc.commitment.IsNull()) {
// having null commitments is ok but we don't use them here, move to the next tx
@ -257,7 +257,7 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre
}
const auto& llmq_params_opt = llmq::GetLLMQParams(qc.commitment.llmqType);
if (!llmq_params_opt.has_value()) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-commitment-type-calc-cbtx-quorummerkleroot");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-commitment-type-calc-cbtx-quorummerkleroot");
}
const auto& llmq_params = llmq_params_opt.value();
auto qcHash = ::SerializeHash(qc.commitment);
@ -291,7 +291,7 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre
const auto& llmq_params_opt = llmq::GetLLMQParams(llmqType);
assert(llmq_params_opt.has_value());
if (vec_hashes.size() > size_t(llmq_params_opt->signingActiveQuorumCount)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "excess-quorums-calc-cbtx-quorummerkleroot");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "excess-quorums-calc-cbtx-quorummerkleroot");
}
// Copy vec_hashes into vec_hashes_final
std::copy(vec_hashes.begin(), vec_hashes.end(), std::back_inserter(vec_hashes_final));
@ -308,7 +308,7 @@ bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPre
LogPrint(BCLog::BENCHMARK, " - ComputeMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkle * 0.000001);
if (mutated) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "mutated-calc-cbtx-quorummerkleroot");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "mutated-calc-cbtx-quorummerkleroot");
}
return true;

View File

@ -8,10 +8,11 @@
#include <primitives/transaction.h>
#include <univalue.h>
class BlockValidationState;
class CBlock;
class CBlockIndex;
class CCoinsViewCache;
class CValidationState;
class TxValidationState;
namespace llmq {
class CQuorumBlockProcessor;
@ -53,10 +54,10 @@ public:
}
};
bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state);
bool CheckCbTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state);
bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const llmq::CQuorumBlockProcessor& quorum_block_processor, CValidationState& state, const CCoinsViewCache& view);
bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, CValidationState& state, const CCoinsViewCache& view);
bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, const llmq::CQuorumBlockProcessor& quorum_block_processor, uint256& merkleRootRet, CValidationState& state);
bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const llmq::CQuorumBlockProcessor& quorum_block_processor, BlockValidationState& state, const CCoinsViewCache& view);
bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev, uint256& merkleRootRet, BlockValidationState& state, const CCoinsViewCache& view);
bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, const llmq::CQuorumBlockProcessor& quorum_block_processor, uint256& merkleRootRet, BlockValidationState& state);
#endif // BITCOIN_EVO_CBTX_H

View File

@ -654,7 +654,7 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
mnInternalIdMap = mnInternalIdMap.erase(dmn->GetInternalId());
}
bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& _state, const CCoinsViewCache& view, bool fJustCheck)
bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockIndex* pindex, BlockValidationState& state, const CCoinsViewCache& view, bool fJustCheck)
{
AssertLockHeld(cs_main);
@ -672,7 +672,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
try {
LOCK(cs);
if (!BuildNewListFromBlock(block, pindex->pprev, _state, view, newList, true)) {
if (!BuildNewListFromBlock(block, pindex->pprev, state, view, newList, true)) {
// pass the state returned by the function above
return false;
}
@ -710,7 +710,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
mnListDiffsCache.emplace(pindex->GetBlockHash(), diff);
} catch (const std::exception& e) {
LogPrintf("CDeterministicMNManager::%s -- internal error: %s\n", __func__, e.what());
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "failed-dmn-block");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "failed-dmn-block");
}
// Don't hold cs while calling signals
@ -723,7 +723,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
if (!consensusParams.DIP0003EnforcementHash.IsNull() && consensusParams.DIP0003EnforcementHash != pindex->GetBlockHash()) {
LogPrintf("CDeterministicMNManager::%s -- DIP3 enforcement block has wrong hash: hash=%s, expected=%s, nHeight=%d\n", __func__,
pindex->GetBlockHash().ToString(), consensusParams.DIP0003EnforcementHash.ToString(), nHeight);
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-dip3-enf-block");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-dip3-enf-block");
}
LogPrintf("CDeterministicMNManager::%s -- DIP3 is enforced now. nHeight=%d\n", __func__, nHeight);
}
@ -775,7 +775,7 @@ void CDeterministicMNManager::UpdatedBlockTip(const CBlockIndex* pindex)
tipIndex = pindex;
}
bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, CValidationState& _state, const CCoinsViewCache& view, CDeterministicMNList& mnListRet, bool debugLogs)
bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, BlockValidationState& state, const CCoinsViewCache& view, CDeterministicMNList& mnListRet, bool debugLogs)
{
AssertLockHeld(cs);
@ -820,11 +820,11 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
if (tx.nType == TRANSACTION_PROVIDER_REGISTER) {
CProRegTx proTx;
if (!GetTxPayload(tx, proTx)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
}
if (proTx.nType == MnType::HighPerformance && !llmq::utils::IsV19Active(pindexPrev)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
}
auto dmn = std::make_shared<CDeterministicMN>(newList.GetTotalRegisteredCount(), proTx.nType);
@ -842,7 +842,7 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
if (!proTx.collateralOutpoint.hash.IsNull() && (!view.GetCoin(dmn->collateralOutpoint, coin) || coin.IsSpent() || coin.out.nValue != expectedCollateral)) {
// should actually never get to this point as CheckProRegTx should have handled this case.
// We do this additional check nevertheless to be 100% sure
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-collateral");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-collateral");
}
auto replacedDmn = newList.GetMNByCollateral(dmn->collateralOutpoint);
@ -858,10 +858,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
}
if (newList.HasUniqueProperty(proTx.addr)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-dup-addr");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr");
}
if (newList.HasUniqueProperty(proTx.keyIDOwner) || newList.HasUniqueProperty(proTx.pubKeyOperator)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-dup-key");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-key");
}
dmn->nOperatorReward = proTx.nOperatorReward;
@ -883,26 +883,26 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
CProUpServTx proTx;
if (!GetTxPayload(tx, proTx)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
}
if (proTx.nType == MnType::HighPerformance && !llmq::utils::IsV19Active(pindexPrev)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
}
if (newList.HasUniqueProperty(proTx.addr) && newList.GetUniquePropertyMN(proTx.addr)->proTxHash != proTx.proTxHash) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-dup-addr");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-dup-addr");
}
CDeterministicMNCPtr dmn = newList.GetMN(proTx.proTxHash);
if (!dmn) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-hash");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
}
if (proTx.nType != dmn->nType) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-type-mismatch");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-type-mismatch");
}
if (!IsValidMnType(proTx.nType)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-type");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-type");
}
auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
@ -932,12 +932,12 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
CProUpRegTx proTx;
if (!GetTxPayload(tx, proTx)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
}
CDeterministicMNCPtr dmn = newList.GetMN(proTx.proTxHash);
if (!dmn) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-hash");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
}
auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
if (newState->pubKeyOperator.Get() != proTx.pubKeyOperator) {
@ -958,12 +958,12 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) {
CProUpRevTx proTx;
if (!GetTxPayload(tx, proTx)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-payload");
}
CDeterministicMNCPtr dmn = newList.GetMN(proTx.proTxHash);
if (!dmn) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-hash");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-protx-hash");
}
auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
newState->ResetOperatorFields();
@ -979,19 +979,19 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
} else if (tx.nType == TRANSACTION_QUORUM_COMMITMENT) {
llmq::CFinalCommitmentTxPayload qc;
if (!GetTxPayload(tx, qc)) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-payload");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-payload");
}
if (!qc.commitment.IsNull()) {
const auto& llmq_params_opt = llmq::GetLLMQParams(qc.commitment.llmqType);
if (!llmq_params_opt.has_value()) {
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-commitment-type");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-commitment-type");
}
int qcnHeight = int(qc.nHeight);
int quorumHeight = qcnHeight - (qcnHeight % llmq_params_opt->dkgInterval) + int(qc.commitment.quorumIndex);
auto pQuorumBaseBlockIndex = pindexPrev->GetAncestor(quorumHeight);
if (!pQuorumBaseBlockIndex || pQuorumBaseBlockIndex->GetBlockHash() != qc.commitment.quorumHash) {
// we should actually never get into this case as validation should have caught it...but let's be sure
return _state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-quorum-hash");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-quorum-hash");
}
HandleQuorumCommitment(qc.commitment, pQuorumBaseBlockIndex, newList, debugLogs);
@ -1348,111 +1348,111 @@ bool CDeterministicMNManager::MigrateDBIfNeeded()
}
template <typename ProTx>
static bool CheckService(const ProTx& proTx, CValidationState& state)
static bool CheckService(const ProTx& proTx, TxValidationState& state)
{
if (!proTx.addr.IsValid()) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-ipaddr");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr");
}
if (Params().RequireRoutableExternalIP() && !proTx.addr.IsRoutable()) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-ipaddr");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr");
}
static int mainnetDefaultPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPort();
if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
if (proTx.addr.GetPort() != mainnetDefaultPort) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-ipaddr-port");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr-port");
}
} else if (proTx.addr.GetPort() == mainnetDefaultPort) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-ipaddr-port");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr-port");
}
if (!proTx.addr.IsIPv4()) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-ipaddr");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-ipaddr");
}
return true;
}
template <typename ProTx>
static bool CheckPlatformFields(const ProTx& proTx, CValidationState& state)
static bool CheckPlatformFields(const ProTx& proTx, TxValidationState& state)
{
if (proTx.platformNodeID.IsNull()) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-platform-nodeid");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-nodeid");
}
static int mainnetPlatformP2PPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPlatformP2PPort();
if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
if (proTx.platformP2PPort != mainnetPlatformP2PPort) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-platform-p2p-port");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-p2p-port");
}
}
static int mainnetPlatformHTTPPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPlatformHTTPPort();
if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
if (proTx.platformHTTPPort != mainnetPlatformHTTPPort) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-platform-http-port");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-http-port");
}
}
static int mainnetDefaultP2PPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPort();
if (proTx.platformP2PPort == mainnetDefaultP2PPort) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-platform-p2p-port");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-p2p-port");
}
if (proTx.platformHTTPPort == mainnetDefaultP2PPort) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-platform-http-port");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-http-port");
}
if (proTx.platformP2PPort == proTx.platformHTTPPort ||
proTx.platformP2PPort == proTx.addr.GetPort() ||
proTx.platformHTTPPort == proTx.addr.GetPort()) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-platform-dup-ports");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-platform-dup-ports");
}
return true;
}
template <typename ProTx>
static bool CheckHashSig(const ProTx& proTx, const PKHash& pkhash, CValidationState& state)
static bool CheckHashSig(const ProTx& proTx, const PKHash& pkhash, TxValidationState& state)
{
std::string strError;
if (!CHashSigner::VerifyHash(::SerializeHash(proTx), ToKeyID(pkhash), proTx.vchSig, strError)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-sig");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-sig");
}
return true;
}
template <typename ProTx>
static bool CheckStringSig(const ProTx& proTx, const PKHash& pkhash, CValidationState& state)
static bool CheckStringSig(const ProTx& proTx, const PKHash& pkhash, TxValidationState& state)
{
std::string strError;
if (!CMessageSigner::VerifyMessage(ToKeyID(pkhash), proTx.vchSig, proTx.MakeSignString(), strError)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-sig");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-sig");
}
return true;
}
template <typename ProTx>
static bool CheckHashSig(const ProTx& proTx, const CBLSPublicKey& pubKey, CValidationState& state)
static bool CheckHashSig(const ProTx& proTx, const CBLSPublicKey& pubKey, TxValidationState& state)
{
if (!proTx.sig.VerifyInsecure(pubKey, ::SerializeHash(proTx))) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-sig");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-sig");
}
return true;
}
bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, bool check_sigs)
bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, const CCoinsViewCache& view, bool check_sigs)
{
if (tx.nType != TRANSACTION_PROVIDER_REGISTER) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-type");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-type");
}
CProRegTx ptx;
if (!GetTxPayload(tx, ptx)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-payload");
}
if (auto maybe_err = ptx.IsTriviallyValid(llmq::utils::IsV19Active(pindexPrev)); maybe_err.did_err) {
return state.Invalid(maybe_err.reason, false, std::string(maybe_err.error_str));
return state.Invalid(maybe_err.reason, std::string(maybe_err.error_str));
}
// It's allowed to set addr to 0, which will put the MN into PoSe-banned state and require a ProUpServTx to be issues later
@ -1477,31 +1477,31 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid
if (!ptx.collateralOutpoint.hash.IsNull()) {
Coin coin;
if (!view.GetCoin(ptx.collateralOutpoint, coin) || coin.IsSpent() || coin.out.nValue != expectedCollateral) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-collateral");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-collateral");
}
if (!ExtractDestination(coin.out.scriptPubKey, collateralTxDest)) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-collateral-dest");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-collateral-dest");
}
// Extract key from collateral. This only works for P2PK and P2PKH collaterals and will fail for P2SH.
// Issuer of this ProRegTx must prove ownership with this key by signing the ProRegTx
keyForPayloadSig = std::get_if<PKHash>(&collateralTxDest);
if (!keyForPayloadSig) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-collateral-pkh");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-collateral-pkh");
}
collateralOutpoint = ptx.collateralOutpoint;
} else {
if (ptx.collateralOutpoint.n >= tx.vout.size()) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-collateral-index");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-collateral-index");
}
if (tx.vout[ptx.collateralOutpoint.n].nValue != expectedCollateral) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-collateral");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-collateral");
}
if (!ExtractDestination(tx.vout[ptx.collateralOutpoint.n].scriptPubKey, collateralTxDest)) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-collateral-dest");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-collateral-dest");
}
collateralOutpoint = COutPoint(tx.GetHash(), ptx.collateralOutpoint.n);
@ -1510,7 +1510,7 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid
// don't allow reuse of collateral key for other keys (don't allow people to put the collateral key onto an online server)
// this check applies to internal and external collateral, but internal collaterals are not necessarily a P2PKH
if (collateralTxDest == CTxDestination(PKHash(ptx.keyIDOwner)) || collateralTxDest == CTxDestination(PKHash(ptx.keyIDVoting))) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-collateral-reuse");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-collateral-reuse");
}
if (pindexPrev) {
@ -1518,30 +1518,30 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid
// only allow reusing of addresses when it's for the same collateral (which replaces the old MN)
if (mnList.HasUniqueProperty(ptx.addr) && mnList.GetUniquePropertyMN(ptx.addr)->collateralOutpoint != collateralOutpoint) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-dup-addr");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr");
}
// never allow duplicate keys, even if this ProTx would replace an existing MN
if (mnList.HasUniqueProperty(ptx.keyIDOwner) || mnList.HasUniqueProperty(ptx.pubKeyOperator)) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-dup-key");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-key");
}
// never allow duplicate platformNodeIds for HPMNs
if (ptx.nType == MnType::HighPerformance) {
if (mnList.HasUniqueProperty(ptx.platformNodeID)) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-dup-platformnodeid");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-platformnodeid");
}
}
if (!deterministicMNManager->IsDIP3Enforced(pindexPrev->nHeight)) {
if (ptx.keyIDOwner != ptx.keyIDVoting) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-key-not-same");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-key-not-same");
}
}
}
if (auto maybe_err = CheckInputsHash(tx, ptx); maybe_err.did_err) {
return state.Invalid(maybe_err.reason, false, std::string(maybe_err.error_str));
return state.Invalid(maybe_err.reason, std::string(maybe_err.error_str));
}
if (keyForPayloadSig) {
@ -1553,26 +1553,26 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid
} else {
// collateral is part of this ProRegTx, so we know the collateral is owned by the issuer
if (!ptx.vchSig.empty()) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-sig");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-sig");
}
}
return true;
}
bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, bool check_sigs)
bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, bool check_sigs)
{
if (tx.nType != TRANSACTION_PROVIDER_UPDATE_SERVICE) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-type");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-type");
}
CProUpServTx ptx;
if (!GetTxPayload(tx, ptx)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-payload");
}
if (auto maybe_err = ptx.IsTriviallyValid(llmq::utils::IsV19Active(pindexPrev)); maybe_err.did_err) {
return state.Invalid(maybe_err.reason, false, std::string(maybe_err.error_str));
return state.Invalid(maybe_err.reason, std::string(maybe_err.error_str));
}
if (!CheckService(ptx, state)) {
@ -1590,34 +1590,34 @@ bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVa
auto mnList = deterministicMNManager->GetListForBlock(pindexPrev);
auto mn = mnList.GetMN(ptx.proTxHash);
if (!mn) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-hash");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-hash");
}
// don't allow updating to addresses already used by other MNs
if (mnList.HasUniqueProperty(ptx.addr) && mnList.GetUniquePropertyMN(ptx.addr)->proTxHash != ptx.proTxHash) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-dup-addr");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-addr");
}
// don't allow updating to platformNodeIds already used by other HPMNs
if (ptx.nType == MnType::HighPerformance) {
if (mnList.HasUniqueProperty(ptx.platformNodeID) && mnList.GetUniquePropertyMN(ptx.platformNodeID)->proTxHash != ptx.proTxHash) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-dup-platformnodeid");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-platformnodeid");
}
}
if (ptx.scriptOperatorPayout != CScript()) {
if (mn->nOperatorReward == 0) {
// don't allow setting operator reward payee in case no operatorReward was set
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-operator-payee");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-operator-payee");
}
if (!ptx.scriptOperatorPayout.IsPayToPublicKeyHash() && !ptx.scriptOperatorPayout.IsPayToScriptHash()) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-operator-payee");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-operator-payee");
}
}
// we can only check the signature if pindexPrev != nullptr and the MN is known
if (auto maybe_err = CheckInputsHash(tx, ptx); maybe_err.did_err) {
return state.Invalid(maybe_err.reason, false, std::string(maybe_err.error_str));
return state.Invalid(maybe_err.reason, std::string(maybe_err.error_str));
}
if (check_sigs && !CheckHashSig(ptx, mn->pdmnState->pubKeyOperator.Get(), state)) {
// pass the state returned by the function above
@ -1628,69 +1628,69 @@ bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVa
return true;
}
bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, bool check_sigs)
bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, const CCoinsViewCache& view, bool check_sigs)
{
if (tx.nType != TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-type");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-type");
}
CProUpRegTx ptx;
if (!GetTxPayload(tx, ptx)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-payload");
}
if (auto maybe_err = ptx.IsTriviallyValid(llmq::utils::IsV19Active(pindexPrev)); maybe_err.did_err) {
return state.Invalid(maybe_err.reason, false, std::string(maybe_err.error_str));
return state.Invalid(maybe_err.reason, std::string(maybe_err.error_str));
}
CTxDestination payoutDest;
if (!ExtractDestination(ptx.scriptPayout, payoutDest)) {
// should not happen as we checked script types before
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-payee-dest");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee-dest");
}
if (pindexPrev) {
auto mnList = deterministicMNManager->GetListForBlock(pindexPrev);
auto dmn = mnList.GetMN(ptx.proTxHash);
if (!dmn) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-hash");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-hash");
}
// don't allow reuse of payee key for other keys (don't allow people to put the payee key onto an online server)
if (payoutDest == CTxDestination(PKHash(dmn->pdmnState->keyIDOwner)) || payoutDest == CTxDestination(PKHash(ptx.keyIDVoting))) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-payee-reuse");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee-reuse");
}
Coin coin;
if (!view.GetCoin(dmn->collateralOutpoint, coin) || coin.IsSpent()) {
// this should never happen (there would be no dmn otherwise)
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-collateral");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-collateral");
}
// don't allow reuse of collateral key for other keys (don't allow people to put the collateral key onto an online server)
CTxDestination collateralTxDest;
if (!ExtractDestination(coin.out.scriptPubKey, collateralTxDest)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-collateral-dest");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-collateral-dest");
}
if (collateralTxDest == CTxDestination(PKHash(dmn->pdmnState->keyIDOwner)) || collateralTxDest == CTxDestination(PKHash(ptx.keyIDVoting))) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-collateral-reuse");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-collateral-reuse");
}
if (mnList.HasUniqueProperty(ptx.pubKeyOperator)) {
auto otherDmn = mnList.GetUniquePropertyMN(ptx.pubKeyOperator);
if (ptx.proTxHash != otherDmn->proTxHash) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-dup-key");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-dup-key");
}
}
if (!deterministicMNManager->IsDIP3Enforced(pindexPrev->nHeight)) {
if (dmn->pdmnState->keyIDOwner != ptx.keyIDVoting) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-protx-key-not-same");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-protx-key-not-same");
}
}
if (auto maybe_err = CheckInputsHash(tx, ptx); maybe_err.did_err) {
return state.Invalid(maybe_err.reason, false, std::string(maybe_err.error_str));
return state.Invalid(maybe_err.reason, std::string(maybe_err.error_str));
}
if (check_sigs && !CheckHashSig(ptx, PKHash(dmn->pdmnState->keyIDOwner), state)) {
// pass the state returned by the function above
@ -1701,29 +1701,29 @@ bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal
return true;
}
bool CheckProUpRevTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, bool check_sigs)
bool CheckProUpRevTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, bool check_sigs)
{
if (tx.nType != TRANSACTION_PROVIDER_UPDATE_REVOKE) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-type");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-type");
}
CProUpRevTx ptx;
if (!GetTxPayload(tx, ptx)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-payload");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-payload");
}
if (auto maybe_err = ptx.IsTriviallyValid(llmq::utils::IsV19Active(pindexPrev)); maybe_err.did_err) {
return state.Invalid(maybe_err.reason, false, std::string(maybe_err.error_str));
return state.Invalid(maybe_err.reason, std::string(maybe_err.error_str));
}
if (pindexPrev) {
auto mnList = deterministicMNManager->GetListForBlock(pindexPrev);
auto dmn = mnList.GetMN(ptx.proTxHash);
if (!dmn)
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-hash");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-hash");
if (auto maybe_err = CheckInputsHash(tx, ptx); maybe_err.did_err) {
return state.Invalid(maybe_err.reason, false, std::string(maybe_err.error_str));
return state.Invalid(maybe_err.reason, std::string(maybe_err.error_str));
}
if (check_sigs && !CheckHashSig(ptx, dmn->pdmnState->pubKeyOperator.Get(), state)) {
// pass the state returned by the function above

View File

@ -27,7 +27,7 @@
class CConnman;
class CBlock;
class CBlockIndex;
class CValidationState;
class TxValidationState;
class CSimplifiedMNListDiff;
extern CCriticalSection cs_main;
@ -563,14 +563,14 @@ public:
m_evoDb(evoDb), connman(_connman) {}
~CDeterministicMNManager() = default;
bool ProcessBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state,
bool ProcessBlock(const CBlock& block, const CBlockIndex* pindex, BlockValidationState& state,
const CCoinsViewCache& view, bool fJustCheck) EXCLUSIVE_LOCKS_REQUIRED(cs_main) LOCKS_EXCLUDED(cs);
bool UndoBlock(const CBlock& block, const CBlockIndex* pindex) LOCKS_EXCLUDED(cs);
void UpdatedBlockTip(const CBlockIndex* pindex) LOCKS_EXCLUDED(cs);
// the returned list will not contain the correct block hash (we can't know it yet as the coinbase TX is not updated yet)
bool BuildNewListFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view,
bool BuildNewListFromBlock(const CBlock& block, const CBlockIndex* pindexPrev, BlockValidationState& state, const CCoinsViewCache& view,
CDeterministicMNList& mnListRet, bool debugLogs) EXCLUSIVE_LOCKS_REQUIRED(cs);
static void HandleQuorumCommitment(const llmq::CFinalCommitment& qc, const CBlockIndex* pQuorumBaseBlockIndex, CDeterministicMNList& mnList, bool debugLogs);
static void DecreasePoSePenalties(CDeterministicMNList& mnList);
@ -595,10 +595,10 @@ private:
CDeterministicMNList GetListForBlockInternal(const CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs);
};
bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, bool check_sigs);
bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, bool check_sigs);
bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, bool check_sigs);
bool CheckProUpRevTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, bool check_sigs);
bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, const CCoinsViewCache& view, bool check_sigs);
bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, bool check_sigs);
bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, const CCoinsViewCache& view, bool check_sigs);
bool CheckProUpRevTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, bool check_sigs);
extern std::unique_ptr<CDeterministicMNManager> deterministicMNManager;

View File

@ -34,33 +34,33 @@ bool MNHFTx::Verify(const CBlockIndex* pQuorumIndex) const
llmq::CSigningManager::VerifyRecoveredSig(llmqType, *llmq::quorumManager, pQuorumIndex->nHeight, requestId, pQuorumIndex->GetBlockHash(), sig, signOffset);
}
bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
{
MNHFTxPayload mnhfTx;
if (!GetTxPayload(tx, mnhfTx)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-mnhf-payload");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-payload");
}
if (mnhfTx.nVersion == 0 || mnhfTx.nVersion > MNHFTxPayload::CURRENT_VERSION) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-mnhf-version");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-version");
}
const CBlockIndex* pindexQuorum = g_chainman.m_blockman.LookupBlockIndex(mnhfTx.signal.quorumHash);
if (!pindexQuorum) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-mnhf-quorum-hash");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-quorum-hash");
}
if (pindexQuorum != pindexPrev->GetAncestor(pindexQuorum->nHeight)) {
// not part of active chain
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-mnhf-quorum-hash");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-quorum-hash");
}
if (!llmq::GetLLMQParams(Params().GetConsensus().llmqTypeMnhf).has_value()) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-mnhf-type");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-type");
}
if (!mnhfTx.signal.Verify(pindexQuorum)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-mnhf-invalid");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-invalid");
}
return true;

View File

@ -12,7 +12,7 @@
#include <univalue.h>
class CBlockIndex;
class CValidationState;
class TxValidationState;
extern CCriticalSection cs_main;
// mnhf signal special transaction
@ -72,6 +72,6 @@ public:
}
};
bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool CheckMNHFTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
#endif // BITCOIN_EVO_MNHFTX_H

View File

@ -14,34 +14,34 @@
maybe_error CProRegTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
{
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-version"};
return {TxValidationResult::TX_CONSENSUS, "bad-protx-version"};
}
if (!IsValidMnType(nType)) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-type"};
return {TxValidationResult::TX_CONSENSUS, "bad-protx-type"};
}
if (nMode != 0) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-mode"};
return {TxValidationResult::TX_CONSENSUS, "bad-protx-mode"};
}
if (keyIDOwner.IsNull() || !pubKeyOperator.IsValid() || keyIDVoting.IsNull()) {
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-key-null"};
return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-key-null"};
}
if (!scriptPayout.IsPayToPublicKeyHash() && !scriptPayout.IsPayToScriptHash()) {
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-payee"};
return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee"};
}
CTxDestination payoutDest;
if (!ExtractDestination(scriptPayout, payoutDest)) {
// should not happen as we checked script types before
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-payee-dest"};
return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee-dest"};
}
// don't allow reuse of payout key for other keys (don't allow people to put the payee key onto an online server)
if (payoutDest == CTxDestination(PKHash(keyIDOwner)) || payoutDest == CTxDestination(PKHash(keyIDVoting))) {
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-payee-reuse"};
return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee-reuse"};
}
if (nOperatorReward > 10000) {
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-operator-reward"};
return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-operator-reward"};
}
return {};
@ -87,7 +87,7 @@ std::string CProRegTx::ToString() const
maybe_error CProUpServTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
{
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-version"};
return {TxValidationResult::TX_CONSENSUS, "bad-protx-version"};
}
return {};
@ -108,17 +108,17 @@ std::string CProUpServTx::ToString() const
maybe_error CProUpRegTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
{
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-version"};
return {TxValidationResult::TX_CONSENSUS, "bad-protx-version"};
}
if (nMode != 0) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-mode"};
return {TxValidationResult::TX_CONSENSUS, "bad-protx-mode"};
}
if (!pubKeyOperator.IsValid() || keyIDVoting.IsNull()) {
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-key-null"};
return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-key-null"};
}
if (!scriptPayout.IsPayToPublicKeyHash() && !scriptPayout.IsPayToScriptHash()) {
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-payee"};
return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee"};
}
return {};
}
@ -138,13 +138,13 @@ std::string CProUpRegTx::ToString() const
maybe_error CProUpRevTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
{
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-version"};
return {TxValidationResult::TX_CONSENSUS, "bad-protx-version"};
}
// nReason < CProUpRevTx::REASON_NOT_SPECIFIED is always `false` since
// nReason is unsigned and CProUpRevTx::REASON_NOT_SPECIFIED == 0
if (nReason > CProUpRevTx::REASON_LAST) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-reason"};
return {TxValidationResult::TX_CONSENSUS, "bad-protx-reason"};
}
return {};
}

View File

@ -20,7 +20,7 @@
class CBlockIndex;
class CCoinsViewCache;
class CValidationState;
class TxValidationState;
class CProRegTx
{
@ -329,7 +329,7 @@ template <typename ProTx>
static maybe_error CheckInputsHash(const CTransaction& tx, const ProTx& proTx)
{
if (uint256 inputsHash = CalcTxInputsHash(tx); inputsHash != proTx.inputsHash) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-inputs-hash"};
return {TxValidationResult::TX_CONSENSUS, "bad-protx-inputs-hash"};
}
return {};

View File

@ -17,11 +17,11 @@
struct maybe_error {
bool did_err{false};
ValidationInvalidReason reason{ValidationInvalidReason::CONSENSUS};
TxValidationResult reason{TxValidationResult::TX_CONSENSUS};
std::string_view error_str;
constexpr maybe_error() = default;
constexpr maybe_error(ValidationInvalidReason reasonIn, std::string_view err): did_err(true), reason(reasonIn), error_str(err) {};
constexpr maybe_error(TxValidationResult reasonIn, std::string_view err): did_err(true), reason(reasonIn), error_str(err) {};
};
template <typename T>

View File

@ -16,7 +16,7 @@
#include <primitives/block.h>
#include <validation.h>
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, bool check_sigs)
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, const CCoinsViewCache& view, bool check_sigs)
{
AssertLockHeld(cs_main);
@ -24,7 +24,7 @@ bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVali
return true;
if (pindexPrev && pindexPrev->nHeight + 1 < Params().GetConsensus().DIP0003Height) {
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-tx-type");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-tx-type");
}
try {
@ -46,13 +46,13 @@ bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVali
}
} catch (const std::exception& e) {
LogPrintf("%s -- failed: %s\n", __func__, e.what());
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "failed-check-special-tx");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "failed-check-special-tx");
}
return state.Invalid(ValidationInvalidReason::TX_BAD_SPECIAL, false, "bad-tx-type-check");
return state.Invalid(TxValidationResult::TX_BAD_SPECIAL, "bad-tx-type-check");
}
bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValidationState& state)
bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, TxValidationState& state)
{
if (tx.nVersion != 3 || tx.nType == TRANSACTION_NORMAL) {
return true;
@ -72,7 +72,7 @@ bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValida
return true; // handled per block
}
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-tx-type-proc");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-tx-type-proc");
}
bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
@ -99,7 +99,7 @@ bool UndoSpecialTx(const CTransaction& tx, const CBlockIndex* pindex)
}
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor,
CValidationState& state, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots)
BlockValidationState& state, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots)
{
AssertLockHeld(cs_main);
@ -112,13 +112,18 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, ll
int64_t nTime1 = GetTimeMicros();
for (const auto& ptr_tx : block.vtx) {
if (!CheckSpecialTx(*ptr_tx, pindex->pprev, state, view, fCheckCbTxMerleRoots)) {
// pass the state returned by the function above
return false;
TxValidationState tx_state;
// At this moment CheckSpecialTx() and ProcessSpecialTx() may fail by 2 possible ways:
// consensus failures and "TX_BAD_SPECIAL"
if (!CheckSpecialTx(*ptr_tx, pindex->pprev, tx_state, view, fCheckCbTxMerleRoots)) {
assert(tx_state.GetResult() == TxValidationResult::TX_CONSENSUS || tx_state.GetResult() == TxValidationResult::TX_BAD_SPECIAL);
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason(),
strprintf("Special Transaction check failed (tx hash %s) %s", ptr_tx->GetHash().ToString(), tx_state.GetDebugMessage()));
}
if (!ProcessSpecialTx(*ptr_tx, pindex, state)) {
// pass the state returned by the function above
return false;
if (!ProcessSpecialTx(*ptr_tx, pindex, tx_state)) {
assert(tx_state.GetResult() == TxValidationResult::TX_CONSENSUS || tx_state.GetResult() == TxValidationResult::TX_BAD_SPECIAL);
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, tx_state.GetRejectReason(),
strprintf("Process Special Transaction failed (tx hash %s) %s", ptr_tx->GetHash().ToString(), tx_state.GetDebugMessage()));
}
}
@ -154,7 +159,7 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, ll
LogPrint(BCLog::BENCHMARK, " - CheckCbTxMerkleRoots: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeMerkle * 0.000001);
} catch (const std::exception& e) {
LogPrintf("%s -- failed: %s\n", __func__, e.what());
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "failed-procspectxsinblock");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "failed-procspectxsinblock");
}
return true;

View File

@ -9,19 +9,20 @@
#include <sync.h>
#include <threadsafety.h>
class BlockValidationState;
class CBlock;
class CBlockIndex;
class CCoinsViewCache;
class CValidationState;
class TxValidationState;
namespace llmq {
class CQuorumBlockProcessor;
} // namespace llmq
extern CCriticalSection cs_main;
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state, const CCoinsViewCache& view, bool check_sigs) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, const CCoinsViewCache& view, bool check_sigs) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor,
CValidationState& state, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
BlockValidationState& state, const CCoinsViewCache& view, bool fJustCheck, bool fCheckCbTxMerleRoots) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
#endif // BITCOIN_EVO_SPECIALTXMAN_H

View File

@ -928,7 +928,7 @@ static void ThreadImport(ChainstateManager& chainman, std::vector<fs::path> vImp
// the chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve
// the relevant pointers before the ABC call.
for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
CValidationState state;
BlockValidationState state;
if (!chainstate->ActivateBestChain(state, chainparams, nullptr)) {
LogPrintf("Failed to connect best block (%s)\n", FormatStateMessage(state));
StartShutdown();

View File

@ -23,7 +23,6 @@ class CFeeRate;
class CRPCCommand;
class CScheduler;
class CTxMemPool;
class CValidationState;
class CFeeRate;
class CBlockIndex;
class Coin;

View File

@ -136,7 +136,7 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m
AddMineableCommitment(qc);
}
bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state, bool fJustCheck, bool fBLSChecks)
bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, const CBlockIndex* pindex, BlockValidationState& state, bool fJustCheck, bool fBLSChecks)
{
AssertLockHeld(cs_main);
@ -172,11 +172,11 @@ bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, const CBlockIndex*
const auto numCommitmentsInNewBlock = qcs.count(params.type);
if (numCommitmentsRequired < numCommitmentsInNewBlock) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-not-allowed");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-not-allowed");
}
if (numCommitmentsRequired > numCommitmentsInNewBlock) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-missing");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-missing");
}
if (llmq::utils::IsQuorumRotationEnabled(params, pindex)) {
LogPrintf("[ProcessBlock] h[%d] numCommitmentsRequired[%d] numCommitmentsInNewBlock[%d]\n", pindex->nHeight, numCommitmentsRequired, numCommitmentsInNewBlock);
@ -210,7 +210,7 @@ static std::tuple<std::string, Consensus::LLMQType, int, uint32_t> BuildInversed
return std::make_tuple(DB_MINED_COMMITMENT_BY_INVERSED_HEIGHT_Q_INDEXED, llmqType, quorumIndex, htobe32(std::numeric_limits<uint32_t>::max() - nMinedHeight));
}
bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockHash, const CFinalCommitment& qc, CValidationState& state, bool fJustCheck, bool fBLSChecks)
bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockHash, const CFinalCommitment& qc, BlockValidationState& state, bool fJustCheck, bool fBLSChecks)
{
AssertLockHeld(cs_main);
@ -234,31 +234,31 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH
if (quorumHash.IsNull()) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s height=%d, type=%d, quorumIndex=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s quorumHash is null.\n", __func__,
nHeight, ToUnderlying(qc.llmqType), qc.quorumIndex, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), qc.quorumPublicKey.ToString());
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-block");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-block");
}
if (quorumHash != qc.quorumHash) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s height=%d, type=%d, quorumIndex=%d, quorumHash=%s, qc.quorumHash=%s signers=%s, validMembers=%d, quorumPublicKey=%s non equal quorumHash.\n", __func__,
nHeight, ToUnderlying(qc.llmqType), qc.quorumIndex, quorumHash.ToString(), qc.quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), qc.quorumPublicKey.ToString());
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-block");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-block");
}
if (qc.IsNull()) {
if (!qc.VerifyNull()) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s height=%d, type=%d, quorumIndex=%d, quorumHash=%s, signers=%s, validMembers=%dqc verifynull failed.\n", __func__,
nHeight, ToUnderlying(qc.llmqType), qc.quorumIndex, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers());
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-invalid-null");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-invalid-null");
}
return true;
}
if (HasMinedCommitment(llmq_params.type, quorumHash)) {
// should not happen as it's already handled in ProcessBlock
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-dup");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-dup");
}
if (!IsMiningPhase(llmq_params, nHeight)) {
// should not happen as it's already handled in ProcessBlock
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-height");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-height");
}
const auto* pQuorumBaseBlockIndex = g_chainman.m_blockman.LookupBlockIndex(qc.quorumHash);
@ -266,7 +266,7 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH
if (!qc.Verify(pQuorumBaseBlockIndex, fBLSChecks)) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s height=%d, type=%d, quorumIndex=%d, quorumHash=%s, signers=%s, validMembers=%d, quorumPublicKey=%s qc verify failed.\n", __func__,
nHeight, ToUnderlying(qc.llmqType), qc.quorumIndex, quorumHash.ToString(), qc.CountSigners(), qc.CountValidMembers(), qc.quorumPublicKey.ToString());
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-invalid");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-invalid");
}
if (fJustCheck) {
@ -313,7 +313,7 @@ bool CQuorumBlockProcessor::UndoBlock(const CBlock& block, const CBlockIndex* pi
llmq::utils::PreComputeQuorumMembers(pindex, true);
std::multimap<Consensus::LLMQType, CFinalCommitment> qcs;
CValidationState dummy;
BlockValidationState dummy;
if (!GetCommitmentsFromBlock(block, pindex, qcs, dummy)) {
return false;
}
@ -378,7 +378,7 @@ bool CQuorumBlockProcessor::UpgradeDB()
assert(r);
std::multimap<Consensus::LLMQType, CFinalCommitment> qcs;
CValidationState dummyState;
BlockValidationState dummyState;
GetCommitmentsFromBlock(block, pindex, qcs, dummyState);
for (const auto& p : qcs) {
@ -407,7 +407,7 @@ bool CQuorumBlockProcessor::UpgradeDB()
return true;
}
bool CQuorumBlockProcessor::GetCommitmentsFromBlock(const CBlock& block, const CBlockIndex* pindex, std::multimap<Consensus::LLMQType, CFinalCommitment>& ret, CValidationState& state)
bool CQuorumBlockProcessor::GetCommitmentsFromBlock(const CBlock& block, const CBlockIndex* pindex, std::multimap<Consensus::LLMQType, CFinalCommitment>& ret, BlockValidationState& state)
{
AssertLockHeld(cs_main);
@ -421,19 +421,19 @@ bool CQuorumBlockProcessor::GetCommitmentsFromBlock(const CBlock& block, const C
if (!GetTxPayload(*tx, qc)) {
// should not happen as it was verified before processing the block
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s height=%d GetTxPayload fails\n", __func__, pindex->nHeight);
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-payload");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-payload");
}
const auto& llmq_params_opt = GetLLMQParams(qc.commitment.llmqType);
if (!llmq_params_opt.has_value()) {
// should not happen as it was verified before processing the block
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-commitment-type");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-commitment-type");
}
// only allow one commitment per type and per block (This was changed with rotation)
if (!utils::IsQuorumRotationEnabled(llmq_params_opt.value(), pindex)) {
if (ret.count(qc.commitment.llmqType) != 0) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-dup");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-dup");
}
}
@ -442,7 +442,7 @@ bool CQuorumBlockProcessor::GetCommitmentsFromBlock(const CBlock& block, const C
}
if (pindex->nHeight < consensus.DIP0003Height && !ret.empty()) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-premature");
return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-qc-premature");
}
return true;

View File

@ -16,9 +16,9 @@
#include <optional>
class BlockValidationState;
class CNode;
class CConnman;
class CValidationState;
class CEvoDB;
extern CCriticalSection cs_main;
@ -49,7 +49,7 @@ public:
void ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv);
bool ProcessBlock(const CBlock& block, const CBlockIndex* pindex, CValidationState& state, bool fJustCheck, bool fBLSChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ProcessBlock(const CBlock& block, const CBlockIndex* pindex, BlockValidationState& state, bool fJustCheck, bool fBLSChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool UndoBlock(const CBlock& block, const CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void AddMineableCommitment(const CFinalCommitment& fqc);
@ -67,8 +67,8 @@ public:
std::vector<std::pair<int, const CBlockIndex*>> GetLastMinedCommitmentsPerQuorumIndexUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, size_t cycle) const;
std::optional<const CBlockIndex*> GetLastMinedCommitmentsByQuorumIndexUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, int quorumIndex, size_t cycle) const;
private:
static bool GetCommitmentsFromBlock(const CBlock& block, const CBlockIndex* pindex, std::multimap<Consensus::LLMQType, CFinalCommitment>& ret, CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ProcessCommitment(int nHeight, const uint256& blockHash, const CFinalCommitment& qc, CValidationState& state, bool fJustCheck, bool fBLSChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
static bool GetCommitmentsFromBlock(const CBlock& block, const CBlockIndex* pindex, std::multimap<Consensus::LLMQType, CFinalCommitment>& ret, BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ProcessCommitment(int nHeight, const uint256& blockHash, const CFinalCommitment& qc, BlockValidationState& state, bool fJustCheck, bool fBLSChecks) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
static bool IsMiningPhase(const Consensus::LLMQParams& llmqParams, int nHeight) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
size_t GetNumCommitmentsRequired(const Consensus::LLMQParams& llmqParams, int nHeight) const EXCLUSIVE_LOCKS_REQUIRED(cs_main);
static uint256 GetQuorumBlockHash(const Consensus::LLMQParams& llmqParams, int nHeight, int quorumIndex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

View File

@ -494,20 +494,20 @@ void CChainLocksHandler::EnforceBestChainLock()
}
}
CValidationState state;
BlockValidationState dummy_state;
const auto &params = Params();
// Go backwards through the chain referenced by clsig until we find a block that is part of the main chain.
// For each of these blocks, check if there are children that are NOT part of the chain referenced by clsig
// and mark all of them as conflicting.
LogPrint(BCLog::CHAINLOCKS, "CChainLocksHandler::%s -- enforcing block %s via CLSIG (%s)\n", __func__, pindex->GetBlockHash().ToString(), clsig->ToString());
::ChainstateActive().EnforceBlock(state, params, pindex);
::ChainstateActive().EnforceBlock(dummy_state, params, pindex);
bool activateNeeded = WITH_LOCK(::cs_main, return ::ChainActive().Tip()->GetAncestor(currentBestChainLockBlockIndex->nHeight)) != currentBestChainLockBlockIndex;
if (activateNeeded) {
if (!::ChainstateActive().ActivateBestChain(state, params)) {
LogPrintf("CChainLocksHandler::%s -- ActivateBestChain failed: %s\n", __func__, FormatStateMessage(state));
if (!::ChainstateActive().ActivateBestChain(dummy_state, params)) {
LogPrintf("CChainLocksHandler::%s -- ActivateBestChain failed: %s\n", __func__, FormatStateMessage(dummy_state));
return;
}
LOCK(cs_main);

View File

@ -176,18 +176,18 @@ bool CFinalCommitment::VerifySizes(const Consensus::LLMQParams& params) const
return true;
}
bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state)
bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state)
{
CFinalCommitmentTxPayload qcTx;
if (!GetTxPayload(tx, qcTx)) {
LogPrintfFinalCommitment("h[%d] GetTxPayload failed\n", pindexPrev->nHeight);
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-payload");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-payload");
}
const auto& llmq_params_opt = GetLLMQParams(qcTx.commitment.llmqType);
if (!llmq_params_opt.has_value()) {
LogPrintfFinalCommitment("h[%d] GetLLMQParams failed for llmqType[%d]\n", pindexPrev->nHeight, ToUnderlying(qcTx.commitment.llmqType));
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-commitment-type");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-commitment-type");
}
if (LogAcceptCategory(BCLog::LLMQ)) {
@ -201,36 +201,36 @@ bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev,
if (qcTx.nVersion == 0 || qcTx.nVersion > CFinalCommitmentTxPayload::CURRENT_VERSION) {
LogPrintfFinalCommitment("h[%d] invalid qcTx.nVersion[%d]\n", pindexPrev->nHeight, qcTx.nVersion);
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-version");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-version");
}
if (qcTx.nHeight != uint32_t(pindexPrev->nHeight + 1)) {
LogPrintfFinalCommitment("h[%d] invalid qcTx.nHeight[%d]\n", pindexPrev->nHeight, qcTx.nHeight);
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-height");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-height");
}
const CBlockIndex* pQuorumBaseBlockIndex = WITH_LOCK(cs_main, return g_chainman.m_blockman.LookupBlockIndex(qcTx.commitment.quorumHash));
if (pQuorumBaseBlockIndex == nullptr) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-quorum-hash");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-quorum-hash");
}
if (pQuorumBaseBlockIndex != pindexPrev->GetAncestor(pQuorumBaseBlockIndex->nHeight)) {
// not part of active chain
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-quorum-hash");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-quorum-hash");
}
if (qcTx.commitment.IsNull()) {
if (!qcTx.commitment.VerifyNull()) {
LogPrintfFinalCommitment("h[%d] invalid qcTx.commitment[%s] VerifyNull failed\n", pindexPrev->nHeight, qcTx.commitment.quorumHash.ToString());
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-invalid-null");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-invalid-null");
}
return true;
}
if (!qcTx.commitment.Verify(pQuorumBaseBlockIndex, false)) {
LogPrintfFinalCommitment("h[%d] invalid qcTx.commitment[%s] Verify failed\n", pindexPrev->nHeight, qcTx.commitment.quorumHash.ToString());
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-qc-invalid");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-qc-invalid");
}
LogPrintfFinalCommitment("h[%d] CheckLLMQCommitment VALID\n", pindexPrev->nHeight);

View File

@ -15,7 +15,7 @@
#include <univalue.h>
class CBlockIndex;
class CValidationState;
class TxValidationState;
namespace llmq
{
@ -168,7 +168,7 @@ public:
}
};
bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state);
bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state);
} // namespace llmq

View File

@ -1477,7 +1477,7 @@ void CInstantSendManager::ResolveBlockConflicts(const uint256& islockHash, const
LogPrintf("CInstantSendManager::%s -- invalidating block %s\n", __func__, pindex->GetBlockHash().ToString());
CValidationState state;
BlockValidationState state;
// need non-const pointer
auto pindex2 = WITH_LOCK(::cs_main, return g_chainman.m_blockman.LookupBlockIndex(pindex->GetBlockHash()));
if (!::ChainstateActive().InvalidateBlock(state, Params(), pindex2)) {
@ -1495,7 +1495,7 @@ void CInstantSendManager::ResolveBlockConflicts(const uint256& islockHash, const
}
if (activateBestChain) {
CValidationState state;
BlockValidationState state;
if (!::ChainstateActive().ActivateBestChain(state, Params())) {
LogPrintf("CChainLocksHandler::%s -- ActivateBestChain failed: %s\n", __func__, FormatStateMessage(state));
// This should not have happened and we are in a state were it's not safe to continue anymore

View File

@ -205,7 +205,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(CChainState& chai
cbTx.nHeight = nHeight;
CValidationState state;
BlockValidationState state;
if (!CalcCbTxMerkleRootMNList(*pblock, pindexPrev, cbTx.merkleRootMNList, state, ::ChainstateActive().CoinsTip())) {
throw std::runtime_error(strprintf("%s: CalcCbTxMerkleRootMNList failed: %s", __func__, FormatStateMessage(state)));
}
@ -233,8 +233,8 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(CChainState& chai
pblocktemplate->nPrevBits = pindexPrev->nBits;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(*pblock->vtx[0]);
CValidationState state;
assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate));
BlockValidationState state;
if (!TestBlockValidity(state, m_clhandler, m_evoDb, chainparams, chainstate, *pblock, pindexPrev, false, false)) {
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
}

View File

@ -1222,7 +1222,7 @@ bool IsBanned(NodeId pnode)
}
/**
* Potentially mark a node discouraged based on the contents of a CValidationState object
* Potentially mark a node discouraged based on the contents of a BlockValidationState object
*
* @param[in] via_compact_block this bool is passed in because net_processing should
* punish peers differently depending on whether the data was provided in a compact
@ -1231,20 +1231,20 @@ bool IsBanned(NodeId pnode)
*
* @return Returns true if the peer was punished (probably disconnected)
*/
static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool via_compact_block, const std::string& message = "")
static bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, bool via_compact_block, const std::string& message = "")
{
switch (state.GetReason()) {
case ValidationInvalidReason::NONE:
switch (state.GetResult()) {
case BlockValidationResult::BLOCK_RESULT_UNSET:
break;
// The node is providing invalid data:
case ValidationInvalidReason::CONSENSUS:
case ValidationInvalidReason::BLOCK_MUTATED:
case BlockValidationResult::BLOCK_CONSENSUS:
case BlockValidationResult::BLOCK_MUTATED:
if (!via_compact_block) {
Misbehaving(nodeid, 100, message);
return true;
}
break;
case ValidationInvalidReason::CACHED_INVALID:
case BlockValidationResult::BLOCK_CACHED_INVALID:
{
LOCK(cs_main);
CNodeState *node_state = State(nodeid);
@ -1260,25 +1260,18 @@ static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool v
}
break;
}
case ValidationInvalidReason::BLOCK_INVALID_HEADER:
case ValidationInvalidReason::BLOCK_CHECKPOINT:
case ValidationInvalidReason::BLOCK_INVALID_PREV:
case BlockValidationResult::BLOCK_INVALID_HEADER:
case BlockValidationResult::BLOCK_CHECKPOINT:
case BlockValidationResult::BLOCK_INVALID_PREV:
Misbehaving(nodeid, 100, message);
return true;
// Conflicting (but not necessarily invalid) data or different policy:
case ValidationInvalidReason::BLOCK_MISSING_PREV:
case ValidationInvalidReason::BLOCK_CHAINLOCK:
case ValidationInvalidReason::TX_BAD_SPECIAL:
case ValidationInvalidReason::TX_CONFLICT_LOCK:
case BlockValidationResult::BLOCK_MISSING_PREV:
case BlockValidationResult::BLOCK_CHAINLOCK:
Misbehaving(nodeid, 10, message);
return true;
case ValidationInvalidReason::RECENT_CONSENSUS_CHANGE:
case ValidationInvalidReason::BLOCK_TIME_FUTURE:
case ValidationInvalidReason::TX_NOT_STANDARD:
case ValidationInvalidReason::TX_MISSING_INPUTS:
case ValidationInvalidReason::TX_PREMATURE_SPEND:
case ValidationInvalidReason::TX_CONFLICT:
case ValidationInvalidReason::TX_MEMPOOL_POLICY:
case BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE:
case BlockValidationResult::BLOCK_TIME_FUTURE:
break;
}
if (message != "") {
@ -1287,6 +1280,41 @@ static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool v
return false;
}
/**
* Potentially ban a node based on the contents of a TxValidationState object
*
* @return Returns true if the peer was punished (probably disconnected)
*
* Changes here may need to be reflected in TxRelayMayResultInDisconnect().
*/
static bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = "") {
switch (state.GetResult()) {
case TxValidationResult::TX_RESULT_UNSET:
break;
// The node is providing invalid data:
case TxValidationResult::TX_CONSENSUS:
{
LOCK(cs_main);
Misbehaving(nodeid, 100, message);
return true;
}
// Conflicting (but not necessarily invalid) data or different policy:
case TxValidationResult::TX_RECENT_CONSENSUS_CHANGE:
case TxValidationResult::TX_NOT_STANDARD:
case TxValidationResult::TX_MISSING_INPUTS:
case TxValidationResult::TX_PREMATURE_SPEND:
case TxValidationResult::TX_CONFLICT:
case TxValidationResult::TX_MEMPOOL_POLICY:
// moved from BLOCK
case TxValidationResult::TX_BAD_SPECIAL:
case TxValidationResult::TX_CONFLICT_LOCK:
break;
}
if (message != "") {
LogPrint(BCLog::NET, "peer=%d: %s\n", nodeid, message);
}
return false;
}
//////////////////////////////////////////////////////////////////////////////
//
@ -1507,7 +1535,7 @@ void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CB
* Handle invalid block rejection and consequent peer discouragement, maintain which
* peers announce compact blocks.
*/
void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationState& state) {
void PeerLogicValidation::BlockChecked(const CBlock& block, const BlockValidationState& state) {
LOCK(cs_main);
const uint256 hash(block.GetHash());
@ -1518,7 +1546,7 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
if (state.IsInvalid() &&
it != mapBlockSource.end() &&
State(it->second.first)) {
MaybePunishNode(/*nodeid=*/ it->second.first, state, /*via_compact_block=*/ !it->second.second);
MaybePunishNodeForBlock(/*nodeid=*/ it->second.first, state, /*via_compact_block=*/ !it->second.second);
}
// Check that:
// 1. The block is valid
@ -1711,7 +1739,7 @@ void static ProcessGetBlockData(CNode& pfrom, const CChainParams& chainparams, c
}
} // release cs_main before calling ActivateBestChain
if (need_activate_chain) {
CValidationState state;
BlockValidationState state;
if (!::ChainstateActive().ActivateBestChain(state, Params(), a_recent_block)) {
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state));
}
@ -2127,11 +2155,10 @@ static void ProcessHeadersMessage(CNode& pfrom, CConnman& connman, ChainstateMan
}
}
CValidationState state;
CBlockHeader first_invalid_header;
if (!chainman.ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast, &first_invalid_header)) {
BlockValidationState state;
if (!chainman.ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast)) {
if (state.IsInvalid()) {
MaybePunishNode(pfrom.GetId(), state, via_compact_block, "invalid header received");
MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
return;
}
}
@ -2266,14 +2293,13 @@ void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set<uin
const CTransactionRef porphanTx = orphan_it->second.tx;
const CTransaction& orphanTx = *porphanTx;
NodeId fromPeer = orphan_it->second.fromPeer;
bool fMissingInputs2 = false;
// Use a new CValidationState because orphans come from different peers (and we call
// MaybePunishNode based on the source peer from the orphan map, not based on the peer
// Use a new TxValidationState because orphans come from different peers (and we call
// MaybePunishNodeForTx based on the source peer from the orphan map, not based on the peer
// that relayed the previous transaction).
CValidationState orphan_state;
TxValidationState orphan_state;
if (setMisbehaving.count(fromPeer)) continue;
if (AcceptToMemoryPool(::ChainstateActive(), mempool, orphan_state, porphanTx, &fMissingInputs2 /* pfMissingInputs */,
if (AcceptToMemoryPool(::ChainstateActive(), mempool, orphan_state, porphanTx,
false /* bypass_limits */, 0 /* nAbsurdFee */)) {
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanTx.GetHash(), connman);
@ -2287,10 +2313,10 @@ void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set<uin
}
EraseOrphanTx(orphanHash);
done = true;
} else if (!fMissingInputs2) {
} else if (orphan_state.GetResult() != TxValidationResult::TX_MISSING_INPUTS) {
if (orphan_state.IsInvalid()) {
// Punish peer that gave us an invalid orphan tx
if (MaybePunishNode(fromPeer, orphan_state, /*via_compact_block*/ false)) {
if (MaybePunishNodeForTx(fromPeer, orphan_state)) {
setMisbehaving.insert(fromPeer);
}
LogPrint(BCLog::MEMPOOL, " invalid orphan tx %s\n", orphanHash.ToString());
@ -2298,7 +2324,6 @@ void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set<uin
// Has inputs but not accepted to mempool
// Probably non-standard or insufficient fee
LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString());
assert(IsTransactionReason(orphan_state.GetReason()));
assert(recentRejects);
recentRejects->insert(orphanHash);
EraseOrphanTx(orphanHash);
@ -3130,7 +3155,7 @@ void PeerLogicValidation::ProcessMessage(
LOCK(cs_most_recent_block);
a_recent_block = most_recent_block;
}
CValidationState state;
BlockValidationState state;
if (!::ChainstateActive().ActivateBestChain(state, Params(), a_recent_block)) {
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state));
}
@ -3346,10 +3371,9 @@ void PeerLogicValidation::ProcessMessage(
LOCK2(cs_main, g_cs_orphans);
bool fMissingInputs = false;
CValidationState state;
TxValidationState state;
if (!AlreadyHave(inv, m_mempool, *m_llmq_ctx) && AcceptToMemoryPool(::ChainstateActive(), m_mempool, state, ptx, &fMissingInputs /* pfMissingInputs */,
if (!AlreadyHave(inv, m_mempool, *m_llmq_ctx) && AcceptToMemoryPool(::ChainstateActive(), m_mempool, state, ptx,
false /* bypass_limits */, 0 /* nAbsurdFee */)) {
// Process custom txes, this changes AlreadyHave to "true"
if (nInvType == MSG_DSTX) {
@ -3380,7 +3404,7 @@ void PeerLogicValidation::ProcessMessage(
// Recursively process any orphan transactions that depended on this one
ProcessOrphanTx(m_connman, m_mempool, pfrom.orphan_work_set);
}
else if (fMissingInputs)
else if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS)
{
bool fRejectedParents = false; // It may be the case that the orphans parents have all been rejected
for (const CTxIn& txin : tx.vin) {
@ -3417,7 +3441,6 @@ void PeerLogicValidation::ProcessMessage(
m_llmq_ctx->isman->TransactionRemovedFromMempool(ptx);
}
} else {
assert(IsTransactionReason(state.GetReason()));
assert(recentRejects);
recentRejects->insert(tx.GetHash());
if (RecursiveDynamicUsage(*ptx) < 100000) {
@ -3460,7 +3483,7 @@ void PeerLogicValidation::ProcessMessage(
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
pfrom.GetId(),
FormatStateMessage(state));
MaybePunishNode(pfrom.GetId(), state, /*via_compact_block*/ false);
MaybePunishNodeForTx(pfrom.GetId(), state);
m_llmq_ctx->isman->TransactionRemovedFromMempool(ptx);
}
return;
@ -3495,10 +3518,10 @@ void PeerLogicValidation::ProcessMessage(
}
const CBlockIndex *pindex = nullptr;
CValidationState state;
BlockValidationState state;
if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) {
if (state.IsInvalid()) {
MaybePunishNode(pfrom.GetId(), state, /*via_compact_block*/ true, "invalid header via cmpctblock");
MaybePunishNodeForBlock(pfrom.GetId(), state, /*via_compact_block*/ true, "invalid header via cmpctblock");
return;
}
}

View File

@ -52,7 +52,7 @@ public:
/**
* Overridden from CValidationInterface.
*/
void BlockChecked(const CBlock& block, const CValidationState& state) override;
void BlockChecked(const CBlock& block, const BlockValidationState& state) override;
/**
* Overridden from CValidationInterface.
*/

View File

@ -39,18 +39,16 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
}
if (!node.mempool->exists(hashTx)) {
// Transaction is not already in the mempool. Submit it.
CValidationState state;
bool fMissingInputs;
if (!AcceptToMemoryPool(::ChainstateActive(), *node.mempool, state, std::move(tx), &fMissingInputs,
TxValidationState state;
if (!AcceptToMemoryPool(::ChainstateActive(), *node.mempool, state, std::move(tx),
bypass_limits, max_tx_fee)) {
err_string = FormatStateMessage(state);
if (state.IsInvalid()) {
err_string = FormatStateMessage(state);
return TransactionError::MEMPOOL_REJECTED;
} else {
if (fMissingInputs) {
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
return TransactionError::MISSING_INPUTS;
}
err_string = FormatStateMessage(state);
return TransactionError::MEMPOOL_REJECTED;
} else {
return TransactionError::MEMPOOL_ERROR;
}
}

View File

@ -1811,7 +1811,7 @@ static UniValue preciousblock(const JSONRPCRequest& request)
}
}
CValidationState state;
BlockValidationState state;
::ChainstateActive().PreciousBlock(state, Params(), pblockindex);
if (!state.IsValid()) {
@ -1836,7 +1836,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
}.Check(request);
uint256 hash(ParseHashV(request.params[0], "blockhash"));
CValidationState state;
BlockValidationState state;
CBlockIndex* pblockindex;
{
@ -1886,7 +1886,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
::ChainstateActive().ResetBlockFailureFlags(pblockindex);
}
CValidationState state;
BlockValidationState state;
::ChainstateActive().ActivateBestChain(state, Params());
if (!state.IsValid()) {

View File

@ -326,7 +326,7 @@ static std::string SignAndSendSpecialTx(const JSONRPCRequest& request, const CMu
{
LOCK(cs_main);
CValidationState state;
TxValidationState state;
if (!CheckSpecialTx(CTransaction(tx), ::ChainActive().Tip(), state, ::ChainstateActive().CoinsTip(), true)) {
throw std::runtime_error(FormatStateMessage(state));
}

View File

@ -380,7 +380,7 @@ static UniValue generateblock(const JSONRPCRequest& request)
{
LOCK(cs_main);
CValidationState state;
BlockValidationState state;
if (!TestBlockValidity(state, *llmq_ctx.clhandler, *node_context.evodb, chainparams, ::ChainstateActive(), block, g_chainman.m_blockman.LookupBlockIndex(block.hashPrevBlock), false, false)) {
throw JSONRPCError(RPC_VERIFY_ERROR, strprintf("TestBlockValidity failed: %s", state.GetRejectReason()));
}
@ -483,7 +483,7 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request)
// NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
static UniValue BIP22ValidationResult(const CValidationState& state)
static UniValue BIP22ValidationResult(const BlockValidationState& state)
{
if (state.IsValid())
return NullUniValue;
@ -670,7 +670,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
// TestBlockValidity only supports blocks built on the current Tip
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
return "inconclusive-not-best-prevblk";
CValidationState state;
BlockValidationState state;
TestBlockValidity(state, *llmq_ctx.clhandler, *node_context.evodb, Params(), ::ChainstateActive(), block, pindexPrev, false, true);
return BIP22ValidationResult(state);
}
@ -951,12 +951,12 @@ class submitblock_StateCatcher : public CValidationInterface
public:
uint256 hash;
bool found;
CValidationState state;
BlockValidationState state;
explicit submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {}
protected:
void BlockChecked(const CBlock& block, const CValidationState& stateIn) override {
void BlockChecked(const CBlock& block, const BlockValidationState& stateIn) override {
if (block.GetHash() != hash)
return;
found = true;
@ -1046,8 +1046,8 @@ static UniValue submitheader(const JSONRPCRequest& request)
}
}
CValidationState state;
EnsureChainman(request.context).ProcessNewBlockHeaders({h}, state, Params(), /* ppindex */ nullptr, /* first_invalid */ nullptr);
BlockValidationState state;
EnsureChainman(request.context).ProcessNewBlockHeaders({h}, state, Params());
if (state.IsValid()) return NullUniValue;
if (state.IsError()) {
throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));

View File

@ -918,20 +918,21 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
UniValue result_0(UniValue::VOBJ);
result_0.pushKV("txid", tx_hash.GetHex());
CValidationState state;
bool missing_inputs;
TxValidationState state;
bool test_accept_res;
{
LOCK(cs_main);
test_accept_res = AcceptToMemoryPool(::ChainstateActive(), mempool, state, std::move(tx), &missing_inputs,
test_accept_res = AcceptToMemoryPool(::ChainstateActive(), mempool, state, std::move(tx),
false /* bypass_limits */, max_raw_tx_fee, /* test_accept */ true);
}
result_0.pushKV("allowed", test_accept_res);
if (!test_accept_res) {
if (state.IsInvalid()) {
result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
} else if (missing_inputs) {
result_0.pushKV("reject-reason", "missing-inputs");
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
result_0.pushKV("reject-reason", "missing-inputs");
} else {
result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
}
} else {
result_0.pushKV("reject-reason", state.GetRejectReason());
}

View File

@ -100,8 +100,8 @@ bool BuildChainTestingSetup::BuildChain(const CBlockIndex* pindex,
block = std::make_shared<CBlock>(CreateBlock(pindex, no_txns, coinbase_script_pub_key));
CBlockHeader header = block->GetBlockHeader();
CValidationState state;
if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, state, Params(), &pindex, nullptr)) {
BlockValidationState state;
if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, state, Params(), &pindex)) {
return false;
}
}

View File

@ -294,12 +294,12 @@ void FuncDIP3Protx(TestChainSetup& setup)
// payload itself. This means, we need to rely on script verification, which takes the hash of the extra payload
// into account
auto tx2 = MalleateProTxPayout<CProRegTx>(tx);
CValidationState dummyState;
TxValidationState dummy_state;
// Technically, the payload is still valid...
{
LOCK(cs_main);
BOOST_ASSERT(CheckProRegTx(CTransaction(tx), ::ChainActive().Tip(), dummyState, ::ChainstateActive().CoinsTip(), true));
BOOST_ASSERT(CheckProRegTx(CTransaction(tx2), ::ChainActive().Tip(), dummyState, ::ChainstateActive().CoinsTip(), true));
BOOST_ASSERT(CheckProRegTx(CTransaction(tx), ::ChainActive().Tip(), dummy_state, ::ChainstateActive().CoinsTip(), true));
BOOST_ASSERT(CheckProRegTx(CTransaction(tx2), ::ChainActive().Tip(), dummy_state, ::ChainstateActive().CoinsTip(), true));
}
// But the signature should not verify anymore
BOOST_ASSERT(CheckTransactionSignature(*(setup.m_node.mempool), tx));
@ -401,11 +401,11 @@ void FuncDIP3Protx(TestChainSetup& setup)
tx = CreateProUpRegTx(*(setup.m_node.mempool), utxos, dmnHashes[0], ownerKeys[dmnHashes[0]], newOperatorKey.GetPublicKey(), ownerKeys[dmnHashes[0]].GetPubKey().GetID(), dmn->pdmnState->scriptPayout, setup.coinbaseKey);
// check malleability protection again, but this time by also relying on the signature inside the ProUpRegTx
auto tx2 = MalleateProTxPayout<CProUpRegTx>(tx);
CValidationState dummyState;
TxValidationState dummy_state;
{
LOCK(cs_main);
BOOST_ASSERT(CheckProUpRegTx(CTransaction(tx), ::ChainActive().Tip(), dummyState, ::ChainstateActive().CoinsTip(), true));
BOOST_ASSERT(!CheckProUpRegTx(CTransaction(tx2), ::ChainActive().Tip(), dummyState, ::ChainstateActive().CoinsTip(), true));
BOOST_ASSERT(CheckProUpRegTx(CTransaction(tx), ::ChainActive().Tip(), dummy_state, ::ChainstateActive().CoinsTip(), true));
BOOST_ASSERT(!CheckProUpRegTx(CTransaction(tx2), ::ChainActive().Tip(), dummy_state, ::ChainstateActive().CoinsTip(), true));
}
BOOST_ASSERT(CheckTransactionSignature(*(setup.m_node.mempool), tx));
BOOST_ASSERT(!CheckTransactionSignature(*(setup.m_node.mempool), tx2));

View File

@ -36,17 +36,17 @@ FUZZ_TARGET_INIT(block, initialize_block)
return;
}
const Consensus::Params& consensus_params = Params().GetConsensus();
CValidationState validation_state_pow_and_merkle;
BlockValidationState validation_state_pow_and_merkle;
const bool valid_incl_pow_and_merkle = CheckBlock(block, validation_state_pow_and_merkle, consensus_params, /* fCheckPOW= */ true, /* fCheckMerkleRoot= */ true);
assert(validation_state_pow_and_merkle.IsValid() || validation_state_pow_and_merkle.IsInvalid() || validation_state_pow_and_merkle.IsError());
(void)validation_state_pow_and_merkle.Error("");
CValidationState validation_state_pow;
BlockValidationState validation_state_pow;
const bool valid_incl_pow = CheckBlock(block, validation_state_pow, consensus_params, /* fCheckPOW= */ true, /* fCheckMerkleRoot= */ false);
assert(validation_state_pow.IsValid() || validation_state_pow.IsInvalid() || validation_state_pow.IsError());
CValidationState validation_state_merkle;
BlockValidationState validation_state_merkle;
const bool valid_incl_merkle = CheckBlock(block, validation_state_merkle, consensus_params, /* fCheckPOW= */ false, /* fCheckMerkleRoot= */ true);
assert(validation_state_merkle.IsValid() || validation_state_merkle.IsInvalid() || validation_state_merkle.IsError());
CValidationState validation_state_none;
BlockValidationState validation_state_none;
const bool valid_incl_none = CheckBlock(block, validation_state_none, consensus_params, /* fCheckPOW= */ false, /* fCheckMerkleRoot= */ false);
assert(validation_state_none.IsValid() || validation_state_none.IsInvalid() || validation_state_none.IsError());
if (valid_incl_pow_and_merkle) {

View File

@ -223,12 +223,12 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
(void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache);
},
[&] {
CValidationState state;
TxValidationState state;
CAmount tx_fee_out;
const CTransaction transaction{random_mutable_transaction};
if (ContainsSpentInput(transaction, coins_view_cache)) {
// Avoid:
// consensus/tx_verify.cpp:171: bool Consensus::CheckTxInputs(const CTransaction &, CValidationState &, const CCoinsViewCache &, int, CAmount &): Assertion `!coin.IsSpent()' failed.
// consensus/tx_verify.cpp:171: bool Consensus::CheckTxInputs(const CTransaction &, TxValidationState&, const CCoinsViewCache &, int, CAmount &): Assertion `!coin.IsSpent()' failed.
return;
}
try {

View File

@ -60,7 +60,7 @@ FUZZ_TARGET_INIT(transaction, initialize_transaction)
return;
}
CValidationState state_with_dupe_check;
TxValidationState state_with_dupe_check;
(void)CheckTransaction(tx, state_with_dupe_check);
std::string reason;

View File

@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(findCommonAncestor)
const CChain& active = Assert(m_node.chainman)->ActiveChain();
auto* orig_tip = active.Tip();
for (int i = 0; i < 10; ++i) {
CValidationState state;
BlockValidationState state;
ChainstateActive().InvalidateBlock(state, Params(), active.Tip());
}
BOOST_CHECK_EQUAL(active.Height(), orig_tip->nHeight - 10);

View File

@ -536,7 +536,7 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
} // unlock cs_main while calling InvalidateBlock
CValidationState state;
BlockValidationState state;
::ChainstateActive().InvalidateBlock(state, chainparams, WITH_LOCK(cs_main, return ::ChainActive().Tip()));
SetMockTime(0);

View File

@ -187,7 +187,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
CDataStream stream(ParseHex(raw_tx), SER_NETWORK, PROTOCOL_VERSION);
stream >> tx;
CValidationState state;
TxValidationState state;
BOOST_CHECK_MESSAGE(CheckTransaction(*tx, state), strTest);
BOOST_CHECK(state.IsValid());

View File

@ -18,15 +18,15 @@
#include <vector>
bool VerifyMNHFTx(const CTransaction& tx, CValidationState& state)
bool VerifyMNHFTx(const CTransaction& tx, TxValidationState& state)
{
MNHFTxPayload mnhfTx;
if (!GetTxPayload(tx, mnhfTx)) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-mnhf-payload");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-payload");
}
if (mnhfTx.nVersion == 0 || mnhfTx.nVersion > MNHFTxPayload::CURRENT_VERSION) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-mnhf-version");
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-mnhf-version");
}
return true;
@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(verify_mnhf_specialtx_tests)
BOOST_CHECK(sig.VerifyInsecure(ag_pk, verHash));
const CMutableTransaction tx = CreateMNHFTx(hash, sig, ver);
CValidationState state;
TxValidationState state;
BOOST_CHECK(VerifyMNHFTx(CTransaction(tx), state));
}

View File

@ -137,7 +137,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx(deserialize, stream);
CValidationState state;
TxValidationState state;
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
BOOST_CHECK(state.IsValid());
@ -214,7 +214,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx(deserialize, stream);
CValidationState state;
TxValidationState state;
fValid = CheckTransaction(tx, state) && state.IsValid();
PrecomputedTransactionData txdata(tx);
@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
CMutableTransaction tx;
stream >> tx;
CValidationState state;
TxValidationState state;
BOOST_CHECK_MESSAGE(CheckTransaction(CTransaction(tx), state) && state.IsValid(), "Simple deserialized transaction should be valid.");
// Check that duplicate txins fail

View File

@ -30,7 +30,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
BOOST_CHECK(CTransaction(coinbaseTx).IsCoinBase());
CValidationState state;
TxValidationState state;
LOCK(cs_main);
@ -39,7 +39,6 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
BOOST_CHECK_EQUAL(
false,
AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, state, MakeTransactionRef(coinbaseTx),
nullptr /* pfMissingInputs */,
true /* bypass_limits */,
0 /* nAbsurdFee */));
@ -49,7 +48,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
// Check that the validation state reflects the unsuccessful attempt.
BOOST_CHECK(state.IsInvalid());
BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase");
BOOST_CHECK(state.GetReason() == ValidationInvalidReason::CONSENSUS);
BOOST_CHECK(state.GetResult() == TxValidationResult::TX_CONSENSUS);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -12,7 +12,7 @@
#include <boost/test/unit_test.hpp>
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks);
bool CheckInputs(const CTransaction& tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CScriptCheck> *pvChecks);
BOOST_AUTO_TEST_SUITE(txvalidationcache_tests)
@ -27,8 +27,8 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
const auto ToMemPool = [this](const CMutableTransaction& tx) {
LOCK(cs_main);
CValidationState state;
return AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, state, MakeTransactionRef(tx), nullptr /* pfMissingInputs */,
TxValidationState validationState;
return AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, validationState, MakeTransactionRef(tx),
true /* bypass_limits */, 0 /* nAbsurdFee */);
};
@ -111,7 +111,7 @@ static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t fail
// If we add many more flags, this loop can get too expensive, but we can
// rewrite in the future to randomly pick a set of flags to evaluate.
for (uint32_t test_flags=0; test_flags < (1U << 16); test_flags += 1) {
CValidationState state;
TxValidationState state;
// Filter out incompatible flag choices
if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) {
// CLEANSTACK requires P2SH, see VerifyScript() in
@ -193,7 +193,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
{
LOCK(cs_main);
CValidationState state;
TxValidationState state;
PrecomputedTransactionData ptd_spend_tx;
BOOST_CHECK(!CheckInputs(CTransaction(spend_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
@ -262,7 +262,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Make it valid, and check again
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
CValidationState state;
TxValidationState state;
PrecomputedTransactionData txdata;
BOOST_CHECK(CheckInputs(CTransaction(invalid_with_cltv_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
}
@ -290,7 +290,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
// Make it valid, and check again
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
CValidationState state;
TxValidationState state;
PrecomputedTransactionData txdata;
BOOST_CHECK(CheckInputs(CTransaction(invalid_with_csv_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
}

View File

@ -253,7 +253,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
m_node.connman->Init(options);
}
CValidationState state;
BlockValidationState state;
if (!::ChainstateActive().ActivateBestChain(state, chainparams)) {
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
}
@ -338,7 +338,7 @@ CBlock TestChainSetup::CreateBlock(const std::vector<CMutableTransaction>& txns,
if (!GetTxPayload(*block.vtx[0], cbTx)) {
BOOST_ASSERT(false);
}
CValidationState state;
BlockValidationState state;
if (!CalcCbTxMerkleRootMNList(block, ::ChainActive().Tip(), cbTx.merkleRootMNList, state, ::ChainstateActive().CoinsTip())) {
BOOST_ASSERT(false);
}

View File

@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
}
bool ignored;
CValidationState state;
BlockValidationState state;
std::vector<CBlockHeader> headers;
std::transform(blocks.begin(), blocks.end(), std::back_inserter(headers), [](std::shared_ptr<const CBlock> b) { return b->GetBlockHeader(); });
@ -296,14 +296,13 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
// Add the txs to the tx pool
{
LOCK(cs_main);
CValidationState state;
TxValidationState state;
for (const auto& tx : txs) {
BOOST_REQUIRE(AcceptToMemoryPool(
::ChainstateActive(),
*m_node.mempool,
state,
tx,
/* pfMissingInputs */ &ignored,
/* bypass_limits */ false,
/* nAbsurdFee */ 0));
}

View File

@ -67,8 +67,8 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
WITH_LOCK(::cs_main, c2.InitCoinsCache(1 << 23));
// Unlike c1, which doesn't have any blocks. Gets us different tip, height.
c2.LoadGenesisBlock(chainparams);
CValidationState _;
BOOST_CHECK(c2.ActivateBestChain(_, chainparams, nullptr));
BlockValidationState dummy_state;
BOOST_CHECK(c2.ActivateBestChain(dummy_state, chainparams, nullptr));
BOOST_CHECK(manager.IsSnapshotActive());
BOOST_CHECK(!manager.IsSnapshotValidated());

View File

@ -1023,9 +1023,9 @@ void CTxMemPool::clear()
static void CheckInputsAndUpdateCoins(const CTransaction& tx, CCoinsViewCache& mempoolDuplicate, const int64_t spendheight)
{
CValidationState state;
TxValidationState dummy_state; // Not used. CheckTxInputs() should always pass
CAmount txfee = 0;
bool fCheckResult = tx.IsCoinBase() || Consensus::CheckTxInputs(tx, state, mempoolDuplicate, spendheight, txfee);
bool fCheckResult = tx.IsCoinBase() || Consensus::CheckTxInputs(tx, dummy_state, mempoolDuplicate, spendheight, txfee);
assert(fCheckResult);
UpdateCoins(tx, mempoolDuplicate, std::numeric_limits<int>::max());
}

View File

@ -8,8 +8,8 @@
#include <consensus/validation.h>
#include <tinyformat.h>
/** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state)
/** Convert ValidationState to a human-readable message for logging */
std::string FormatStateMessage(const ValidationState &state)
{
return strprintf("%s%s",
state.GetRejectReason(),

View File

@ -8,9 +8,9 @@
#include <string>
class CValidationState;
class ValidationState;
/** Convert CValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state);
/** Convert ValidationState to a human-readable message for logging */
std::string FormatStateMessage(const ValidationState &state);
#endif // BITCOIN_UTIL_VALIDATION_H

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@ class CQuorumBlockProcessor;
class CEvoDB;
class CChainState;
class BlockValidationState;
class CBlockIndex;
class CBlockTreeDB;
class CBlockUndo;
@ -52,7 +53,7 @@ class CInv;
class CConnman;
class CScriptCheck;
class CTxMemPool;
class CValidationState;
class TxValidationState;
class ChainstateManager;
struct PrecomputedTransactionData;
struct ChainTxData;
@ -215,8 +216,8 @@ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune);
void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeight);
/** (try to) add transaction to memory pool */
bool AcceptToMemoryPool(CChainState& active_chainstate, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
bool* pfMissingInputs, bool bypass_limits,
bool AcceptToMemoryPool(CChainState& active_chainstate, CTxMemPool& pool, TxValidationState &state, const CTransactionRef &tx,
bool bypass_limits,
const CAmount nAbsurdFee, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool GetUTXOCoin(const COutPoint& outpoint, Coin& coin);
@ -315,10 +316,10 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex);
/** Functions for validating blocks and updating the block tree */
/** Context-independent validity checks */
bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
/** Check a block is completely valid from start to finish (only works on top of our current best block) */
bool TestBlockValidity(CValidationState& state,
bool TestBlockValidity(BlockValidationState& state,
llmq::CChainLocksHandler& clhandler,
CEvoDB& evoDb,
const CChainParams& chainparams,
@ -454,7 +455,7 @@ public:
*/
bool AcceptBlockHeader(
const CBlockHeader& block,
CValidationState& state,
BlockValidationState& state,
const CChainParams& chainparams,
CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -681,7 +682,7 @@ public:
*/
bool FlushStateToDisk(
const CChainParams& chainparams,
CValidationState &state,
BlockValidationState &state,
FlushStateMode mode,
int nManualPruneHeight = 0);
@ -708,29 +709,29 @@ public:
* @returns true unless a system error occurred
*/
bool ActivateBestChain(
CValidationState& state,
BlockValidationState& state,
const CChainParams& chainparams,
std::shared_ptr<const CBlock> pblock = nullptr) LOCKS_EXCLUDED(cs_main);
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Block (dis)connection on a given view:
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool ConnectBlock(const CBlock& block, BlockValidationState& state, CBlockIndex* pindex, CCoinsViewCache& view, const CChainParams& chainparams, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
// Apply the effects of a block disconnection on the UTXO set.
bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs);
bool DisconnectTip(BlockValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs);
// Manual block validity manipulation:
/** Mark a block as precious and reorganize.
*
* May not be called in a validationinterface callback.
*/
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
bool PreciousBlock(BlockValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
/** Mark a block as invalid. */
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
bool InvalidateBlock(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
/** Enforce a block marking all the other chains as conflicting. */
void EnforceBlock(CValidationState& state, const CChainParams& chainparams, const CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
void EnforceBlock(BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
/** Remove invalidity status from a block and its descendants. */
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -738,7 +739,7 @@ public:
bool ReplayBlocks(const CChainParams& params);
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
bool LoadGenesisBlock(const CChainParams& chainparams);
bool AddGenesisBlock(const CChainParams& chainparams, const CBlock& block, CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool AddGenesisBlock(const CChainParams& chainparams, const CBlock& block, BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void PruneBlockIndexCandidates();
@ -774,10 +775,10 @@ public:
std::string ToString() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
private:
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs);
bool ConnectTip(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions& disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs);
bool ActivateBestChainStep(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs);
bool ConnectTip(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexNew, const std::shared_ptr<const CBlock>& pblock, ConnectTrace& connectTrace, DisconnectedBlockTransactions& disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, m_mempool.cs);
void InvalidBlockFound(CBlockIndex* pindex, const CValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void InvalidBlockFound(CBlockIndex* pindex, const BlockValidationState& state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -785,7 +786,7 @@ private:
bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
//! Mark a block as conflicting
bool MarkConflictingBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool MarkConflictingBlock(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
//! Mark a block as not having block data
void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -990,7 +991,7 @@ public:
* @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
* @param[out] first_invalid First header that fails validation, if one exists
*/
bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, CValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr, CBlockHeader* first_invalid = nullptr) LOCKS_EXCLUDED(cs_main);
bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
//! Load the block tree and coins database from disk, initializing state if we're running with -reindex
bool LoadBlockIndex(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);

View File

@ -44,7 +44,7 @@ struct MainSignalsInstance {
boost::signals2::signal<void (const std::shared_ptr<const CBlock>&, const CBlockIndex* pindex)> BlockDisconnected;
boost::signals2::signal<void (const CTransactionRef &, MemPoolRemovalReason)> TransactionRemovedFromMempool;
boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed;
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
boost::signals2::signal<void (const CBlock&, const BlockValidationState&)> BlockChecked;
boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
boost::signals2::signal<void (const CBlockIndex *)>AcceptedBlockHeader;
boost::signals2::signal<void (const CBlockIndex *, bool)>NotifyHeaderTip;
@ -198,7 +198,7 @@ void CMainSignals::ChainStateFlushed(const CBlockLocator &locator) {
});
}
void CMainSignals::BlockChecked(const CBlock& block, const CValidationState& state) {
void CMainSignals::BlockChecked(const CBlock& block, const BlockValidationState& state) {
m_internals->BlockChecked(block, state);
}

View File

@ -13,12 +13,12 @@
#include <memory>
extern CCriticalSection cs_main;
class BlockValidationState;
class CBlock;
class CBlockIndex;
struct CBlockLocator;
class CConnman;
class CValidationInterface;
class CValidationState;
class CGovernanceVote;
class CGovernanceObject;
class CDeterministicMNList;
@ -185,11 +185,11 @@ protected:
virtual void ChainStateFlushed(const CBlockLocator &locator) {}
/**
* Notifies listeners of a block validation result.
* If the provided CValidationState IsValid, the provided block
* If the provided BlockValidationState IsValid, the provided block
* is guaranteed to be the current best block at the time the
* callback was generated (not necessarily now)
*/
virtual void BlockChecked(const CBlock&, const CValidationState&) {}
virtual void BlockChecked(const CBlock&, const BlockValidationState&) {}
/**
* Notifies listeners that a block which builds directly on our current tip
* has been received and connected to the headers tree, though not validated yet */
@ -236,7 +236,7 @@ public:
void NotifyRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig> &sig);
void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman);
void ChainStateFlushed(const CBlockLocator &);
void BlockChecked(const CBlock&, const CValidationState&);
void BlockChecked(const CBlock&, const BlockValidationState&);
void NewPoWValidBlock(const CBlockIndex *, const std::shared_ptr<const CBlock>&);
};

View File

@ -232,7 +232,7 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
# Assert that the conflicting tx got mined and the locked TX is not valid
assert self.nodes[0].getrawtransaction(rawtx1_txid, True)['confirmations'] > 0
assert_raises_rpc_error(-25, "Missing inputs", self.nodes[0].sendrawtransaction, rawtx2)
assert_raises_rpc_error(-25, "bad-txns-inputs-missingorspent", self.nodes[0].sendrawtransaction, rawtx2)
# Create the block and the corresponding clsig but do not relay clsig yet
cl_block = self.create_block(self.nodes[0])

View File

@ -151,7 +151,7 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx)
# This will raise an exception since there are missing inputs
assert_raises_rpc_error(-25, "Missing inputs", self.nodes[2].sendrawtransaction, rawtx['hex'])
assert_raises_rpc_error(-25, "bad-txns-inputs-missingorspent", self.nodes[2].sendrawtransaction, rawtx['hex'])
#####################################
# getrawtransaction with block hash #