From 53a49c0246d265f9ce9a74b5d04448d37a692b21 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Thu, 5 Feb 2015 20:56:10 -0800 Subject: Implement BIP 66 validation rules and switchover logic --- src/main.cpp | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 9d1eca948..ba397a59e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1966,6 +1966,12 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C unsigned int flags = SCRIPT_VERIFY_NOCACHE | (fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE); + if (block.nVersion >= 3 && + ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 750, 1000)) || + (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 51, 100)))) { + flags |= SCRIPT_VERIFY_DERSIG; + } + CBlockUndo blockundo; CCheckQueueControl control(fScriptChecks && nScriptCheckThreads ? &scriptcheckqueue : NULL); @@ -2755,21 +2761,30 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, REJECT_INVALID, "bad-txns-nonfinal"); } - // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height - if (block.nVersion >= 2) - { - // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): - if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 750, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 51, 100))) + // Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded: + if (block.nVersion < 3) { - CScript expect = CScript() << nHeight; - if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || - !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { - pindex->nStatus |= BLOCK_FAILED_VALID; - return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), - REJECT_INVALID, "bad-cb-height"); + if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 950, 1000)) || + (TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 75, 100))) + { + return state.Invalid(error("AcceptBlock() : rejected nVersion=2 block"), + REJECT_OBSOLETE, "bad-version"); } } + // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height + if (block.nVersion >= 2) + { + // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): + if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 750, 1000)) || + (TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 51, 100))) + CScript expect = CScript() << nHeight; + if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || + !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { + pindex->nStatus |= BLOCK_FAILED_VALID; + return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), + REJECT_INVALID, "bad-cb-height"); + } + } } // Write block to history file -- cgit v1.2.3 From c71c3511769b7726498dd79213aa5ef970c5e3a2 Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Tue, 28 Jul 2015 19:02:55 +0100 Subject: Correct BIP 66 patches --- src/main.cpp | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index ba397a59e..b85236f8c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2761,29 +2761,30 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, REJECT_INVALID, "bad-txns-nonfinal"); } - // Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded: - if (block.nVersion < 3) + // Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded: + if (block.nVersion < 3) + { + if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 950, 1000)) || + (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 75, 100))) { - if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 950, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 75, 100))) - { - return state.Invalid(error("AcceptBlock() : rejected nVersion=2 block"), - REJECT_OBSOLETE, "bad-version"); - } + return state.Invalid(error("AcceptBlock() : rejected nVersion=2 block"), + REJECT_OBSOLETE, "bad-version"); } - // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height - if (block.nVersion >= 2) + } + // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height + if (block.nVersion >= 2) + { + // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): + if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 750, 1000)) || + (TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 51, 100))) { - // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): - if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 750, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 51, 100))) - CScript expect = CScript() << nHeight; - if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || - !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { - pindex->nStatus |= BLOCK_FAILED_VALID; - return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), - REJECT_INVALID, "bad-cb-height"); - } + CScript expect = CScript() << nHeight; + if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || + !std::equal(expect.begin(), expect.end(), block.vtx[0].vin[0].scriptSig.begin())) { + pindex->nStatus |= BLOCK_FAILED_VALID; + return state.DoS(100, error("AcceptBlock() : block height mismatch in coinbase"), + REJECT_INVALID, "bad-cb-height"); + } } } -- cgit v1.2.3 From 096d657914ea0c3e191ed1da21dd7e9296254384 Mon Sep 17 00:00:00 2001 From: Patrick Lodder Date: Fri, 7 Aug 2015 14:02:34 +0200 Subject: Implement [CBlock|CBlockIndex]::GetBaseVersion() - nVersion & 0xff to easily compare versions without aux data - change implementations checking nVersion throughout main.ccp --- src/main.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index b85236f8c..0f1ce5493 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1966,7 +1966,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C unsigned int flags = SCRIPT_VERIFY_NOCACHE | (fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE); - if (block.nVersion >= 3 && + if (block.GetBaseVersion() >= 3 && ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 750, 1000)) || (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 51, 100)))) { flags |= SCRIPT_VERIFY_DERSIG; @@ -2137,7 +2137,7 @@ void static UpdateTip(CBlockIndex *pindexNew) { const CBlockIndex* pindex = chainActive.Tip(); for (int i = 0; i < 100 && pindex != NULL; i++) { - if (pindex->nVersion > CBlock::CURRENT_VERSION && !IsAuxPowVersion(pindex->nVersion)) + if (pindex->GetBaseVersion() > CBlock::CURRENT_VERSION) ++nUpgraded; pindex = pindex->pprev; } @@ -2713,7 +2713,7 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex return state.DoS(100, error("AcceptBlock() : forked chain older than last checkpoint (height %d)", nHeight)); // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: - if (block.nVersion < 2) + if (block.GetBaseVersion() < 2) { if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) || (TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100))) @@ -2762,7 +2762,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, } // Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded: - if (block.nVersion < 3) + if (block.GetBaseVersion() < 3) { if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 950, 1000)) || (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 75, 100))) @@ -2772,7 +2772,7 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, } } // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height - if (block.nVersion >= 2) + if (block.GetBaseVersion() >= 2) { // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 750, 1000)) || @@ -2826,7 +2826,7 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns unsigned int nFound = 0; for (unsigned int i = 0; i < nToCheck && nFound < nRequired && pstart != NULL; i++) { - if (pstart->nVersion >= minVersion) + if (pstart->GetBaseVersion() >= minVersion) ++nFound; pstart = pstart->pprev; } -- cgit v1.2.3 From e1a900b1bc7bff625e8f97116c0f878f139c9056 Mon Sep 17 00:00:00 2001 From: Patrick Lodder Date: Fri, 7 Aug 2015 15:50:24 +0200 Subject: enable CBlockIndex::IsSuperMajority This has been disabled since 1.5 for unclear reasons, but we need it for the bip66 softfork in 1.10 that is backported here. This commit re-enables the logic. --- src/main.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 0f1ce5493..d9810842b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2820,8 +2820,6 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, unsigned int nRequired, unsigned int nToCheck) { - // Dogecoin: temporarily disable v2 block lockin until we are ready for v2 transition - return false; unsigned int nFound = 0; for (unsigned int i = 0; i < nToCheck && nFound < nRequired && pstart != NULL; i++) -- cgit v1.2.3 From 320234c0e5d594f9205c4780fff33a10590d21f4 Mon Sep 17 00:00:00 2001 From: Patrick Lodder Date: Fri, 7 Aug 2015 15:57:51 +0200 Subject: Reject version 1 blocks with version 3 supermajority Because CBlockIndex::IsSuperMajority was disabled since 1.5, we cannot enforce version 1 block rejection on the live chains with a v2 supermajority. Instead, we piggyback the version 3 supermajority switch to also enforce the version 2 softfork and all is good. --- src/main.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index d9810842b..f34b037d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2713,10 +2713,12 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex return state.DoS(100, error("AcceptBlock() : forked chain older than last checkpoint (height %d)", nHeight)); // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: + // Dogecoin: reject ONLY if block.nVersion=3 has a supermajority because CBlockIndex::IsSuperMajority + // was hard-disabled until now if (block.GetBaseVersion() < 2) { - if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 950, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(2, pindexPrev, 75, 100))) + if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 950, 1000)) || + (TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 75, 100))) { return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"), REJECT_OBSOLETE, "bad-version"); @@ -2772,11 +2774,13 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, } } // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height + // Dogecoin: reject ONLY if block.nVersion=3 has a supermajority because CBlockIndex::IsSuperMajority + // was hard-disabled until now if (block.GetBaseVersion() >= 2) { // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): - if ((!TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 750, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(2, pindex->pprev, 51, 100))) + if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 750, 1000)) || + (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 51, 100))) { CScript expect = CScript() << nHeight; if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || -- cgit v1.2.3 From 288fc013bab3d16b827de6bcc0be077e8cff7f6a Mon Sep 17 00:00:00 2001 From: Patrick Lodder Date: Mon, 10 Aug 2015 10:45:16 +0200 Subject: Use the same time-based constraints as in 1.10 Backport of #1225 to 1.8.x, sets: - majority window to 2000 blocks on mainnet, 1000 on testnet - enforcement triggers to 1500 on mainnet, 501 on testnet - reject triggers to 1900 on mainnet, 750 on testnet --- src/main.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index f34b037d8..1b51e4968 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1967,8 +1967,8 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C (fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE); if (block.GetBaseVersion() >= 3 && - ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 750, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 51, 100)))) { + ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 1500, 2000)) || + (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 501, 1000)))) { flags |= SCRIPT_VERIFY_DERSIG; } @@ -2717,8 +2717,8 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex // was hard-disabled until now if (block.GetBaseVersion() < 2) { - if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 950, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 75, 100))) + if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 1900, 2000)) || + (TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 750, 1000))) { return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"), REJECT_OBSOLETE, "bad-version"); @@ -2766,8 +2766,8 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, // Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded: if (block.GetBaseVersion() < 3) { - if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 950, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 75, 100))) + if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 1900, 2000)) || + (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 750, 1000))) { return state.Invalid(error("AcceptBlock() : rejected nVersion=2 block"), REJECT_OBSOLETE, "bad-version"); @@ -2779,8 +2779,8 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, if (block.GetBaseVersion() >= 2) { // if 750 of the last 1,000 blocks are version 2 or greater (51/100 if testnet): - if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 750, 1000)) || - (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 51, 100))) + if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 1500, 2000)) || + (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 501, 1000))) { CScript expect = CScript() << nHeight; if (block.vtx[0].vin[0].scriptSig.size() < expect.size() || -- cgit v1.2.3 From bc4aebb8a76839132352d3af8ca6053811fe0656 Mon Sep 17 00:00:00 2001 From: Patrick Lodder Date: Mon, 10 Aug 2015 13:41:55 +0200 Subject: Only test supermajority for block rejects against v3 blocks Since v2 and v1 blocks will be rejected at exactly the same time, only check for supermajority once to save 2000 iterations over blockheaders per block. Also moves the version check to AcceptBlockHeader() rather than AcceptBlock() to be able to reject early on. --- src/main.cpp | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 1b51e4968..5cf8d744c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2712,17 +2712,13 @@ bool AcceptBlockHeader(CBlockHeader& block, CValidationState& state, CBlockIndex if (pcheckpoint && nHeight < pcheckpoint->nHeight) return state.DoS(100, error("AcceptBlock() : forked chain older than last checkpoint (height %d)", nHeight)); - // Reject block.nVersion=1 blocks when 95% (75% on testnet) of the network has upgraded: - // Dogecoin: reject ONLY if block.nVersion=3 has a supermajority because CBlockIndex::IsSuperMajority - // was hard-disabled until now - if (block.GetBaseVersion() < 2) - { + // Reject block.nVersion<3 blocks when 95% (75% on testnet) of the network has upgraded + // Dogecoin: reject v2 and v1 blocks at the same time, only check once + if (block.GetBaseVersion() < 3) { if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 1900, 2000)) || (TestNet() && CBlockIndex::IsSuperMajority(3, pindexPrev, 750, 1000))) - { - return state.Invalid(error("AcceptBlock() : rejected nVersion=1 block"), + return state.Invalid(error("AcceptBlock() : rejected nVersion<3 block"), REJECT_OBSOLETE, "bad-version"); - } } } @@ -2763,16 +2759,6 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex** ppindex, REJECT_INVALID, "bad-txns-nonfinal"); } - // Reject block.nVersion=2 blocks when 95% (75% on testnet) of the network has upgraded: - if (block.GetBaseVersion() < 3) - { - if ((!TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 1900, 2000)) || - (TestNet() && CBlockIndex::IsSuperMajority(3, pindex->pprev, 750, 1000))) - { - return state.Invalid(error("AcceptBlock() : rejected nVersion=2 block"), - REJECT_OBSOLETE, "bad-version"); - } - } // Enforce block.nVersion=2 rule that the coinbase starts with serialized block height // Dogecoin: reject ONLY if block.nVersion=3 has a supermajority because CBlockIndex::IsSuperMajority // was hard-disabled until now -- cgit v1.2.3