mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-10 10:52:31 -05:00
consensus: Explain why fCheckDuplicateInputs can not be skipped and remove it
This commit is contained in:
parent
d53828cb79
commit
fa92813407
4 changed files with 13 additions and 18 deletions
|
@ -7,7 +7,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 fCheckDuplicateInputs)
|
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 (tx.vin.empty())
|
if (tx.vin.empty())
|
||||||
|
@ -31,14 +31,15 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe
|
||||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-txouttotal-toolarge");
|
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-txouttotal-toolarge");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
|
// Check for duplicate inputs (see CVE-2018-17144)
|
||||||
if (fCheckDuplicateInputs) {
|
// While Consensus::CheckTxInputs does check if all inputs of a tx are available, and UpdateCoins marks all inputs
|
||||||
std::set<COutPoint> vInOutPoints;
|
// of a tx as spent, it does not check if the tx has duplicate inputs.
|
||||||
for (const auto& txin : tx.vin)
|
// Failure to run this check will result in either a crash or an inflation bug, depending on the implementation of
|
||||||
{
|
// the underlying coins database.
|
||||||
if (!vInOutPoints.insert(txin.prevout).second)
|
std::set<COutPoint> vInOutPoints;
|
||||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputs-duplicate");
|
for (const auto& txin : tx.vin) {
|
||||||
}
|
if (!vInOutPoints.insert(txin.prevout).second)
|
||||||
|
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-txns-inputs-duplicate");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tx.IsCoinBase())
|
if (tx.IsCoinBase())
|
||||||
|
|
|
@ -15,6 +15,6 @@
|
||||||
class CTransaction;
|
class CTransaction;
|
||||||
class CValidationState;
|
class CValidationState;
|
||||||
|
|
||||||
bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true);
|
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
||||||
|
|
||||||
#endif // BITCOIN_CONSENSUS_TX_CHECK_H
|
#endif // BITCOIN_CONSENSUS_TX_CHECK_H
|
||||||
|
|
|
@ -43,12 +43,7 @@ void test_one_input(const std::vector<uint8_t>& buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
CValidationState state_with_dupe_check;
|
CValidationState state_with_dupe_check;
|
||||||
const bool valid_with_dupe_check = CheckTransaction(tx, state_with_dupe_check, /* fCheckDuplicateInputs= */ true);
|
(void)CheckTransaction(tx, state_with_dupe_check);
|
||||||
CValidationState state_without_dupe_check;
|
|
||||||
const bool valid_without_dupe_check = CheckTransaction(tx, state_without_dupe_check, /* fCheckDuplicateInputs= */ false);
|
|
||||||
if (valid_with_dupe_check) {
|
|
||||||
assert(valid_without_dupe_check);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
|
const CFeeRate dust_relay_fee{DUST_RELAY_TX_FEE};
|
||||||
std::string reason;
|
std::string reason;
|
||||||
|
|
|
@ -3301,9 +3301,8 @@ bool CheckBlock(const CBlock& block, CValidationState& state, const Consensus::P
|
||||||
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-multiple", "more than one coinbase");
|
return state.Invalid(ValidationInvalidReason::CONSENSUS, false, "bad-cb-multiple", "more than one coinbase");
|
||||||
|
|
||||||
// Check transactions
|
// Check transactions
|
||||||
// Must check for duplicate inputs (see CVE-2018-17144)
|
|
||||||
for (const auto& tx : block.vtx)
|
for (const auto& tx : block.vtx)
|
||||||
if (!CheckTransaction(*tx, state, true))
|
if (!CheckTransaction(*tx, state))
|
||||||
return state.Invalid(state.GetReason(), false, state.GetRejectReason(),
|
return state.Invalid(state.GetReason(), false, state.GetRejectReason(),
|
||||||
strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage()));
|
strprintf("Transaction check failed (tx hash %s) %s", tx->GetHash().ToString(), state.GetDebugMessage()));
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue