diff --git a/src/chain.h b/src/chain.h index dea2936012..445a76b4c7 100644 --- a/src/chain.h +++ b/src/chain.h @@ -238,6 +238,7 @@ public: nVersion = block.nVersion; hashMerkleRoot = block.hashMerkleRoot; nTime = block.nTime; + nHeight = block.nHeight; proof = block.proof; } @@ -267,6 +268,7 @@ public: block.hashPrevBlock = pprev->GetBlockHash(); block.hashMerkleRoot = hashMerkleRoot; block.nTime = nTime; + block.nHeight = nHeight; block.proof = proof; return block; } @@ -393,6 +395,7 @@ public: block.hashMerkleRoot = hashMerkleRoot; block.nTime = nTime; block.proof = proof; + block.nHeight = nHeight; return block.GetHash(); } diff --git a/src/miner.cpp b/src/miner.cpp index cc9c083a55..74659d1f44 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -200,6 +200,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev); ResetChallenge(*pblock, *pindexPrev, chainparams.GetConsensus()); ResetProof(*pblock); + pblock->nHeight = nHeight; pblocktemplate->vTxSigOpsCost[0] = WITNESS_SCALE_FACTOR * GetLegacySigOpCount(*pblock->vtx[0]); CValidationState state; diff --git a/src/primitives/block.h b/src/primitives/block.h index 0427fdac2a..9151d911dc 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -99,6 +99,7 @@ public: uint256 hashPrevBlock; uint256 hashMerkleRoot; uint32_t nTime; + uint32_t nHeight; CBitcoinProof bitcoinproof; CProof proof; @@ -117,8 +118,10 @@ public: READWRITE(nTime); if (IsBitcoinBlock() || (nVersion & SERIALIZE_BITCOIN_BLOCK_OR_TX)) READWRITE(bitcoinproof); - else + else { + READWRITE(nHeight); READWRITE(proof); + } } void SetNull() @@ -127,6 +130,7 @@ public: hashPrevBlock.SetNull(); hashMerkleRoot.SetNull(); nTime = 0; + nHeight = 0; bitcoinproof.SetNull(); proof.SetNull(); } @@ -192,6 +196,7 @@ public: block.hashPrevBlock = hashPrevBlock; block.hashMerkleRoot = hashMerkleRoot; block.nTime = nTime; + block.nHeight = nHeight; block.bitcoinproof = bitcoinproof; block.proof = proof; return block; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 3f1e5faec9..82a432cf4e 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -557,6 +557,9 @@ UniValue getblocktemplate(const JSONRPCRequest& request) // NOTE: If at some point we support pre-segwit miners post-segwit-activation, this needs to take segwit support into consideration const bool fPreSegWit = (THRESHOLD_ACTIVE != VersionBitsState(pindexPrev, consensusParams, Consensus::DEPLOYMENT_SEGWIT, versionbitscache)); + // Update height in header + pblock->nHeight = pindexPrev->nHeight+1; + UniValue aCaps(UniValue::VARR); aCaps.push_back("proposal"); UniValue transactions(UniValue::VARR); diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 5dc0b454e7..7ec91e1e28 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -209,12 +209,15 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // We can't make transactions until we have inputs // Therefore, load 100 blocks :) + unsigned int blockheight = pblocktemplate->block.nHeight; + int baseheight = 0; std::vector txFirst; for (unsigned int i = 0; i < sizeof(blockinfo)/sizeof(*blockinfo); ++i) { CBlock *pblock = &pblocktemplate->block; // pointer for convenience pblock->nVersion = 1; + pblock->nHeight = blockheight++; pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1; CMutableTransaction txCoinbase(*pblock->vtx[0]); txCoinbase.nVersion = 1; diff --git a/src/validation.cpp b/src/validation.cpp index 0361f64111..95fdb61730 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2037,6 +2037,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin if (block.GetHash() == chainparams.GetConsensus().hashGenesisBlock) { if (!fJustCheck) { assert(block.vtx.size() == 1); + assert(block.nHeight == 0); std::vector > vPos; std::multimap > mLocksCreated; @@ -3347,6 +3348,11 @@ bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& sta if (block.GetBlockTime() <= pindexPrev->GetMedianTimePast()) return state.Invalid(false, REJECT_INVALID, "time-too-old", "block's timestamp is too early"); + // Check height in header against prev + if ((uint32_t)pindexPrev->nHeight + 1 != block.nHeight) + return state.Invalid(error("%s: block height in header is incorrect", __func__), + REJECT_INVALID, "bad-header-height"); + // Check timestamp if (block.GetBlockTime() > nAdjustedTime + 2 * 60 * 60) return state.Invalid(false, REJECT_INVALID, "time-too-new", "block timestamp too far in the future");