From e1d3be4adc32fd34e380ab146463c4d2987fa087 Mon Sep 17 00:00:00 2001 From: Kittywhiskers Van Gogh <63189531+kittywhiskers@users.noreply.github.com> Date: Sun, 27 Aug 2023 03:15:22 +0530 Subject: [PATCH] partial bitcoin#11389: Support having SegWit always active in regtest excludes: - d618458184742b15a7ab0349127ede7a2946a182 --- src/chainparams.cpp | 22 ++++++++++-------- src/consensus/params.h | 12 ++++++++++ src/test/miner_tests.cpp | 37 ++++++++++++++++--------------- src/test/versionbits_tests.cpp | 15 +++++++++++++ src/validation.cpp | 9 ++++---- src/versionbits.cpp | 10 +++++++++ test/functional/rpc_blockchain.py | 6 ++--- 7 files changed, 77 insertions(+), 34 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 78d61f8b9d..293024341f 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -136,6 +136,7 @@ public: CMainParams() { strNetworkID = CBaseChainParams::MAIN; consensus.nSubsidyHalvingInterval = 210240; // Note: actual number of blocks per calendar year with DGW v3 is ~200700 (for example 449750 - 249050) + consensus.BIP16Height = 0; consensus.nMasternodePaymentsStartBlock = 100000; // not true, but it's ok as long as it's less then nMasternodePaymentsIncreaseBlock consensus.nMasternodePaymentsIncreaseBlock = 158000; // actual historical value consensus.nMasternodePaymentsIncreasePeriod = 576*30; // 17280 - actual historical value @@ -182,7 +183,7 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_V20].bit = 9; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nStartTime = 19999999999; // TODO: To be determined later - consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize = 4032; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdStart = 3226; // 80% of 4032 consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdMin = 2420; // 60% of 4032 @@ -190,7 +191,7 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 19999999999; // TODO: To be determined later - consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 4032; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 3226; // 80% of 4032 consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 2420; // 60% of 4032 @@ -332,6 +333,7 @@ public: CTestNetParams() { strNetworkID = CBaseChainParams::TESTNET; consensus.nSubsidyHalvingInterval = 210240; + consensus.BIP16Height = 0; consensus.nMasternodePaymentsStartBlock = 4010; // not true, but it's ok as long as it's less then nMasternodePaymentsIncreaseBlock consensus.nMasternodePaymentsIncreaseBlock = 4030; consensus.nMasternodePaymentsIncreasePeriod = 10; @@ -378,7 +380,7 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_V20].bit = 9; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nStartTime = 19999999999; // TODO: To be determined later - consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize = 100; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdStart = 80; // 80% of 100 consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdMin = 60; // 60% of 100 @@ -386,7 +388,7 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 19999999999; // TODO: To be determined later - consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 100; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 80; // 80% of 100 consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 60; // 60% of 100 @@ -503,6 +505,7 @@ public: explicit CDevNetParams(const ArgsManager& args) { strNetworkID = CBaseChainParams::DEVNET; consensus.nSubsidyHalvingInterval = 210240; + consensus.BIP16Height = 0; consensus.nMasternodePaymentsStartBlock = 4010; // not true, but it's ok as long as it's less then nMasternodePaymentsIncreaseBlock consensus.nMasternodePaymentsIncreaseBlock = 4030; consensus.nMasternodePaymentsIncreasePeriod = 10; @@ -548,7 +551,7 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_V20].bit = 9; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nStartTime = 1661990400; // Sep 1st, 2022 - consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize = 120; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdStart = 80; // 80% of 100 consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdMin = 60; // 60% of 100 @@ -556,7 +559,7 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 1661990400; // Sep 1st, 2022 - consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 120; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 80; // 80% of 100 consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 60; // 60% of 100 @@ -739,6 +742,7 @@ public: explicit CRegTestParams(const ArgsManager& args) { strNetworkID = CBaseChainParams::REGTEST; consensus.nSubsidyHalvingInterval = 150; + consensus.BIP16Height = 0; // always enforce P2SH BIP16 on regtest consensus.nMasternodePaymentsStartBlock = 240; consensus.nMasternodePaymentsIncreaseBlock = 350; consensus.nMasternodePaymentsIncreasePeriod = 10; @@ -781,11 +785,11 @@ public: consensus.nMinerConfirmationWindow = 144; // Faster than normal for regtest (144 instead of 2016) consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28; consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 0; - consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_V20].bit = 9; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nStartTime = 0; - consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_V20].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nWindowSize = 480; consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdStart = 384; // 80% of 480 consensus.vDeployments[Consensus::DEPLOYMENT_V20].nThresholdMin = 288; // 60% of 480 @@ -793,7 +797,7 @@ public: consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].bit = 10; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nStartTime = 0; - consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = 999999999999ULL; + consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nTimeout = Consensus::BIP9Deployment::NO_TIMEOUT; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nWindowSize = 1030; consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdStart = 800; // 80% of 1000 consensus.vDeployments[Consensus::DEPLOYMENT_MN_RR].nThresholdMin = 600; // 60% of 1000 diff --git a/src/consensus/params.h b/src/consensus/params.h index 7922112870..4e3442cb0e 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -9,6 +9,7 @@ #include #include +#include #include namespace Consensus { @@ -39,6 +40,15 @@ struct BIP9Deployment { int64_t nThresholdMin{0}; /** A coefficient which adjusts the speed a required number of signaling blocks is decreasing from nThresholdStart to nThresholdMin at with each period. */ int64_t nFalloffCoeff{0}; + + /** Constant for nTimeout very far in the future. */ + static constexpr int64_t NO_TIMEOUT = std::numeric_limits::max(); + + /** Special value for nStartTime indicating that the deployment is always active. + * This is useful for testing, as it means tests don't need to deal with the activation + * process (which takes at least 3 BIP9 intervals). Only tests that specifically test the + * behaviour during activation cannot use this. */ + static constexpr int64_t ALWAYS_ACTIVE = -1; }; /** @@ -48,6 +58,8 @@ struct Params { uint256 hashGenesisBlock; uint256 hashDevnetGenesisBlock; int nSubsidyHalvingInterval; + /** Block height at which BIP16 becomes active */ + int BIP16Height; int nMasternodePaymentsStartBlock; int nMasternodePaymentsIncreaseBlock; int nMasternodePaymentsIncreasePeriod; // in blocks diff --git a/src/test/miner_tests.cpp b/src/test/miner_tests.cpp index 73e7b8fdf8..cb56ecd027 100644 --- a/src/test/miner_tests.cpp +++ b/src/test/miner_tests.cpp @@ -369,24 +369,6 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("bad-cb-multiple")); m_node.mempool->clear(); - // invalid (pre-p2sh) txn in mempool, template creation fails - tx.vin[0].prevout.hash = txFirst[0]->GetHash(); - tx.vin[0].prevout.n = 0; - tx.vin[0].scriptSig = CScript() << OP_1; - tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE; - script = CScript() << OP_0; - tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script)); - hash = tx.GetHash(); - m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); - tx.vin[0].prevout.hash = hash; - tx.vin[0].scriptSig = CScript() << std::vector(script.begin(), script.end()); - tx.vout[0].nValue -= LOWFEE; - hash = tx.GetHash(); - m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); - // Should throw block-validation-failed - BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed")); - m_node.mempool->clear(); - // double spend txn pair in mempool, template creation fails tx.vin[0].prevout.hash = txFirst[0]->GetHash(); tx.vin[0].scriptSig = CScript() << OP_1; @@ -426,6 +408,25 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity) // ::ChainActive().SetTip(next); // } //BOOST_CHECK(pblocktemplate = BlockAssembler(chainparams).CreateNewBlock(scriptPubKey)); + + // invalid (pre-p2sh) txn in mempool, template creation fails + tx.vin[0].prevout.hash = txFirst[0]->GetHash(); + tx.vin[0].prevout.n = 0; + tx.vin[0].scriptSig = CScript() << OP_1; + tx.vout[0].nValue = BLOCKSUBSIDY-LOWFEE; + script = CScript() << OP_0; + tx.vout[0].scriptPubKey = GetScriptForDestination(ScriptHash(script)); + hash = tx.GetHash(); + m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(true).FromTx(tx)); + tx.vin[0].prevout.hash = hash; + tx.vin[0].scriptSig = CScript() << std::vector(script.begin(), script.end()); + tx.vout[0].nValue -= LOWFEE; + hash = tx.GetHash(); + m_node.mempool->addUnchecked(entry.Fee(LOWFEE).Time(GetTime()).SpendsCoinbase(false).FromTx(tx)); + // Should throw block-validation-failed + BOOST_CHECK_EXCEPTION(AssemblerForTest(chainparams).CreateNewBlock(scriptPubKey), std::runtime_error, HasReason("block-validation-failed")); + m_node.mempool->clear(); + // // Delete the dummy blocks again. // while (::ChainActive().Tip()->nHeight > nHeight) { // CBlockIndex* del = ::ChainActive().Tip(); diff --git a/src/test/versionbits_tests.cpp b/src/test/versionbits_tests.cpp index 9c657ffc68..6bafad6472 100644 --- a/src/test/versionbits_tests.cpp +++ b/src/test/versionbits_tests.cpp @@ -32,6 +32,12 @@ public: int GetStateSinceHeightFor(const CBlockIndex* pindexPrev) const { return AbstractThresholdConditionChecker::GetStateSinceHeightFor(pindexPrev, paramsDummy, cache); } }; +class TestAlwaysActiveConditionChecker : public TestConditionChecker +{ +public: + int64_t BeginTime(const Consensus::Params& params) const override { return Consensus::BIP9Deployment::ALWAYS_ACTIVE; } +}; + #define CHECKERS 6 class VersionBitsTester @@ -43,6 +49,8 @@ class VersionBitsTester // The first one performs all checks, the second only 50%, the third only 25%, etc... // This is to test whether lack of cached information leads to the same results. TestConditionChecker checker[CHECKERS]; + // Another 6 that assume always active activation + TestAlwaysActiveConditionChecker checker_always[CHECKERS]; // Test counter (to identify failures) int num; @@ -56,6 +64,7 @@ public: } for (unsigned int i = 0; i < CHECKERS; i++) { checker[i] = TestConditionChecker(); + checker_always[i] = TestAlwaysActiveConditionChecker(); } vpblock.clear(); return *this; @@ -82,6 +91,7 @@ public: for (int i = 0; i < CHECKERS; i++) { if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == height, strprintf("Test %i for StateSinceHeight", num)); + BOOST_CHECK_MESSAGE(checker_always[i].GetStateSinceHeightFor(vpblock.empty() ? nullptr : vpblock.back()) == 0, strprintf("Test %i for StateSinceHeight (always active)", num)); } } num++; @@ -92,6 +102,7 @@ public: for (int i = 0; i < CHECKERS; i++) { if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::DEFINED, strprintf("Test %i for DEFINED", num)); + BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); } } num++; @@ -102,6 +113,7 @@ public: for (int i = 0; i < CHECKERS; i++) { if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::STARTED, strprintf("Test %i for STARTED", num)); + BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); } } num++; @@ -112,6 +124,7 @@ public: for (int i = 0; i < CHECKERS; i++) { if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::LOCKED_IN, strprintf("Test %i for LOCKED_IN", num)); + BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); } } num++; @@ -122,6 +135,7 @@ public: for (int i = 0; i < CHECKERS; i++) { if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE", num)); + BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); } } num++; @@ -132,6 +146,7 @@ public: for (int i = 0; i < CHECKERS; i++) { if (InsecureRandBits(i) == 0) { BOOST_CHECK_MESSAGE(checker[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::FAILED, strprintf("Test %i for FAILED", num)); + BOOST_CHECK_MESSAGE(checker_always[i].GetStateFor(vpblock.empty() ? nullptr : vpblock.back()) == ThresholdState::ACTIVE, strprintf("Test %i for ACTIVE (always active)", num)); } } num++; diff --git a/src/validation.cpp b/src/validation.cpp index 031c950e12..081c1c70db 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1966,11 +1966,12 @@ static ThresholdConditionCache warningcache[VERSIONBITS_NUM_BITS] GUARDED_BY(cs_ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { AssertLockHeld(cs_main); - // BIP16 didn't become active until Apr 1 2012 - int64_t nBIP16SwitchTime = 1333238400; - bool fStrictPayToScriptHash = (pindex->GetBlockTime() >= nBIP16SwitchTime); + unsigned int flags = SCRIPT_VERIFY_NONE; - unsigned int flags = fStrictPayToScriptHash ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE; + // Start enforcing P2SH (BIP16) + if (pindex->nHeight >= consensusparams.BIP16Height) { + flags |= SCRIPT_VERIFY_P2SH; + } // Start enforcing the DERSIG (BIP66) rule if (pindex->nHeight >= consensusparams.BIP66Height) { diff --git a/src/versionbits.cpp b/src/versionbits.cpp index 95ec5d6651..e3910056d8 100644 --- a/src/versionbits.cpp +++ b/src/versionbits.cpp @@ -11,6 +11,11 @@ ThresholdState AbstractThresholdConditionChecker::GetStateFor(const CBlockIndex* int64_t nTimeStart = BeginTime(params); int64_t nTimeTimeout = EndTime(params); + // Check if this deployment is always active. + if (nTimeStart == Consensus::BIP9Deployment::ALWAYS_ACTIVE) { + return ThresholdState::ACTIVE; + } + // A block's state is always the same as that of the first of its period, so it is computed based on a pindexPrev whose height equals a multiple of nPeriod - 1. if (pindexPrev != nullptr) { pindexPrev = pindexPrev->GetAncestor(pindexPrev->nHeight - ((pindexPrev->nHeight + 1) % nPeriod)); @@ -161,6 +166,11 @@ BIP9Stats AbstractThresholdConditionChecker::GetStateStatisticsFor(const CBlockI int AbstractThresholdConditionChecker::GetStateSinceHeightFor(const CBlockIndex* pindexPrev, const Consensus::Params& params, ThresholdConditionCache& cache) const { + int64_t start_time = BeginTime(params); + if (start_time == Consensus::BIP9Deployment::ALWAYS_ACTIVE) { + return 0; + } + const ThresholdState initialState = GetStateFor(pindexPrev, params, cache); // BIP 9 about state DEFINED: "The genesis block is by definition in this state for each deployment." diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 699b297f47..b9d4d3c003 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -145,7 +145,7 @@ class BlockchainTest(BitcoinTestFramework): 'bip9': { 'status': 'defined', 'start_time': 0, - 'timeout': 999999999999, + 'timeout': 9223372036854775807, 'since': 0 }, 'active': False}, 'mn_rr': { @@ -153,7 +153,7 @@ class BlockchainTest(BitcoinTestFramework): 'bip9': { 'status': 'defined', 'start_time': 0, - 'timeout': 999999999999, + 'timeout': 9223372036854775807, 'since': 0 }, 'active': False}, @@ -163,7 +163,7 @@ class BlockchainTest(BitcoinTestFramework): 'status': 'started', 'bit': 28, 'start_time': 0, - 'timeout': 999999999999, # testdummy does not have a timeout so is set to the max int64 value + 'timeout': 9223372036854775807, # testdummy does not have a timeout so is set to the max int64 value 'since': 144, 'statistics': { 'period': 144,