mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-16 13:01:19 +02:00
Merge 3c40bc6726 into merged_master (Bitcoin PR #15921)
This commit is contained in:
commit
bde84fefc4
36 changed files with 470 additions and 440 deletions
|
|
@ -39,8 +39,8 @@ static void AssembleBlock(benchmark::State& state)
|
|||
LOCK(::cs_main); // Required for ::AcceptToMemoryPool.
|
||||
|
||||
for (const auto& txr : txs) {
|
||||
CValidationState state;
|
||||
bool ret{::AcceptToMemoryPool(::mempool, state, txr, nullptr /* pfMissingInputs */, nullptr /* plTxnReplaced */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
|
||||
TxValidationState state;
|
||||
bool ret{::AcceptToMemoryPool(::mempool, state, txr, nullptr /* plTxnReplaced */, false /* bypass_limits */, /* nAbsurdFee */ 0)};
|
||||
assert(ret);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ static void DeserializeAndCheckBlockTest(benchmark::State& state)
|
|||
bool rewound = stream.Rewind(benchmark::data::block413567.size());
|
||||
assert(rewound);
|
||||
|
||||
CValidationState validationState;
|
||||
BlockValidationState validationState;
|
||||
bool checked = CheckBlock(block, validationState, chainParams->GetConsensus());
|
||||
assert(checked);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ static void DuplicateInputs(benchmark::State& state)
|
|||
block.hashMerkleRoot = BlockMerkleRoot(block);
|
||||
|
||||
while (state.KeepRunning()) {
|
||||
CValidationState cvstate{};
|
||||
BlockValidationState cvstate{};
|
||||
assert(!CheckBlock(block, cvstate, chainparams.GetConsensus(), false, false));
|
||||
assert(cvstate.GetRejectReason() == "bad-txns-inputs-duplicate");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,13 +203,13 @@ ReadStatus PartiallyDownloadedBlock::FillBlock(CBlock& block, const std::vector<
|
|||
if (vtx_missing.size() != tx_missing_offset)
|
||||
return READ_STATUS_INVALID;
|
||||
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
if (!CheckBlock(block, state, Params().GetConsensus(), check_pow)) {
|
||||
// TODO: We really want to just check merkle tree manually here,
|
||||
// but that is expensive, and CheckBlock caches a block's
|
||||
// "checked-status" (in the CBlock?). CBlock should be able to
|
||||
// check its own merkle root and cache that check.
|
||||
if (state.GetReason() == ValidationInvalidReason::BLOCK_MUTATED)
|
||||
if (state.GetResult() == BlockValidationResult::BLOCK_MUTATED)
|
||||
return READ_STATUS_FAILED; // Possible Short ID collision
|
||||
return READ_STATUS_CHECKBLOCK_FAILED;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,32 +7,32 @@
|
|||
#include <primitives/transaction.h>
|
||||
#include <consensus/validation.h>
|
||||
|
||||
bool CheckTransaction(const CTransaction& tx, CValidationState& state)
|
||||
bool CheckTransaction(const CTransaction& tx, TxValidationState& state)
|
||||
{
|
||||
// Basic checks that don't depend on any context
|
||||
if (tx.vin.empty())
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vin-empty");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vin-empty");
|
||||
if (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 (this doesn't take the witness into account, as that hasn't been checked for malleability)
|
||||
if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-oversize");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-oversize");
|
||||
|
||||
// Check for negative or overflow output values (see CVE-2010-5139)
|
||||
CAmount nValueOutExplicit = 0;
|
||||
for (const auto& txout : tx.vout)
|
||||
{
|
||||
if (!txout.nValue.IsValid())
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-amount-invalid");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-amount-invalid");
|
||||
if (!txout.nValue.IsExplicit())
|
||||
continue;
|
||||
if (txout.nValue.GetAmount() < 0)
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-negative");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-negative");
|
||||
if (txout.nValue.GetAmount() > MAX_MONEY)
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-vout-toolarge");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-toolarge");
|
||||
nValueOutExplicit += txout.nValue.GetAmount();
|
||||
if (!MoneyRange(nValueOutExplicit))
|
||||
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)
|
||||
|
|
@ -43,17 +43,17 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
|
|||
std::set<COutPoint> vInOutPoints;
|
||||
for (const auto& txin : tx.vin) {
|
||||
if (!vInOutPoints.insert(txin.prevout).second)
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputs-duplicate");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputs-duplicate");
|
||||
}
|
||||
|
||||
if (tx.IsCoinBase())
|
||||
{
|
||||
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-length");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cb-length");
|
||||
|
||||
for (unsigned int i = 0; i < tx.vout.size(); i++) {
|
||||
if (tx.vout[i].IsFee()) {
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-fee");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cb-fee");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -61,7 +61,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState& state)
|
|||
{
|
||||
for (const auto& txin : tx.vin)
|
||||
if (txin.prevout.IsNull())
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-prevout-null");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-prevout-null");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
*/
|
||||
|
||||
class CTransaction;
|
||||
class CValidationState;
|
||||
class TxValidationState;
|
||||
|
||||
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
||||
bool CheckTransaction(const CTransaction& tx, TxValidationState& state);
|
||||
|
||||
#endif // BITCOIN_CONSENSUS_TX_CHECK_H
|
||||
|
|
|
|||
|
|
@ -183,11 +183,11 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
|
|||
return nSigOps;
|
||||
}
|
||||
|
||||
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<std::pair<CScript, CScript>>& fedpegscripts)
|
||||
bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<std::pair<CScript, CScript>>& fedpegscripts)
|
||||
{
|
||||
// are the actual inputs available?
|
||||
if (!inputs.HaveInputs(tx)) {
|
||||
return state.Invalid(ValidationInvalidReason::TX_MISSING_INPUTS, false, "bad-txns-inputs-missingorspent",
|
||||
return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent",
|
||||
strprintf("%s: inputs missing/spent", __func__));
|
||||
}
|
||||
|
||||
|
|
@ -199,14 +199,14 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
|
|||
// Check existence and validity of pegin witness
|
||||
std::string err;
|
||||
if (tx.witness.vtxinwit.size() <= i || !IsValidPeginWitness(tx.witness.vtxinwit[i].m_pegin_witness, fedpegscripts, prevout, err, true)) {
|
||||
return state.Invalid(ValidationInvalidReason::TX_WITNESS_MUTATED, false, "bad-pegin-witness", err);
|
||||
return state.Invalid(TxValidationResult::TX_WITNESS_MUTATED, "bad-pegin-witness", err);
|
||||
}
|
||||
std::pair<uint256, COutPoint> pegin = std::make_pair(uint256(tx.witness.vtxinwit[i].m_pegin_witness.stack[2]), prevout);
|
||||
if (inputs.IsPeginSpent(pegin)) {
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-double-pegin", strprintf("Double-pegin of %s:%d", prevout.hash.ToString(), prevout.n));
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-double-pegin", strprintf("Double-pegin of %s:%d", prevout.hash.ToString(), prevout.n));
|
||||
}
|
||||
if (setPeginsSpent.count(pegin)) {
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-double-pegin-in-obj",
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-double-pegin-in-obj",
|
||||
strprintf("Double-pegin of %s:%d in single tx/block", prevout.hash.ToString(), prevout.n));
|
||||
}
|
||||
setPeginsSpent.insert(pegin);
|
||||
|
|
@ -216,7 +216,7 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
|
|||
const CTxOut& out = spent_inputs.back();
|
||||
nValueIn += out.nValue.GetAmount(); // Non-explicit already filtered by IsValidPeginWitness
|
||||
if (!MoneyRange(out.nValue.GetAmount())) {
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputvalues-outofrange");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputvalues-outofrange");
|
||||
}
|
||||
} else {
|
||||
const Coin& coin = inputs.AccessCoin(prevout);
|
||||
|
|
@ -224,7 +224,7 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
|
|||
|
||||
// If prev is coinbase, check that it's matured
|
||||
if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < COINBASE_MATURITY) {
|
||||
return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, "bad-txns-premature-spend-of-coinbase",
|
||||
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-premature-spend-of-coinbase",
|
||||
strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
|
||||
}
|
||||
spent_inputs.push_back(coin.out);
|
||||
|
|
@ -237,25 +237,25 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, c
|
|||
if (g_con_elementsmode) {
|
||||
// Tally transaction fees
|
||||
if (!HasValidFee(tx)) {
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-fee-outofrange");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-fee-outofrange");
|
||||
}
|
||||
|
||||
// Verify that amounts add up.
|
||||
if (fScriptChecks && !VerifyAmounts(spent_inputs, tx, pvChecks, cacheStore)) {
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-in-ne-out", "value in != value out");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-in-ne-out", "value in != value out");
|
||||
}
|
||||
fee_map += GetFeeMap(tx);
|
||||
} else {
|
||||
const CAmount value_out = tx.GetValueOutMap()[CAsset()];
|
||||
if (nValueIn < value_out) {
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-in-belowout",
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-in-belowout",
|
||||
strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
|
||||
}
|
||||
|
||||
// Tally transaction fees
|
||||
const CAmount txfee_aux = nValueIn - value_out;
|
||||
if (!MoneyRange(txfee_aux)) {
|
||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-fee-outofrange");
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-fee-outofrange");
|
||||
}
|
||||
|
||||
fee_map[CAsset()] += txfee_aux;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
class CBlockIndex;
|
||||
class CCoinsViewCache;
|
||||
class CTransaction;
|
||||
class CValidationState;
|
||||
class TxValidationState;
|
||||
class COutPoint;
|
||||
|
||||
/** Transaction validation functions */
|
||||
|
|
@ -28,7 +28,7 @@ namespace Consensus {
|
|||
* @param[out] fee_map Set to the transaction fee if successful.
|
||||
* Preconditions: tx.IsCoinBase() is false.
|
||||
*/
|
||||
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<std::pair<CScript, CScript>>& fedpegscripts);
|
||||
bool CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<std::pair<CScript, CScript>>& fedpegscripts);
|
||||
} // namespace Consensus
|
||||
|
||||
/** Auxiliary functions for transaction validation (ideally should not be exposed) */
|
||||
|
|
|
|||
|
|
@ -12,13 +12,12 @@
|
|||
#include <primitives/transaction.h>
|
||||
#include <primitives/block.h>
|
||||
|
||||
/** A "reason" why something was invalid, suitable for determining whether the
|
||||
* provider of the object should be banned/ignored/disconnected/etc.
|
||||
/** A "reason" why a transaction was invalid, suitable for determining whether the
|
||||
* provider of the transaction should be banned/ignored/disconnected/etc.
|
||||
*/
|
||||
enum class ValidationInvalidReason {
|
||||
// txn and blocks:
|
||||
NONE, //!< not actually invalid
|
||||
CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
|
||||
enum class TxValidationResult {
|
||||
TX_RESULT_UNSET, //!< initial value. Tx has not yet been rejected
|
||||
TX_CONSENSUS, //!< invalid by consensus rules
|
||||
/**
|
||||
* Invalid by a change to consensus rules more recent than SegWit.
|
||||
* Currently unused as there are no such consensus rule changes, and any download
|
||||
|
|
@ -26,18 +25,9 @@ enum class ValidationInvalidReason {
|
|||
* so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
|
||||
* is uninteresting.
|
||||
*/
|
||||
RECENT_CONSENSUS_CHANGE,
|
||||
// Only blocks (or headers):
|
||||
CACHED_INVALID, //!< this object was cached as being invalid, but we don't know why
|
||||
BLOCK_INVALID_HEADER, //!< invalid proof of work or time too old
|
||||
BLOCK_MUTATED, //!< the block's data didn't match the data committed to by the PoW
|
||||
BLOCK_MISSING_PREV, //!< We don't have the previous block the checked one is built on
|
||||
BLOCK_INVALID_PREV, //!< A block this one builds on is invalid
|
||||
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
|
||||
// Only loose txn:
|
||||
TX_RECENT_CONSENSUS_CHANGE,
|
||||
TX_NOT_STANDARD, //!< didn't meet our local policy rules
|
||||
TX_MISSING_INPUTS, //!< a transaction was missing some of its inputs
|
||||
TX_MISSING_INPUTS, //!< transaction was missing some of its inputs
|
||||
TX_PREMATURE_SPEND, //!< transaction spends a coinbase too early, or violates locktime/sequence locks
|
||||
/**
|
||||
* Transaction might be missing a witness, have a witness prior to SegWit
|
||||
|
|
@ -48,82 +38,107 @@ enum class ValidationInvalidReason {
|
|||
/**
|
||||
* Tx already in mempool or conflicts with a tx in the chain
|
||||
* (if it conflicts with another tx in mempool, we use MEMPOOL_POLICY as it failed to reach the RBF threshold)
|
||||
* 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
|
||||
* Currently this is only used if the transaction already exists in the mempool or on chain.
|
||||
*/
|
||||
TX_CONFLICT,
|
||||
TX_MEMPOOL_POLICY, //!< violated mempool's fee/size/descendant/RBF/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_WITNESS_MUTATED ||
|
||||
r == ValidationInvalidReason::TX_CONFLICT ||
|
||||
r == ValidationInvalidReason::TX_MEMPOOL_POLICY;
|
||||
}
|
||||
/** A "reason" why a block was invalid, suitable for determining whether the
|
||||
* provider of the block should be banned/ignored/disconnected/etc.
|
||||
* These are much more granular than the rejection codes, which may be more
|
||||
* useful for some other use-cases.
|
||||
*/
|
||||
enum class BlockValidationResult {
|
||||
BLOCK_RESULT_UNSET, //!< initial value. Block has not yet been rejected
|
||||
BLOCK_CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
|
||||
/**
|
||||
* Invalid by a change to consensus rules more recent than SegWit.
|
||||
* Currently unused as there are no such consensus rule changes, and any download
|
||||
* sources realistically need to support SegWit in order to provide useful data,
|
||||
* so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
|
||||
* is uninteresting.
|
||||
*/
|
||||
BLOCK_RECENT_CONSENSUS_CHANGE,
|
||||
BLOCK_CACHED_INVALID, //!< this block was cached as being invalid and we didn't store the reason why
|
||||
BLOCK_INVALID_HEADER, //!< invalid proof of work or time too old
|
||||
BLOCK_MUTATED, //!< the block's data didn't match the data committed to by the PoW
|
||||
BLOCK_MISSING_PREV, //!< We don't have the previous block the checked one is built on
|
||||
BLOCK_INVALID_PREV, //!< A block this one builds on is invalid
|
||||
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
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/** Capture information about block/transaction validation */
|
||||
class CValidationState {
|
||||
|
||||
/** Base class for capturing information about block/transaction validation. This is subclassed
|
||||
* by TxValidationState and BlockValidationState for validation information on transactions
|
||||
* and blocks respectively. */
|
||||
class ValidationState {
|
||||
private:
|
||||
enum mode_state {
|
||||
MODE_VALID, //!< everything ok
|
||||
MODE_INVALID, //!< network rule violation (DoS value may be set)
|
||||
MODE_ERROR, //!< run-time error
|
||||
} mode;
|
||||
ValidationInvalidReason m_reason;
|
||||
std::string strRejectReason;
|
||||
std::string strDebugMessage;
|
||||
public:
|
||||
CValidationState() : mode(MODE_VALID), m_reason(ValidationInvalidReason::NONE) {}
|
||||
bool Invalid(ValidationInvalidReason reasonIn, bool ret = false,
|
||||
const std::string &strRejectReasonIn="",
|
||||
const std::string &strDebugMessageIn="") {
|
||||
m_reason = reasonIn;
|
||||
strRejectReason = strRejectReasonIn;
|
||||
strDebugMessage = strDebugMessageIn;
|
||||
if (mode == MODE_ERROR)
|
||||
return ret;
|
||||
mode = MODE_INVALID;
|
||||
return ret;
|
||||
} m_mode;
|
||||
std::string m_reject_reason;
|
||||
std::string m_debug_message;
|
||||
protected:
|
||||
void Invalid(const std::string &reject_reason="",
|
||||
const std::string &debug_message="")
|
||||
{
|
||||
m_reject_reason = reject_reason;
|
||||
m_debug_message = debug_message;
|
||||
if (m_mode != MODE_ERROR) m_mode = MODE_INVALID;
|
||||
}
|
||||
bool Error(const std::string& strRejectReasonIn) {
|
||||
if (mode == MODE_VALID)
|
||||
strRejectReason = strRejectReasonIn;
|
||||
mode = MODE_ERROR;
|
||||
public:
|
||||
// ValidationState is abstract. Have a pure virtual destructor.
|
||||
virtual ~ValidationState() = 0;
|
||||
|
||||
ValidationState() : m_mode(MODE_VALID) {}
|
||||
bool Error(const std::string& reject_reason)
|
||||
{
|
||||
if (m_mode == MODE_VALID)
|
||||
m_reject_reason = reject_reason;
|
||||
m_mode = MODE_ERROR;
|
||||
return false;
|
||||
}
|
||||
bool IsValid() const {
|
||||
return mode == MODE_VALID;
|
||||
bool IsValid() const { return m_mode == MODE_VALID; }
|
||||
bool IsInvalid() const { return m_mode == MODE_INVALID; }
|
||||
bool IsError() const { return m_mode == MODE_ERROR; }
|
||||
std::string GetRejectReason() const { return m_reject_reason; }
|
||||
std::string GetDebugMessage() const { return m_debug_message; }
|
||||
};
|
||||
|
||||
inline ValidationState::~ValidationState() {};
|
||||
|
||||
class TxValidationState : public ValidationState {
|
||||
private:
|
||||
TxValidationResult m_result;
|
||||
public:
|
||||
bool Invalid(TxValidationResult result,
|
||||
const std::string &reject_reason="",
|
||||
const std::string &debug_message="")
|
||||
{
|
||||
m_result = result;
|
||||
ValidationState::Invalid(reject_reason, debug_message);
|
||||
return false;
|
||||
}
|
||||
bool IsInvalid() const {
|
||||
return mode == MODE_INVALID;
|
||||
TxValidationResult GetResult() const { return m_result; }
|
||||
};
|
||||
|
||||
class BlockValidationState : public ValidationState {
|
||||
private:
|
||||
BlockValidationResult m_result;
|
||||
public:
|
||||
bool Invalid(BlockValidationResult result,
|
||||
const std::string &reject_reason="",
|
||||
const std::string &debug_message="") {
|
||||
m_result = result;
|
||||
ValidationState::Invalid(reject_reason, debug_message);
|
||||
return false;
|
||||
}
|
||||
bool IsError() const {
|
||||
return mode == MODE_ERROR;
|
||||
}
|
||||
ValidationInvalidReason GetReason() const { return m_reason; }
|
||||
std::string GetRejectReason() const { return strRejectReason; }
|
||||
std::string GetDebugMessage() const { return strDebugMessage; }
|
||||
BlockValidationResult GetResult() const { return m_result; }
|
||||
};
|
||||
|
||||
// These implement the weight = (stripped_size * 4) + witness_size formula,
|
||||
|
|
|
|||
|
|
@ -757,7 +757,7 @@ static void ThreadImport(std::vector<fs::path> vImportFiles)
|
|||
}
|
||||
|
||||
// scan for better chains in the block chain database, that are not yet connected in the active best chain
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
if (!ActivateBestChain(state, chainparams)) {
|
||||
LogPrintf("Failed to connect best block (%s)\n", FormatStateMessage(state));
|
||||
StartShutdown();
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ class CBlock;
|
|||
class CFeeRate;
|
||||
class CRPCCommand;
|
||||
class CScheduler;
|
||||
class CValidationState;
|
||||
class Coin;
|
||||
class uint256;
|
||||
enum class RBFTransactionState;
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock(const CScript& sc
|
|||
pblock->nNonce = 0;
|
||||
pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]);
|
||||
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
if (!TestBlockValidity(state, chainparams, *pblock, pindexPrev, false, false)) {
|
||||
throw std::runtime_error(strprintf("%s: TestBlockValidity failed: %s", __func__, FormatStateMessage(state)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -982,14 +982,12 @@ void Misbehaving(NodeId pnode, int howmuch, const std::string& message) EXCLUSIV
|
|||
* banning/disconnecting us. We use this to determine which unaccepted
|
||||
* transactions from a whitelisted peer that we can safely relay.
|
||||
*/
|
||||
static bool TxRelayMayResultInDisconnect(const CValidationState& state)
|
||||
{
|
||||
assert(IsTransactionReason(state.GetReason()));
|
||||
return state.GetReason() == ValidationInvalidReason::CONSENSUS;
|
||||
static bool TxRelayMayResultInDisconnect(const TxValidationState& state) {
|
||||
return state.GetResult() == TxValidationResult::TX_CONSENSUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Potentially ban a node based on the contents of a CValidationState object
|
||||
* Potentially ban a node based on the contents of a BlockValidationState object
|
||||
*
|
||||
* @param[in] via_compact_block: this bool is passed in because net_processing should
|
||||
* punish peers differently depending on whether the data was provided in a compact
|
||||
|
|
@ -997,23 +995,21 @@ static bool TxRelayMayResultInDisconnect(const CValidationState& state)
|
|||
* txs, the peer should not be punished. See BIP 152.
|
||||
*
|
||||
* @return Returns true if the peer was punished (probably disconnected)
|
||||
*
|
||||
* Changes here may need to be reflected in TxRelayMayResultInDisconnect().
|
||||
*/
|
||||
static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool via_compact_block, const std::string& message = "") {
|
||||
switch (state.GetReason()) {
|
||||
case ValidationInvalidReason::NONE:
|
||||
static bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, bool via_compact_block, const std::string& message = "") {
|
||||
switch (state.GetResult()) {
|
||||
case BlockValidationResult::BLOCK_RESULT_UNSET:
|
||||
break;
|
||||
// The node is providing invalid data:
|
||||
case ValidationInvalidReason::CONSENSUS:
|
||||
case ValidationInvalidReason::BLOCK_MUTATED:
|
||||
case BlockValidationResult::BLOCK_CONSENSUS:
|
||||
case BlockValidationResult::BLOCK_MUTATED:
|
||||
if (!via_compact_block) {
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeid, 100, message);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case ValidationInvalidReason::CACHED_INVALID:
|
||||
case BlockValidationResult::BLOCK_CACHED_INVALID:
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CNodeState *node_state = State(nodeid);
|
||||
|
|
@ -1029,30 +1025,24 @@ static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool v
|
|||
}
|
||||
break;
|
||||
}
|
||||
case ValidationInvalidReason::BLOCK_INVALID_HEADER:
|
||||
case ValidationInvalidReason::BLOCK_CHECKPOINT:
|
||||
case ValidationInvalidReason::BLOCK_INVALID_PREV:
|
||||
case BlockValidationResult::BLOCK_INVALID_HEADER:
|
||||
case BlockValidationResult::BLOCK_CHECKPOINT:
|
||||
case BlockValidationResult::BLOCK_INVALID_PREV:
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeid, 100, message);
|
||||
}
|
||||
return true;
|
||||
// Conflicting (but not necessarily invalid) data or different policy:
|
||||
case ValidationInvalidReason::BLOCK_MISSING_PREV:
|
||||
case BlockValidationResult::BLOCK_MISSING_PREV:
|
||||
{
|
||||
// TODO: Handle this much more gracefully (10 DoS points is super arbitrary)
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeid, 10, message);
|
||||
}
|
||||
return true;
|
||||
case ValidationInvalidReason::RECENT_CONSENSUS_CHANGE:
|
||||
case ValidationInvalidReason::BLOCK_TIME_FUTURE:
|
||||
case ValidationInvalidReason::TX_NOT_STANDARD:
|
||||
case ValidationInvalidReason::TX_MISSING_INPUTS:
|
||||
case ValidationInvalidReason::TX_PREMATURE_SPEND:
|
||||
case ValidationInvalidReason::TX_WITNESS_MUTATED:
|
||||
case ValidationInvalidReason::TX_CONFLICT:
|
||||
case ValidationInvalidReason::TX_MEMPOOL_POLICY:
|
||||
case BlockValidationResult::BLOCK_RECENT_CONSENSUS_CHANGE:
|
||||
case BlockValidationResult::BLOCK_TIME_FUTURE:
|
||||
break;
|
||||
}
|
||||
if (message != "") {
|
||||
|
|
@ -1061,6 +1051,39 @@ static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool v
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Potentially ban a node based on the contents of a TxValidationState object
|
||||
*
|
||||
* @return Returns true if the peer was punished (probably disconnected)
|
||||
*
|
||||
* Changes here may need to be reflected in TxRelayMayResultInDisconnect().
|
||||
*/
|
||||
static bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = "") {
|
||||
switch (state.GetResult()) {
|
||||
case TxValidationResult::TX_RESULT_UNSET:
|
||||
break;
|
||||
// The node is providing invalid data:
|
||||
case TxValidationResult::TX_CONSENSUS:
|
||||
{
|
||||
LOCK(cs_main);
|
||||
Misbehaving(nodeid, 100, message);
|
||||
return true;
|
||||
}
|
||||
// Conflicting (but not necessarily invalid) data or different policy:
|
||||
case TxValidationResult::TX_RECENT_CONSENSUS_CHANGE:
|
||||
case TxValidationResult::TX_NOT_STANDARD:
|
||||
case TxValidationResult::TX_MISSING_INPUTS:
|
||||
case TxValidationResult::TX_PREMATURE_SPEND:
|
||||
case TxValidationResult::TX_WITNESS_MUTATED:
|
||||
case TxValidationResult::TX_CONFLICT:
|
||||
case TxValidationResult::TX_MEMPOOL_POLICY:
|
||||
break;
|
||||
}
|
||||
if (message != "") {
|
||||
LogPrint(BCLog::NET, "peer=%d: %s\n", nodeid, message);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1229,7 +1252,7 @@ void PeerLogicValidation::UpdatedBlockTip(const CBlockIndex *pindexNew, const CB
|
|||
* Handle invalid block rejection and consequent peer banning, maintain which
|
||||
* peers announce compact blocks.
|
||||
*/
|
||||
void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationState& state) {
|
||||
void PeerLogicValidation::BlockChecked(const CBlock& block, const BlockValidationState& state) {
|
||||
LOCK(cs_main);
|
||||
|
||||
const uint256 hash(block.GetHash());
|
||||
|
|
@ -1240,7 +1263,7 @@ void PeerLogicValidation::BlockChecked(const CBlock& block, const CValidationSta
|
|||
if (state.IsInvalid() &&
|
||||
it != mapBlockSource.end() &&
|
||||
State(it->second.first)) {
|
||||
MaybePunishNode(/*nodeid=*/ it->second.first, state, /*via_compact_block=*/ !it->second.second);
|
||||
MaybePunishNodeForBlock(/*nodeid=*/ it->second.first, state, /*via_compact_block=*/ !it->second.second);
|
||||
}
|
||||
// Check that:
|
||||
// 1. The block is valid
|
||||
|
|
@ -1378,7 +1401,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
|
|||
}
|
||||
} // release cs_main before calling ActivateBestChain
|
||||
if (need_activate_chain) {
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
if (!ActivateBestChain(state, Params(), a_recent_block)) {
|
||||
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state));
|
||||
}
|
||||
|
|
@ -1674,11 +1697,10 @@ bool static ProcessHeadersMessage(CNode *pfrom, CConnman *connman, const std::ve
|
|||
}
|
||||
}
|
||||
|
||||
CValidationState state;
|
||||
CBlockHeader first_invalid_header;
|
||||
if (!ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast, &first_invalid_header)) {
|
||||
BlockValidationState state;
|
||||
if (!ProcessNewBlockHeaders(headers, state, chainparams, &pindexLast)) {
|
||||
if (state.IsInvalid()) {
|
||||
MaybePunishNode(pfrom->GetId(), state, via_compact_block, "invalid header received");
|
||||
MaybePunishNodeForBlock(pfrom->GetId(), state, via_compact_block, "invalid header received");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1814,14 +1836,13 @@ void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_se
|
|||
const CTransactionRef porphanTx = orphan_it->second.tx;
|
||||
const CTransaction& orphanTx = *porphanTx;
|
||||
NodeId fromPeer = orphan_it->second.fromPeer;
|
||||
bool fMissingInputs2 = false;
|
||||
// Use a new CValidationState because orphans come from different peers (and we call
|
||||
// MaybePunishNode based on the source peer from the orphan map, not based on the peer
|
||||
// Use a new TxValidationState because orphans come from different peers (and we call
|
||||
// MaybePunishNodeForTx based on the source peer from the orphan map, not based on the peer
|
||||
// that relayed the previous transaction).
|
||||
CValidationState orphan_state;
|
||||
TxValidationState orphan_state;
|
||||
|
||||
if (setMisbehaving.count(fromPeer)) continue;
|
||||
if (AcceptToMemoryPool(mempool, orphan_state, porphanTx, &fMissingInputs2, &removed_txn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
|
||||
if (AcceptToMemoryPool(mempool, orphan_state, porphanTx, &removed_txn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
|
||||
LogPrint(BCLog::MEMPOOL, " accepted orphan tx %s\n", orphanHash.ToString());
|
||||
RelayTransaction(orphanHash, *connman);
|
||||
for (unsigned int i = 0; i < orphanTx.vout.size(); i++) {
|
||||
|
|
@ -1834,10 +1855,10 @@ void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_se
|
|||
}
|
||||
EraseOrphanTx(orphanHash);
|
||||
done = true;
|
||||
} else if (!fMissingInputs2) {
|
||||
} else if (orphan_state.GetResult() != TxValidationResult::TX_MISSING_INPUTS) {
|
||||
if (orphan_state.IsInvalid()) {
|
||||
// Punish peer that gave us an invalid orphan tx
|
||||
if (MaybePunishNode(fromPeer, orphan_state, /*via_compact_block*/ false)) {
|
||||
if (MaybePunishNodeForTx(fromPeer, orphan_state)) {
|
||||
setMisbehaving.insert(fromPeer);
|
||||
}
|
||||
LogPrint(BCLog::MEMPOOL, " invalid orphan tx %s\n", orphanHash.ToString());
|
||||
|
|
@ -1845,8 +1866,7 @@ void static ProcessOrphanTx(CConnman* connman, std::set<uint256>& orphan_work_se
|
|||
// Has inputs but not accepted to mempool
|
||||
// Probably non-standard or insufficient fee
|
||||
LogPrint(BCLog::MEMPOOL, " removed orphan tx %s\n", orphanHash.ToString());
|
||||
assert(IsTransactionReason(orphan_state.GetReason()));
|
||||
if (!orphanTx.HasWitness() && orphan_state.GetReason() != ValidationInvalidReason::TX_WITNESS_MUTATED) {
|
||||
if (!orphanTx.HasWitness() && orphan_state.GetResult() != TxValidationResult::TX_WITNESS_MUTATED) {
|
||||
// Do not use rejection cache for witness transactions or
|
||||
// witness-stripped transactions, as they can have been malleated.
|
||||
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
|
||||
|
|
@ -2291,7 +2311,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
LOCK(cs_most_recent_block);
|
||||
a_recent_block = most_recent_block;
|
||||
}
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
if (!ActivateBestChain(state, Params(), a_recent_block)) {
|
||||
LogPrint(BCLog::NET, "failed to activate chain (%s)\n", FormatStateMessage(state));
|
||||
}
|
||||
|
|
@ -2471,8 +2491,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
|
||||
LOCK2(cs_main, g_cs_orphans);
|
||||
|
||||
bool fMissingInputs = false;
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
|
||||
CNodeState* nodestate = State(pfrom->GetId());
|
||||
nodestate->m_tx_download.m_tx_announced.erase(inv.hash);
|
||||
|
|
@ -2482,7 +2501,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
std::list<CTransactionRef> lRemovedTxn;
|
||||
|
||||
if (!AlreadyHave(inv) &&
|
||||
AcceptToMemoryPool(mempool, state, ptx, &fMissingInputs, &lRemovedTxn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
|
||||
AcceptToMemoryPool(mempool, state, ptx, &lRemovedTxn, false /* bypass_limits */, 0 /* nAbsurdFee */)) {
|
||||
mempool.check(&::ChainstateActive().CoinsTip());
|
||||
RelayTransaction(tx.GetHash(), *connman);
|
||||
for (unsigned int i = 0; i < tx.vout.size(); i++) {
|
||||
|
|
@ -2504,7 +2523,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
// Recursively process any orphan transactions that depended on this one
|
||||
ProcessOrphanTx(connman, pfrom->orphan_work_set, lRemovedTxn);
|
||||
}
|
||||
else if (fMissingInputs)
|
||||
else if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS)
|
||||
{
|
||||
bool fRejectedParents = false; // It may be the case that the orphans parents have all been rejected
|
||||
for (const CTxIn& txin : tx.vin) {
|
||||
|
|
@ -2537,8 +2556,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
recentRejects->insert(tx.GetHash());
|
||||
}
|
||||
} else {
|
||||
assert(IsTransactionReason(state.GetReason()));
|
||||
if (!tx.HasWitness() && state.GetReason() != ValidationInvalidReason::TX_WITNESS_MUTATED) {
|
||||
if (!tx.HasWitness() && state.GetResult() != TxValidationResult::TX_WITNESS_MUTATED) {
|
||||
// Do not use rejection cache for witness transactions or
|
||||
// witness-stripped transactions, as they can have been malleated.
|
||||
// See https://github.com/bitcoin/bitcoin/issues/8279 for details.
|
||||
|
|
@ -2593,7 +2611,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
LogPrint(BCLog::MEMPOOLREJ, "%s from peer=%d was not accepted: %s\n", tx.GetHash().ToString(),
|
||||
pfrom->GetId(),
|
||||
FormatStateMessage(state));
|
||||
MaybePunishNode(pfrom->GetId(), state, /*via_compact_block*/ false);
|
||||
MaybePunishNodeForTx(pfrom->GetId(), state);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2627,10 +2645,10 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
|||
}
|
||||
|
||||
const CBlockIndex *pindex = nullptr;
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
if (!ProcessNewBlockHeaders({cmpctblock.header}, state, chainparams, &pindex)) {
|
||||
if (state.IsInvalid()) {
|
||||
MaybePunishNode(pfrom->GetId(), state, /*via_compact_block*/ true, "invalid header via cmpctblock");
|
||||
MaybePunishNodeForBlock(pfrom->GetId(), state, /*via_compact_block*/ true, "invalid header via cmpctblock");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public:
|
|||
/**
|
||||
* Overridden from CValidationInterface.
|
||||
*/
|
||||
void BlockChecked(const CBlock& block, const CValidationState& state) override;
|
||||
void BlockChecked(const CBlock& block, const BlockValidationState& state) override;
|
||||
/**
|
||||
* Overridden from CValidationInterface.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -37,18 +37,16 @@ TransactionError BroadcastTransaction(NodeContext& node, const CTransactionRef t
|
|||
}
|
||||
if (!mempool.exists(hashTx)) {
|
||||
// Transaction is not already in the mempool. Submit it.
|
||||
CValidationState state;
|
||||
bool fMissingInputs;
|
||||
if (!AcceptToMemoryPool(mempool, state, std::move(tx), &fMissingInputs,
|
||||
TxValidationState state;
|
||||
if (!AcceptToMemoryPool(mempool, state, std::move(tx),
|
||||
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_tx_fee)) {
|
||||
err_string = FormatStateMessage(state);
|
||||
if (state.IsInvalid()) {
|
||||
err_string = FormatStateMessage(state);
|
||||
return TransactionError::MEMPOOL_REJECTED;
|
||||
} else {
|
||||
if (fMissingInputs) {
|
||||
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
|
||||
return TransactionError::MISSING_INPUTS;
|
||||
}
|
||||
err_string = FormatStateMessage(state);
|
||||
return TransactionError::MEMPOOL_REJECTED;
|
||||
} else {
|
||||
return TransactionError::MEMPOOL_ERROR;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1608,7 +1608,7 @@ static UniValue preciousblock(const JSONRPCRequest& request)
|
|||
}
|
||||
}
|
||||
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
PreciousBlock(state, Params(), pblockindex);
|
||||
|
||||
if (!state.IsValid()) {
|
||||
|
|
@ -1633,7 +1633,7 @@ static UniValue invalidateblock(const JSONRPCRequest& request)
|
|||
}.Check(request);
|
||||
|
||||
uint256 hash(ParseHashV(request.params[0], "blockhash"));
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
|
||||
CBlockIndex* pblockindex;
|
||||
{
|
||||
|
|
@ -1683,7 +1683,7 @@ static UniValue reconsiderblock(const JSONRPCRequest& request)
|
|||
ResetBlockFailureFlags(pblockindex);
|
||||
}
|
||||
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
ActivateBestChain(state, Params());
|
||||
|
||||
if (!state.IsValid()) {
|
||||
|
|
|
|||
|
|
@ -319,7 +319,7 @@ static UniValue prioritisetransaction(const JSONRPCRequest& request)
|
|||
|
||||
|
||||
// NOTE: Assumes a conclusive result; if result is inconclusive, it must be handled by caller
|
||||
static UniValue BIP22ValidationResult(const CValidationState& state)
|
||||
static UniValue BIP22ValidationResult(const BlockValidationState& state)
|
||||
{
|
||||
if (state.IsValid())
|
||||
return NullUniValue;
|
||||
|
|
@ -468,7 +468,7 @@ static UniValue getblocktemplate(const JSONRPCRequest& request)
|
|||
// TestBlockValidity only supports blocks built on the current Tip
|
||||
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
|
||||
return "inconclusive-not-best-prevblk";
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
TestBlockValidity(state, Params(), block, pindexPrev, false, true);
|
||||
return BIP22ValidationResult(state);
|
||||
}
|
||||
|
|
@ -735,12 +735,12 @@ class submitblock_StateCatcher : public CValidationInterface
|
|||
public:
|
||||
uint256 hash;
|
||||
bool found;
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
|
||||
explicit submitblock_StateCatcher(const uint256 &hashIn) : hash(hashIn), found(false), state() {}
|
||||
|
||||
protected:
|
||||
void BlockChecked(const CBlock& block, const CValidationState& stateIn) override {
|
||||
void BlockChecked(const CBlock& block, const BlockValidationState& stateIn) override {
|
||||
if (block.GetHash() != hash)
|
||||
return;
|
||||
found = true;
|
||||
|
|
@ -839,8 +839,8 @@ static UniValue submitheader(const JSONRPCRequest& request)
|
|||
}
|
||||
}
|
||||
|
||||
CValidationState state;
|
||||
ProcessNewBlockHeaders({h}, state, Params(), /* ppindex */ nullptr, /* first_invalid */ nullptr);
|
||||
BlockValidationState state;
|
||||
ProcessNewBlockHeaders({h}, state, Params());
|
||||
if (state.IsValid()) return NullUniValue;
|
||||
if (state.IsError()) {
|
||||
throw JSONRPCError(RPC_VERIFY_ERROR, FormatStateMessage(state));
|
||||
|
|
@ -1467,7 +1467,7 @@ UniValue testproposedblock(const JSONRPCRequest& request)
|
|||
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
|
||||
throw JSONRPCError(RPC_VERIFY_ERROR, "proposal was not based on our best chain");
|
||||
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
if (!TestBlockValidity(state, Params(), block, pindexPrev, false, true) || !state.IsValid()) {
|
||||
std::string strRejectReason = state.GetRejectReason();
|
||||
if (strRejectReason.empty())
|
||||
|
|
|
|||
|
|
@ -945,20 +945,21 @@ static UniValue testmempoolaccept(const JSONRPCRequest& request)
|
|||
UniValue result_0(UniValue::VOBJ);
|
||||
result_0.pushKV("txid", tx_hash.GetHex());
|
||||
|
||||
CValidationState state;
|
||||
bool missing_inputs;
|
||||
TxValidationState state;
|
||||
bool test_accept_res;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx), &missing_inputs,
|
||||
test_accept_res = AcceptToMemoryPool(mempool, state, std::move(tx),
|
||||
nullptr /* plTxnReplaced */, false /* bypass_limits */, max_raw_tx_fee, /* test_accept */ true);
|
||||
}
|
||||
result_0.pushKV("allowed", test_accept_res);
|
||||
if (!test_accept_res) {
|
||||
if (state.IsInvalid()) {
|
||||
result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
|
||||
} else if (missing_inputs) {
|
||||
result_0.pushKV("reject-reason", "missing-inputs");
|
||||
if (state.GetResult() == TxValidationResult::TX_MISSING_INPUTS) {
|
||||
result_0.pushKV("reject-reason", "missing-inputs");
|
||||
} else {
|
||||
result_0.pushKV("reject-reason", strprintf("%s", state.GetRejectReason()));
|
||||
}
|
||||
} else {
|
||||
result_0.pushKV("reject-reason", state.GetRejectReason());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,8 +102,8 @@ static bool BuildChain(const CBlockIndex* pindex, const CScript& coinbase_script
|
|||
block = std::make_shared<CBlock>(CreateBlock(pindex, no_txns, coinbase_script_pub_key));
|
||||
CBlockHeader header = block->GetBlockHeader();
|
||||
|
||||
CValidationState state;
|
||||
if (!ProcessNewBlockHeaders({header}, state, Params(), &pindex, nullptr)) {
|
||||
BlockValidationState state;
|
||||
if (!ProcessNewBlockHeaders({header}, state, Params(), &pindex)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
|
|||
return;
|
||||
}
|
||||
|
||||
CValidationState state_with_dupe_check;
|
||||
TxValidationState state_with_dupe_check;
|
||||
(void)CheckTransaction(tx, state_with_dupe_check);
|
||||
|
||||
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ BOOST_AUTO_TEST_CASE(witness_valid)
|
|||
CAmountMap fee_map;
|
||||
|
||||
std::set<std::pair<uint256, COutPoint> > setPeginsSpent;
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
CCoinsView coinsDummy;
|
||||
CCoinsViewCache coins(&coinsDummy);
|
||||
// Get the latest block index to look up fedpegscripts
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::string& fedp
|
|||
throw std::runtime_error("LoadGenesisBlock failed.");
|
||||
}
|
||||
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
if (!ActivateBestChain(state, chainparams)) {
|
||||
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", FormatStateMessage(state)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
|
|||
CDataStream stream(ParseHex(raw_tx), SER_NETWORK, PROTOCOL_VERSION);
|
||||
stream >> tx;
|
||||
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
BOOST_CHECK_MESSAGE(CheckTransaction(*tx, state), strTest);
|
||||
BOOST_CHECK(state.IsValid());
|
||||
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
|||
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransaction tx(deserialize, stream);
|
||||
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
|
||||
BOOST_CHECK(state.IsValid());
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
|||
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION );
|
||||
CTransaction tx(deserialize, stream);
|
||||
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
fValid = CheckTransaction(tx, state) && state.IsValid();
|
||||
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
|
|
@ -274,7 +274,7 @@ BOOST_AUTO_TEST_CASE(basic_transaction_tests)
|
|||
CDataStream stream(vch, SER_DISK, CLIENT_VERSION);
|
||||
CMutableTransaction tx;
|
||||
stream >> tx;
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
BOOST_CHECK_MESSAGE(CheckTransaction(CTransaction(tx), state) && state.IsValid(), "Simple deserialized transaction should be valid.");
|
||||
|
||||
// Check that duplicate txins fail
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
|
|||
|
||||
BOOST_CHECK(CTransaction(coinbaseTx).IsCoinBase());
|
||||
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
|
||||
LOCK(cs_main);
|
||||
|
||||
|
|
@ -39,7 +39,6 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
|
|||
BOOST_CHECK_EQUAL(
|
||||
false,
|
||||
AcceptToMemoryPool(mempool, state, MakeTransactionRef(coinbaseTx),
|
||||
nullptr /* pfMissingInputs */,
|
||||
nullptr /* plTxnReplaced */,
|
||||
true /* bypass_limits */,
|
||||
0 /* nAbsurdFee */));
|
||||
|
|
@ -50,7 +49,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_reject_coinbase, TestChain100Setup)
|
|||
// Check that the validation state reflects the unsuccessful attempt.
|
||||
BOOST_CHECK(state.IsInvalid());
|
||||
BOOST_CHECK_EQUAL(state.GetRejectReason(), "coinbase");
|
||||
BOOST_CHECK(state.GetReason() == ValidationInvalidReason::CONSENSUS);
|
||||
BOOST_CHECK(state.GetResult() == TxValidationResult::TX_CONSENSUS);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CCheck*> *pvChecks);
|
||||
bool CheckInputs(const CTransaction& tx, TxValidationState &state, const CCoinsViewCache &inputs, unsigned int flags, bool cacheSigStore, bool cacheFullScriptStore, PrecomputedTransactionData& txdata, std::vector<CCheck*> *pvChecks);
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(tx_validationcache_tests)
|
||||
|
||||
|
|
@ -23,8 +23,8 @@ ToMemPool(const CMutableTransaction& tx)
|
|||
{
|
||||
LOCK(cs_main);
|
||||
|
||||
CValidationState state;
|
||||
return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx), nullptr /* pfMissingInputs */,
|
||||
TxValidationState state;
|
||||
return AcceptToMemoryPool(mempool, state, MakeTransactionRef(tx),
|
||||
nullptr /* plTxnReplaced */, true /* bypass_limits */, 0 /* nAbsurdFee */);
|
||||
}
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ static void ValidateCheckInputsForAllFlags(const CTransaction &tx, uint32_t fail
|
|||
// If we add many more flags, this loop can get too expensive, but we can
|
||||
// rewrite in the future to randomly pick a set of flags to evaluate.
|
||||
for (uint32_t test_flags=0; test_flags < (1U << 16); test_flags += 1) {
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
// Filter out incompatible flag choices
|
||||
if ((test_flags & SCRIPT_VERIFY_CLEANSTACK)) {
|
||||
// CLEANSTACK requires P2SH and WITNESS, see VerifyScript() in
|
||||
|
|
@ -202,7 +202,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
|||
{
|
||||
LOCK(cs_main);
|
||||
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
PrecomputedTransactionData ptd_spend_tx(spend_tx);
|
||||
|
||||
BOOST_CHECK(!CheckInputs(CTransaction(spend_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_DERSIG, true, true, ptd_spend_tx, nullptr));
|
||||
|
|
@ -271,7 +271,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
|||
|
||||
// Make it valid, and check again
|
||||
invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
PrecomputedTransactionData txdata(invalid_with_cltv_tx);
|
||||
BOOST_CHECK(CheckInputs(CTransaction(invalid_with_cltv_tx), state, ::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY, true, true, txdata, nullptr));
|
||||
}
|
||||
|
|
@ -299,7 +299,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
|||
|
||||
// Make it valid, and check again
|
||||
invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 100;
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
PrecomputedTransactionData txdata(invalid_with_csv_tx);
|
||||
BOOST_CHECK(CheckInputs(CTransaction(invalid_with_csv_tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_CHECKSEQUENCEVERIFY, true, true, txdata, nullptr));
|
||||
}
|
||||
|
|
@ -362,7 +362,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup)
|
|||
// Invalidate vin[1]
|
||||
tx.witness.vtxinwit[1].scriptWitness.SetNull();
|
||||
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
// This transaction is now invalid under segwit, because of the second input.
|
||||
BOOST_CHECK(!CheckInputs(CTransaction(tx), state, &::ChainstateActive().CoinsTip(), SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, true, true, txdata, nullptr));
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(processnewblock_signals_ordering)
|
|||
}
|
||||
|
||||
bool ignored;
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
std::vector<CBlockHeader> headers;
|
||||
std::transform(blocks.begin(), blocks.end(), std::back_inserter(headers), [](std::shared_ptr<const CBlock> b) { return b->GetBlockHeader(); });
|
||||
|
||||
|
|
@ -281,14 +281,13 @@ BOOST_AUTO_TEST_CASE(mempool_locks_reorg)
|
|||
// Add the txs to the tx pool
|
||||
{
|
||||
LOCK(cs_main);
|
||||
CValidationState state;
|
||||
TxValidationState state;
|
||||
std::list<CTransactionRef> plTxnReplaced;
|
||||
for (const auto& tx : txs) {
|
||||
BOOST_REQUIRE(AcceptToMemoryPool(
|
||||
::mempool,
|
||||
state,
|
||||
tx,
|
||||
/* pfMissingInputs */ &ignored,
|
||||
&plTxnReplaced,
|
||||
/* bypass_limits */ false,
|
||||
/* nAbsurdFee */ 0));
|
||||
|
|
|
|||
|
|
@ -648,11 +648,11 @@ void CTxMemPool::clear()
|
|||
static void CheckInputsAndUpdateCoins(const CTxMemPoolEntry& entry, CCoinsViewCache& mempoolDuplicate, const int64_t spendheight, std::set<std::pair<uint256, COutPoint>>& setGlobalPeginsSpent)
|
||||
{
|
||||
CTransaction tx = entry.GetTx();
|
||||
CValidationState state;
|
||||
TxValidationState dummy_state; // Not used. CheckTxInputs() should always pass
|
||||
CAmountMap fee_map;
|
||||
std::set<std::pair<uint256, COutPoint> > setPeginsSpent;
|
||||
const auto& fedpegscripts = GetValidFedpegScripts(::ChainActive().Tip(), Params().GetConsensus(), true /* nextblock_validation */);
|
||||
bool fCheckResult = tx.IsCoinBase() || Consensus::CheckTxInputs(tx, state, mempoolDuplicate, spendheight, fee_map, setPeginsSpent, NULL, false, true, fedpegscripts);
|
||||
bool fCheckResult = tx.IsCoinBase() || Consensus::CheckTxInputs(tx, dummy_state, mempoolDuplicate, spendheight, fee_map, setPeginsSpent, NULL, false, true, fedpegscripts);
|
||||
assert(fCheckResult);
|
||||
UpdateCoins(tx, mempoolDuplicate, std::numeric_limits<int>::max());
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
#include <consensus/validation.h>
|
||||
#include <tinyformat.h>
|
||||
|
||||
/** Convert CValidationState to a human-readable message for logging */
|
||||
std::string FormatStateMessage(const CValidationState &state)
|
||||
/** Convert ValidationState to a human-readable message for logging */
|
||||
std::string FormatStateMessage(const ValidationState &state)
|
||||
{
|
||||
return strprintf("%s%s",
|
||||
state.GetRejectReason(),
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
class CValidationState;
|
||||
class ValidationState;
|
||||
|
||||
/** Convert CValidationState to a human-readable message for logging */
|
||||
std::string FormatStateMessage(const CValidationState &state);
|
||||
/** Convert ValidationState to a human-readable message for logging */
|
||||
std::string FormatStateMessage(const ValidationState &state);
|
||||
|
||||
extern const std::string strMessageMagic;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -37,6 +37,7 @@
|
|||
#include <primitives/pak.h> // CPAKList
|
||||
|
||||
class CChainState;
|
||||
class BlockValidationState;
|
||||
class CBlockIndex;
|
||||
class CBlockTreeDB;
|
||||
class CBlockUndo;
|
||||
|
|
@ -46,7 +47,7 @@ class CConnman;
|
|||
class CScriptCheck;
|
||||
class CBlockPolicyEstimator;
|
||||
class CTxMemPool;
|
||||
class CValidationState;
|
||||
class TxValidationState;
|
||||
struct ChainTxData;
|
||||
|
||||
struct DisconnectedBlockTransactions;
|
||||
|
|
@ -233,9 +234,8 @@ bool ProcessNewBlock(const CChainParams& chainparams, const std::shared_ptr<cons
|
|||
* @param[out] state This may be set to an Error state if any error occurred processing them
|
||||
* @param[in] chainparams The params for the chain we want to connect to
|
||||
* @param[out] ppindex If set, the pointer will be set to point to the last new block index object for the given headers
|
||||
* @param[out] first_invalid First header that fails validation, if one exists
|
||||
*/
|
||||
bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, CValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr, CBlockHeader* first_invalid = nullptr) LOCKS_EXCLUDED(cs_main);
|
||||
bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& block, BlockValidationState& state, const CChainParams& chainparams, const CBlockIndex** ppindex = nullptr) LOCKS_EXCLUDED(cs_main);
|
||||
|
||||
/** Open a block file (blk?????.dat) */
|
||||
FILE* OpenBlockFile(const FlatFilePos &pos, bool fReadOnly = false);
|
||||
|
|
@ -260,7 +260,7 @@ bool GetTransaction(const uint256& hash, CTransactionRef& tx, const Consensus::P
|
|||
* May not be called with cs_main held. May not be called in a
|
||||
* validationinterface callback.
|
||||
*/
|
||||
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>());
|
||||
bool ActivateBestChain(BlockValidationState& state, const CChainParams& chainparams, std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>());
|
||||
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params& consensusParams);
|
||||
|
||||
/** Guess verification progress (as a fraction between 0.0=genesis and 1.0=current tip). */
|
||||
|
|
@ -284,8 +284,8 @@ void PruneBlockFilesManual(int nManualPruneHeight);
|
|||
|
||||
/** (try to) add transaction to memory pool
|
||||
* plTxnReplaced will be appended to with all transactions replaced from mempool **/
|
||||
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx,
|
||||
bool* pfMissingInputs, std::list<CTransactionRef>* plTxnReplaced,
|
||||
bool AcceptToMemoryPool(CTxMemPool& pool, TxValidationState &state, const CTransactionRef &tx,
|
||||
std::list<CTransactionRef>* plTxnReplaced,
|
||||
bool bypass_limits, const CAmount nAbsurdFee, bool test_accept=false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
/** Get the BIP9 state for a given deployment at the current tip. */
|
||||
|
|
@ -367,10 +367,10 @@ bool UndoReadFromDisk(CBlockUndo& blockundo, const CBlockIndex* pindex);
|
|||
/** Functions for validating blocks and updating the block tree */
|
||||
|
||||
/** Context-independent validity checks */
|
||||
bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
bool CheckBlock(const CBlock& block, BlockValidationState& state, const Consensus::Params& consensusParams, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
|
||||
|
||||
/** Check a block is completely valid from start to finish (only works on top of our current best block) */
|
||||
bool TestBlockValidity(CValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool TestBlockValidity(BlockValidationState& state, const CChainParams& chainparams, const CBlock& block, CBlockIndex* pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
/** Check whether witness commitments are required for a block, and whether to enforce NULLDUMMY (BIP 147) rules.
|
||||
* Note that transaction witness validation rules are always enforced when P2SH is enforced. */
|
||||
|
|
@ -492,7 +492,7 @@ public:
|
|||
*/
|
||||
bool AcceptBlockHeader(
|
||||
const CBlockHeader& block,
|
||||
CValidationState& state,
|
||||
BlockValidationState& state,
|
||||
const CChainParams& chainparams,
|
||||
CBlockIndex** ppindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
};
|
||||
|
|
@ -656,7 +656,7 @@ public:
|
|||
*/
|
||||
bool FlushStateToDisk(
|
||||
const CChainParams& chainparams,
|
||||
CValidationState &state,
|
||||
BlockValidationState &state,
|
||||
FlushStateMode mode,
|
||||
int nManualPruneHeight = 0);
|
||||
|
||||
|
|
@ -682,23 +682,23 @@ public:
|
|||
* @returns true unless a system error occurred
|
||||
*/
|
||||
bool ActivateBestChain(
|
||||
CValidationState& state,
|
||||
BlockValidationState& state,
|
||||
const CChainParams& chainparams,
|
||||
std::shared_ptr<const CBlock> pblock) LOCKS_EXCLUDED(cs_main);
|
||||
|
||||
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
bool AcceptBlock(const std::shared_ptr<const CBlock>& pblock, BlockValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex, bool fRequested, const FlatFilePos* dbp, bool* fNewBlock) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
// Block (dis)connection on a given view:
|
||||
DisconnectResult DisconnectBlock(const CBlock& block, const CBlockIndex* pindex, CCoinsViewCache& view);
|
||||
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex,
|
||||
bool ConnectBlock(const CBlock& block, BlockValidationState& state, CBlockIndex* pindex,
|
||||
CCoinsViewCache& view, const CChainParams& chainparams, std::set<std::pair<uint256, COutPoint>>* setPeginsSpent, bool fJustCheck = false) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
// Apply the effects of a block disconnection on the UTXO set.
|
||||
bool DisconnectTip(CValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::mempool.cs);
|
||||
bool DisconnectTip(BlockValidationState& state, const CChainParams& chainparams, DisconnectedBlockTransactions* disconnectpool) EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::mempool.cs);
|
||||
|
||||
// Manual block validity manipulation:
|
||||
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
|
||||
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
|
||||
bool PreciousBlock(BlockValidationState& state, const CChainParams& params, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
|
||||
bool InvalidateBlock(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
|
||||
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
/** Replay blocks that aren't fully applied to the database. */
|
||||
|
|
@ -724,10 +724,10 @@ public:
|
|||
bool LoadChainTip(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
private:
|
||||
bool ActivateBestChainStep(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindexMostWork, const std::shared_ptr<const CBlock>& pblock, bool& fInvalidFound, ConnectTrace& connectTrace) EXCLUSIVE_LOCKS_REQUIRED(cs_main, ::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, ::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, ::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, ::mempool.cs);
|
||||
|
||||
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
void InvalidBlockFound(CBlockIndex *pindex, const BlockValidationState &state) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
CBlockIndex* FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
void ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pindexNew, const FlatFilePos& pos, const Consensus::Params& consensusParams) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
||||
|
|
@ -742,10 +742,10 @@ private:
|
|||
* May not be called in a
|
||||
* validationinterface callback.
|
||||
*/
|
||||
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main);
|
||||
bool PreciousBlock(BlockValidationState& state, const CChainParams& params, CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main);
|
||||
|
||||
/** Mark a block as invalid. */
|
||||
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
|
||||
bool InvalidateBlock(BlockValidationState& state, const CChainParams& chainparams, CBlockIndex* pindex) LOCKS_EXCLUDED(cs_main);
|
||||
|
||||
/** Remove invalidity status from a block and its descendants. */
|
||||
void ResetBlockFailureFlags(CBlockIndex* pindex) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ struct MainSignalsInstance {
|
|||
boost::signals2::signal<void (const std::shared_ptr<const CBlock> &)> BlockDisconnected;
|
||||
boost::signals2::signal<void (const CTransactionRef &)> TransactionRemovedFromMempool;
|
||||
boost::signals2::signal<void (const CBlockLocator &)> ChainStateFlushed;
|
||||
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
|
||||
boost::signals2::signal<void (const CBlock&, const BlockValidationState&)> BlockChecked;
|
||||
boost::signals2::signal<void (const CBlockIndex *, const std::shared_ptr<const CBlock>&)> NewPoWValidBlock;
|
||||
|
||||
// We are not allowed to assume the scheduler only runs in one thread,
|
||||
|
|
@ -168,7 +168,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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@
|
|||
#include <memory>
|
||||
|
||||
extern CCriticalSection cs_main;
|
||||
class BlockValidationState;
|
||||
class CBlock;
|
||||
class CBlockIndex;
|
||||
struct CBlockLocator;
|
||||
class CConnman;
|
||||
class CValidationInterface;
|
||||
class CValidationState;
|
||||
class uint256;
|
||||
class CScheduler;
|
||||
class CTxMemPool;
|
||||
|
|
@ -134,11 +134,11 @@ protected:
|
|||
virtual void ChainStateFlushed(const CBlockLocator &locator) {}
|
||||
/**
|
||||
* Notifies listeners of a block validation result.
|
||||
* If the provided CValidationState IsValid, the provided block
|
||||
* If the provided BlockValidationState IsValid, the provided block
|
||||
* is guaranteed to be the current best block at the time the
|
||||
* callback was generated (not necessarily now)
|
||||
*/
|
||||
virtual void BlockChecked(const CBlock&, const CValidationState&) {}
|
||||
virtual void BlockChecked(const CBlock&, const BlockValidationState&) {}
|
||||
/**
|
||||
* Notifies listeners that a block which builds directly on our current tip
|
||||
* has been received and connected to the headers tree, though not validated yet */
|
||||
|
|
@ -180,7 +180,7 @@ public:
|
|||
void BlockConnected(const std::shared_ptr<const CBlock> &, const CBlockIndex *pindex, const std::shared_ptr<const std::vector<CTransactionRef>> &);
|
||||
void BlockDisconnected(const std::shared_ptr<const CBlock> &);
|
||||
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>&);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4788,7 +4788,7 @@ UniValue signblock(const JSONRPCRequest& request)
|
|||
if (block.hashPrevBlock != pindexPrev->GetBlockHash())
|
||||
throw JSONRPCError(RPC_VERIFY_ERROR, "proposal was not based on our best chain");
|
||||
|
||||
CValidationState state;
|
||||
BlockValidationState state;
|
||||
if (!TestBlockValidity(state, Params(), block, pindexPrev, false, true) || !state.IsValid()) {
|
||||
std::string strRejectReason = state.GetRejectReason();
|
||||
if (strRejectReason.empty())
|
||||
|
|
@ -5631,9 +5631,9 @@ UniValue claimpegin(const JSONRPCRequest& request)
|
|||
}
|
||||
|
||||
// To check if it's not double spending an existing pegin UTXO, we check mempool acceptance.
|
||||
CValidationState acceptState;
|
||||
TxValidationState acceptState;
|
||||
LockAssertion lock(::cs_main); //TODO(stevenroose) replace with locked_chain later
|
||||
bool accepted = ::AcceptToMemoryPool(mempool, acceptState, MakeTransactionRef(mtx), nullptr /* pfMissingInputs */,
|
||||
bool accepted = ::AcceptToMemoryPool(mempool, acceptState, MakeTransactionRef(mtx),
|
||||
nullptr /* plTxnReplaced */, false /* bypass_limits */, pwallet->m_default_max_tx_fee, true /* test_accept */);
|
||||
if (!accepted) {
|
||||
std::string strError = strprintf("Error: The transaction was rejected! Reason given: %s", FormatStateMessage(acceptState));
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ class RawTransactionsTest(BitcoinTestFramework):
|
|||
rawtx = self.nodes[2].signrawtransactionwithwallet(rawtx)
|
||||
|
||||
# This will raise an exception since there are missing inputs
|
||||
assert_raises_rpc_error(-25, "Missing inputs", self.nodes[2].sendrawtransaction, rawtx['hex'])
|
||||
assert_raises_rpc_error(-25, "bad-txns-inputs-missingorspent", self.nodes[2].sendrawtransaction, rawtx['hex'])
|
||||
|
||||
#####################################
|
||||
# getrawtransaction with block hash #
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue