From de237cbfa4c1aa7d4f9888e650f870a50b77de73 Mon Sep 17 00:00:00 2001 From: Gavin Andresen Date: Wed, 27 Jun 2012 19:30:39 -0400 Subject: Block height in coinbase as a new block rule "Version 2" blocks are blocks that have nVersion=2 and have the block height as the first item in their coinbase. Block-height-in-the-coinbase is strictly enforced when version=2 blocks are a supermajority in the block chain (750 of the last 1,000 blocks on main net, 51 of 100 for testnet). This does not affect old clients/miners at all, which will continue producing nVersion=1 blocks, and which will continue to be valid. --- src/main.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 846802713..7a003c0ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1826,6 +1826,19 @@ bool CBlock::AcceptBlock() if (!Checkpoints::CheckBlock(nHeight, hash)) return DoS(100, error("AcceptBlock() : rejected by checkpoint lock-in at %d", nHeight)); + // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height + if (nVersion > 1) + { + // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): + if ((!fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 750, 1000)) || + (fTestNet && CBlockIndex::IsSuperMajority(2, pindexPrev, 51, 100))) + { + CScript expect = CScript() << nHeight; + if (!std::equal(expect.begin(), expect.end(), vtx[0].vin[0].scriptSig.begin())) + return DoS(100, error("AcceptBlock() : block height mismatch in coinbase")); + } + } + // Write block to history file if (!CheckDiskSpace(::GetSerializeSize(*this, SER_DISK, CLIENT_VERSION))) return error("AcceptBlock() : out of disk space"); @@ -1849,6 +1862,18 @@ bool CBlock::AcceptBlock() return true; } +bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned int nRequired, unsigned int nToCheck) +{ + unsigned int nFound = 0; + for (unsigned int i = 0; i < nToCheck && nFound < nRequired && pstart != NULL; i++) + { + if (pstart->nVersion >= minVersion) + ++nFound; + pstart = pstart->pprev; + } + return (nFound >= nRequired); +} + bool ProcessBlock(CNode* pfrom, CBlock* pblock) { // Check for duplicate @@ -3663,7 +3688,8 @@ void IncrementExtraNonce(CBlock* pblock, CBlockIndex* pindexPrev, unsigned int& hashPrevBlock = pblock->hashPrevBlock; } ++nExtraNonce; - pblock->vtx[0].vin[0].scriptSig = (CScript() << pblock->nTime << CBigNum(nExtraNonce)) + COINBASE_FLAGS; + unsigned int nHeight = pindexPrev->nHeight+1; // Height first in coinbase required for block.version=2 + pblock->vtx[0].vin[0].scriptSig = (CScript() << nHeight << CBigNum(nExtraNonce)) + COINBASE_FLAGS; assert(pblock->vtx[0].vin[0].scriptSig.size() <= 100); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); -- cgit v1.2.3