From 548bbd95f019cb59924419945528906507b2f122 Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Tue, 1 Nov 2016 19:58:56 -0500 Subject: [PATCH] Adjust consensus rule to accept genesis block without height in coinbase Closes #1753 --- src/gtest/test_checkblock.cpp | 43 +++++++++++++++++++++++++++++++++++ src/main.cpp | 5 +++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/gtest/test_checkblock.cpp b/src/gtest/test_checkblock.cpp index be6fde35e..eab73afad 100644 --- a/src/gtest/test_checkblock.cpp +++ b/src/gtest/test_checkblock.cpp @@ -29,3 +29,46 @@ TEST(CheckBlock, VersionTooLow) { EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "version-too-low", false)).Times(1); EXPECT_FALSE(CheckBlock(block, state, false, false)); } + +TEST(ContextualCheckBlock, BadCoinbaseHeight) { + SelectParams(CBaseChainParams::MAIN); + + // Create a block with no height in scriptSig + CMutableTransaction mtx; + mtx.vin.resize(1); + mtx.vin[0].prevout.SetNull(); + mtx.vin[0].scriptSig = CScript() << OP_0; + mtx.vout.resize(1); + mtx.vout[0].scriptPubKey = CScript() << OP_TRUE; + mtx.vout[0].nValue = 0; + CTransaction tx {mtx}; + CBlock block; + block.vtx.push_back(tx); + + // Treating block as genesis should pass + MockCValidationState state; + EXPECT_TRUE(ContextualCheckBlock(block, state, NULL)); + + // Treating block as non-genesis should fail + mtx.vout.push_back(CTxOut(GetBlockSubsidy(1, Params().GetConsensus())/5, Params().GetFoundersRewardScriptAtHeight(1))); + CTransaction tx2 {mtx}; + block.vtx[0] = tx2; + CBlock prev; + CBlockIndex indexPrev {prev}; + indexPrev.nHeight = 0; + EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); + EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); + + // Setting to an incorrect height should fail + mtx.vin[0].scriptSig = CScript() << 2 << OP_0; + CTransaction tx3 {mtx}; + block.vtx[0] = tx3; + EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-cb-height", false)).Times(1); + EXPECT_FALSE(ContextualCheckBlock(block, state, &indexPrev)); + + // After correcting the scriptSig, should pass + mtx.vin[0].scriptSig = CScript() << 1 << OP_0; + CTransaction tx4 {mtx}; + block.vtx[0] = tx4; + EXPECT_TRUE(ContextualCheckBlock(block, state, &indexPrev)); +} diff --git a/src/main.cpp b/src/main.cpp index 1cad27fe8..c432bcd63 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3090,7 +3090,10 @@ bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIn // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): - if (block.nVersion >= 2) + // Since MIN_BLOCK_VERSION = 4 all blocks with nHeight > 0 should satisfy this. + // This rule is not applied to the genesis block, which didn't include the height + // in the coinbase. + if (nHeight > 0) { CScript expect = CScript() << nHeight; if (block.vtx[0].vin[0].scriptSig.size() < expect.size() ||