diff --git a/doc/release-notes-6325.md b/doc/release-notes-6325.md new file mode 100644 index 0000000000000..84c02201d48b0 --- /dev/null +++ b/doc/release-notes-6325.md @@ -0,0 +1,4 @@ +Tests +----- + +- Command line arguments -dip8params, -bip147height are removed in favour of -testactivationheight. (dash#6325) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 616f4e650f42c..671e08e4b14d8 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -189,7 +189,6 @@ class CMainParams : public CChainParams { consensus.DIP0008Height = 1088640; // 00000000000000112e41e4b3afda8b233b8cc07c532d2eac5de097b68358c43e consensus.BRRHeight = 1374912; // 000000000000000c5a124f3eccfbe6e17876dca79cec9e63dfa70d269113c926 consensus.DIP0020Height = 1516032; // 000000000000000f64ed3bd9af1078177ac026f6aa2677aa4d8beeae43be56cc - consensus.DIP0024Height = 1737792; // 0000000000000001342be9c0b75ad40c276beaad91616423c4d9cb101b3db438 consensus.DIP0024QuorumsHeight = 1738698; // 000000000000001aa25181e4c466e593992c98f9eb21c69ee757b8bb0af50244 consensus.V19Height = 1899072; // 0000000000000015e32e73052d663626327004c81c5c22cb8b42c361015c0eae consensus.V20Height = 1987776; // 000000000000001bf41cff06b76780050682ca29e61a91c391893d4745579777 @@ -387,7 +386,6 @@ class CTestNetParams : public CChainParams { consensus.DIP0008Height = 78800; // 000000000e9329d964d80e7dab2e704b43b6bd2b91fea1e9315d38932e55fb55 consensus.BRRHeight = 387500; // 0000001537dbfd09dea69f61c1f8b2afa27c8dc91c934e144797761c9f10367b consensus.DIP0020Height = 414100; // 000000cf961868662fbfbb5d1af6f1caa1809f6a4e390efe5f8cd3031adea668 - consensus.DIP0024Height = 769700; // 0000008d84e4efd890ae95c70a7a6126a70a80e5c19e4cb264a5b3469aeef172 consensus.DIP0024QuorumsHeight = 770730; // 0000003c43b3ae7fffe61278ca5537a0e256ebf4d709d45f0ab040271074d51e consensus.V19Height = 850100; // 000004728b8ff2a16b9d4eebb0fd61eeffadc9c7fe4b0ec0b5a739869401ab5b consensus.V20Height = 905100; // 0000020c5e0f86f385cbf8e90210de9a9fd63633f01433bf47a6b3227a2851fd @@ -560,12 +558,11 @@ class CDevNetParams : public CChainParams { consensus.DIP0008Height = 2; // DIP0008 activated immediately on devnet consensus.BRRHeight = 2; // BRR (realloc) activated immediately on devnet consensus.DIP0020Height = 2; // DIP0020 activated immediately on devnet - consensus.DIP0024Height = 2; // DIP0024 activated immediately on devnet consensus.DIP0024QuorumsHeight = 2; // DIP0024 activated immediately on devnet consensus.V19Height = 2; // V19 activated immediately on devnet consensus.V20Height = 2; // V20 activated immediately on devnet consensus.MN_RRHeight = 2; // MN_RR activated immediately on devnet - consensus.MinBIP9WarningHeight = 2 + 2016; // v19 activation height + miner confirmation window + consensus.MinBIP9WarningHeight = 2 + 2016; // mn_rr activation height + miner confirmation window consensus.powLimit = uint256S("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // ~uint256(0) >> 1 consensus.nPowTargetTimespan = 24 * 60 * 60; // Dash: 1 day consensus.nPowTargetSpacing = 2.5 * 60; // Dash: 2.5 minutes @@ -790,14 +787,14 @@ class CRegTestParams : public CChainParams { consensus.BIP147Height = 1; // Always active unless overridden consensus.CSVHeight = 1; // Always active unless overridden consensus.DIP0001Height = 1; // Always active unless overridden - consensus.DIP0003Height = 432; + consensus.DIP0003Height = 432; // Always active for DashTestFramework in functional tests (see dip3params) + // For unit tests and for BitcoinTestFramework is disabled due to missing quorum commitment for blocks created by helpers such as create_blocks consensus.DIP0003EnforcementHeight = 500; consensus.DIP0003EnforcementHash = uint256(); consensus.DIP0008Height = 1; // Always active unless overridden consensus.BRRHeight = 1; // Always active unless overridden consensus.DIP0020Height = 1; // Always active unless overridden - consensus.DIP0024Height = 900; - consensus.DIP0024QuorumsHeight = 900; + consensus.DIP0024QuorumsHeight = 1; // Always have dip0024 quorums unless overridden consensus.V19Height = 900; consensus.V20Height = 900; consensus.MN_RRHeight = 900; @@ -845,8 +842,6 @@ class CRegTestParams : public CChainParams { UpdateActivationParametersFromArgs(args); UpdateDIP3ParametersFromArgs(args); - UpdateDIP8ParametersFromArgs(args); - UpdateBIP147ParametersFromArgs(args); UpdateBudgetParametersFromArgs(args); genesis = CreateGenesisBlock(1417713337, 1096447, 0x207fffff, 1, 50 * COIN); @@ -965,21 +960,6 @@ class CRegTestParams : public CChainParams { } void UpdateDIP3ParametersFromArgs(const ArgsManager& args); - /** - * Allows modifying the DIP8 activation height - */ - void UpdateDIP8Parameters(int nActivationHeight) - { - consensus.DIP0008Height = nActivationHeight; - } - void UpdateDIP8ParametersFromArgs(const ArgsManager& args); - - void UpdateBIP147Parameters(int nActivationHeight) - { - consensus.BIP147Height = nActivationHeight; - } - void UpdateBIP147ParametersFromArgs(const ArgsManager& args); - /** * Allows modifying the budget regtest parameters. */ @@ -1045,6 +1025,8 @@ static void MaybeUpdateHeights(const ArgsManager& args, Consensus::Params& conse consensus.DIP0001Height = int{height}; } else if (name == "dip0008") { consensus.DIP0008Height = int{height}; + } else if (name == "dip0024") { + consensus.DIP0024QuorumsHeight = int{height}; } else if (name == "v20") { consensus.V20Height = int{height}; } else if (name == "mn_rr") { @@ -1136,35 +1118,6 @@ void CRegTestParams::UpdateDIP3ParametersFromArgs(const ArgsManager& args) UpdateDIP3Parameters(nDIP3ActivationHeight, nDIP3EnforcementHeight); } -void CRegTestParams::UpdateDIP8ParametersFromArgs(const ArgsManager& args) -{ - if (!args.IsArgSet("-dip8params")) return; - - std::string strParams = args.GetArg("-dip8params", ""); - std::vector vParams = SplitString(strParams, ':'); - if (vParams.size() != 1) { - throw std::runtime_error("DIP8 parameters malformed, expecting "); - } - int nDIP8ActivationHeight; - if (!ParseInt32(vParams[0], &nDIP8ActivationHeight)) { - throw std::runtime_error(strprintf("Invalid activation height (%s)", vParams[0])); - } - LogPrintf("Setting DIP8 parameters to activation=%ld\n", nDIP8ActivationHeight); - UpdateDIP8Parameters(nDIP8ActivationHeight); -} - -void CRegTestParams::UpdateBIP147ParametersFromArgs(const ArgsManager& args) -{ - if (!args.IsArgSet("-bip147height")) return; - int nBIP147Height; - const std::string strParams = args.GetArg("-bip147height", ""); - if (!ParseInt32(strParams, &nBIP147Height)) { - throw std::runtime_error(strprintf("Invalid activation height (%s)", strParams)); - } - LogPrintf("Setting BIP147 parameters to activation=%lld\n", nBIP147Height); - UpdateBIP147Parameters(nBIP147Height); -} - void CRegTestParams::UpdateBudgetParametersFromArgs(const ArgsManager& args) { if (!args.IsArgSet("-budgetparams")) return; diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index d7ef237c0eee8..1a05491f065ba 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -20,9 +20,7 @@ void SetupChainParamsBaseOptions(ArgsManager& argsman) argsman.AddArg("-budgetparams=::", "Override masternode, budget and superblock start heights (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-devnet=", "Use devnet chain with provided name", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-dip3params=:", "Override DIP3 activation and enforcement heights (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-dip8params=", "Override DIP8 activation height (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-bip147height=", "Override BIP147 activation height (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::CHAINPARAMS); - argsman.AddArg("-testactivationheight=name@height.", "Set the activation height of 'name' (bip147, bip34, dersig, cltv, csv, brr, dip0001, dip0008, v20, mn_rr). (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); + argsman.AddArg("-testactivationheight=name@height.", "Set the activation height of 'name' (bip147, bip34, dersig, cltv, csv, brr, dip0001, dip0008, dip0024, v20, mn_rr). (regtest-only)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST); argsman.AddArg("-highsubsidyblocks=", "The number of blocks with a higher than normal subsidy to mine at the start of a chain. Block after that height will have fixed subsidy base. (default: 0, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-highsubsidyfactor=", "The factor to multiply the normal block subsidy by while in the highsubsidyblocks window of a chain (default: 1, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); argsman.AddArg("-llmqchainlocks=", "Override the default LLMQ type used for ChainLocks. Allows using ChainLocks with smaller LLMQs. (default: llmq_devnet, devnet-only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS); diff --git a/src/consensus/params.h b/src/consensus/params.h index 508d477c54f43..74a0c035d4ba7 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -137,8 +137,6 @@ struct Params { int BRRHeight; /** Block height at which DIP0020, DIP0021 and LLMQ_100_67 quorums become active */ int DIP0020Height; - /** Block height at which DIP0024 (Quorum Rotation) and decreased governance proposal fee becomes active */ - int DIP0024Height; /** Block height at which the first DIP0024 quorum was mined */ int DIP0024QuorumsHeight; /** Block height at which V19 (Basic BLS and EvoNodes) becomes active */ @@ -205,7 +203,7 @@ struct Params { case DEPLOYMENT_DIP0020: return DIP0020Height; case DEPLOYMENT_DIP0024: - return DIP0024Height; + return DIP0024QuorumsHeight; case DEPLOYMENT_BRR: return BRRHeight; case DEPLOYMENT_V19: diff --git a/src/evo/creditpool.cpp b/src/evo/creditpool.cpp index abcf72650a412..c16950eba1f17 100644 --- a/src/evo/creditpool.cpp +++ b/src/evo/creditpool.cpp @@ -112,24 +112,29 @@ void CCreditPoolManager::AddToCache(const uint256& block_hash, int height, const } } -static std::optional GetBlockForCreditPool(const CBlockIndex* const block_index, const Consensus::Params& consensusParams) +static std::optional GetBlockForCreditPool(const gsl::not_null block_index, + const Consensus::Params& consensusParams) { + // There's no CbTx before DIP0003 activation + if (!DeploymentActiveAt(*block_index, Params().GetConsensus(), Consensus::DEPLOYMENT_DIP0003)) { + return std::nullopt; + } + CBlock block; if (!ReadBlockFromDisk(block, block_index, consensusParams)) { throw std::runtime_error("failed-getcbforblock-read"); } - assert(!block.vtx.empty()); - - // Should not fail if V20 (DIP0027) is active but it happens for RegChain (unit tests) - if (!block.vtx[0]->IsSpecialTxVersion()) return std::nullopt; - - assert(!block.vtx[0]->vExtraPayload.empty()); + if (block.vtx.empty() || block.vtx[0]->vExtraPayload.empty() || !block.vtx[0]->IsSpecialTxVersion()) { + LogPrintf("%s: ERROR: empty CbTx for CreditPool at height=%d\n", __func__, block_index->nHeight); + return std::nullopt; + } return block; } -CCreditPool CCreditPoolManager::ConstructCreditPool(const CBlockIndex* const block_index, CCreditPool prev, const Consensus::Params& consensusParams) +CCreditPool CCreditPoolManager::ConstructCreditPool(const gsl::not_null block_index, + CCreditPool prev, const Consensus::Params& consensusParams) { std::optional block = GetBlockForCreditPool(block_index, consensusParams); if (!block) { @@ -210,7 +215,7 @@ CCreditPool CCreditPoolManager::ConstructCreditPool(const CBlockIndex* const blo CCreditPool CCreditPoolManager::GetCreditPool(const CBlockIndex* block_index, const Consensus::Params& consensusParams) { - std::stack to_calculate; + std::stack> to_calculate; std::optional poolTmp; while (block_index != nullptr && !(poolTmp = GetFromCache(*block_index)).has_value()) { diff --git a/src/evo/creditpool.h b/src/evo/creditpool.h index de6f13595b2eb..c27179edaa953 100644 --- a/src/evo/creditpool.h +++ b/src/evo/creditpool.h @@ -16,6 +16,7 @@ #include +#include #include #include @@ -134,7 +135,8 @@ class CCreditPoolManager std::optional GetFromCache(const CBlockIndex& block_index); void AddToCache(const uint256& block_hash, int height, const CCreditPool& pool); - CCreditPool ConstructCreditPool(const CBlockIndex* block_index, CCreditPool prev, const Consensus::Params& consensusParams); + CCreditPool ConstructCreditPool(const gsl::not_null block_index, CCreditPool prev, + const Consensus::Params& consensusParams); }; std::optional GetCreditPoolDiffForBlock(CCreditPoolManager& cpoolman, const BlockManager& blockman, const llmq::CQuorumManager& qman, diff --git a/src/evo/specialtxman.cpp b/src/evo/specialtxman.cpp index 5ed1e08c10ba0..969efa2703055 100644 --- a/src/evo/specialtxman.cpp +++ b/src/evo/specialtxman.cpp @@ -267,16 +267,20 @@ bool CSpecialTxProcessor::CheckCreditPoolDiffForBlock(const CBlock& block, const try { if (!DeploymentActiveAt(*pindex, m_consensus_params, Consensus::DEPLOYMENT_DIP0003)) return true; + if (!DeploymentActiveAt(*pindex, m_consensus_params, Consensus::DEPLOYMENT_DIP0008)) return true; if (!DeploymentActiveAt(*pindex, m_consensus_params, Consensus::DEPLOYMENT_V20)) return true; auto creditPoolDiff = GetCreditPoolDiffForBlock(m_cpoolman, m_chainman.m_blockman, m_qman, block, pindex->pprev, m_consensus_params, blockSubsidy, state); if (!creditPoolDiff.has_value()) return false; // If we get there we have v20 activated and credit pool amount must be included in block CbTx + if (block.vtx.empty()) { + return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-missing-cbtx"); + } const auto& tx = *block.vtx[0]; - assert(tx.IsCoinBase()); - assert(tx.IsSpecialTxVersion()); - assert(tx.nType == TRANSACTION_COINBASE); + if (!tx.IsCoinBase() || !tx.IsSpecialTxVersion() || tx.nType != TRANSACTION_COINBASE) { + return state.Invalid(BlockValidationResult::BLOCK_CONSENSUS, "bad-cbtx-type"); + } const auto opt_cbTx = GetTxPayload(tx); if (!opt_cbTx) { diff --git a/src/llmq/options.cpp b/src/llmq/options.cpp index c1956e8a67a1b..d0723f7f12f29 100644 --- a/src/llmq/options.cpp +++ b/src/llmq/options.cpp @@ -116,26 +116,26 @@ std::map GetEnabledQuorumVvecSyncEntries() bool IsQuorumTypeEnabled(Consensus::LLMQType llmqType, gsl::not_null pindexPrev) { - return IsQuorumTypeEnabledInternal(llmqType, pindexPrev, std::nullopt, std::nullopt); + return IsQuorumTypeEnabledInternal(llmqType, pindexPrev, std::nullopt); } bool IsQuorumTypeEnabledInternal(Consensus::LLMQType llmqType, gsl::not_null pindexPrev, - std::optional optDIP0024IsActive, std::optional optHaveDIP0024Quorums) + std::optional optIsDIP0024Active) { const Consensus::Params& consensusParams = Params().GetConsensus(); - const bool fDIP0024IsActive{optDIP0024IsActive.value_or(DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DIP0024))}; - const bool fHaveDIP0024Quorums{optHaveDIP0024Quorums.value_or(pindexPrev->nHeight >= consensusParams.DIP0024QuorumsHeight)}; + const bool fDIP0024IsActive{ + optIsDIP0024Active.value_or(DeploymentActiveAfter(pindexPrev, consensusParams, Consensus::DEPLOYMENT_DIP0024))}; switch (llmqType) { case Consensus::LLMQType::LLMQ_DEVNET: return true; case Consensus::LLMQType::LLMQ_50_60: - return !fDIP0024IsActive || !fHaveDIP0024Quorums || Params().NetworkIDString() == CBaseChainParams::TESTNET || + return !fDIP0024IsActive || Params().NetworkIDString() == CBaseChainParams::TESTNET || Params().NetworkIDString() == CBaseChainParams::DEVNET; case Consensus::LLMQType::LLMQ_TEST_INSTANTSEND: - return !fDIP0024IsActive || !fHaveDIP0024Quorums || - consensusParams.llmqTypeDIP0024InstantSend == Consensus::LLMQType::LLMQ_TEST_INSTANTSEND; + return !fDIP0024IsActive || + consensusParams.llmqTypeDIP0024InstantSend == Consensus::LLMQType::LLMQ_TEST_INSTANTSEND; case Consensus::LLMQType::LLMQ_TEST: case Consensus::LLMQType::LLMQ_TEST_PLATFORM: case Consensus::LLMQType::LLMQ_400_60: diff --git a/src/llmq/options.h b/src/llmq/options.h index f78f2362fdfc0..de220f499c014 100644 --- a/src/llmq/options.h +++ b/src/llmq/options.h @@ -44,7 +44,8 @@ bool IsWatchQuorumsEnabled(); std::map GetEnabledQuorumVvecSyncEntries(); bool IsQuorumTypeEnabled(Consensus::LLMQType llmqType, gsl::not_null pindexPrev); -bool IsQuorumTypeEnabledInternal(Consensus::LLMQType llmqType, gsl::not_null pindexPrev, std::optional optDIP0024IsActive, std::optional optHaveDIP0024Quorums); +bool IsQuorumTypeEnabledInternal(Consensus::LLMQType llmqType, gsl::not_null pindexPrev, + std::optional optHaveDIP0024Quorums); std::vector GetEnabledQuorumTypes(gsl::not_null pindex); std::vector> GetEnabledQuorumParams(gsl::not_null pindex); diff --git a/src/test/evo_utils_tests.cpp b/src/test/evo_utils_tests.cpp index 4d555492469b4..65c405f9bda22 100644 --- a/src/test/evo_utils_tests.cpp +++ b/src/test/evo_utils_tests.cpp @@ -21,18 +21,14 @@ void Test(NodeContext& node) using namespace llmq; auto tip = node.chainman->ActiveTip(); const auto& consensus_params = Params().GetConsensus(); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeDIP0024InstantSend, tip, false, false), false); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeDIP0024InstantSend, tip, true, false), true); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeDIP0024InstantSend, tip, true, true), true); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeChainLocks, tip, false, false), true); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeChainLocks, tip, true, false), true); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeChainLocks, tip, true, true), true); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypePlatform, tip, false, false), Params().IsTestChain()); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypePlatform, tip, true, false), Params().IsTestChain()); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypePlatform, tip, true, true), Params().IsTestChain()); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeMnhf, tip, false, false), true); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeMnhf, tip, true, false), true); - BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeMnhf, tip, true, true), true); + BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeDIP0024InstantSend, tip, false), false); + BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeDIP0024InstantSend, tip, true), true); + BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeChainLocks, tip, false), true); + BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeChainLocks, tip, true), true); + BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypePlatform, tip, false), Params().IsTestChain()); + BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypePlatform, tip, true), Params().IsTestChain()); + BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeMnhf, tip, false), true); + BOOST_CHECK_EQUAL(IsQuorumTypeEnabledInternal(consensus_params.llmqTypeMnhf, tip, true), true); } BOOST_FIXTURE_TEST_CASE(utils_IsQuorumTypeEnabled_tests_regtest, RegTestingSetup) diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 25b355ef717af..b97546f767298 100644 --- a/src/test/util/setup_common.cpp +++ b/src/test/util/setup_common.cpp @@ -354,9 +354,9 @@ TestChainSetup::TestChainSetup(int num_blocks, const std::vector& e /* TestChainDIP3BeforeActivationSetup */ { 430, uint256S("0x0bcefaa33fec56cd84d05d0e76cd6a78badcc20f627d91903646de6a07930a14") }, /* TestChainBRRBeforeActivationSetup */ - { 497, uint256S("0x23c31820ec5160b7181bfdf328e2b76cd12c9fa4544d892b7f01e74dd6220849") }, + { 497, uint256S("0x3c71d807d28b9b813434eb0679ec3d5bcf424c20088cf578f3757521c3e3eded") }, /* TestChainV19BeforeActivationSetup */ - { 894, uint256S("0x2885cf0fe8fdf29803b6c65002ba2570ff011531d8ea92be312a85d655e00c51") }, + { 894, uint256S("0x3f031e5cceade15bdfa559ddecb2ccb2b8d17083bdfd871a9d23b17d04b15292") }, } }; diff --git a/test/functional/feature_dip4_coinbasemerkleroots.py b/test/functional/feature_dip4_coinbasemerkleroots.py index d8e05cb2e0b43..920633c08b023 100755 --- a/test/functional/feature_dip4_coinbasemerkleroots.py +++ b/test/functional/feature_dip4_coinbasemerkleroots.py @@ -18,6 +18,7 @@ from test_framework.util import assert_equal DIP0008_HEIGHT = 432 +DIP0024_HEIGHT = 900 # TODO: this helper used in many tests, find a new home for it class TestP2PConn(P2PInterface): @@ -43,7 +44,7 @@ def getmnlistdiff(self, baseBlockHash, blockHash): class LLMQCoinbaseCommitmentsTest(DashTestFramework): def set_test_params(self): - self.extra_args = [[ f'-testactivationheight=dip0008@{DIP0008_HEIGHT}', "-vbparams=testdummy:999999999999:999999999999" ]] * 4 + self.extra_args = [[ f'-testactivationheight=dip0008@{DIP0008_HEIGHT}', f'-testactivationheight=dip0024@{DIP0024_HEIGHT}', "-vbparams=testdummy:999999999999:999999999999" ]] * 4 self.set_dash_test_params(4, 3, extra_args = self.extra_args) def remove_masternode(self, idx): diff --git a/test/functional/feature_index_prune.py b/test/functional/feature_index_prune.py index dcb649362f820..7fa3a56c5c19f 100755 --- a/test/functional/feature_index_prune.py +++ b/test/functional/feature_index_prune.py @@ -11,16 +11,17 @@ ) from test_framework.governance import EXPECTED_STDERR_NO_GOV_PRUNE -DEPLOYMENT_ARG = "-testactivationheight=v20@3000" +# TODO: remove testactivationheight=v20@3000 when it will be activated from block 1 +DEPLOYMENT_ARGS = ["-testactivationheight=v20@3000", "-dip3params=3000:3000"] class FeatureIndexPruneTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 4 self.extra_args = [ - ["-fastprune", "-prune=1", "-blockfilterindex=1", DEPLOYMENT_ARG], - ["-fastprune", "-prune=1", "-coinstatsindex=1", DEPLOYMENT_ARG], - ["-fastprune", "-prune=1", "-blockfilterindex=1", "-coinstatsindex=1", DEPLOYMENT_ARG], - [DEPLOYMENT_ARG] + ["-fastprune", "-prune=1", "-blockfilterindex=1"] + DEPLOYMENT_ARGS, + ["-fastprune", "-prune=1", "-coinstatsindex=1"] + DEPLOYMENT_ARGS, + ["-fastprune", "-prune=1", "-blockfilterindex=1", "-coinstatsindex=1"] + DEPLOYMENT_ARGS, + [] + DEPLOYMENT_ARGS, ] def sync_index(self, height): @@ -51,7 +52,7 @@ def mine_batches(self, blocks): def restart_without_indices(self): for i in range(3): - self.restart_node(i, extra_args=["-fastprune", "-prune=1", DEPLOYMENT_ARG], expected_stderr=EXPECTED_STDERR_NO_GOV_PRUNE) + self.restart_node(i, extra_args=["-fastprune", "-prune=1"] + DEPLOYMENT_ARGS, expected_stderr=EXPECTED_STDERR_NO_GOV_PRUNE) self.reconnect_nodes() def run_test(self): @@ -110,7 +111,7 @@ def run_test(self): self.log.info("prune exactly up to the indices best blocks while the indices are disabled") for i in range(3): pruneheight_2 = self.nodes[i].pruneblockchain(1000) - assert_equal(pruneheight_2, 932) + assert_equal(pruneheight_2, 732) # Restart the nodes again with the indices activated self.restart_node(i, extra_args=self.extra_args[i], expected_stderr=EXPECTED_STDERR_NO_GOV_PRUNE) @@ -145,7 +146,7 @@ def run_test(self): for node in self.nodes[:2]: with node.assert_debug_log(['limited pruning to height 2489']): pruneheight_new = node.pruneblockchain(2500) - assert_equal(pruneheight_new, 2197) + assert_equal(pruneheight_new, 2125) self.log.info("ensure that prune locks don't prevent indices from failing in a reorg scenario") with self.nodes[0].assert_debug_log(['basic block filter index prune lock moved back to 2480']): diff --git a/test/functional/feature_llmq_rotation.py b/test/functional/feature_llmq_rotation.py index 233f39d495c38..9a11e6c940303 100755 --- a/test/functional/feature_llmq_rotation.py +++ b/test/functional/feature_llmq_rotation.py @@ -81,11 +81,9 @@ def run_test(self): h_0 = self.mine_quorum() h_100_0 = QuorumId(100, int(h_0, 16)) h_106_0 = QuorumId(106, int(h_0, 16)) - h_104_0 = QuorumId(104, int(h_0, 16)) h_1 = self.mine_quorum() h_100_1 = QuorumId(100, int(h_1, 16)) h_106_1 = QuorumId(106, int(h_1, 16)) - h_104_1 = QuorumId(104, int(h_1, 16)) self.log.info("Mine single block, wait for chainlock") self.generate(self.nodes[0], 1, sync_fun=self.no_op) @@ -103,10 +101,10 @@ def run_test(self): assert_equal(dkg_info['active_dkgs'], 0) nonzero_dkgs += dkg_info['active_dkgs'] assert_equal(dkg_info['next_dkg'], next_dkg) - assert_equal(nonzero_dkgs, 11) # 2 quorums 4 nodes each and 1 quorum of 3 nodes + assert_equal(nonzero_dkgs, 7) # 1 quorums 4 nodes and 1 quorum of 3 nodes expectedDeleted = [] - expectedNew = [h_100_0, h_106_0, h_104_0, h_100_1, h_106_1, h_104_1] + expectedNew = [h_100_0, h_106_0, h_100_1, h_106_1] quorumList = self.test_getmnlistdiff_quorums(b_h_0, b_h_1, {}, expectedDeleted, expectedNew, testQuorumsCLSigs=False) projected_activation_height = 900 @@ -363,7 +361,6 @@ def get_llmq_size(self, llmq_type): 100: 4, # In this test size for llmqType 100 is overwritten to 4 102: 3, 103: 4, - 104: 4, # In this test size for llmqType 104 is overwritten to 4 106: 3 }.get(llmq_type, -1) @@ -392,7 +389,7 @@ def move_to_next_cycle(self): # move forward to next DKG skip_count = cycle_length - (cur_block % cycle_length) if skip_count != 0: - self.bump_mocktime(1, nodes=nodes) + self.bump_mocktime(1) self.generate(self.nodes[0], skip_count, sync_fun=self.no_op) self.sync_blocks(nodes) self.log.info('Moved from block %d to %d' % (cur_block, self.nodes[0].getblockcount())) diff --git a/test/functional/feature_llmq_signing.py b/test/functional/feature_llmq_signing.py index 082bfe7e83467..11bda6dbfa881 100755 --- a/test/functional/feature_llmq_signing.py +++ b/test/functional/feature_llmq_signing.py @@ -16,6 +16,7 @@ from test_framework.util import assert_equal, assert_raises_rpc_error, force_finish_mnsync +q_type=100 class LLMQSigningTest(DashTestFramework): def set_test_params(self): self.set_dash_test_params(6, 5) @@ -43,11 +44,11 @@ def run_test(self): def check_sigs(hasrecsigs, isconflicting1, isconflicting2): for mn in self.mninfo: - if mn.node.quorum("hasrecsig", 104, id, msgHash) != hasrecsigs: + if mn.node.quorum("hasrecsig", q_type, id, msgHash) != hasrecsigs: return False - if mn.node.quorum("isconflicting", 104, id, msgHash) != isconflicting1: + if mn.node.quorum("isconflicting", q_type, id, msgHash) != isconflicting1: return False - if mn.node.quorum("isconflicting", 104, id, msgHashConflict) != isconflicting2: + if mn.node.quorum("isconflicting", q_type, id, msgHashConflict) != isconflicting2: return False return True @@ -61,24 +62,24 @@ def assert_sigs_nochange(hasrecsigs, isconflicting1, isconflicting2, timeout): wait_for_sigs(False, False, False, 1) # Sign first share without any optional parameter, should not result in recovered sig - self.mninfo[0].node.quorum("sign", 104, id, msgHash) + self.mninfo[0].node.quorum("sign", q_type, id, msgHash) assert_sigs_nochange(False, False, False, 3) # Sign second share and test optional quorumHash parameter, should not result in recovered sig # 1. Providing an invalid quorum hash should fail and cause no changes for sigs - assert not self.mninfo[1].node.quorum("sign", 104, id, msgHash, msgHash) + assert not self.mninfo[1].node.quorum("sign", q_type, id, msgHash, msgHash) assert_sigs_nochange(False, False, False, 3) # 2. Providing a valid quorum hash should succeed and cause no changes for sigss - quorumHash = self.mninfo[1].node.quorum("selectquorum", 104, id)["quorumHash"] - assert self.mninfo[1].node.quorum("sign", 104, id, msgHash, quorumHash) + quorumHash = self.mninfo[1].node.quorum("selectquorum", q_type, id)["quorumHash"] + assert self.mninfo[1].node.quorum("sign", q_type, id, msgHash, quorumHash) assert_sigs_nochange(False, False, False, 3) # Sign third share and test optional submit parameter if spork21 is enabled, should result in recovered sig # and conflict for msgHashConflict if self.options.spork21: # 1. Providing an invalid quorum hash and set submit=false, should throw an error - assert_raises_rpc_error(-8, 'quorum not found', self.mninfo[2].node.quorum, "sign", 104, id, msgHash, id, False) + assert_raises_rpc_error(-8, 'quorum not found', self.mninfo[2].node.quorum, "sign", q_type, id, msgHash, id, False) # 2. Providing a valid quorum hash and set submit=false, should return a valid sigShare object - sig_share_rpc_1 = self.mninfo[2].node.quorum("sign", 104, id, msgHash, quorumHash, False) - sig_share_rpc_2 = self.mninfo[2].node.quorum("sign", 104, id, msgHash, "", False) + sig_share_rpc_1 = self.mninfo[2].node.quorum("sign", q_type, id, msgHash, quorumHash, False) + sig_share_rpc_2 = self.mninfo[2].node.quorum("sign", q_type, id, msgHash, "", False) assert_equal(sig_share_rpc_1, sig_share_rpc_2) assert_sigs_nochange(False, False, False, 3) # 3. Sending the sig share received from RPC to the recovery member through P2P interface, should result @@ -93,7 +94,7 @@ def assert_sigs_nochange(hasrecsigs, isconflicting1, isconflicting2, timeout): for mn in self.mninfo: assert mn.node.getconnectioncount() == self.llmq_size # Get the current recovery member of the quorum - q = self.nodes[0].quorum('selectquorum', 104, id) + q = self.nodes[0].quorum('selectquorum', q_type, id) mn = self.get_mninfo(q['recoveryMembers'][0]) # Open a P2P connection to it p2p_interface = mn.node.add_p2p_connection(P2PInterface()) @@ -101,7 +102,7 @@ def assert_sigs_nochange(hasrecsigs, isconflicting1, isconflicting2, timeout): p2p_interface.send_message(msg_qsigshare([sig_share])) else: # If spork21 is not enabled just sign regularly - self.mninfo[2].node.quorum("sign", 104, id, msgHash) + self.mninfo[2].node.quorum("sign", q_type, id, msgHash) wait_for_sigs(True, False, True, 15) @@ -110,19 +111,19 @@ def assert_sigs_nochange(hasrecsigs, isconflicting1, isconflicting2, timeout): # Test `quorum verify` rpc node = self.mninfo[0].node - recsig = node.quorum("getrecsig", 104, id, msgHash) + recsig = node.quorum("getrecsig", q_type, id, msgHash) # Find quorum automatically height = node.getblockcount() height_bad = node.getblockheader(recsig["quorumHash"])["height"] hash_bad = node.getblockhash(0) - assert node.quorum("verify", 104, id, msgHash, recsig["sig"]) - assert node.quorum("verify", 104, id, msgHash, recsig["sig"], "", height) - assert not node.quorum("verify", 104, id, msgHashConflict, recsig["sig"]) - assert not node.quorum("verify", 104, id, msgHash, recsig["sig"], "", height_bad) + assert node.quorum("verify", q_type, id, msgHash, recsig["sig"]) + assert node.quorum("verify", q_type, id, msgHash, recsig["sig"], "", height) + assert not node.quorum("verify", q_type, id, msgHashConflict, recsig["sig"]) + assert not node.quorum("verify", q_type, id, msgHash, recsig["sig"], "", height_bad) # Use specific quorum - assert node.quorum("verify", 104, id, msgHash, recsig["sig"], recsig["quorumHash"]) - assert not node.quorum("verify", 104, id, msgHashConflict, recsig["sig"], recsig["quorumHash"]) - assert_raises_rpc_error(-8, "quorum not found", node.quorum, "verify", 104, id, msgHash, recsig["sig"], hash_bad) + assert node.quorum("verify", q_type, id, msgHash, recsig["sig"], recsig["quorumHash"]) + assert not node.quorum("verify", q_type, id, msgHashConflict, recsig["sig"], recsig["quorumHash"]) + assert_raises_rpc_error(-8, "quorum not found", node.quorum, "verify", q_type, id, msgHash, recsig["sig"], hash_bad) # Mine one more quorum, so that we have 2 active ones, nothing should change self.mine_quorum() @@ -131,10 +132,10 @@ def assert_sigs_nochange(hasrecsigs, isconflicting1, isconflicting2, timeout): # Create a recovered sig for the oldest quorum i.e. the active quorum which will be moved # out of the active set when a new quorum appears request_id = 2 - oldest_quorum_hash = node.quorum("list")["llmq_test_instantsend"][-1] + oldest_quorum_hash = node.quorum("list")["llmq_test"][-1] # Search for a request id which selects the last active quorum while True: - selected_hash = node.quorum('selectquorum', 104, uint256_to_string(request_id))["quorumHash"] + selected_hash = node.quorum('selectquorum', q_type, uint256_to_string(request_id))["quorumHash"] if selected_hash == oldest_quorum_hash: break else: @@ -142,12 +143,12 @@ def assert_sigs_nochange(hasrecsigs, isconflicting1, isconflicting2, timeout): # Produce the recovered signature id = uint256_to_string(request_id) for mn in self.mninfo: - mn.node.quorum("sign", 104, id, msgHash) + mn.node.quorum("sign", q_type, id, msgHash) # And mine a quorum to move the quorum which signed out of the active set self.mine_quorum() # Verify the recovered sig. This triggers the "signHeight + dkgInterval" verification - recsig = node.quorum("getrecsig", 104, id, msgHash) - assert node.quorum("verify", 104, id, msgHash, recsig["sig"], "", node.getblockcount()) + recsig = node.quorum("getrecsig", q_type, id, msgHash) + assert node.quorum("verify", q_type, id, msgHash, recsig["sig"], "", node.getblockcount()) recsig_time = self.mocktime @@ -166,21 +167,21 @@ def assert_sigs_nochange(hasrecsigs, isconflicting1, isconflicting2, timeout): wait_for_sigs(False, False, False, 15) for i in range(2): - self.mninfo[i].node.quorum("sign", 104, id, msgHashConflict) + self.mninfo[i].node.quorum("sign", q_type, id, msgHashConflict) for i in range(2, 5): - self.mninfo[i].node.quorum("sign", 104, id, msgHash) + self.mninfo[i].node.quorum("sign", q_type, id, msgHash) wait_for_sigs(True, False, True, 15) if self.options.spork21: id = uint256_to_string(request_id + 1) # Isolate the node that is responsible for the recovery of a signature and assert that recovery fails - q = self.nodes[0].quorum('selectquorum', 104, id) + q = self.nodes[0].quorum('selectquorum', q_type, id) mn = self.get_mninfo(q['recoveryMembers'][0]) mn.node.setnetworkactive(False) self.wait_until(lambda: mn.node.getconnectioncount() == 0) for i in range(4): - self.mninfo[i].node.quorum("sign", 104, id, msgHash) + self.mninfo[i].node.quorum("sign", q_type, id, msgHash) assert_sigs_nochange(False, False, False, 3) # Need to re-connect so that it later gets the recovered sig mn.node.setnetworkactive(True) diff --git a/test/functional/feature_llmq_simplepose.py b/test/functional/feature_llmq_simplepose.py index ea4d51d381e2e..c65f1844fa61a 100755 --- a/test/functional/feature_llmq_simplepose.py +++ b/test/functional/feature_llmq_simplepose.py @@ -18,8 +18,10 @@ class LLMQSimplePoSeTest(DashTestFramework): def set_test_params(self): + self.extra_args = [[ f'-testactivationheight=dip0024@9999' ]] * 6 self.set_dash_test_params(6, 5) self.set_dash_llmq_test_params(5, 3) + # rotating quorums add instability for this functional tests def run_test(self): @@ -177,6 +179,11 @@ def test_banning(self, invalidate_proc, expected_connections=None): self.log.info("Expecting instant PoSe banning") self.reset_probe_timeouts() self.mine_quorum(expected_connections=expected_connections, expected_members=expected_contributors, expected_contributions=expected_contributors, expected_complaints=expected_complaints, expected_commitments=expected_contributors, mninfos_online=mninfos_online, mninfos_valid=mninfos_valid) + + if not self.check_banned(mn): + self.log.info("Instant ban still requires 2 missing DKG round. If it is not banned yet, mine 2nd one") + self.reset_probe_timeouts() + self.mine_quorum(expected_connections=expected_connections, expected_members=expected_contributors, expected_contributions=expected_contributors, expected_complaints=expected_complaints, expected_commitments=expected_contributors, mninfos_online=mninfos_online, mninfos_valid=mninfos_valid) else: # It's ok to miss probes/quorum connections up to 5 times. # 6th time is when it should be banned for sure. diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 38eb7a7fb021a..287641142d684 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -168,7 +168,7 @@ def _test_getblockchaininfo(self): 'dip0003': { 'type': 'buried', 'active': False, 'height': 432}, 'dip0008': { 'type': 'buried', 'active': True, 'height': 1}, 'dip0020': { 'type': 'buried', 'active': True, 'height': 1}, - 'dip0024': { 'type': 'buried', 'active': False, 'height': 900}, + 'dip0024': { 'type': 'buried', 'active': True, 'height': 1}, 'realloc': { 'type': 'buried', 'active': True, 'height': 1}, 'v19': { 'type': 'buried', 'active': False, 'height': 900}, 'v20': { 'type': 'buried', 'active': False, 'height': 900}, diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 6aa7a4a53ce5a..9c84236369fbb 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1836,7 +1836,7 @@ def mine_quorum(self, llmq_type_name="llmq_test", llmq_type=100, expected_connec # move forward to next DKG skip_count = 24 - (self.nodes[0].getblockcount() % 24) if skip_count != 0: - self.bump_mocktime(1, nodes=nodes) + self.bump_mocktime(1) self.generate(self.nodes[0], skip_count, sync_fun=self.no_op) self.sync_blocks(nodes) @@ -1844,9 +1844,9 @@ def mine_quorum(self, llmq_type_name="llmq_test", llmq_type=100, expected_connec self.log.info("Expected quorum_hash:"+str(q)) self.log.info("Waiting for phase 1 (init)") self.wait_for_quorum_phase(q, 1, expected_members, None, 0, mninfos_online, llmq_type_name=llmq_type_name) - self.wait_for_quorum_connections(q, expected_connections, mninfos_online, wait_proc=lambda: self.bump_mocktime(1, nodes=nodes), llmq_type_name=llmq_type_name) + self.wait_for_quorum_connections(q, expected_connections, mninfos_online, wait_proc=lambda: self.bump_mocktime(1), llmq_type_name=llmq_type_name) if spork23_active: - self.wait_for_masternode_probes(q, mninfos_online, wait_proc=lambda: self.bump_mocktime(1, nodes=nodes)) + self.wait_for_masternode_probes(q, mninfos_online, wait_proc=lambda: self.bump_mocktime(1)) self.move_blocks(nodes, 2) @@ -1877,7 +1877,7 @@ def mine_quorum(self, llmq_type_name="llmq_test", llmq_type=100, expected_connec self.wait_for_quorum_commitment(q, nodes, llmq_type=llmq_type) self.log.info("Mining final commitment") - self.bump_mocktime(1, nodes=nodes) + self.bump_mocktime(1) self.nodes[0].getblocktemplate() # this calls CreateNewBlock self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_blocks(nodes)) @@ -1928,9 +1928,9 @@ def mine_cycle_quorum(self, is_first=True): self.log.info("quorumIndex 0: Waiting for phase 1 (init)") self.wait_for_quorum_phase(q_0, 1, expected_members, None, 0, mninfos_online, llmq_type_name) self.log.info("quorumIndex 0: Waiting for quorum connections (init)") - self.wait_for_quorum_connections(q_0, expected_connections, mninfos_online, llmq_type_name, wait_proc=lambda: self.bump_mocktime(1, nodes=nodes)) + self.wait_for_quorum_connections(q_0, expected_connections, mninfos_online, llmq_type_name, wait_proc=lambda: self.bump_mocktime(1)) if spork23_active: - self.wait_for_masternode_probes(q_0, mninfos_online, wait_proc=lambda: self.bump_mocktime(1, nodes=nodes), llmq_type_name=llmq_type_name) + self.wait_for_masternode_probes(q_0, mninfos_online, wait_proc=lambda: self.bump_mocktime(1), llmq_type_name=llmq_type_name) self.move_blocks(nodes, 1) @@ -1940,9 +1940,9 @@ def mine_cycle_quorum(self, is_first=True): self.log.info("quorumIndex 1: Waiting for phase 1 (init)") self.wait_for_quorum_phase(q_1, 1, expected_members, None, 0, mninfos_online, llmq_type_name) self.log.info("quorumIndex 1: Waiting for quorum connections (init)") - self.wait_for_quorum_connections(q_1, expected_connections, mninfos_online, llmq_type_name, wait_proc=lambda: self.bump_mocktime(1, nodes=nodes)) + self.wait_for_quorum_connections(q_1, expected_connections, mninfos_online, llmq_type_name, wait_proc=lambda: self.bump_mocktime(1)) if spork23_active: - self.wait_for_masternode_probes(q_1, mninfos_online, wait_proc=lambda: self.bump_mocktime(1, nodes=nodes), llmq_type_name=llmq_type_name) + self.wait_for_masternode_probes(q_1, mninfos_online, wait_proc=lambda: self.bump_mocktime(1), llmq_type_name=llmq_type_name) self.move_blocks(nodes, 1) @@ -1994,7 +1994,7 @@ def mine_cycle_quorum(self, is_first=True): self.log.info("quorumIndex 1: Waiting for phase 6 (finalization)") self.wait_for_quorum_phase(q_1, 6, expected_members, None, 0, mninfos_online, llmq_type_name) self.log.info("Mining final commitments") - self.bump_mocktime(1, nodes=nodes) + self.bump_mocktime(1) self.nodes[0].getblocktemplate() # this calls CreateNewBlock self.generate(self.nodes[0], 1, sync_fun=lambda: self.sync_blocks(nodes))