From 26e9813672d5d9da6483c0b9ef7ace2e4e1713fa Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 10 Oct 2024 16:03:30 +0700 Subject: [PATCH 01/11] fix: assertion in Credit Pool validation during connecting blocks It can happen because now order of activation of hardforks v20, mn_rr, dip3 can be changed by using testactivationheight on Regtest and no more guarantee about this assertions --- src/evo/specialtxman.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/evo/specialtxman.cpp b/src/evo/specialtxman.cpp index 5ed1e08c10..969efa2703 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) { From 4dafec870c692420f30c6be3350277f6574efe90 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 21 Nov 2024 16:05:27 +0700 Subject: [PATCH 02/11] fix: add check that DIP0003 activated before retrieving CbTx for CreditPool --- src/evo/creditpool.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/evo/creditpool.cpp b/src/evo/creditpool.cpp index abcf72650a..e1b0bb3756 100644 --- a/src/evo/creditpool.cpp +++ b/src/evo/creditpool.cpp @@ -114,17 +114,20 @@ void CCreditPoolManager::AddToCache(const uint256& block_hash, int height, const static std::optional GetBlockForCreditPool(const CBlockIndex* const 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; } From d8ce0a74fa64deec8c263cfe872b3a952abe961a Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 10 Oct 2024 15:33:54 +0700 Subject: [PATCH 03/11] docs: updated comment for DIP0003 activation on RegTest --- src/chainparams.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 616f4e650f..b4b47682ad 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -790,7 +790,8 @@ public: 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 From de821b9b1516d9dd39f99f2edb76a99b5f4dcd81 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Fri, 9 Aug 2024 00:59:32 +0700 Subject: [PATCH 04/11] refactor: remove command line argument -bip147height, -dip8params bip147height is superseeded by -testactivationheight=bip147@height dip8params is superseeded by -testactivationheight=dip0008@height --- doc/release-notes-6325.md | 4 ++++ src/chainparams.cpp | 46 --------------------------------------- src/chainparamsbase.cpp | 2 -- 3 files changed, 4 insertions(+), 48 deletions(-) create mode 100644 doc/release-notes-6325.md diff --git a/doc/release-notes-6325.md b/doc/release-notes-6325.md new file mode 100644 index 0000000000..84c02201d4 --- /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 b4b47682ad..4d7e5841bc 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -846,8 +846,6 @@ public: UpdateActivationParametersFromArgs(args); UpdateDIP3ParametersFromArgs(args); - UpdateDIP8ParametersFromArgs(args); - UpdateBIP147ParametersFromArgs(args); UpdateBudgetParametersFromArgs(args); genesis = CreateGenesisBlock(1417713337, 1096447, 0x207fffff, 1, 50 * COIN); @@ -966,21 +964,6 @@ public: } 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. */ @@ -1137,35 +1120,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 d7ef237c0e..755025c17e 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -20,8 +20,6 @@ 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("-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); From 343c74b77984e03811acc2d6abf9898108de3b71 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Fri, 22 Nov 2024 21:57:56 +0700 Subject: [PATCH 05/11] fix: intermittent error in feature_index_prune due to DKG influence --- test/functional/feature_index_prune.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/test/functional/feature_index_prune.py b/test/functional/feature_index_prune.py index dcb649362f..7fa3a56c5c 100755 --- a/test/functional/feature_index_prune.py +++ b/test/functional/feature_index_prune.py @@ -11,16 +11,17 @@ from test_framework.util import ( ) 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 @@ class FeatureIndexPruneTest(BitcoinTestFramework): 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 @@ class FeatureIndexPruneTest(BitcoinTestFramework): 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 @@ class FeatureIndexPruneTest(BitcoinTestFramework): 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']): From 632c4c4bcd0bff39483dc82284edad8a389929ec Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 27 Aug 2024 18:10:39 +0700 Subject: [PATCH 06/11] feat: re-bury DIP0024 with new height when quorums actually appeared For current implementation it is not important when exactly fork happened yet important to know when first rotating quorum formed --- src/chainparams.cpp | 6 +----- src/consensus/params.h | 4 +--- src/llmq/options.cpp | 14 +++++++------- src/llmq/options.h | 3 ++- src/test/evo_utils_tests.cpp | 20 ++++++++------------ 5 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 4d7e5841bc..5f05fc0262 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -189,7 +189,6 @@ public: 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 @@ public: 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 @@ public: 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 @@ -797,7 +794,6 @@ public: 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.V19Height = 900; consensus.V20Height = 900; diff --git a/src/consensus/params.h b/src/consensus/params.h index 508d477c54..74a0c035d4 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/llmq/options.cpp b/src/llmq/options.cpp index c1956e8a67..d0723f7f12 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 f78f2362fd..de220f499c 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 4d55549246..65c405f9bd 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) From 2bafadfc34966c26996670130bdd9060c9ee6e0b Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Wed, 9 Oct 2024 14:42:14 +0700 Subject: [PATCH 07/11] feat: put DIP0024 activation to block 1 on RegTest --- src/chainparams.cpp | 4 +- src/chainparamsbase.cpp | 2 +- src/test/util/setup_common.cpp | 4 +- .../feature_dip4_coinbasemerkleroots.py | 3 +- test/functional/feature_llmq_rotation.py | 7 +-- test/functional/feature_llmq_signing.py | 59 ++++++++++--------- test/functional/rpc_blockchain.py | 2 +- 7 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 5f05fc0262..671e08e4b1 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -794,7 +794,7 @@ public: consensus.DIP0008Height = 1; // Always active unless overridden consensus.BRRHeight = 1; // Always active unless overridden consensus.DIP0020Height = 1; // Always active unless overridden - consensus.DIP0024QuorumsHeight = 900; + consensus.DIP0024QuorumsHeight = 1; // Always have dip0024 quorums unless overridden consensus.V19Height = 900; consensus.V20Height = 900; consensus.MN_RRHeight = 900; @@ -1025,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") { diff --git a/src/chainparamsbase.cpp b/src/chainparamsbase.cpp index 755025c17e..1a05491f06 100644 --- a/src/chainparamsbase.cpp +++ b/src/chainparamsbase.cpp @@ -20,7 +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("-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/test/util/setup_common.cpp b/src/test/util/setup_common.cpp index 25b355ef71..b97546f767 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 d8e05cb2e0..920633c08b 100755 --- a/test/functional/feature_dip4_coinbasemerkleroots.py +++ b/test/functional/feature_dip4_coinbasemerkleroots.py @@ -18,6 +18,7 @@ from test_framework.test_framework import DashTestFramework 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 @@ class TestP2PConn(P2PInterface): 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_llmq_rotation.py b/test/functional/feature_llmq_rotation.py index 233f39d495..1d4141c436 100755 --- a/test/functional/feature_llmq_rotation.py +++ b/test/functional/feature_llmq_rotation.py @@ -81,11 +81,9 @@ class LLMQQuorumRotationTest(DashTestFramework): 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 @@ class LLMQQuorumRotationTest(DashTestFramework): 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 @@ class LLMQQuorumRotationTest(DashTestFramework): 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) diff --git a/test/functional/feature_llmq_signing.py b/test/functional/feature_llmq_signing.py index 082bfe7e83..11bda6dbfa 100755 --- a/test/functional/feature_llmq_signing.py +++ b/test/functional/feature_llmq_signing.py @@ -16,6 +16,7 @@ from test_framework.test_framework import DashTestFramework 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 @@ class LLMQSigningTest(DashTestFramework): 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 @@ class LLMQSigningTest(DashTestFramework): 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 @@ class LLMQSigningTest(DashTestFramework): 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 @@ class LLMQSigningTest(DashTestFramework): 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 @@ class LLMQSigningTest(DashTestFramework): # 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 @@ class LLMQSigningTest(DashTestFramework): # 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 @@ class LLMQSigningTest(DashTestFramework): # 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 @@ class LLMQSigningTest(DashTestFramework): 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/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 38eb7a7fb0..287641142d 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -168,7 +168,7 @@ class BlockchainTest(BitcoinTestFramework): '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}, From efd4701d30350e0b7db74c6fd9accaaa03a1b2de Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 21 Nov 2024 16:48:40 +0700 Subject: [PATCH 08/11] fix: intermittent error for feature_llmq_simplepose due to rotating quorums --- test/functional/feature_llmq_simplepose.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/functional/feature_llmq_simplepose.py b/test/functional/feature_llmq_simplepose.py index ea4d51d381..3d5c382249 100755 --- a/test/functional/feature_llmq_simplepose.py +++ b/test/functional/feature_llmq_simplepose.py @@ -18,8 +18,10 @@ from test_framework.util import assert_equal, force_finish_mnsync, p2p_port 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): From cf84dffc9f4a89df2843c9c50a91d6322ec6ec23 Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Thu, 21 Nov 2024 21:51:37 +0700 Subject: [PATCH 09/11] fix: bump time for all nodes during mine_quorum in feature_llmq_rotation.py test --- test/functional/feature_llmq_rotation.py | 2 +- .../test_framework/test_framework.py | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/functional/feature_llmq_rotation.py b/test/functional/feature_llmq_rotation.py index 1d4141c436..9a11e6c940 100755 --- a/test/functional/feature_llmq_rotation.py +++ b/test/functional/feature_llmq_rotation.py @@ -389,7 +389,7 @@ class LLMQQuorumRotationTest(DashTestFramework): # 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/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index 6aa7a4a53c..9c84236369 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -1836,7 +1836,7 @@ class DashTestFramework(BitcoinTestFramework): # 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 @@ class DashTestFramework(BitcoinTestFramework): 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 @@ class DashTestFramework(BitcoinTestFramework): 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 @@ class DashTestFramework(BitcoinTestFramework): 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 @@ class DashTestFramework(BitcoinTestFramework): 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 @@ class DashTestFramework(BitcoinTestFramework): 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)) From f1905ca95039c6d6525483cfaef779a32a419dab Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Fri, 6 Dec 2024 21:43:19 +0700 Subject: [PATCH 10/11] fix: intermittent missing of PoSe ban in feature_llmq_simplepose.py --- test/functional/feature_llmq_simplepose.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/functional/feature_llmq_simplepose.py b/test/functional/feature_llmq_simplepose.py index 3d5c382249..c65f1844fa 100755 --- a/test/functional/feature_llmq_simplepose.py +++ b/test/functional/feature_llmq_simplepose.py @@ -179,6 +179,11 @@ class LLMQSimplePoSeTest(DashTestFramework): 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. From 906c2d79ba31629cd1637326dc0a6670df78746c Mon Sep 17 00:00:00 2001 From: Konstantin Akimov Date: Tue, 10 Dec 2024 15:41:30 +0700 Subject: [PATCH 11/11] refactor: add annotation gsl::not_null for ConstructCreditPool --- src/evo/creditpool.cpp | 8 +++++--- src/evo/creditpool.h | 4 +++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/evo/creditpool.cpp b/src/evo/creditpool.cpp index e1b0bb3756..c16950eba1 100644 --- a/src/evo/creditpool.cpp +++ b/src/evo/creditpool.cpp @@ -112,7 +112,8 @@ 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)) { @@ -132,7 +133,8 @@ static std::optional GetBlockForCreditPool(const CBlockIndex* const bloc 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) { @@ -213,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 de6f13595b..c27179edaa 100644 --- a/src/evo/creditpool.h +++ b/src/evo/creditpool.h @@ -16,6 +16,7 @@ #include +#include #include #include @@ -134,7 +135,8 @@ private: 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,