From 7ac924cdb7bdad2601c46014e488e9190806b38c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 21 Oct 2016 23:07:50 -0500 Subject: [PATCH 1/2] Disallow v0 transactions as a consensus rule Closes #1557 --- src/consensus/consensus.h | 2 ++ src/gtest/test_checktransaction.cpp | 10 ++++++++++ src/main.cpp | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 0d1a3fdde..6472885a8 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 7dd1b86d2..3849cf367 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 39bbf8ff7..3b089ede4 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()) From f4f1b4b097f45de6bb6060a58752de5eb672dcd0 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Sat, 22 Oct 2016 11:09:07 -0500 Subject: [PATCH 2/2] Update sighash tests for new consensus rule --- src/test/sighash_tests.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 164bba576..c825a8bad 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -237,8 +237,14 @@ BOOST_AUTO_TEST_CASE(sighash_from_data) stream >> tx; CValidationState state; - BOOST_CHECK_MESSAGE(CheckTransactionWithoutProofVerification(tx, state), strTest); - BOOST_CHECK(state.IsValid()); + if (tx.nVersion < MIN_TX_VERSION) { + // Transaction must be invalid + BOOST_CHECK_MESSAGE(!CheckTransactionWithoutProofVerification(tx, state), strTest); + BOOST_CHECK(!state.IsValid()); + } else { + BOOST_CHECK_MESSAGE(CheckTransactionWithoutProofVerification(tx, state), strTest); + BOOST_CHECK(state.IsValid()); + } std::vector raw = ParseHex(raw_script); scriptCode.insert(scriptCode.end(), raw.begin(), raw.end());