diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 0d1a3fdd..6472885a 100644 --- a/src/consensus/consensus.h +++ b/src/consensus/consensus.h @@ -6,6 +6,8 @@ #ifndef BITCOIN_CONSENSUS_CONSENSUS_H #define BITCOIN_CONSENSUS_CONSENSUS_H +/** The minimum allowed transaction version (network rule) */ +static const int32_t MIN_TX_VERSION = 1; /** The maximum allowed size for a serialized block, in bytes (network rule) */ static const unsigned int MAX_BLOCK_SIZE = 2000000; /** The maximum allowed number of signature check operations in a block (network rule) */ diff --git a/src/gtest/test_checktransaction.cpp b/src/gtest/test_checktransaction.cpp index 7dd1b86d..3849cf36 100644 --- a/src/gtest/test_checktransaction.cpp +++ b/src/gtest/test_checktransaction.cpp @@ -94,6 +94,16 @@ TEST(checktransaction_tests, valid_transaction) { EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state)); } +TEST(checktransaction_tests, BadVersionTooLow) { + CMutableTransaction mtx = GetValidTransaction(); + mtx.nVersion = 0; + + CTransaction tx(mtx); + MockCValidationState state; + EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-version-too-low", false)).Times(1); + CheckTransactionWithoutProofVerification(tx, state); +} + TEST(checktransaction_tests, bad_txns_vin_empty) { CMutableTransaction mtx = GetValidTransaction(); mtx.vjoinsplit.resize(0); diff --git a/src/main.cpp b/src/main.cpp index 39bbf8ff..3b089ede 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -851,6 +851,12 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio { // Basic checks that don't depend on any context + // Check transaction version + if (tx.nVersion < MIN_TX_VERSION) { + return state.DoS(100, error("CheckTransaction(): version too low"), + REJECT_INVALID, "bad-version-too-low"); + } + // Transactions can contain empty `vin` and `vout` so long as // `vjoinsplit` is non-empty. if (tx.vin.empty() && tx.vjoinsplit.empty())