From 80f4cdcf8f43743fc428ad704d76f1dab48e5b8f Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Thu, 20 Oct 2016 15:26:34 -0500 Subject: [PATCH] Reject block versions lower than 4 Closes #1556 --- src/Makefile.gtest.include | 1 + src/consensus/consensus.h | 2 ++ src/gtest/test_checkblock.cpp | 31 +++++++++++++++++++++++++++++++ src/main.cpp | 5 +++++ 4 files changed, 39 insertions(+) create mode 100644 src/gtest/test_checkblock.cpp diff --git a/src/Makefile.gtest.include b/src/Makefile.gtest.include index 5ee9c1fe0..8c41ef783 100644 --- a/src/Makefile.gtest.include +++ b/src/Makefile.gtest.include @@ -5,6 +5,7 @@ bin_PROGRAMS += zcash-gtest zcash_gtest_SOURCES = \ gtest/main.cpp \ gtest/utils.cpp \ + gtest/test_checkblock.cpp \ gtest/test_checktransaction.cpp \ gtest/json_test_vectors.cpp \ gtest/json_test_vectors.h \ diff --git a/src/consensus/consensus.h b/src/consensus/consensus.h index 6472885a8..d700666bc 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 block version (network rule) */ +static const int32_t MIN_BLOCK_VERSION = 4; /** 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) */ diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp new file mode 100644 index 000000000..be6fde35e --- /dev/null +++ b/src/gtest/test_checkblock.cpp @@ -0,0 +1,31 @@ +#include +#include + +#include "consensus/validation.h" +#include "main.h" + +class MockCValidationState : public CValidationState { +public: + MOCK_METHOD5(DoS, bool(int level, bool ret, + unsigned char chRejectCodeIn, std::string strRejectReasonIn, + bool corruptionIn)); + MOCK_METHOD3(Invalid, bool(bool ret, + unsigned char _chRejectCode, std::string _strRejectReason)); + MOCK_METHOD1(Error, bool(std::string strRejectReasonIn)); + MOCK_CONST_METHOD0(IsValid, bool()); + MOCK_CONST_METHOD0(IsInvalid, bool()); + MOCK_CONST_METHOD0(IsError, bool()); + MOCK_CONST_METHOD1(IsInvalid, bool(int &nDoSOut)); + MOCK_CONST_METHOD0(CorruptionPossible, bool()); + MOCK_CONST_METHOD0(GetRejectCode, unsigned char()); + MOCK_CONST_METHOD0(GetRejectReason, std::string()); +}; + +TEST(CheckBlock, VersionTooLow) { + CBlock block; + block.nVersion = 1; + + MockCValidationState state; + EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false)).Times(1); + EXPECT_FALSE(CheckBlock(block, state, false, false)); +} diff --git a/src/main.cpp b/src/main.cpp index 3b089ede4..58c6300ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2940,6 +2940,11 @@ bool FindUndoPos(CValidationState &state, int nFile, CDiskBlockPos &pos, unsigne bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW) { + // Check block version + if (block.nVersion < MIN_BLOCK_VERSION) + return state.DoS(100, error("CheckBlockHeader(): block version too low"), + REJECT_INVALID, "version-too-low"); + // Check Equihash solution is valid if (fCheckPOW && !CheckEquihashSolution(&block, Params())) return state.DoS(100, error("CheckBlockHeader(): Equihash solution invalid"),