From 0ff1c2a838da9e8dc7f77609adc89124bbea3e2b Mon Sep 17 00:00:00 2001 From: Suhas Daftuar Date: Fri, 8 Mar 2019 09:55:23 -0500 Subject: Separate reason for premature spends (coinbase/locktime) --- src/consensus/tx_verify.cpp | 2 +- src/consensus/validation.h | 4 +++- src/net_processing.cpp | 1 + src/validation.cpp | 13 +++++++------ 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index c13a38cd6f..4b93cae848 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -172,7 +172,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_MISSING_INPUTS, false, REJECT_INVALID, "bad-txns-premature-spend-of-coinbase", + return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_INVALID, "bad-txns-premature-spend-of-coinbase", strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight)); } diff --git a/src/consensus/validation.h b/src/consensus/validation.h index 3079f3b08c..2e23f4b3a4 100644 --- a/src/consensus/validation.h +++ b/src/consensus/validation.h @@ -49,7 +49,8 @@ enum class ValidationInvalidReason { BLOCK_CHECKPOINT, //!< the block failed to meet one of our checkpoints // Only loose txn: TX_NOT_STANDARD, //!< didn't meet our local policy rules - TX_MISSING_INPUTS, //!< a transaction was missing some of its inputs (or its inputs were spent at < coinbase maturity height) + 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 /** * Transaction might be missing a witness, have a witness prior to SegWit * activation, or witness may have been malleated (which includes @@ -72,6 +73,7 @@ inline bool IsTransactionReason(ValidationInvalidReason r) 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 || diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 3319d3211a..71ebd72b83 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1040,6 +1040,7 @@ static bool MaybePunishNode(NodeId nodeid, const CValidationState& state, bool v 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: diff --git a/src/validation.cpp b/src/validation.cpp index c29bff9d30..c394afd82a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -596,7 +596,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // block; we don't want our mempool filled up with transactions that can't // be mined yet. if (!CheckFinalTx(tx, STANDARD_LOCKTIME_VERIFY_FLAGS)) - return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "non-final"); + return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-final"); // is it already in the memory pool? if (pool.exists(hash)) { @@ -685,7 +685,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // Must keep pool.cs for this unless we change CheckSequenceLocks to take a // CoinsViewCache instead of create its own if (!CheckSequenceLocks(pool, tx, STANDARD_LOCKTIME_VERIFY_FLAGS, &lp)) - return state.Invalid(ValidationInvalidReason::TX_NOT_STANDARD, false, REJECT_NONSTANDARD, "non-BIP68-final"); + return state.Invalid(ValidationInvalidReason::TX_PREMATURE_SPEND, false, REJECT_NONSTANDARD, "non-BIP68-final"); CAmount nFees = 0; if (!Consensus::CheckTxInputs(tx, state, view, GetSpendHeight(view), nFees)) { @@ -1965,13 +1965,14 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl { CAmount txfee = 0; if (!Consensus::CheckTxInputs(tx, state, view, pindex->nHeight, txfee)) { - if (state.GetReason() == ValidationInvalidReason::TX_MISSING_INPUTS) { - // CheckTxInputs may return MISSING_INPUTS but we can't return that, as - // it's not defined for a block, so we reset the reason flag to CONSENSUS here. + if (!IsBlockReason(state.GetReason())) { + // CheckTxInputs may return MISSING_INPUTS or + // PREMATURE_SPEND but we can't return that, as it's not + // defined for a block, so we reset the reason flag to + // CONSENSUS here. state.Invalid(ValidationInvalidReason::CONSENSUS, false, state.GetRejectCode(), state.GetRejectReason(), state.GetDebugMessage()); } - assert(IsBlockReason(state.GetReason())); return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, tx.GetHash().ToString(), FormatStateMessage(state)); } nFees += txfee; -- cgit v1.2.3