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. LOCK(::cs_main); // Required for ::AcceptToMemoryPool.
for (const auto& txr : txs) { for (const auto& txr : txs) {
CValidationState state; TxValidationState state;
bool ret{::AcceptToMemoryPool(::ChainstateActive(), *test_setup.m_node.mempool, state, txr, nullptr /* pfMissingInputs */, false /* bypass_limits */, /* nAbsurdFee */ 0)}; bool ret{::AcceptToMemoryPool(::ChainstateActive(), *test_setup.m_node.mempool, state, txr, false /* bypass_limits */, /* nAbsurdFee */ 0)};
assert(ret); assert(ret);
} }
} }

View File

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

View File

@ -56,7 +56,7 @@ static void DuplicateInputs(benchmark::Bench& bench)
block.hashMerkleRoot = BlockMerkleRoot(block); block.hashMerkleRoot = BlockMerkleRoot(block);
bench.minEpochIterations(10).run([&] { bench.minEpochIterations(10).run([&] {
CValidationState cvstate{}; BlockValidationState cvstate{};
assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false)); assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false));
assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate"); 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) if (vtx_missing.size() != tx_missing_offset)
return READ_STATUS_INVALID; return READ_STATUS_INVALID;
CValidationState state; BlockValidationState state;
if (!CheckBlock(block, state, Params().GetConsensus())) { if (!CheckBlock(block, state, Params().GetConsensus())) {
// TODO: We really want to just check merkle tree manually here, // TODO: We really want to just check merkle tree manually here,
// but that is expensive, and CheckBlock caches a block's // but that is expensive, and CheckBlock caches a block's
// "checked-status" (in the CBlock?). CBlock should be able to // "checked-status" (in the CBlock?). CBlock should be able to
// check its own merkle root and cache that check. // 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_FAILED; // Possible Short ID collision
return READ_STATUS_CHECKBLOCK_FAILED; return READ_STATUS_CHECKBLOCK_FAILED;
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -158,11 +158,11 @@ unsigned int GetTransactionSigOpCount(const CTransaction& tx, const CCoinsViewCa
return nSigOps; 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? // are the actual inputs available?
if (!inputs.HaveInputs(tx)) { 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__)); 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 prev is coinbase, check that it's matured
if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) { 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)); strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
} }
// Check for negative or overflow input values // Check for negative or overflow input values
nValueIn += coin.out.nValue; nValueIn += coin.out.nValue;
if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) { 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(); const CAmount value_out = tx.GetValueOut();
if (nValueIn < value_out) { 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))); strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
} }
// Tally transaction fees // Tally transaction fees
const CAmount txfee_aux = nValueIn - value_out; const CAmount txfee_aux = nValueIn - value_out;
if (!MoneyRange(txfee_aux)) { 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; txfee = txfee_aux;

View File

@ -13,7 +13,7 @@
class CBlockIndex; class CBlockIndex;
class CCoinsViewCache; class CCoinsViewCache;
class CTransaction; class CTransaction;
class CValidationState; class TxValidationState;
/** Transaction validation functions */ /** Transaction validation functions */
@ -24,7 +24,7 @@ namespace Consensus {
* @param[out] txfee Set to the transaction fee if successful. * @param[out] txfee Set to the transaction fee if successful.
* Preconditions: tx.IsCoinBase() is false. * 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 } // namespace Consensus
/** Auxiliary functions for transaction validation (ideally should not be exposed) */ /** Auxiliary functions for transaction validation (ideally should not be exposed) */

View File

@ -8,19 +8,47 @@
#include <string> #include <string>
/** A "reason" why something was invalid, suitable for determining whether the /** A "reason" why a transaction was invalid, suitable for determining whether the
* provider of the object should be banned/ignored/disconnected/etc. * provider of the transaction should be banned/ignored/disconnected/etc.
*/ */
enum class ValidationInvalidReason { enum class TxValidationResult {
// txn and blocks: TX_RESULT_UNSET, //!< initial value. Tx has not yet been rejected
NONE, //!< not actually invalid TX_CONSENSUS, //!< invalid by consensus rules
CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
/** /**
* Invalid by a change to consensus rules more recent than some major deployment. * Invalid by a change to consensus rules more recent than some major deployment.
*/ */
RECENT_CONSENSUS_CHANGE, // Only loose txn:
// Only blocks (or headers): TX_RECENT_CONSENSUS_CHANGE,
CACHED_INVALID, //!< this object was cached as being invalid, but we don't know why 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_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_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 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_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_CHECKPOINT, //!< the block failed to meet one of our checkpoints
BLOCK_CHAINLOCK, //!< the block conflicts with the ChainLock 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 */ /** Base class for capturing information about block/transaction validation. This is subclassed
class CValidationState { * by TxValidationState and BlockValidationState for validation information on transactions
* and blocks respectively. */
class ValidationState {
private: private:
enum mode_state { enum mode_state {
MODE_VALID, //!< everything ok MODE_VALID, //!< everything ok
MODE_INVALID, //!< network rule violation (DoS value may be set) MODE_INVALID, //!< network rule violation (DoS value may be set)
MODE_ERROR, //!< run-time error MODE_ERROR, //!< run-time error
} mode; } m_mode;
ValidationInvalidReason m_reason; std::string m_reject_reason;
std::string strRejectReason; std::string m_debug_message;
std::string strDebugMessage; protected:
public: void Invalid(const std::string &reject_reason="",
CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE) {} const std::string &debug_message="")
bool Invalid(ValidationInvalidReason reasonIn, bool ret = false, {
const std::string &strRejectReasonIn="", m_reject_reason = reject_reason;
const std::string &strDebugMessageIn="") { m_debug_message = debug_message;
m_reason = reasonIn; if (m_mode != MODE_ERROR) m_mode = MODE_INVALID;
strRejectReason = strRejectReasonIn;
strDebugMessage = strDebugMessageIn;
if (mode == MODE_ERROR)
return ret;
mode = MODE_INVALID;
return ret;
} }
bool Error(const std::string& strRejectReasonIn) { public:
if (mode == MODE_VALID) // ValidationState is abstract. Have a pure virtual destructor.
strRejectReason = strRejectReasonIn; virtual ~ValidationState() = 0;
mode = MODE_ERROR;
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; return false;
} }
bool IsValid() const { bool IsValid() const { return m_mode == MODE_VALID; }
return 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 { TxValidationResult GetResult() const { return m_result; }
return mode == MODE_INVALID; };
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 { BlockValidationResult GetResult() const { return m_result; }
return mode == MODE_ERROR;
}
ValidationInvalidReason GetReason() const { return m_reason; }
std::string GetRejectReason() const { return strRejectReason; }
std::string GetDebugMessage() const { return strDebugMessage; }
}; };
#endif // BITCOIN_CONSENSUS_VALIDATION_H #endif // BITCOIN_CONSENSUS_VALIDATION_H

View File

@ -15,33 +15,33 @@
#include <chainparams.h> #include <chainparams.h>
#include <consensus/merkle.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) { 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()) { if (!tx.IsCoinBase()) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cbtx-invalid"); return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cbtx-invalid");
} }
CCbTx cbTx; CCbTx cbTx;
if (!GetTxPayload(tx, 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) { 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) { 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) { if (pindexPrev) {
bool fDIP0008Active = pindexPrev->nHeight >= Params().GetConsensus().DIP0008Height; bool fDIP0008Active = pindexPrev->nHeight >= Params().GetConsensus().DIP0008Height;
if (fDIP0008Active && cbTx.nVersion < 2) { 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 // 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) { if (block.vtx[0]->nType != TRANSACTION_COINBASE) {
return true; return true;
@ -61,7 +61,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const
CCbTx cbTx; CCbTx cbTx;
if (!GetTxPayload(*block.vtx[0], 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; int64_t nTime2 = GetTimeMicros(); nTimePayload += nTime2 - nTime1;
@ -77,7 +77,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const
return false; return false;
} }
if (calculatedMerkleRoot != cbTx.merkleRootMNList) { 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; int64_t nTime3 = GetTimeMicros(); nTimeMerkleMNL += nTime3 - nTime2;
@ -89,7 +89,7 @@ bool CheckCbTxMerkleRoots(const CBlock& block, const CBlockIndex* pindex, const
return false; return false;
} }
if (calculatedMerkleRoot != cbTx.merkleRootQuorums) { 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; 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); LOCK(deterministicMNManager->cs);
@ -134,7 +134,7 @@ bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev
if (sml == smlCached) { if (sml == smlCached) {
merkleRootRet = merkleRootCached; merkleRootRet = merkleRootCached;
if (mutatedCached) { 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; return true;
} }
@ -150,13 +150,13 @@ bool CalcCbTxMerkleRootMNList(const CBlock& block, const CBlockIndex* pindexPrev
mutatedCached = mutated; mutatedCached = mutated;
if (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; return true;
} catch (const std::exception& e) { } catch (const std::exception& e) {
LogPrintf("%s -- failed: %s\n", __func__, e.what()); 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; 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 nTimeMined = 0;
static int64_t nTimeLoop = 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); auto retVal = CachedGetQcHashesQcIndexedHashes(pindexPrev, quorum_block_processor);
if (!retVal) { 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 // The returned quorums are in reversed order, so the most recent one is at index 0
auto [qcHashes, qcIndexedHashes] = retVal.value(); 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) { if (tx->nVersion == 3 && tx->nType == TRANSACTION_QUORUM_COMMITMENT) {
llmq::CFinalCommitmentTxPayload qc; llmq::CFinalCommitmentTxPayload qc;
if (!GetTxPayload(*tx, 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()) { if (qc.commitment.IsNull()) {
// having null commitments is ok but we don't use them here, move to the next tx // 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); const auto& llmq_params_opt = llmq::GetLLMQParams(qc.commitment.llmqType);
if (!llmq_params_opt.has_value()) { 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(); const auto& llmq_params = llmq_params_opt.value();
auto qcHash = ::SerializeHash(qc.commitment); 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); const auto& llmq_params_opt = llmq::GetLLMQParams(llmqType);
assert(llmq_params_opt.has_value()); assert(llmq_params_opt.has_value());
if (vec_hashes.size() > size_t(llmq_params_opt->signingActiveQuorumCount)) { 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 // Copy vec_hashes into vec_hashes_final
std::copy(vec_hashes.begin(), vec_hashes.end(), std::back_inserter(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); LogPrint(BCLog::BENCHMARK, " - ComputeMerkleRoot: %.2fms [%.2fs]\n", 0.001 * (nTime4 - nTime3), nTimeMerkle * 0.000001);
if (mutated) { if (mutated) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "mutated-calc-cbtx-quorummerkleroot"); return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "mutated-calc-cbtx-quorummerkleroot");
} }
return true; return true;

View File

@ -8,10 +8,11 @@
#include <primitives/transaction.h> #include <primitives/transaction.h>
#include <univalue.h> #include <univalue.h>
class BlockValidationState;
class CBlock; class CBlock;
class CBlockIndex; class CBlockIndex;
class CCoinsViewCache; class CCoinsViewCache;
class CValidationState; class TxValidationState;
namespace llmq { namespace llmq {
class CQuorumBlockProcessor; 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 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, CValidationState& 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, CValidationState& state); bool CalcCbTxMerkleRootQuorums(const CBlock& block, const CBlockIndex* pindexPrev, const llmq::CQuorumBlockProcessor& quorum_block_processor, uint256& merkleRootRet, BlockValidationState& state);
#endif // BITCOIN_EVO_CBTX_H #endif // BITCOIN_EVO_CBTX_H

View File

@ -654,7 +654,7 @@ void CDeterministicMNList::RemoveMN(const uint256& proTxHash)
mnInternalIdMap = mnInternalIdMap.erase(dmn->GetInternalId()); 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); AssertLockHeld(cs_main);
@ -672,7 +672,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
try { try {
LOCK(cs); 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 // pass the state returned by the function above
return false; return false;
} }
@ -710,7 +710,7 @@ bool CDeterministicMNManager::ProcessBlock(const CBlock& block, const CBlockInde
mnListDiffsCache.emplace(pindex->GetBlockHash(), diff); mnListDiffsCache.emplace(pindex->GetBlockHash(), diff);
} catch (const std::exception& e) { } catch (const std::exception& e) {
LogPrintf("CDeterministicMNManager::%s -- internal error: %s\n", __func__, e.what()); 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 // 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()) { 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__, LogPrintf("CDeterministicMNManager::%s -- DIP3 enforcement block has wrong hash: hash=%s, expected=%s, nHeight=%d\n", __func__,
pindex->GetBlockHash().ToString(), consensusParams.DIP0003EnforcementHash.ToString(), nHeight); 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); LogPrintf("CDeterministicMNManager::%s -- DIP3 is enforced now. nHeight=%d\n", __func__, nHeight);
} }
@ -775,7 +775,7 @@ void CDeterministicMNManager::UpdatedBlockTip(const CBlockIndex* pindex)
tipIndex = 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); AssertLockHeld(cs);
@ -820,11 +820,11 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
if (tx.nType == TRANSACTION_PROVIDER_REGISTER) { if (tx.nType == TRANSACTION_PROVIDER_REGISTER) {
CProRegTx proTx; CProRegTx proTx;
if (!GetTxPayload(tx, 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)) { 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); 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)) { 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. // should actually never get to this point as CheckProRegTx should have handled this case.
// We do this additional check nevertheless to be 100% sure // 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); auto replacedDmn = newList.GetMNByCollateral(dmn->collateralOutpoint);
@ -858,10 +858,10 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
} }
if (newList.HasUniqueProperty(proTx.addr)) { 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)) { 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; dmn->nOperatorReward = proTx.nOperatorReward;
@ -883,26 +883,26 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
} else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) { } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_SERVICE) {
CProUpServTx proTx; CProUpServTx proTx;
if (!GetTxPayload(tx, 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)) { 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) { 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); CDeterministicMNCPtr dmn = newList.GetMN(proTx.proTxHash);
if (!dmn) { 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) { 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)) { 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); 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) { } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REGISTRAR) {
CProUpRegTx proTx; CProUpRegTx proTx;
if (!GetTxPayload(tx, 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); CDeterministicMNCPtr dmn = newList.GetMN(proTx.proTxHash);
if (!dmn) { 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); auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
if (newState->pubKeyOperator.Get() != proTx.pubKeyOperator) { 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) { } else if (tx.nType == TRANSACTION_PROVIDER_UPDATE_REVOKE) {
CProUpRevTx proTx; CProUpRevTx proTx;
if (!GetTxPayload(tx, 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); CDeterministicMNCPtr dmn = newList.GetMN(proTx.proTxHash);
if (!dmn) { 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); auto newState = std::make_shared<CDeterministicMNState>(*dmn->pdmnState);
newState->ResetOperatorFields(); newState->ResetOperatorFields();
@ -979,19 +979,19 @@ bool CDeterministicMNManager::BuildNewListFromBlock(const CBlock& block, const C
} else if (tx.nType == TRANSACTION_QUORUM_COMMITMENT) { } else if (tx.nType == TRANSACTION_QUORUM_COMMITMENT) {
llmq::CFinalCommitmentTxPayload qc; llmq::CFinalCommitmentTxPayload qc;
if (!GetTxPayload(tx, 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()) { if (!qc.commitment.IsNull()) {
const auto& llmq_params_opt = llmq::GetLLMQParams(qc.commitment.llmqType); const auto& llmq_params_opt = llmq::GetLLMQParams(qc.commitment.llmqType);
if (!llmq_params_opt.has_value()) { 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 qcnHeight = int(qc.nHeight);
int quorumHeight = qcnHeight - (qcnHeight % llmq_params_opt->dkgInterval) + int(qc.commitment.quorumIndex); int quorumHeight = qcnHeight - (qcnHeight % llmq_params_opt->dkgInterval) + int(qc.commitment.quorumIndex);
auto pQuorumBaseBlockIndex = pindexPrev->GetAncestor(quorumHeight); auto pQuorumBaseBlockIndex = pindexPrev->GetAncestor(quorumHeight);
if (!pQuorumBaseBlockIndex || pQuorumBaseBlockIndex->GetBlockHash() != qc.commitment.quorumHash) { 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 // 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); HandleQuorumCommitment(qc.commitment, pQuorumBaseBlockIndex, newList, debugLogs);
@ -1348,111 +1348,111 @@ bool CDeterministicMNManager::MigrateDBIfNeeded()
} }
template <typename ProTx> template <typename ProTx>
static bool CheckService(const ProTx& proTx, CValidationState& state) static bool CheckService(const ProTx& proTx, TxValidationState& state)
{ {
if (!proTx.addr.IsValid()) { 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()) { 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(); static int mainnetDefaultPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPort();
if (Params().NetworkIDString() == CBaseChainParams::MAIN) { if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
if (proTx.addr.GetPort() != mainnetDefaultPort) { 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) { } 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()) { 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; return true;
} }
template <typename ProTx> template <typename ProTx>
static bool CheckPlatformFields(const ProTx& proTx, CValidationState& state) static bool CheckPlatformFields(const ProTx& proTx, TxValidationState& state)
{ {
if (proTx.platformNodeID.IsNull()) { 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(); static int mainnetPlatformP2PPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPlatformP2PPort();
if (Params().NetworkIDString() == CBaseChainParams::MAIN) { if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
if (proTx.platformP2PPort != mainnetPlatformP2PPort) { 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(); static int mainnetPlatformHTTPPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPlatformHTTPPort();
if (Params().NetworkIDString() == CBaseChainParams::MAIN) { if (Params().NetworkIDString() == CBaseChainParams::MAIN) {
if (proTx.platformHTTPPort != mainnetPlatformHTTPPort) { 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(); static int mainnetDefaultP2PPort = CreateChainParams(CBaseChainParams::MAIN)->GetDefaultPort();
if (proTx.platformP2PPort == mainnetDefaultP2PPort) { 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) { 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 || if (proTx.platformP2PPort == proTx.platformHTTPPort ||
proTx.platformP2PPort == proTx.addr.GetPort() || proTx.platformP2PPort == proTx.addr.GetPort() ||
proTx.platformHTTPPort == 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; return true;
} }
template <typename ProTx> 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; std::string strError;
if (!CHashSigner::VerifyHash(::SerializeHash(proTx), ToKeyID(pkhash), proTx.vchSig, 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; return true;
} }
template <typename ProTx> 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; std::string strError;
if (!CMessageSigner::VerifyMessage(ToKeyID(pkhash), proTx.vchSig, proTx.MakeSignString(), 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; return true;
} }
template <typename ProTx> 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))) { 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; 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) { 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; CProRegTx ptx;
if (!GetTxPayload(tx, 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) { 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 // 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()) { if (!ptx.collateralOutpoint.hash.IsNull()) {
Coin coin; Coin coin;
if (!view.GetCoin(ptx.collateralOutpoint, coin) || coin.IsSpent() || coin.out.nValue != expectedCollateral) { 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)) { 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. // 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 // Issuer of this ProRegTx must prove ownership with this key by signing the ProRegTx
keyForPayloadSig = std::get_if<PKHash>(&collateralTxDest); keyForPayloadSig = std::get_if<PKHash>(&collateralTxDest);
if (!keyForPayloadSig) { 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; collateralOutpoint = ptx.collateralOutpoint;
} else { } else {
if (ptx.collateralOutpoint.n >= tx.vout.size()) { 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) { 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)) { 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); 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) // 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 // 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))) { 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) { 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) // 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) { 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 // never allow duplicate keys, even if this ProTx would replace an existing MN
if (mnList.HasUniqueProperty(ptx.keyIDOwner) || mnList.HasUniqueProperty(ptx.pubKeyOperator)) { 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 // never allow duplicate platformNodeIds for HPMNs
if (ptx.nType == MnType::HighPerformance) { if (ptx.nType == MnType::HighPerformance) {
if (mnList.HasUniqueProperty(ptx.platformNodeID)) { 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 (!deterministicMNManager->IsDIP3Enforced(pindexPrev->nHeight)) {
if (ptx.keyIDOwner != ptx.keyIDVoting) { 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) { 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) { if (keyForPayloadSig) {
@ -1553,26 +1553,26 @@ bool CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CValid
} else { } else {
// collateral is part of this ProRegTx, so we know the collateral is owned by the issuer // collateral is part of this ProRegTx, so we know the collateral is owned by the issuer
if (!ptx.vchSig.empty()) { if (!ptx.vchSig.empty()) {
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-protx-sig"); return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-protx-sig");
} }
} }
return true; 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) { 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; CProUpServTx ptx;
if (!GetTxPayload(tx, 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) { 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)) { if (!CheckService(ptx, state)) {
@ -1590,34 +1590,34 @@ bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVa
auto mnList = deterministicMNManager->GetListForBlock(pindexPrev); auto mnList = deterministicMNManager->GetListForBlock(pindexPrev);
auto mn = mnList.GetMN(ptx.proTxHash); auto mn = mnList.GetMN(ptx.proTxHash);
if (!mn) { 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 // don't allow updating to addresses already used by other MNs
if (mnList.HasUniqueProperty(ptx.addr) && mnList.GetUniquePropertyMN(ptx.addr)->proTxHash != ptx.proTxHash) { 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 // don't allow updating to platformNodeIds already used by other HPMNs
if (ptx.nType == MnType::HighPerformance) { if (ptx.nType == MnType::HighPerformance) {
if (mnList.HasUniqueProperty(ptx.platformNodeID) && mnList.GetUniquePropertyMN(ptx.platformNodeID)->proTxHash != ptx.proTxHash) { 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 (ptx.scriptOperatorPayout != CScript()) {
if (mn->nOperatorReward == 0) { if (mn->nOperatorReward == 0) {
// don't allow setting operator reward payee in case no operatorReward was set // 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()) { 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 // 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) { 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)) { if (check_sigs && !CheckHashSig(ptx, mn->pdmnState->pubKeyOperator.Get(), state)) {
// pass the state returned by the function above // pass the state returned by the function above
@ -1628,69 +1628,69 @@ bool CheckProUpServTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVa
return true; 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) { 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; CProUpRegTx ptx;
if (!GetTxPayload(tx, 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) { 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; CTxDestination payoutDest;
if (!ExtractDestination(ptx.scriptPayout, payoutDest)) { if (!ExtractDestination(ptx.scriptPayout, payoutDest)) {
// should not happen as we checked script types before // 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) { if (pindexPrev) {
auto mnList = deterministicMNManager->GetListForBlock(pindexPrev); auto mnList = deterministicMNManager->GetListForBlock(pindexPrev);
auto dmn = mnList.GetMN(ptx.proTxHash); auto dmn = mnList.GetMN(ptx.proTxHash);
if (!dmn) { 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) // 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))) { 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; Coin coin;
if (!view.GetCoin(dmn->collateralOutpoint, coin) || coin.IsSpent()) { if (!view.GetCoin(dmn->collateralOutpoint, coin) || coin.IsSpent()) {
// this should never happen (there would be no dmn otherwise) // 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) // 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; CTxDestination collateralTxDest;
if (!ExtractDestination(coin.out.scriptPubKey, 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))) { 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)) { if (mnList.HasUniqueProperty(ptx.pubKeyOperator)) {
auto otherDmn = mnList.GetUniquePropertyMN(ptx.pubKeyOperator); auto otherDmn = mnList.GetUniquePropertyMN(ptx.pubKeyOperator);
if (ptx.proTxHash != otherDmn->proTxHash) { 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 (!deterministicMNManager->IsDIP3Enforced(pindexPrev->nHeight)) {
if (dmn->pdmnState->keyIDOwner != ptx.keyIDVoting) { 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) { 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)) { if (check_sigs && !CheckHashSig(ptx, PKHash(dmn->pdmnState->keyIDOwner), state)) {
// pass the state returned by the function above // pass the state returned by the function above
@ -1701,29 +1701,29 @@ bool CheckProUpRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVal
return true; 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) { 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; CProUpRevTx ptx;
if (!GetTxPayload(tx, 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) { 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) { if (pindexPrev) {
auto mnList = deterministicMNManager->GetListForBlock(pindexPrev); auto mnList = deterministicMNManager->GetListForBlock(pindexPrev);
auto dmn = mnList.GetMN(ptx.proTxHash); auto dmn = mnList.GetMN(ptx.proTxHash);
if (!dmn) 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) { 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)) { if (check_sigs && !CheckHashSig(ptx, dmn->pdmnState->pubKeyOperator.Get(), state)) {
// pass the state returned by the function above // pass the state returned by the function above

View File

@ -27,7 +27,7 @@
class CConnman; class CConnman;
class CBlock; class CBlock;
class CBlockIndex; class CBlockIndex;
class CValidationState; class TxValidationState;
class CSimplifiedMNListDiff; class CSimplifiedMNListDiff;
extern CCriticalSection cs_main; extern CCriticalSection cs_main;
@ -563,14 +563,14 @@ public:
m_evoDb(evoDb), connman(_connman) {} m_evoDb(evoDb), connman(_connman) {}
~CDeterministicMNManager() = default; ~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); const CCoinsViewCache& view, bool fJustCheck) EXCLUSIVE_LOCKS_REQUIRED(cs_main) LOCKS_EXCLUDED(cs);
bool UndoBlock(const CBlock& block, const CBlockIndex* pindex) LOCKS_EXCLUDED(cs); bool UndoBlock(const CBlock& block, const CBlockIndex* pindex) LOCKS_EXCLUDED(cs);
void UpdatedBlockTip(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) // 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); CDeterministicMNList& mnListRet, bool debugLogs) EXCLUSIVE_LOCKS_REQUIRED(cs);
static void HandleQuorumCommitment(const llmq::CFinalCommitment& qc, const CBlockIndex* pQuorumBaseBlockIndex, CDeterministicMNList& mnList, bool debugLogs); static void HandleQuorumCommitment(const llmq::CFinalCommitment& qc, const CBlockIndex* pQuorumBaseBlockIndex, CDeterministicMNList& mnList, bool debugLogs);
static void DecreasePoSePenalties(CDeterministicMNList& mnList); static void DecreasePoSePenalties(CDeterministicMNList& mnList);
@ -595,10 +595,10 @@ private:
CDeterministicMNList GetListForBlockInternal(const CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs); 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 CheckProRegTx(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state, const CCoinsViewCache& view, bool check_sigs);
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);
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);
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);
extern std::unique_ptr<CDeterministicMNManager> deterministicMNManager; 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); 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; MNHFTxPayload mnhfTx;
if (!GetTxPayload(tx, 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) { 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); const CBlockIndex* pindexQuorum = g_chainman.m_blockman.LookupBlockIndex(mnhfTx.signal.quorumHash);
if (!pindexQuorum) { 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)) { if (pindexQuorum != pindexPrev->GetAncestor(pindexQuorum->nHeight)) {
// not part of active chain // 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()) { 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)) { 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; return true;

View File

@ -12,7 +12,7 @@
#include <univalue.h> #include <univalue.h>
class CBlockIndex; class CBlockIndex;
class CValidationState; class TxValidationState;
extern CCriticalSection cs_main; extern CCriticalSection cs_main;
// mnhf signal special transaction // 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 #endif // BITCOIN_EVO_MNHFTX_H

View File

@ -14,34 +14,34 @@
maybe_error CProRegTx::IsTriviallyValid(bool is_bls_legacy_scheme) const maybe_error CProRegTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
{ {
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) { 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)) { if (!IsValidMnType(nType)) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-type"}; return {TxValidationResult::TX_CONSENSUS, "bad-protx-type"};
} }
if (nMode != 0) { if (nMode != 0) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-mode"}; return {TxValidationResult::TX_CONSENSUS, "bad-protx-mode"};
} }
if (keyIDOwner.IsNull() || !pubKeyOperator.IsValid() || keyIDVoting.IsNull()) { 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()) { if (!scriptPayout.IsPayToPublicKeyHash() && !scriptPayout.IsPayToScriptHash()) {
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-payee"}; return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee"};
} }
CTxDestination payoutDest; CTxDestination payoutDest;
if (!ExtractDestination(scriptPayout, payoutDest)) { if (!ExtractDestination(scriptPayout, payoutDest)) {
// should not happen as we checked script types before // 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) // 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))) { 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) { if (nOperatorReward > 10000) {
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-operator-reward"}; return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-operator-reward"};
} }
return {}; return {};
@ -87,7 +87,7 @@ std::string CProRegTx::ToString() const
maybe_error CProUpServTx::IsTriviallyValid(bool is_bls_legacy_scheme) const maybe_error CProUpServTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
{ {
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) { if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-version"}; return {TxValidationResult::TX_CONSENSUS, "bad-protx-version"};
} }
return {}; return {};
@ -108,17 +108,17 @@ std::string CProUpServTx::ToString() const
maybe_error CProUpRegTx::IsTriviallyValid(bool is_bls_legacy_scheme) const maybe_error CProUpRegTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
{ {
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) { 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) { if (nMode != 0) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-mode"}; return {TxValidationResult::TX_CONSENSUS, "bad-protx-mode"};
} }
if (!pubKeyOperator.IsValid() || keyIDVoting.IsNull()) { 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()) { if (!scriptPayout.IsPayToPublicKeyHash() && !scriptPayout.IsPayToScriptHash()) {
return {ValidationInvalidReason::TX_BAD_SPECIAL, "bad-protx-payee"}; return {TxValidationResult::TX_BAD_SPECIAL, "bad-protx-payee"};
} }
return {}; return {};
} }
@ -138,13 +138,13 @@ std::string CProUpRegTx::ToString() const
maybe_error CProUpRevTx::IsTriviallyValid(bool is_bls_legacy_scheme) const maybe_error CProUpRevTx::IsTriviallyValid(bool is_bls_legacy_scheme) const
{ {
if (nVersion == 0 || nVersion > GetVersion(is_bls_legacy_scheme)) { 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 < CProUpRevTx::REASON_NOT_SPECIFIED is always `false` since
// nReason is unsigned and CProUpRevTx::REASON_NOT_SPECIFIED == 0 // nReason is unsigned and CProUpRevTx::REASON_NOT_SPECIFIED == 0
if (nReason > CProUpRevTx::REASON_LAST) { if (nReason > CProUpRevTx::REASON_LAST) {
return {ValidationInvalidReason::CONSENSUS, "bad-protx-reason"}; return {TxValidationResult::TX_CONSENSUS, "bad-protx-reason"};
} }
return {}; return {};
} }

View File

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

View File

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

View File

@ -16,7 +16,7 @@
#include <primitives/block.h> #include <primitives/block.h>
#include <validation.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); AssertLockHeld(cs_main);
@ -24,7 +24,7 @@ bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVali
return true; return true;
if (pindexPrev && pindexPrev->nHeight + 1 < Params().GetConsensus().DIP0003Height) { 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 { try {
@ -46,13 +46,13 @@ bool CheckSpecialTx(const CTransaction& tx, const CBlockIndex* pindexPrev, CVali
} }
} catch (const std::exception& e) { } catch (const std::exception& e) {
LogPrintf("%s -- failed: %s\n", __func__, e.what()); 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) { if (tx.nVersion != 3 || tx.nType == TRANSACTION_NORMAL) {
return true; return true;
@ -72,7 +72,7 @@ bool ProcessSpecialTx(const CTransaction& tx, const CBlockIndex* pindex, CValida
return true; // handled per block 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) 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, 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); AssertLockHeld(cs_main);
@ -112,13 +112,18 @@ bool ProcessSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, ll
int64_t nTime1 = GetTimeMicros(); int64_t nTime1 = GetTimeMicros();
for (const auto& ptr_tx : block.vtx) { for (const auto& ptr_tx : block.vtx) {
if (!CheckSpecialTx(*ptr_tx, pindex->pprev, state, view, fCheckCbTxMerleRoots)) { TxValidationState tx_state;
// pass the state returned by the function above // At this moment CheckSpecialTx() and ProcessSpecialTx() may fail by 2 possible ways:
return false; // 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)) { if (!ProcessSpecialTx(*ptr_tx, pindex, tx_state)) {
// pass the state returned by the function above assert(tx_state.GetResult() == TxValidationResult::TX_CONSENSUS || tx_state.GetResult() == TxValidationResult::TX_BAD_SPECIAL);
return false; 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); LogPrint(BCLog::BENCHMARK, " - CheckCbTxMerkleRoots: %.2fms [%.2fs]\n", 0.001 * (nTime5 - nTime4), nTimeMerkle * 0.000001);
} catch (const std::exception& e) { } catch (const std::exception& e) {
LogPrintf("%s -- failed: %s\n", __func__, e.what()); 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; return true;

View File

@ -9,19 +9,20 @@
#include <sync.h> #include <sync.h>
#include <threadsafety.h> #include <threadsafety.h>
class BlockValidationState;
class CBlock; class CBlock;
class CBlockIndex; class CBlockIndex;
class CCoinsViewCache; class CCoinsViewCache;
class CValidationState; class TxValidationState;
namespace llmq { namespace llmq {
class CQuorumBlockProcessor; class CQuorumBlockProcessor;
} // namespace llmq } // namespace llmq
extern CCriticalSection cs_main; 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, 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); bool UndoSpecialTxsInBlock(const CBlock& block, const CBlockIndex* pindex, llmq::CQuorumBlockProcessor& quorum_block_processor) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
#endif // BITCOIN_EVO_SPECIALTXMAN_H #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 chainman unique_ptrs since ABC requires us not to be holding cs_main, so retrieve
// the relevant pointers before the ABC call. // the relevant pointers before the ABC call.
for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) { for (CChainState* chainstate : WITH_LOCK(::cs_main, return chainman.GetAll())) {
CValidationState state; BlockValidationState state;
if (!chainstate->ActivateBestChain(state, chainparams, nullptr)) { if (!chainstate->ActivateBestChain(state, chainparams, nullptr)) {
LogPrintf("Failed to connect best block (%s)\n", FormatStateMessage(state)); LogPrintf("Failed to connect best block (%s)\n", FormatStateMessage(state));
StartShutdown(); StartShutdown();

View File

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

View File

@ -136,7 +136,7 @@ void CQuorumBlockProcessor::ProcessMessage(const CNode& peer, std::string_view m
AddMineableCommitment(qc); 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); AssertLockHeld(cs_main);
@ -172,11 +172,11 @@ bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, const CBlockIndex*
const auto numCommitmentsInNewBlock = qcs.count(params.type); const auto numCommitmentsInNewBlock = qcs.count(params.type);
if (numCommitmentsRequired < numCommitmentsInNewBlock) { 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) { 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)) { if (llmq::utils::IsQuorumRotationEnabled(params, pindex)) {
LogPrintf("[ProcessBlock] h[%d] numCommitmentsRequired[%d] numCommitmentsInNewBlock[%d]\n", pindex->nHeight, numCommitmentsRequired, numCommitmentsInNewBlock); 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)); 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); AssertLockHeld(cs_main);
@ -234,31 +234,31 @@ bool CQuorumBlockProcessor::ProcessCommitment(int nHeight, const uint256& blockH
if (quorumHash.IsNull()) { 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__, 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()); 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) { 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__, 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()); 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.IsNull()) {
if (!qc.VerifyNull()) { if (!qc.VerifyNull()) {
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s height=%d, type=%d, quorumIndex=%d, quorumHash=%s, signers=%s, validMembers=%dqc verifynull failed.\n", __func__, 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()); 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; return true;
} }
if (HasMinedCommitment(llmq_params.type, quorumHash)) { if (HasMinedCommitment(llmq_params.type, quorumHash)) {
// should not happen as it's already handled in ProcessBlock // 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)) { if (!IsMiningPhase(llmq_params, nHeight)) {
// should not happen as it's already handled in ProcessBlock // 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); 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)) { 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__, 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()); 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) { if (fJustCheck) {
@ -313,7 +313,7 @@ bool CQuorumBlockProcessor::UndoBlock(const CBlock& block, const CBlockIndex* pi
llmq::utils::PreComputeQuorumMembers(pindex, true); llmq::utils::PreComputeQuorumMembers(pindex, true);
std::multimap<Consensus::LLMQType, CFinalCommitment> qcs; std::multimap<Consensus::LLMQType, CFinalCommitment> qcs;
CValidationState dummy; BlockValidationState dummy;
if (!GetCommitmentsFromBlock(block, pindex, qcs, dummy)) { if (!GetCommitmentsFromBlock(block, pindex, qcs, dummy)) {
return false; return false;
} }
@ -378,7 +378,7 @@ bool CQuorumBlockProcessor::UpgradeDB()
assert(r); assert(r);
std::multimap<Consensus::LLMQType, CFinalCommitment> qcs; std::multimap<Consensus::LLMQType, CFinalCommitment> qcs;
CValidationState dummyState; BlockValidationState dummyState;
GetCommitmentsFromBlock(block, pindex, qcs, dummyState); GetCommitmentsFromBlock(block, pindex, qcs, dummyState);
for (const auto& p : qcs) { for (const auto& p : qcs) {
@ -407,7 +407,7 @@ bool CQuorumBlockProcessor::UpgradeDB()
return true; 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); AssertLockHeld(cs_main);
@ -421,19 +421,19 @@ bool CQuorumBlockProcessor::GetCommitmentsFromBlock(const CBlock& block, const C
if (!GetTxPayload(*tx, qc)) { if (!GetTxPayload(*tx, qc)) {
// should not happen as it was verified before processing the block // should not happen as it was verified before processing the block
LogPrint(BCLog::LLMQ, "CQuorumBlockProcessor::%s height=%d GetTxPayload fails\n", __func__, pindex->nHeight); 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); const auto& llmq_params_opt = GetLLMQParams(qc.commitment.llmqType);
if (!llmq_params_opt.has_value()) { if (!llmq_params_opt.has_value()) {
// should not happen as it was verified before processing the block // 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) // only allow one commitment per type and per block (This was changed with rotation)
if (!utils::IsQuorumRotationEnabled(llmq_params_opt.value(), pindex)) { if (!utils::IsQuorumRotationEnabled(llmq_params_opt.value(), pindex)) {
if (ret.count(qc.commitment.llmqType) != 0) { 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()) { 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; return true;

View File

@ -16,9 +16,9 @@
#include <optional> #include <optional>
class BlockValidationState;
class CNode; class CNode;
class CConnman; class CConnman;
class CValidationState;
class CEvoDB; class CEvoDB;
extern CCriticalSection cs_main; extern CCriticalSection cs_main;
@ -49,7 +49,7 @@ public:
void ProcessMessage(const CNode& peer, std::string_view msg_type, CDataStream& vRecv); 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); bool UndoBlock(const CBlock& block, const CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void AddMineableCommitment(const CFinalCommitment& fqc); 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::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; std::optional<const CBlockIndex*> GetLastMinedCommitmentsByQuorumIndexUntilBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex, int quorumIndex, size_t cycle) const;
private: private:
static bool GetCommitmentsFromBlock(const CBlock& block, const CBlockIndex* pindex, std::multimap<Consensus::LLMQType, CFinalCommitment>& ret, CValidationState& state) 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, CValidationState& state, bool fJustCheck, bool fBLSChecks) 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); 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); 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); 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(); const auto &params = Params();
// Go backwards through the chain referenced by clsig until we find a block that is part of the main chain. // 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 // 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. // 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()); 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; bool activateNeeded = WITH_LOCK(::cs_main, return ::ChainActive().Tip()->GetAncestor(currentBestChainLockBlockIndex->nHeight)) != currentBestChainLockBlockIndex;
if (activateNeeded) { if (activateNeeded) {
if (!::ChainstateActive().ActivateBestChain(state, params)) { if (!::ChainstateActive().ActivateBestChain(dummy_state, params)) {
LogPrintf("CChainLocksHandler::%s -- ActivateBestChain failed: %s\n", __func__, FormatStateMessage(state)); LogPrintf("CChainLocksHandler::%s -- ActivateBestChain failed: %s\n", __func__, FormatStateMessage(dummy_state));
return; return;
} }
LOCK(cs_main); LOCK(cs_main);

View File

@ -176,18 +176,18 @@ bool CFinalCommitment::VerifySizes(const Consensus::LLMQParams& params) const
return true; return true;
} }
bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, CValidationState& state) bool CheckLLMQCommitment(const CTransaction& tx, const CBlockIndex* pindexPrev, TxValidationState& state)
{ {
CFinalCommitmentTxPayload qcTx; CFinalCommitmentTxPayload qcTx;
if (!GetTxPayload(tx, qcTx)) { if (!GetTxPayload(tx, qcTx)) {
LogPrintfFinalCommitment("h[%d] GetTxPayload failed\n", pindexPrev->nHeight); 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); const auto& llmq_params_opt = GetLLMQParams(qcTx.commitment.llmqType);
if (!llmq_params_opt.has_value()) { if (!llmq_params_opt.has_value()) {
LogPrintfFinalCommitment("h[%d] GetLLMQParams failed for llmqType[%d]\n", pindexPrev->nHeight, ToUnderlying(qcTx.commitment.llmqType)); 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)) { 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) { if (qcTx.nVersion == 0 || qcTx.nVersion > CFinalCommitmentTxPayload::CURRENT_VERSION) {
LogPrintfFinalCommitment("h[%d] invalid qcTx.nVersion[%d]\n", pindexPrev->nHeight, qcTx.nVersion); 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)) { if (qcTx.nHeight != uint32_t(pindexPrev->nHeight + 1)) {
LogPrintfFinalCommitment("h[%d] invalid qcTx.nHeight[%d]\n", pindexPrev->nHeight, qcTx.nHeight); 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)); const CBlockIndex* pQuorumBaseBlockIndex = WITH_LOCK(cs_main, return g_chainman.m_blockman.LookupBlockIndex(qcTx.commitment.quorumHash));
if (pQuorumBaseBlockIndex == nullptr) { 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)) { if (pQuorumBaseBlockIndex != pindexPrev->GetAncestor(pQuorumBaseBlockIndex->nHeight)) {
// not part of active chain // 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.IsNull()) {
if (!qcTx.commitment.VerifyNull()) { if (!qcTx.commitment.VerifyNull()) {
LogPrintfFinalCommitment("h[%d] invalid qcTx.commitment[%s] VerifyNull failed\n", pindexPrev->nHeight, qcTx.commitment.quorumHash.ToString()); 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; return true;
} }
if (!qcTx.commitment.Verify(pQuorumBaseBlockIndex, false)) { if (!qcTx.commitment.Verify(pQuorumBaseBlockIndex, false)) {
LogPrintfFinalCommitment("h[%d] invalid qcTx.commitment[%s] Verify failed\n", pindexPrev->nHeight, qcTx.commitment.quorumHash.ToString()); 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); LogPrintfFinalCommitment("h[%d] CheckLLMQCommitment VALID\n", pindexPrev->nHeight);

View File

@ -15,7 +15,7 @@
#include <univalue.h> #include <univalue.h>
class CBlockIndex; class CBlockIndex;
class CValidationState; class TxValidationState;
namespace llmq 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 } // 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()); LogPrintf("CInstantSendManager::%s -- invalidating block %s\n", __func__, pindex->GetBlockHash().ToString());
CValidationState state; BlockValidationState state;
// need non-const pointer // need non-const pointer
auto pindex2 = WITH_LOCK(::cs_main, return g_chainman.m_blockman.LookupBlockIndex(pindex->GetBlockHash())); auto pindex2 = WITH_LOCK(::cs_main, return g_chainman.m_blockman.LookupBlockIndex(pindex->GetBlockHash()));
if (!::ChainstateActive().InvalidateBlock(state, Params(), pindex2)) { if (!::ChainstateActive().InvalidateBlock(state, Params(), pindex2)) {
@ -1495,7 +1495,7 @@ void CInstantSendManager::ResolveBlockConflicts(const uint256& islockHash, const
} }
if (activateBestChain) { if (activateBestChain) {
CValidationState state; BlockValidationState state;
if (!::ChainstateActive().ActivateBestChain(state, Params())) { if (!::ChainstateActive().ActivateBestChain(state, Params())) {
LogPrintf("CChainLocksHandler::%s -- ActivateBestChain failed: %s\n", __func__, FormatStateMessage(state)); 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 // 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; cbTx.nHeight = nHeight;
CValidationState state; BlockValidationState state;
if (!CalcCbTxMerkleRootMNList(*pblock, pindexPrev, cbTx.merkleRootMNList, state, ::ChainstateActive().CoinsTip())) { if (!CalcCbTxMerkleRootMNList(*pblock, pindexPrev, cbTx.merkleRootMNList, state, ::ChainstateActive().CoinsTip())) {
throw std::runtime_error(strprintf("%s: CalcCbTxMerkleRootMNList failed: %s", __func__, FormatStateMessage(state))); 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->nPrevBits = pindexPrev->nBits;
pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(*pblock->vtx[0]); pblocktemplate->vTxSigOps[0] = GetLegacySigOpCount(*pblock->vtx[0]);
CValidationState state;
assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate)); assert(std::addressof(::ChainstateActive()) == std::addressof(chainstate));
BlockValidationState state;
if (!TestBlockValidity(state, m_clhandler, m_evoDb, chainparams, chainstate, *pblock, pindexPrev, false, false)) { 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))); 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 * @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 * 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) * @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()) { switch (state.GetResult()) {
case ValidationInvalidReason::NONE: case BlockValidationResult::BLOCK_RESULT_UNSET:
break; break;
// The node is providing invalid data: // The node is providing invalid data:
case ValidationInvalidReason::CONSENSUS: case BlockValidationResult::BLOCK_CONSENSUS:
case ValidationInvalidReason::BLOCK_MUTATED: case BlockValidationResult::BLOCK_MUTATED:
if (!via_compact_block) { if (!via_compact_block) {
Misbehaving(nodeid, 100, message); Misbehaving(nodeid, 100, message);
return true; return true;
} }
break; break;
case ValidationInvalidReason::CACHED_INVALID: case BlockValidationResult::BLOCK_CACHED_INVALID:
{ {
LOCK(cs_main); LOCK(cs_main);
CNodeState *node_state = State(nodeid); CNodeState *node_state = State(nodeid);
@ -1260,25 +1260,18 @@ static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool v
} }
break; break;
} }
case ValidationInvalidReason::BLOCK_INVALID_HEADER: case BlockValidationResult::BLOCK_INVALID_HEADER:
case ValidationInvalidReason::BLOCK_CHECKPOINT: case BlockValidationResult::BLOCK_CHECKPOINT:
case ValidationInvalidReason::BLOCK_INVALID_PREV: case BlockValidationResult::BLOCK_INVALID_PREV:
Misbehaving(nodeid, 100, message); Misbehaving(nodeid, 100, message);
return true; return true;
// Conflicting (but not necessarily invalid) data or different policy: // Conflicting (but not necessarily invalid) data or different policy:
case ValidationInvalidReason::BLOCK_MISSING_PREV: case BlockValidationResult::BLOCK_MISSING_PREV:
case ValidationInvalidReason::BLOCK_CHAINLOCK: case BlockValidationResult::BLOCK_CHAINLOCK:
case ValidationInvalidReason::TX_BAD_SPECIAL:
case ValidationInvalidReason::TX_CONFLICT_LOCK:
Misbehaving(nodeid, 10, message); Misbehaving(nodeid, 10, message);
return true; return true;
case ValidationInvalidReason::RECENT_CONSENSUS_CHANGE: case BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE:
case ValidationInvalidReason::BLOCK_TIME_FUTURE: case BlockValidationResult::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:
break; break;
} }
if (message != "") { if (message != "") {
@ -1287,6 +1280,41 @@ static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool v
return false; 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 * Handle invalid block rejection and consequent peer discouragement, maintain which
* peers announce compact blocks. * 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); LOCK(cs_main);
const uint256 hash(block.GetHash()); const uint256 hash(block.GetHash());
@ -1518,7 +1546,7 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
if (state.IsInvalid() && if (state.IsInvalid() &&
it != mapBlockSource.end() && it != mapBlockSource.end() &&
State(it->second.first)) { 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: // Check that:
// 1. The block is valid // 1. The block is valid
@ -1711,7 +1739,7 @@ void static ProcessGetBlockData(CNode& pfrom, const CChainParams& chainparams, c
} }
} // release cs_main before calling ActivateBestChain } // release cs_main before calling ActivateBestChain
if (need_activate_chain) { if (need_activate_chain) {
CValidationState state; BlockValidationState state;
if (!::ChainstateActive().ActivateBestChain(state, Params(), a_recent_block)) { if (!::ChainstateActive().ActivateBestChain(state, Params(), a_recent_block)) {
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state)); 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; BlockValidationState state;
CBlockHeader first_invalid_header; if (!chainman.ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast)) {
if (!chainman.ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast, &first_invalid_header)) {
if (state.IsInvalid()) { if (state.IsInvalid()) {
MaybePunishNode(pfrom.GetId(), state, via_compact_block, "invalid header received"); MaybePunishNodeForBlock(pfrom.GetId(), state, via_compact_block, "invalid header received");
return; return;
} }
} }
@ -2266,14 +2293,13 @@ void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set<uin
const CTransactionRef porphanTx = orphan_it->second.tx; const CTransactionRef porphanTx = orphan_it->second.tx;
const CTransaction& orphanTx = *porphanTx; const CTransaction& orphanTx = *porphanTx;
NodeId fromPeer = orphan_it->second.fromPeer; NodeId fromPeer = orphan_it->second.fromPeer;
bool fMissingInputs2 = false; // Use a new TxValidationState because orphans come from different peers (and we call
// Use a new CValidationState because orphans come from different peers (and we call // MaybePunishNodeForTx based on the source peer from the orphan map, not based on the peer
// MaybePunishNode based on the source peer from the orphan map, not based on the peer
// that relayed the previous transaction). // that relayed the previous transaction).
CValidationState orphan_state; TxValidationState orphan_state;
if (setMisbehaving.count(fromPeer)) continue; 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 */)) { false /* bypass_limits */, 0 /* nAbsurdFee */)) {
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString()); LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
RelayTransaction(orphanTx.GetHash(), connman); RelayTransaction(orphanTx.GetHash(), connman);
@ -2287,10 +2313,10 @@ void static ProcessOrphanTx(CConnman& connman, CTxMemPool& mempool, std::set<uin
} }
EraseOrphanTx(orphanHash); EraseOrphanTx(orphanHash);
done = true; done = true;
} else if (!fMissingInputs2) { } else if (orphan_state.GetResult() != TxValidationResult::TX_MISSING_INPUTS) {
if (orphan_state.IsInvalid()) { if (orphan_state.IsInvalid()) {
// Punish peer that gave us an invalid orphan tx // 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); setMisbehaving.insert(fromPeer);
} }
LogPrint(BCLog::MEMPOOL, " invalid orphan tx %s\n", orphanHash.ToString()); 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 // Has inputs but not accepted to mempool
// Probably non-standard or insufficient fee // Probably non-standard or insufficient fee
LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString()); LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString());
assert(IsTransactionReason(orphan_state.GetReason()));
assert(recentRejects); assert(recentRejects);
recentRejects->insert(orphanHash); recentRejects->insert(orphanHash);
EraseOrphanTx(orphanHash); EraseOrphanTx(orphanHash);
@ -3130,7 +3155,7 @@ void PeerLogicValidation::ProcessMessage(
LOCK(cs_most_recent_block); LOCK(cs_most_recent_block);
a_recent_block = most_recent_block; a_recent_block = most_recent_block;
} }
CValidationState state; BlockValidationState state;
if (!::ChainstateActive().ActivateBestChain(state, Params(), a_recent_block)) { if (!::ChainstateActive().ActivateBestChain(state, Params(), a_recent_block)) {
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state)); LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state));
} }
@ -3346,10 +3371,9 @@ void PeerLogicValidation::ProcessMessage(
LOCK2(cs_main, g_cs_orphans); LOCK2(cs_main, g_cs_orphans);
bool fMissingInputs = false; TxValidationState state;
CValidationState 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 */)) { false /* bypass_limits */, 0 /* nAbsurdFee */)) {
// Process custom txes, this changes AlreadyHave to "true" // Process custom txes, this changes AlreadyHave to "true"
if (nInvType == MSG_DSTX) { if (nInvType == MSG_DSTX) {
@ -3380,7 +3404,7 @@ void PeerLogicValidation::ProcessMessage(
// Recursively process any orphan transactions that depended on this one // Recursively process any orphan transactions that depended on this one
ProcessOrphanTx(m_connman, m_mempool, pfrom.orphan_work_set); 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 bool fRejectedParents = false; // It may be the case that the orphans parents have all been rejected
for (const CTxIn& txin : tx.vin) { for (const CTxIn& txin : tx.vin) {
@ -3417,7 +3441,6 @@ void PeerLogicValidation::ProcessMessage(
m_llmq_ctx->isman->TransactionRemovedFromMempool(ptx); m_llmq_ctx->isman->TransactionRemovedFromMempool(ptx);
} }
} else { } else {
assert(IsTransactionReason(state.GetReason()));
assert(recentRejects); assert(recentRejects);
recentRejects->insert(tx.GetHash()); recentRejects->insert(tx.GetHash());
if (RecursiveDynamicUsage(*ptx) < 100000) { 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(), LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
pfrom.GetId(), pfrom.GetId(),
FormatStateMessage(state)); FormatStateMessage(state));
MaybePunishNode(pfrom.GetId(), state, /*via_compact_block*/ false); MaybePunishNodeForTx(pfrom.GetId(), state);
m_llmq_ctx->isman->TransactionRemovedFromMempool(ptx); m_llmq_ctx->isman->TransactionRemovedFromMempool(ptx);
} }
return; return;
@ -3495,10 +3518,10 @@ void PeerLogicValidation::ProcessMessage(
} }
const CBlockIndex *pindex = nullptr; const CBlockIndex *pindex = nullptr;
CValidationState state; BlockValidationState state;
if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) { if (!m_chainman.ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) {
if (state.IsInvalid()) { 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; return;
} }
} }

View File

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

View File

@ -39,18 +39,16 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
} }
if (!node.mempool->exists(hashTx)) { if (!node.mempool->exists(hashTx)) {
// Transaction is not already in the mempool. Submit it. // Transaction is not already in the mempool. Submit it.
CValidationState state; TxValidationState state;
bool fMissingInputs; if (!AcceptToMemoryPool(::ChainstateActive(), *node.mempool, state, std::move(tx),
if (!AcceptToMemoryPool(::ChainstateActive(), *node.mempool, state, std::move(tx), &fMissingInputs,
bypass_limits, max_tx_fee)) { bypass_limits, max_tx_fee)) {
err_string = FormatStateMessage(state);
if (state.IsInvalid()) { if (state.IsInvalid()) {
err_string = FormatStateMessage(state); if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
return TransactionError::MEMPOOL_REJECTED;
} else {
if (fMissingInputs) {
return TransactionError::MISSING_INPUTS; return TransactionError::MISSING_INPUTS;
} }
err_string = FormatStateMessage(state); return TransactionError::MEMPOOL_REJECTED;
} else {
return TransactionError::MEMPOOL_ERROR; 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); ::ChainstateActive().PreciousBlock(state, Params(), pblockindex);
if (!state.IsValid()) { if (!state.IsValid()) {
@ -1836,7 +1836,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
}.Check(request); }.Check(request);
uint256 hash(ParseHashV(request.params[0], "blockhash")); uint256 hash(ParseHashV(request.params[0], "blockhash"));
CValidationState state; BlockValidationState state;
CBlockIndex* pblockindex; CBlockIndex* pblockindex;
{ {
@ -1886,7 +1886,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
::ChainstateActive().ResetBlockFailureFlags(pblockindex); ::ChainstateActive().ResetBlockFailureFlags(pblockindex);
} }
CValidationState state; BlockValidationState state;
::ChainstateActive().ActivateBestChain(state, Params()); ::ChainstateActive().ActivateBestChain(state, Params());
if (!state.IsValid()) { if (!state.IsValid()) {

View File

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

View File

@ -380,7 +380,7 @@ static UniValue generateblock(const JSONRPCRequest& request)
{ {
LOCK(cs_main); 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)) { 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())); 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 // 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()) if (state.IsValid())
return NullUniValue; return NullUniValue;
@ -670,7 +670,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
// TestBlockValidity only supports blocks built on the current Tip // TestBlockValidity only supports blocks built on the current Tip
if (block.hashPrevBlock != pindexPrev->GetBlockHash()) if (block.hashPrevBlock != pindexPrev->GetBlockHash())
return "inconclusive-not-best-prevblk"; return "inconclusive-not-best-prevblk";
CValidationState state; BlockValidationState state;
TestBlockValidity(state, *llmq_ctx.clhandler, *node_context.evodb, Params(), ::ChainstateActive(), block, pindexPrev, false, true); TestBlockValidity(state, *llmq_ctx.clhandler, *node_context.evodb, Params(), ::ChainstateActive(), block, pindexPrev, false, true);
return BIP22ValidationResult(state); return BIP22ValidationResult(state);
} }
@ -951,12 +951,12 @@ class submitblock_StateCatcher : public CValidationInterface
public: public:
uint256 hash; uint256 hash;
bool found; bool found;
CValidationState state; BlockValidationState state;
explicit submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {} explicit submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {}
protected: protected:
void BlockChecked(const CBlock& block, const CValidationState& stateIn) override { void BlockChecked(const CBlock& block, const BlockValidationState& stateIn) override {
if (block.GetHash() != hash) if (block.GetHash() != hash)
return; return;
found = true; found = true;
@ -1046,8 +1046,8 @@ static UniValue submitheader(const JSONRPCRequest& request)
} }
} }
CValidationState state; BlockValidationState state;
EnsureChainman(request.context).ProcessNewBlockHeaders({h}, state, Params(), /* ppindex */ nullptr, /* first_invalid */ nullptr); EnsureChainman(request.context).ProcessNewBlockHeaders({h}, state, Params());
if (state.IsValid()) return NullUniValue; if (state.IsValid()) return NullUniValue;
if (state.IsError()) { if (state.IsError()) {
throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state)); throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));

View File

@ -918,20 +918,21 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
UniValue result_0(UniValue::VOBJ); UniValue result_0(UniValue::VOBJ);
result_0.pushKV("txid", tx_hash.GetHex()); result_0.pushKV("txid", tx_hash.GetHex());
CValidationState state; TxValidationState state;
bool missing_inputs;
bool test_accept_res; bool test_accept_res;
{ {
LOCK(cs_main); 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); false /* bypass_limits */, max_raw_tx_fee, /* test_accept */ true);
} }
result_0.pushKV("allowed", test_accept_res); result_0.pushKV("allowed", test_accept_res);
if (!test_accept_res) { if (!test_accept_res) {
if (state.IsInvalid()) { if (state.IsInvalid()) {
result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason())); if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
} else if (missing_inputs) { result_0.pushKV("reject-reason", "missing-inputs");
result_0.pushKV("reject-reason", "missing-inputs"); } else {
result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
}
} else { } else {
result_0.pushKV("reject-reason", state.GetRejectReason()); 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)); block = std::make_shared<CBlock>(CreateBlock(pindex, no_txns, coinbase_script_pub_key));
CBlockHeader header = block->GetBlockHeader(); CBlockHeader header = block->GetBlockHeader();
CValidationState state; BlockValidationState state;
if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, state, Params(), &pindex, nullptr)) { if (!Assert(m_node.chainman)->ProcessNewBlockHeaders({header}, state, Params(), &pindex)) {
return false; 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 // payload itself. This means, we need to rely on script verification, which takes the hash of the extra payload
// into account // into account
auto tx2 = MalleateProTxPayout<CProRegTx>(tx); auto tx2 = MalleateProTxPayout<CProRegTx>(tx);
CValidationState dummyState; TxValidationState dummy_state;
// Technically, the payload is still valid... // Technically, the payload is still valid...
{ {
LOCK(cs_main); LOCK(cs_main);
BOOST_ASSERT(CheckProRegTx(CTransaction(tx), ::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(), dummyState, ::ChainstateActive().CoinsTip(), true)); BOOST_ASSERT(CheckProRegTx(CTransaction(tx2), ::ChainActive().Tip(), dummy_state, ::ChainstateActive().CoinsTip(), true));
} }
// But the signature should not verify anymore // But the signature should not verify anymore
BOOST_ASSERT(CheckTransactionSignature(*(setup.m_node.mempool), tx)); 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); 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 // check malleability protection again, but this time by also relying on the signature inside the ProUpRegTx
auto tx2 = MalleateProTxPayout<CProUpRegTx>(tx); auto tx2 = MalleateProTxPayout<CProUpRegTx>(tx);
CValidationState dummyState; TxValidationState dummy_state;
{ {
LOCK(cs_main); LOCK(cs_main);
BOOST_ASSERT(CheckProUpRegTx(CTransaction(tx), ::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(), dummyState, ::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), tx));
BOOST_ASSERT(!CheckTransactionSignature(*(setup.m_node.mempool), tx2)); BOOST_ASSERT(!CheckTransactionSignature(*(setup.m_node.mempool), tx2));

View File

@ -36,17 +36,17 @@ FUZZ_TARGET_INIT(block, initialize_block)
return; return;
} }
const Consensus::Params& consensus_params = Params().GetConsensus(); 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); 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()); 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(""); (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); 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()); 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); 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()); 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); 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()); assert(validation_state_none.IsValid() || validation_state_none.IsInvalid() || validation_state_none.IsError());
if (valid_incl_pow_and_merkle) { 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); (void)AreInputsStandard(CTransaction{random_mutable_transaction}, coins_view_cache);
}, },
[&] { [&] {
CValidationState state; TxValidationState state;
CAmount tx_fee_out; CAmount tx_fee_out;
const CTransaction transaction{random_mutable_transaction}; const CTransaction transaction{random_mutable_transaction};
if (ContainsSpentInput(transaction, coins_view_cache)) { if (ContainsSpentInput(transaction, coins_view_cache)) {
// Avoid: // 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; return;
} }
try { try {

View File

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

View File

@ -97,7 +97,7 @@ BOOST_AUTO_TEST_CASE(findCommonAncestor)
const CChain& active = Assert(m_node.chainman)->ActiveChain(); const CChain& active = Assert(m_node.chainman)->ActiveChain();
auto* orig_tip = active.Tip(); auto* orig_tip = active.Tip();
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
CValidationState state; BlockValidationState state;
ChainstateActive().InvalidateBlock(state, Params(), active.Tip()); ChainstateActive().InvalidateBlock(state, Params(), active.Tip());
} }
BOOST_CHECK_EQUAL(active.Height(), orig_tip->nHeight - 10); 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); BOOST_CHECK_EQUAL(pblocktemplate->block.vtx.size(), 5U);
} // unlock cs_main while calling InvalidateBlock } // unlock cs_main while calling InvalidateBlock
CValidationState state; BlockValidationState state;
::ChainstateActive().InvalidateBlock(state, chainparams, WITH_LOCK(cs_main, return ::ChainActive().Tip())); ::ChainstateActive().InvalidateBlock(state, chainparams, WITH_LOCK(cs_main, return ::ChainActive().Tip()));
SetMockTime(0); SetMockTime(0);

View File

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

View File

@ -18,15 +18,15 @@
#include <vector> #include <vector>
bool VerifyMNHFTx(const CTransaction& tx, CValidationState& state) bool VerifyMNHFTx(const CTransaction& tx, TxValidationState& state)
{ {
MNHFTxPayload mnhfTx; MNHFTxPayload mnhfTx;
if (!GetTxPayload(tx, 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) { 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; return true;
@ -78,7 +78,7 @@ BOOST_AUTO_TEST_CASE(verify_mnhf_specialtx_tests)
BOOST_CHECK(sig.VerifyInsecure(ag_pk, verHash)); BOOST_CHECK(sig.VerifyInsecure(ag_pk, verHash));
const CMutableTransaction tx = CreateMNHFTx(hash, sig, ver); const CMutableTransaction tx = CreateMNHFTx(hash, sig, ver);
CValidationState state; TxValidationState state;
BOOST_CHECK(VerifyMNHFTx(CTransaction(tx), 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); CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx(deserialize, stream); CTransaction tx(deserialize, stream);
CValidationState state; TxValidationState state;
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest); BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
BOOST_CHECK(state.IsValid()); BOOST_CHECK(state.IsValid());
@ -214,7 +214,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION); CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
CTransaction tx(deserialize, stream); CTransaction tx(deserialize, stream);
CValidationState state; TxValidationState state;
fValid = CheckTransaction(tx, state) && state.IsValid(); fValid = CheckTransaction(tx, state) && state.IsValid();
PrecomputedTransactionData txdata(tx); PrecomputedTransactionData txdata(tx);
@ -245,7 +245,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
CDataStream stream(vch, SER_DISK, CLIENT_VERSION); CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
CMutableTransaction tx; CMutableTransaction tx;
stream >> tx; stream >> tx;
CValidationState state; TxValidationState state;
BOOST_CHECK_MESSAGE(CheckTransaction(CTransaction(tx), state) && state.IsValid(), "Simple deserialized transaction should be valid."); BOOST_CHECK_MESSAGE(CheckTransaction(CTransaction(tx), state) && state.IsValid(), "Simple deserialized transaction should be valid.");
// Check that duplicate txins fail // 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()); BOOST_CHECK(CTransaction(coinbaseTx).IsCoinBase());
CValidationState state; TxValidationState state;
LOCK(cs_main); LOCK(cs_main);
@ -39,7 +39,6 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
BOOST_CHECK_EQUAL( BOOST_CHECK_EQUAL(
false, false,
AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, state, MakeTransactionRef(coinbaseTx), AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, state, MakeTransactionRef(coinbaseTx),
nullptr /* pfMissingInputs */,
true /* bypass_limits */, true /* bypass_limits */,
0 /* nAbsurdFee */)); 0 /* nAbsurdFee */));
@ -49,7 +48,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
// Check that the validation state reflects the unsuccessful attempt. // Check that the validation state reflects the unsuccessful attempt.
BOOST_CHECK(state.IsInvalid()); BOOST_CHECK(state.IsInvalid());
BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase"); BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase");
BOOST_CHECK(state.GetReason() == ValidationInvalidReason::CONSENSUS); BOOST_CHECK(state.GetResult() == TxValidationResult::TX_CONSENSUS);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()

View File

@ -12,7 +12,7 @@
#include <boost/test/unit_test.hpp> #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) 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) { const auto ToMemPool = [this](const CMutableTransaction& tx) {
LOCK(cs_main); LOCK(cs_main);
CValidationState state; TxValidationState validationState;
return AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, state, MakeTransactionRef(tx), nullptr /* pfMissingInputs */, return AcceptToMemoryPool(::ChainstateActive(), *m_node.mempool, validationState, MakeTransactionRef(tx),
true /* bypass_limits */, 0 /* nAbsurdFee */); 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 // 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. // 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) { for (uint32_t test_flags=0; test_flags < (1U << 16); test_flags += 1) {
CValidationState state; TxValidationState state;
// Filter out incompatible flag choices // Filter out incompatible flag choices
if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) { if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) {
// CLEANSTACK requires P2SH, see VerifyScript() in // CLEANSTACK requires P2SH, see VerifyScript() in
@ -193,7 +193,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
{ {
LOCK(cs_main); LOCK(cs_main);
CValidationState state; TxValidationState state;
PrecomputedTransactionData ptd_spend_tx; 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)); 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 // Make it valid, and check again
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100; invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
CValidationState state; TxValidationState state;
PrecomputedTransactionData txdata; PrecomputedTransactionData txdata;
BOOST_CHECK(CheckInputs(CTransaction(invalid_with_cltv_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr)); 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 // Make it valid, and check again
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100; invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
CValidationState state; TxValidationState state;
PrecomputedTransactionData txdata; PrecomputedTransactionData txdata;
BOOST_CHECK(CheckInputs(CTransaction(invalid_with_csv_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr)); 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); m_node.connman->Init(options);
} }
CValidationState state; BlockValidationState state;
if (!::ChainstateActive().ActivateBestChain(state, chainparams)) { if (!::ChainstateActive().ActivateBestChain(state, chainparams)) {
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state))); 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)) { if (!GetTxPayload(*block.vtx[0], cbTx)) {
BOOST_ASSERT(false); BOOST_ASSERT(false);
} }
CValidationState state; BlockValidationState state;
if (!CalcCbTxMerkleRootMNList(block, ::ChainActive().Tip(), cbTx.merkleRootMNList, state, ::ChainstateActive().CoinsTip())) { if (!CalcCbTxMerkleRootMNList(block, ::ChainActive().Tip(), cbTx.merkleRootMNList, state, ::ChainstateActive().CoinsTip())) {
BOOST_ASSERT(false); BOOST_ASSERT(false);
} }

View File

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

View File

@ -67,8 +67,8 @@ BOOST_AUTO_TEST_CASE(chainstatemanager)
WITH_LOCK(::cs_main, c2.InitCoinsCache(1 << 23)); WITH_LOCK(::cs_main, c2.InitCoinsCache(1 << 23));
// Unlike c1, which doesn't have any blocks. Gets us different tip, height. // Unlike c1, which doesn't have any blocks. Gets us different tip, height.
c2.LoadGenesisBlock(chainparams); c2.LoadGenesisBlock(chainparams);
CValidationState _; BlockValidationState dummy_state;
BOOST_CHECK(c2.ActivateBestChain(_, chainparams, nullptr)); BOOST_CHECK(c2.ActivateBestChain(dummy_state, chainparams, nullptr));
BOOST_CHECK(manager.IsSnapshotActive()); BOOST_CHECK(manager.IsSnapshotActive());
BOOST_CHECK(!manager.IsSnapshotValidated()); 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) 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; 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); assert(fCheckResult);
UpdateCoins(tx, mempoolDuplicate, std::numeric_limits<int>::max()); UpdateCoins(tx, mempoolDuplicate, std::numeric_limits<int>::max());
} }

View File

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

View File

@ -8,9 +8,9 @@
#include <string> #include <string>
class CValidationState; class ValidationState;
/** Convert CValidationState to a human-readable message for logging */ /** Convert ValidationState to a human-readable message for logging */
std::string FormatStateMessage(const CValidationState &state); std::string FormatStateMessage(const ValidationState &state);
#endif // BITCOIN_UTIL_VALIDATION_H #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 CEvoDB;
class CChainState; class CChainState;
class BlockValidationState;
class CBlockIndex; class CBlockIndex;
class CBlockTreeDB; class CBlockTreeDB;
class CBlockUndo; class CBlockUndo;
@ -52,7 +53,7 @@ class CInv;
class CConnman; class CConnman;
class CScriptCheck; class CScriptCheck;
class CTxMemPool; class CTxMemPool;
class CValidationState; class TxValidationState;
class ChainstateManager; class ChainstateManager;
struct PrecomputedTransactionData; struct PrecomputedTransactionData;
struct ChainTxData; struct ChainTxData;
@ -215,8 +216,8 @@ void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune);
void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeight); void PruneBlockFilesManual(CChainState& active_chainstate, int nManualPruneHeight);
/** (try to) add transaction to memory pool */ /** (try to) add transaction to memory pool */
bool AcceptToMemoryPool(CChainState& active_chainstate, CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool AcceptToMemoryPool(CChainState& active_chainstate, CTxMemPool& pool, TxValidationState &state, const CTransactionRef &tx,
bool* pfMissingInputs, bool bypass_limits, bool bypass_limits,
const CAmount nAbsurdFee, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main); const CAmount nAbsurdFee, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
bool GetUTXOCoin(const COutPoint& outpoint, Coin& coin); 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 */ /** Functions for validating blocks and updating the block tree */
/** Context-independent validity checks */ /** 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) */ /** 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, llmq::CChainLocksHandler& clhandler,
CEvoDB& evoDb, CEvoDB& evoDb,
const CChainParams& chainparams, const CChainParams& chainparams,
@ -454,7 +455,7 @@ public:
*/ */
bool AcceptBlockHeader( bool AcceptBlockHeader(
const CBlockHeader& block, const CBlockHeader& block,
CValidationState& state, BlockValidationState& state,
const CChainParams& chainparams, const CChainParams& chainparams,
CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -681,7 +682,7 @@ public:
*/ */
bool FlushStateToDisk( bool FlushStateToDisk(
const CChainParams& chainparams, const CChainParams& chainparams,
CValidationState &state, BlockValidationState &state,
FlushStateMode mode, FlushStateMode mode,
int nManualPruneHeight = 0); int nManualPruneHeight = 0);
@ -708,29 +709,29 @@ public:
* @returns true unless a system error occurred * @returns true unless a system error occurred
*/ */
bool ActivateBestChain( bool ActivateBestChain(
CValidationState& state, BlockValidationState& state,
const CChainParams& chainparams, const CChainParams& chainparams,
std::shared_ptr<const CBlock> pblock = nullptr) LOCKS_EXCLUDED(cs_main); 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: // Block (dis)connection on a given view:
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view) EXCLUSIVE_LOCKS_REQUIRED(cs_main); 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. // 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: // Manual block validity manipulation:
/** Mark a block as precious and reorganize. /** Mark a block as precious and reorganize.
* *
* May not be called in a validationinterface callback. * 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. */ /** 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. */ /** 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. */ /** Remove invalidity status from a block and its descendants. */
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main); void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
@ -738,7 +739,7 @@ public:
bool ReplayBlocks(const CChainParams& params); bool ReplayBlocks(const CChainParams& params);
/** Ensures we have a genesis block in the block tree, possibly writing one to disk. */ /** Ensures we have a genesis block in the block tree, possibly writing one to disk. */
bool LoadGenesisBlock(const CChainParams& chainparams); 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(); void PruneBlockIndexCandidates();
@ -774,10 +775,10 @@ public:
std::string ToString() EXCLUSIVE_LOCKS_REQUIRED(::cs_main); std::string ToString() EXCLUSIVE_LOCKS_REQUIRED(::cs_main);
private: 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 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(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 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); CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos) 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); bool RollforwardBlock(const CBlockIndex* pindex, CCoinsViewCache& inputs, const CChainParams& params) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
//! Mark a block as conflicting //! 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 //! Mark a block as not having block data
void EraseBlockData(CBlockIndex* index) EXCLUSIVE_LOCKS_REQUIRED(cs_main); 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] 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 * @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 //! 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); 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 std::shared_ptr<const CBlock>&, const CBlockIndex* pindex)> BlockDisconnected;
boost::signals2::signal<void (const CTransactionRef &, MemPoolRemovalReason)> TransactionRemovedFromMempool; boost::signals2::signal<void (const CTransactionRef &, MemPoolRemovalReason)> TransactionRemovedFromMempool;
boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed; 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 *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
boost::signals2::signal<void (const CBlockIndex *)>AcceptedBlockHeader; boost::signals2::signal<void (const CBlockIndex *)>AcceptedBlockHeader;
boost::signals2::signal<void (const CBlockIndex *, bool)>NotifyHeaderTip; 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); m_internals->BlockChecked(block, state);
} }

View File

@ -13,12 +13,12 @@
#include <memory> #include <memory>
extern CCriticalSection cs_main; extern CCriticalSection cs_main;
class BlockValidationState;
class CBlock; class CBlock;
class CBlockIndex; class CBlockIndex;
struct CBlockLocator; struct CBlockLocator;
class CConnman; class CConnman;
class CValidationInterface; class CValidationInterface;
class CValidationState;
class CGovernanceVote; class CGovernanceVote;
class CGovernanceObject; class CGovernanceObject;
class CDeterministicMNList; class CDeterministicMNList;
@ -185,11 +185,11 @@ protected:
virtual void ChainStateFlushed(const CBlockLocator &locator) {} virtual void ChainStateFlushed(const CBlockLocator &locator) {}
/** /**
* Notifies listeners of a block validation result. * 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 * is guaranteed to be the current best block at the time the
* callback was generated (not necessarily now) * 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 * 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 */ * 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 NotifyRecoveredSig(const std::shared_ptr<const llmq::CRecoveredSig> &sig);
void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman); void NotifyMasternodeListChanged(bool undo, const CDeterministicMNList& oldMNList, const CDeterministicMNListDiff& diff, CConnman& connman);
void ChainStateFlushed(const CBlockLocator &); 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>&); 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 that the conflicting tx got mined and the locked TX is not valid
assert self.nodes[0].getrawtransaction(rawtx1_txid, True)['confirmations'] > 0 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 # Create the block and the corresponding clsig but do not relay clsig yet
cl_block = self.create_block(self.nodes[0]) cl_block = self.create_block(self.nodes[0])

View File

@ -151,7 +151,7 @@ class RawTransactionsTest(BitcoinTestFramework):
rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx) rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx)
# This will raise an exception since there are missing inputs # 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 # # getrawtransaction with block hash #