From 5429d82061d80bfcac1788094d551346b0e2331f Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 2 Dec 2020 14:12:53 +0300 Subject: [PATCH 01/12] Add LLMQ_100_67 quorums --- src/chainparams.cpp | 27 +++++++++++++++++++++++++++ src/consensus/params.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index ed63f6385cdf..02b848c9304c 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -262,6 +262,26 @@ static Consensus::LLMQParams llmq400_85 = { .recoveryMembers = 100, }; +// Used for Platform +static Consensus::LLMQParams llmq100_67 = { + .type = Consensus::LLMQ_100_67, + .name = "llmq_100_67", + .size = 100, + .minSize = 90, + .threshold = 67, + + .dkgInterval = 24, // one DKG per hour + .dkgPhaseBlocks = 2, + .dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization + .dkgMiningWindowEnd = 18, + .dkgBadVotesThreshold = 80, + + .signingActiveQuorumCount = 24, // a full day worth of LLMQs + + .keepOldConnections = 25, + .recoveryMembers = 50, +}; + /** * Main network @@ -417,8 +437,10 @@ class CMainParams : public CChainParams { consensus.llmqs[Consensus::LLMQ_50_60] = llmq50_60; consensus.llmqs[Consensus::LLMQ_400_60] = llmq400_60; consensus.llmqs[Consensus::LLMQ_400_85] = llmq400_85; + consensus.llmqs[Consensus::LLMQ_100_67] = llmq100_67; consensus.llmqTypeChainLocks = Consensus::LLMQ_400_60; consensus.llmqTypeInstantSend = Consensus::LLMQ_50_60; + consensus.llmqTypePlatform = Consensus::LLMQ_100_67; fDefaultConsistencyChecks = false; fRequireStandard = true; @@ -615,8 +637,10 @@ class CTestNetParams : public CChainParams { consensus.llmqs[Consensus::LLMQ_50_60] = llmq50_60; consensus.llmqs[Consensus::LLMQ_400_60] = llmq400_60; consensus.llmqs[Consensus::LLMQ_400_85] = llmq400_85; + consensus.llmqs[Consensus::LLMQ_100_67] = llmq100_67; consensus.llmqTypeChainLocks = Consensus::LLMQ_50_60; consensus.llmqTypeInstantSend = Consensus::LLMQ_50_60; + consensus.llmqTypePlatform = Consensus::LLMQ_100_67; fDefaultConsistencyChecks = false; fRequireStandard = false; @@ -794,8 +818,10 @@ class CDevNetParams : public CChainParams { consensus.llmqs[Consensus::LLMQ_50_60] = llmq50_60; consensus.llmqs[Consensus::LLMQ_400_60] = llmq400_60; consensus.llmqs[Consensus::LLMQ_400_85] = llmq400_85; + consensus.llmqs[Consensus::LLMQ_100_67] = llmq100_67; consensus.llmqTypeChainLocks = Consensus::LLMQ_50_60; consensus.llmqTypeInstantSend = Consensus::LLMQ_50_60; + consensus.llmqTypePlatform = Consensus::LLMQ_100_67; fDefaultConsistencyChecks = false; fRequireStandard = false; @@ -974,6 +1000,7 @@ class CRegTestParams : public CChainParams { consensus.llmqs[Consensus::LLMQ_TEST] = llmq_test; consensus.llmqTypeChainLocks = Consensus::LLMQ_TEST; consensus.llmqTypeInstantSend = Consensus::LLMQ_TEST; + consensus.llmqTypePlatform = Consensus::LLMQ_TEST; } }; diff --git a/src/consensus/params.h b/src/consensus/params.h index 9c3faa21dc2d..5509c0c8b0e6 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -53,6 +53,7 @@ enum LLMQType : uint8_t LLMQ_50_60 = 1, // 50 members, 30 (60%) threshold, one per hour LLMQ_400_60 = 2, // 400 members, 240 (60%) threshold, one every 12 hours LLMQ_400_85 = 3, // 400 members, 340 (85%) threshold, one every 24 hours + LLMQ_100_67 = 4, // 100 members, 67 (67%) threshold, one per hour // for testing only LLMQ_TEST = 100, // 3 members, 2 (66%) threshold, one per hour. Params might differ when -llmqtestparams is used @@ -190,6 +191,7 @@ struct Params { std::map llmqs; LLMQType llmqTypeChainLocks; LLMQType llmqTypeInstantSend{LLMQ_NONE}; + LLMQType llmqTypePlatform{LLMQ_NONE}; }; } // namespace Consensus From 25e1fba75b52d31e328a75ee1f653167b6d2c1b7 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 2 Dec 2020 14:14:28 +0300 Subject: [PATCH 02/12] Re-use DEPLOYMENT_V17 bit to activate LLMQ_100_67 quorums --- src/llmq/quorums_blockprocessor.cpp | 3 ++- src/llmq/quorums_utils.cpp | 39 +++++++++++++++++++++++++++++ src/llmq/quorums_utils.h | 2 ++ src/miner.cpp | 2 +- src/rpc/rpcquorums.cpp | 6 ++--- 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index 3799d8a29198..280b6493582a 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -132,7 +132,8 @@ bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, const CBlockIndex* // The following checks make sure that there is always a (possibly null) commitment while in the mining phase // until the first non-null commitment has been mined. After the non-null commitment, no other commitments are // allowed, including null commitments. - for (const auto& p : Params().GetConsensus().llmqs) { + // Note: must only check quorums that were enabled at the _previous_ block height to match mining logic + for (const auto& p : CLLMQUtils::GetEnabledQuorumTypes(pindex->pprev)) { // skip these checks when replaying blocks after the crash if (!chainActive.Tip()) { break; diff --git a/src/llmq/quorums_utils.cpp b/src/llmq/quorums_utils.cpp index 80245acb5acc..d24e9d8ba1a8 100644 --- a/src/llmq/quorums_utils.cpp +++ b/src/llmq/quorums_utils.cpp @@ -17,6 +17,9 @@ namespace llmq std::vector CLLMQUtils::GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum) { + if (!IsQuorumTypeEnabledAtBlock(llmqType, pindexQuorum->pprev)) { + return {}; + } auto& params = Params().GetConsensus().llmqs.at(llmqType); auto allMns = deterministicMNManager->GetListForBlock(pindexQuorum); auto modifier = ::SerializeHash(std::make_pair(llmqType, pindexQuorum->GetBlockHash())); @@ -254,5 +257,41 @@ bool CLLMQUtils::IsQuorumActive(Consensus::LLMQType llmqType, const uint256& quo return false; } +bool CLLMQUtils::IsQuorumTypeEnabledAtBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex) +{ + const Consensus::Params& consensusParams = Params().GetConsensus(); + bool f_v17_Active = VersionBitsState(pindex, consensusParams, Consensus::DEPLOYMENT_V17, versionbitscache) == ThresholdState::ACTIVE; + + switch (llmqType) + { + case Consensus::LLMQ_50_60: + case Consensus::LLMQ_400_60: + case Consensus::LLMQ_400_85: + break; + case Consensus::LLMQ_100_67: + if (!f_v17_Active) { + return false; + } + break; + case Consensus::LLMQ_TEST: + case Consensus::LLMQ_DEVNET: + break; + default: + throw std::runtime_error(strprintf("%s: Unknown LLMQ type %d", __func__, llmqType)); + } + + return true; +} + +std::map CLLMQUtils::GetEnabledQuorumTypes(const CBlockIndex* pindex) +{ + std::map ret; + for (const auto& pair : Params().GetConsensus().llmqs) { + if (IsQuorumTypeEnabledAtBlock(pair.first, pindex)) { + ret.emplace(pair); + } + } + return ret; +} } // namespace llmq diff --git a/src/llmq/quorums_utils.h b/src/llmq/quorums_utils.h index 2dea1a15da94..c717f3881ddd 100644 --- a/src/llmq/quorums_utils.h +++ b/src/llmq/quorums_utils.h @@ -41,6 +41,8 @@ class CLLMQUtils static void AddQuorumProbeConnections(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& myProTxHash); static bool IsQuorumActive(Consensus::LLMQType llmqType, const uint256& quorumHash); + static bool IsQuorumTypeEnabledAtBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex); + static std::map GetEnabledQuorumTypes(const CBlockIndex* pindex); template static void IterateNodesRandom(NodesContainer& nodeStates, Continue&& cont, Callback&& callback, FastRandomContext& rnd) diff --git a/src/miner.cpp b/src/miner.cpp index 6de45f9d00f1..0877adabbc5e 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -148,7 +148,7 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc : pblock->GetBlockTime(); if (fDIP0003Active_context) { - for (auto& p : chainparams.GetConsensus().llmqs) { + for (auto& p : llmq::CLLMQUtils::GetEnabledQuorumTypes(pindexPrev)) { CTransactionRef qcTx; if (llmq::quorumBlockProcessor->GetMinableCommitmentTx(p.first, nHeight, qcTx)) { pblock->vtx.emplace_back(qcTx); diff --git a/src/rpc/rpcquorums.cpp b/src/rpc/rpcquorums.cpp index 95150061350f..3e980e1cafa0 100644 --- a/src/rpc/rpcquorums.cpp +++ b/src/rpc/rpcquorums.cpp @@ -54,7 +54,7 @@ UniValue quorum_list(const JSONRPCRequest& request) UniValue ret(UniValue::VOBJ); - for (auto& p : Params().GetConsensus().llmqs) { + for (auto& p : llmq::CLLMQUtils::GetEnabledQuorumTypes(chainActive.Tip())) { UniValue v(UniValue::VARR); auto quorums = llmq::quorumManager->ScanQuorums(p.first, chainActive.Tip(), count > -1 ? count : p.second.signingActiveQuorumCount); @@ -181,7 +181,7 @@ UniValue quorum_dkgstatus(const JSONRPCRequest& request) UniValue minableCommitments(UniValue::VOBJ); UniValue quorumConnections(UniValue::VOBJ); - for (const auto& p : Params().GetConsensus().llmqs) { + for (const auto& p : llmq::CLLMQUtils::GetEnabledQuorumTypes(chainActive.Tip())) { auto& params = p.second; if (fMasternodeMode) { @@ -265,7 +265,7 @@ UniValue quorum_memberof(const JSONRPCRequest& request) UniValue result(UniValue::VARR); - for (const auto& p : Params().GetConsensus().llmqs) { + for (const auto& p : llmq::CLLMQUtils::GetEnabledQuorumTypes(pindexTip)) { auto& params = p.second; size_t count = params.signingActiveQuorumCount; if (scanQuorumsCount != -1) { From 44a0fafbead466939aaedffd553349686cf883f2 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 2 Dec 2020 14:17:33 +0300 Subject: [PATCH 03/12] Add LLMQ_TEST_NEW quorum and test its activation --- src/chainparams.cpp | 21 +++++++++++++ src/consensus/params.h | 3 ++ src/llmq/quorums_utils.cpp | 1 + test/functional/feature_platform_quorums.py | 34 +++++++++++++++++++++ test/functional/test_runner.py | 1 + 5 files changed, 60 insertions(+) create mode 100755 test/functional/feature_platform_quorums.py diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 02b848c9304c..e8ef954b5c9a 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -184,6 +184,26 @@ static Consensus::LLMQParams llmq_test = { .recoveryMembers = 3, }; +// this one is for testing only +static Consensus::LLMQParams llmq_test_new = { + .type = Consensus::LLMQ_TEST_NEW, + .name = "llmq_test_new", + .size = 3, + .minSize = 2, + .threshold = 2, + + .dkgInterval = 24, // one DKG per hour + .dkgPhaseBlocks = 2, + .dkgMiningWindowStart = 10, // dkgPhaseBlocks * 5 = after finalization + .dkgMiningWindowEnd = 18, + .dkgBadVotesThreshold = 2, + + .signingActiveQuorumCount = 2, // just a few ones to allow easier testing + + .keepOldConnections = 3, + .recoveryMembers = 3, +}; + // this one is for devnets only static Consensus::LLMQParams llmq_devnet = { .type = Consensus::LLMQ_DEVNET, @@ -998,6 +1018,7 @@ class CRegTestParams : public CChainParams { // long living quorum params consensus.llmqs[Consensus::LLMQ_TEST] = llmq_test; + consensus.llmqs[Consensus::LLMQ_TEST_NEW] = llmq_test_new; consensus.llmqTypeChainLocks = Consensus::LLMQ_TEST; consensus.llmqTypeInstantSend = Consensus::LLMQ_TEST; consensus.llmqTypePlatform = Consensus::LLMQ_TEST; diff --git a/src/consensus/params.h b/src/consensus/params.h index 5509c0c8b0e6..c6cf03839c9f 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -60,6 +60,9 @@ enum LLMQType : uint8_t // for devnets only LLMQ_DEVNET = 101, // 10 members, 6 (60%) threshold, one per hour. Params might differ when -llmqdevnetparams is used + + // for testing activation of new quorums only + LLMQ_TEST_NEW = 102, // 3 members, 2 (66%) threshold, one per hour. Params might differ when -llmqtestparams is used }; // Configures a LLMQ and its DKG diff --git a/src/llmq/quorums_utils.cpp b/src/llmq/quorums_utils.cpp index d24e9d8ba1a8..dd0d0ff13d71 100644 --- a/src/llmq/quorums_utils.cpp +++ b/src/llmq/quorums_utils.cpp @@ -269,6 +269,7 @@ bool CLLMQUtils::IsQuorumTypeEnabledAtBlock(Consensus::LLMQType llmqType, const case Consensus::LLMQ_400_85: break; case Consensus::LLMQ_100_67: + case Consensus::LLMQ_TEST_NEW: if (!f_v17_Active) { return false; } diff --git a/test/functional/feature_platform_quorums.py b/test/functional/feature_platform_quorums.py new file mode 100755 index 000000000000..50fe1001aefc --- /dev/null +++ b/test/functional/feature_platform_quorums.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 +# Copyright (c) 2015-2020 The Dash Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import assert_equal, get_bip9_status + +''' +feature_platform_quorums.py + +Checks block reward reallocation correctness + +''' + + +class PlatformQuorumActivationTest(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 1 + + def run_test(self): + assert_equal(get_bip9_status(self.nodes[0], 'v17')['status'], 'locked_in') + ql = self.nodes[0].quorum("list") + assert_equal(len(ql), 1) + assert("llmq_test_new" not in ql) + self.nodes[0].generate(99) + assert_equal(get_bip9_status(self.nodes[0], 'v17')['status'], 'active') + self.nodes[0].generate(1) + ql = self.nodes[0].quorum("list") + assert_equal(len(ql), 2) + assert("llmq_test_new" in ql) + + +if __name__ == '__main__': + PlatformQuorumActivationTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 740e22946321..293688874f1e 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -147,6 +147,7 @@ 'wallet_encryption.py', 'feature_dersig.py', 'feature_cltv.py', + 'feature_platform_quorums.py', 'feature_governance_objects.py', 'rpc_uptime.py', 'wallet_resendwallettransactions.py', From 0e0305b5cb62ec8e8c77c312e1ff42dfc79d7176 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 2 Dec 2020 23:41:44 +0300 Subject: [PATCH 04/12] Tweak mine_quorum to work correctly with multiple quorum types And to avoid a potentialy endless "while" loop --- .../test_framework/test_framework.py | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/test/functional/test_framework/test_framework.py b/test/functional/test_framework/test_framework.py index c3a19fd52e12..371aafce355a 100755 --- a/test/functional/test_framework/test_framework.py +++ b/test/functional/test_framework/test_framework.py @@ -899,6 +899,16 @@ def check_dkg_comitments(): return all_ok wait_until(check_dkg_comitments, timeout=timeout, sleep=0.1) + def wait_for_quorum_list(self, quorum_hash, nodes, timeout=15, sleep=2): + def wait_func(): + if quorum_hash in self.nodes[0].quorum("list")["llmq_test"]: + return True + self.bump_mocktime(sleep, nodes=nodes) + self.nodes[0].generate(1) + sync_blocks(nodes) + return False + wait_until(wait_func, timeout=timeout, sleep=sleep) + def mine_quorum(self, expected_connections=None, expected_members=None, expected_contributions=None, expected_complaints=0, expected_justifications=0, expected_commitments=None, mninfos_online=None, mninfos_valid=None): spork21_active = self.nodes[0].spork('show')['SPORK_21_QUORUM_ALL_CONNECTED'] <= 1 @@ -921,8 +931,6 @@ def mine_quorum(self, expected_connections=None, expected_members=None, expected nodes = [self.nodes[0]] + [mn.node for mn in mninfos_online] - quorums = self.nodes[0].quorum("list") - # move forward to next DKG skip_count = 24 - (self.nodes[0].getblockcount() % 24) if skip_count != 0: @@ -974,12 +982,13 @@ def mine_quorum(self, expected_connections=None, expected_members=None, expected self.log.info("Mining final commitment") self.bump_mocktime(1, nodes=nodes) self.nodes[0].generate(1) - while quorums == self.nodes[0].quorum("list"): - time.sleep(2) - self.bump_mocktime(1, nodes=nodes) - self.nodes[0].generate(1) - sync_blocks(nodes) + sync_blocks(nodes) + + self.log.info("Waiting for quorum to appear in the list") + self.wait_for_quorum_list(q, nodes) + new_quorum = self.nodes[0].quorum("list", 1)["llmq_test"][0] + assert_equal(q, new_quorum) quorum_info = self.nodes[0].quorum("info", 100, new_quorum) # Mine 8 (SIGN_HEIGHT_OFFSET) more blocks to make sure that the new quorum gets eligable for signing sessions From 2d05a85407a28075c77661816a32c620961e69fc Mon Sep 17 00:00:00 2001 From: xdustinface Date: Fri, 4 Dec 2020 19:06:51 +0100 Subject: [PATCH 05/12] llmq: Rename IsQuorumTypeEnabledAtBlock -> IsQuorumTypeEnabled --- src/llmq/quorums_utils.cpp | 6 +++--- src/llmq/quorums_utils.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/llmq/quorums_utils.cpp b/src/llmq/quorums_utils.cpp index dd0d0ff13d71..685c9ddffbdb 100644 --- a/src/llmq/quorums_utils.cpp +++ b/src/llmq/quorums_utils.cpp @@ -17,7 +17,7 @@ namespace llmq std::vector CLLMQUtils::GetAllQuorumMembers(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum) { - if (!IsQuorumTypeEnabledAtBlock(llmqType, pindexQuorum->pprev)) { + if (!IsQuorumTypeEnabled(llmqType, pindexQuorum->pprev)) { return {}; } auto& params = Params().GetConsensus().llmqs.at(llmqType); @@ -257,7 +257,7 @@ bool CLLMQUtils::IsQuorumActive(Consensus::LLMQType llmqType, const uint256& quo return false; } -bool CLLMQUtils::IsQuorumTypeEnabledAtBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex) +bool CLLMQUtils::IsQuorumTypeEnabled(Consensus::LLMQType llmqType, const CBlockIndex* pindex) { const Consensus::Params& consensusParams = Params().GetConsensus(); bool f_v17_Active = VersionBitsState(pindex, consensusParams, Consensus::DEPLOYMENT_V17, versionbitscache) == ThresholdState::ACTIVE; @@ -288,7 +288,7 @@ std::map CLLMQUtils::GetEnabledQuoru { std::map ret; for (const auto& pair : Params().GetConsensus().llmqs) { - if (IsQuorumTypeEnabledAtBlock(pair.first, pindex)) { + if (IsQuorumTypeEnabled(pair.first, pindex)) { ret.emplace(pair); } } diff --git a/src/llmq/quorums_utils.h b/src/llmq/quorums_utils.h index c717f3881ddd..b377e8a6a794 100644 --- a/src/llmq/quorums_utils.h +++ b/src/llmq/quorums_utils.h @@ -41,7 +41,7 @@ class CLLMQUtils static void AddQuorumProbeConnections(Consensus::LLMQType llmqType, const CBlockIndex* pindexQuorum, const uint256& myProTxHash); static bool IsQuorumActive(Consensus::LLMQType llmqType, const uint256& quorumHash); - static bool IsQuorumTypeEnabledAtBlock(Consensus::LLMQType llmqType, const CBlockIndex* pindex); + static bool IsQuorumTypeEnabled(Consensus::LLMQType llmqType, const CBlockIndex* pindex); static std::map GetEnabledQuorumTypes(const CBlockIndex* pindex); template From d00c9aa5a830e996222b93edcdb64eec51fd55b7 Mon Sep 17 00:00:00 2001 From: xdustinface Date: Fri, 4 Dec 2020 19:15:14 +0100 Subject: [PATCH 06/12] chainparams|test: Rename llmq_test_new -> llmq_test_v17 --- src/chainparams.cpp | 6 +++--- test/functional/feature_platform_quorums.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index e8ef954b5c9a..35e62f8fcfee 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -185,9 +185,9 @@ static Consensus::LLMQParams llmq_test = { }; // this one is for testing only -static Consensus::LLMQParams llmq_test_new = { +static Consensus::LLMQParams llmq_test_v17 = { .type = Consensus::LLMQ_TEST_NEW, - .name = "llmq_test_new", + .name = "llmq_test_v17", .size = 3, .minSize = 2, .threshold = 2, @@ -1018,7 +1018,7 @@ class CRegTestParams : public CChainParams { // long living quorum params consensus.llmqs[Consensus::LLMQ_TEST] = llmq_test; - consensus.llmqs[Consensus::LLMQ_TEST_NEW] = llmq_test_new; + consensus.llmqs[Consensus::LLMQ_TEST_NEW] = llmq_test_v17; consensus.llmqTypeChainLocks = Consensus::LLMQ_TEST; consensus.llmqTypeInstantSend = Consensus::LLMQ_TEST; consensus.llmqTypePlatform = Consensus::LLMQ_TEST; diff --git a/test/functional/feature_platform_quorums.py b/test/functional/feature_platform_quorums.py index 50fe1001aefc..7a39c81eaa4d 100755 --- a/test/functional/feature_platform_quorums.py +++ b/test/functional/feature_platform_quorums.py @@ -21,13 +21,13 @@ def run_test(self): assert_equal(get_bip9_status(self.nodes[0], 'v17')['status'], 'locked_in') ql = self.nodes[0].quorum("list") assert_equal(len(ql), 1) - assert("llmq_test_new" not in ql) + assert("llmq_test_v17" not in ql) self.nodes[0].generate(99) assert_equal(get_bip9_status(self.nodes[0], 'v17')['status'], 'active') self.nodes[0].generate(1) ql = self.nodes[0].quorum("list") assert_equal(len(ql), 2) - assert("llmq_test_new" in ql) + assert("llmq_test_v17" in ql) if __name__ == '__main__': From b092b79e480ab34a7ae811075b43db0d5143db1a Mon Sep 17 00:00:00 2001 From: xdustinface Date: Fri, 4 Dec 2020 20:06:24 +0100 Subject: [PATCH 07/12] chainparams|consensus|llmq: Rename LLMQ_TEST_NEW -> LLMQ_TEST_V17 --- src/chainparams.cpp | 4 ++-- src/consensus/params.h | 2 +- src/llmq/quorums_utils.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 35e62f8fcfee..1b7030efb6af 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -186,7 +186,7 @@ static Consensus::LLMQParams llmq_test = { // this one is for testing only static Consensus::LLMQParams llmq_test_v17 = { - .type = Consensus::LLMQ_TEST_NEW, + .type = Consensus::LLMQ_TEST_V17, .name = "llmq_test_v17", .size = 3, .minSize = 2, @@ -1018,7 +1018,7 @@ class CRegTestParams : public CChainParams { // long living quorum params consensus.llmqs[Consensus::LLMQ_TEST] = llmq_test; - consensus.llmqs[Consensus::LLMQ_TEST_NEW] = llmq_test_v17; + consensus.llmqs[Consensus::LLMQ_TEST_V17] = llmq_test_v17; consensus.llmqTypeChainLocks = Consensus::LLMQ_TEST; consensus.llmqTypeInstantSend = Consensus::LLMQ_TEST; consensus.llmqTypePlatform = Consensus::LLMQ_TEST; diff --git a/src/consensus/params.h b/src/consensus/params.h index c6cf03839c9f..b11e9f7cdd10 100644 --- a/src/consensus/params.h +++ b/src/consensus/params.h @@ -62,7 +62,7 @@ enum LLMQType : uint8_t LLMQ_DEVNET = 101, // 10 members, 6 (60%) threshold, one per hour. Params might differ when -llmqdevnetparams is used // for testing activation of new quorums only - LLMQ_TEST_NEW = 102, // 3 members, 2 (66%) threshold, one per hour. Params might differ when -llmqtestparams is used + LLMQ_TEST_V17 = 102, // 3 members, 2 (66%) threshold, one per hour. Params might differ when -llmqtestparams is used }; // Configures a LLMQ and its DKG diff --git a/src/llmq/quorums_utils.cpp b/src/llmq/quorums_utils.cpp index 685c9ddffbdb..1676e17587c8 100644 --- a/src/llmq/quorums_utils.cpp +++ b/src/llmq/quorums_utils.cpp @@ -269,7 +269,7 @@ bool CLLMQUtils::IsQuorumTypeEnabled(Consensus::LLMQType llmqType, const CBlockI case Consensus::LLMQ_400_85: break; case Consensus::LLMQ_100_67: - case Consensus::LLMQ_TEST_NEW: + case Consensus::LLMQ_TEST_V17: if (!f_v17_Active) { return false; } From de92158df3151d3011baee0f3e51502b1f765b45 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Fri, 4 Dec 2020 23:27:16 +0300 Subject: [PATCH 08/12] Tweak few strings and the name of the test --- ...m_quorums.py => feature_new_quorum_type_activation.py} | 8 ++++---- test/functional/test_runner.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) rename test/functional/{feature_platform_quorums.py => feature_new_quorum_type_activation.py} (81%) diff --git a/test/functional/feature_platform_quorums.py b/test/functional/feature_new_quorum_type_activation.py similarity index 81% rename from test/functional/feature_platform_quorums.py rename to test/functional/feature_new_quorum_type_activation.py index 7a39c81eaa4d..a590361e51b6 100755 --- a/test/functional/feature_platform_quorums.py +++ b/test/functional/feature_new_quorum_type_activation.py @@ -6,14 +6,14 @@ from test_framework.util import assert_equal, get_bip9_status ''' -feature_platform_quorums.py +feature_new_quorum_type_activation.py -Checks block reward reallocation correctness +Tests the activation of a new quorum type in v17 via a bip9-like hardfork ''' -class PlatformQuorumActivationTest(BitcoinTestFramework): +class NewQuorumTypeActivationTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 1 @@ -31,4 +31,4 @@ def run_test(self): if __name__ == '__main__': - PlatformQuorumActivationTest().main() + NewQuorumTypeActivationTest().main() diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 293688874f1e..a41e74045151 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -147,7 +147,7 @@ 'wallet_encryption.py', 'feature_dersig.py', 'feature_cltv.py', - 'feature_platform_quorums.py', + 'feature_new_quorum_type_activation.py', 'feature_governance_objects.py', 'rpc_uptime.py', 'wallet_resendwallettransactions.py', From 1ae70b1cd26e84bcfeb732aebb6556b6529ce0c8 Mon Sep 17 00:00:00 2001 From: pasta Date: Sat, 5 Dec 2020 16:59:33 -0600 Subject: [PATCH 09/12] llmq: Make GetEnabledQuorumTypes return a vector of LLMQTypes, introduce GetLLMQParams Signed-off-by: pasta --- src/llmq/quorums_blockprocessor.cpp | 4 +--- src/llmq/quorums_utils.cpp | 15 ++++++++++----- src/llmq/quorums_utils.h | 3 ++- src/miner.cpp | 4 ++-- src/rpc/rpcquorums.cpp | 15 ++++++++------- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/src/llmq/quorums_blockprocessor.cpp b/src/llmq/quorums_blockprocessor.cpp index 280b6493582a..04cafddac9d1 100644 --- a/src/llmq/quorums_blockprocessor.cpp +++ b/src/llmq/quorums_blockprocessor.cpp @@ -133,14 +133,12 @@ bool CQuorumBlockProcessor::ProcessBlock(const CBlock& block, const CBlockIndex* // until the first non-null commitment has been mined. After the non-null commitment, no other commitments are // allowed, including null commitments. // Note: must only check quorums that were enabled at the _previous_ block height to match mining logic - for (const auto& p : CLLMQUtils::GetEnabledQuorumTypes(pindex->pprev)) { + for (const auto& type : CLLMQUtils::GetEnabledQuorumTypes(pindex->pprev)) { // skip these checks when replaying blocks after the crash if (!chainActive.Tip()) { break; } - auto type = p.first; - // does the currently processed block contain a (possibly null) commitment for the current session? bool hasCommitmentInNewBlock = qcs.count(type) != 0; bool isCommitmentRequired = IsCommitmentRequired(type, pindex->nHeight); diff --git a/src/llmq/quorums_utils.cpp b/src/llmq/quorums_utils.cpp index 1676e17587c8..e53627c0ff05 100644 --- a/src/llmq/quorums_utils.cpp +++ b/src/llmq/quorums_utils.cpp @@ -284,15 +284,20 @@ bool CLLMQUtils::IsQuorumTypeEnabled(Consensus::LLMQType llmqType, const CBlockI return true; } -std::map CLLMQUtils::GetEnabledQuorumTypes(const CBlockIndex* pindex) +std::vector CLLMQUtils::GetEnabledQuorumTypes(const CBlockIndex* pindex) { - std::map ret; - for (const auto& pair : Params().GetConsensus().llmqs) { - if (IsQuorumTypeEnabled(pair.first, pindex)) { - ret.emplace(pair); + std::vector ret; + for (const auto& p : Params().GetConsensus().llmqs) { + if (IsQuorumTypeEnabled(p.first, pindex)) { + ret.push_back(p.first); } } return ret; } +Consensus::LLMQParams CLLMQUtils::GetLLMQParams(Consensus::LLMQType llmqType) +{ + return Params().GetConsensus().llmqs.at(llmqType); +} + } // namespace llmq diff --git a/src/llmq/quorums_utils.h b/src/llmq/quorums_utils.h index b377e8a6a794..1588ca76e074 100644 --- a/src/llmq/quorums_utils.h +++ b/src/llmq/quorums_utils.h @@ -42,7 +42,8 @@ class CLLMQUtils static bool IsQuorumActive(Consensus::LLMQType llmqType, const uint256& quorumHash); static bool IsQuorumTypeEnabled(Consensus::LLMQType llmqType, const CBlockIndex* pindex); - static std::map GetEnabledQuorumTypes(const CBlockIndex* pindex); + static std::vector GetEnabledQuorumTypes(const CBlockIndex* pindex); + static Consensus::LLMQParams GetLLMQParams(const Consensus::LLMQType llmqType); template static void IterateNodesRandom(NodesContainer& nodeStates, Continue&& cont, Callback&& callback, FastRandomContext& rnd) diff --git a/src/miner.cpp b/src/miner.cpp index 0877adabbc5e..ef2131518d71 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -148,9 +148,9 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc : pblock->GetBlockTime(); if (fDIP0003Active_context) { - for (auto& p : llmq::CLLMQUtils::GetEnabledQuorumTypes(pindexPrev)) { + for (const Consensus::LLMQType& type : llmq::CLLMQUtils::GetEnabledQuorumTypes(pindexPrev)) { CTransactionRef qcTx; - if (llmq::quorumBlockProcessor->GetMinableCommitmentTx(p.first, nHeight, qcTx)) { + if (llmq::quorumBlockProcessor->GetMinableCommitmentTx(type, nHeight, qcTx)) { pblock->vtx.emplace_back(qcTx); pblocktemplate->vTxFees.emplace_back(0); pblocktemplate->vTxSigOps.emplace_back(0); diff --git a/src/rpc/rpcquorums.cpp b/src/rpc/rpcquorums.cpp index 3e980e1cafa0..4e23d229c984 100644 --- a/src/rpc/rpcquorums.cpp +++ b/src/rpc/rpcquorums.cpp @@ -54,15 +54,16 @@ UniValue quorum_list(const JSONRPCRequest& request) UniValue ret(UniValue::VOBJ); - for (auto& p : llmq::CLLMQUtils::GetEnabledQuorumTypes(chainActive.Tip())) { + for (auto& type : llmq::CLLMQUtils::GetEnabledQuorumTypes(chainActive.Tip())) { + const auto& params = llmq::CLLMQUtils::GetLLMQParams(type); UniValue v(UniValue::VARR); - auto quorums = llmq::quorumManager->ScanQuorums(p.first, chainActive.Tip(), count > -1 ? count : p.second.signingActiveQuorumCount); + auto quorums = llmq::quorumManager->ScanQuorums(type, chainActive.Tip(), count > -1 ? count : params.signingActiveQuorumCount); for (auto& q : quorums) { v.push_back(q->qc.quorumHash.ToString()); } - ret.pushKV(p.second.name, v); + ret.pushKV(params.name, v); } @@ -181,8 +182,8 @@ UniValue quorum_dkgstatus(const JSONRPCRequest& request) UniValue minableCommitments(UniValue::VOBJ); UniValue quorumConnections(UniValue::VOBJ); - for (const auto& p : llmq::CLLMQUtils::GetEnabledQuorumTypes(chainActive.Tip())) { - auto& params = p.second; + for (const auto& type : llmq::CLLMQUtils::GetEnabledQuorumTypes(chainActive.Tip())) { + const auto& params = llmq::CLLMQUtils::GetLLMQParams(type); if (fMasternodeMode) { const CBlockIndex* pindexQuorum = chainActive[tipHeight - (tipHeight % params.dkgInterval)]; @@ -265,8 +266,8 @@ UniValue quorum_memberof(const JSONRPCRequest& request) UniValue result(UniValue::VARR); - for (const auto& p : llmq::CLLMQUtils::GetEnabledQuorumTypes(pindexTip)) { - auto& params = p.second; + for (const auto& type : llmq::CLLMQUtils::GetEnabledQuorumTypes(pindexTip)) { + const auto& params = llmq::CLLMQUtils::GetLLMQParams(type); size_t count = params.signingActiveQuorumCount; if (scanQuorumsCount != -1) { count = (size_t)scanQuorumsCount; From 8f822154a10498f7ae7e671ee6aab43435a0466b Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 9 Dec 2020 22:51:24 +0300 Subject: [PATCH 10/12] Tweak minSize Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> --- src/chainparams.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 1b7030efb6af..c50e780d33e1 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -287,7 +287,7 @@ static Consensus::LLMQParams llmq100_67 = { .type = Consensus::LLMQ_100_67, .name = "llmq_100_67", .size = 100, - .minSize = 90, + .minSize = 80, .threshold = 67, .dkgInterval = 24, // one DKG per hour From ff997dbf0b00e913e3335fa634ee699e45de9bcb Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 9 Dec 2020 23:37:07 +0300 Subject: [PATCH 11/12] Exclude LLMQ_100_67 from Concentrated Recovery --- src/llmq/quorums_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llmq/quorums_utils.cpp b/src/llmq/quorums_utils.cpp index e53627c0ff05..d3223c000e61 100644 --- a/src/llmq/quorums_utils.cpp +++ b/src/llmq/quorums_utils.cpp @@ -53,7 +53,7 @@ bool CLLMQUtils::IsAllMembersConnectedEnabled(Consensus::LLMQType llmqType) if (spork21 == 0) { return true; } - if (spork21 == 1 && llmqType != Consensus::LLMQ_400_60 && llmqType != Consensus::LLMQ_400_85) { + if (spork21 == 1 && llmqType != Consensus::LLMQ_100_67 && llmqType != Consensus::LLMQ_400_60 && llmqType != Consensus::LLMQ_400_85) { return true; } return false; From 6b71409ccbb061c8a988f5e599ab3279ccb9a741 Mon Sep 17 00:00:00 2001 From: UdjinM6 Date: Wed, 9 Dec 2020 23:53:09 +0300 Subject: [PATCH 12/12] Update test/functional/feature_new_quorum_type_activation.py Co-authored-by: PastaPastaPasta <6443210+PastaPastaPasta@users.noreply.github.com> --- test/functional/feature_new_quorum_type_activation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/functional/feature_new_quorum_type_activation.py b/test/functional/feature_new_quorum_type_activation.py index a590361e51b6..061fe8d20459 100755 --- a/test/functional/feature_new_quorum_type_activation.py +++ b/test/functional/feature_new_quorum_type_activation.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) 2015-2020 The Dash Core developers +# Copyright (c) 2020 The Dash Core developers # Distributed under the MIT software license, see the accompanying # file COPYING or http://www.opensource.org/licenses/mit-license.php. from test_framework.test_framework import BitcoinTestFramework