diff --git a/src/llmq/snapshot.cpp b/src/llmq/snapshot.cpp index 81043f98729d..2d27a667536e 100644 --- a/src/llmq/snapshot.cpp +++ b/src/llmq/snapshot.cpp @@ -14,6 +14,8 @@ #include +#include + namespace { constexpr std::string_view DB_QUORUM_SNAPSHOT{"llmq_S"}; @@ -74,10 +76,9 @@ bool BuildQuorumRotationInfo(CDeterministicMNManager& dmnman, CQuorumSnapshotMan } baseBlockIndexes.push_back(blockIndex); } - if (use_legacy_construction) { - std::sort(baseBlockIndexes.begin(), baseBlockIndexes.end(), - [](const CBlockIndex* a, const CBlockIndex* b) { return a->nHeight < b->nHeight; }); - } + std::sort(baseBlockIndexes.begin(), baseBlockIndexes.end(), + [](const CBlockIndex* a, const CBlockIndex* b) { return a->nHeight < b->nHeight; }); + baseBlockIndexes.erase(std::unique(baseBlockIndexes.begin(), baseBlockIndexes.end()), baseBlockIndexes.end()); } const CBlockIndex* tipBlockIndex = chainman.ActiveChain().Tip(); diff --git a/src/test/llmq_snapshot_tests.cpp b/src/test/llmq_snapshot_tests.cpp index 7e3b1d191ece..a353a2d64638 100644 --- a/src/test/llmq_snapshot_tests.cpp +++ b/src/test/llmq_snapshot_tests.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -176,6 +177,39 @@ BOOST_AUTO_TEST_CASE(quorum_rotation_info_construction_test) // Note: CQuorumRotationInfo serialization requires complex setup // This is better tested in functional tests +BOOST_AUTO_TEST_CASE(get_last_base_block_hash_repeated_base_blocks_test) +{ + std::vector blocks(4); + std::vector hashes{ + GetTestBlockHash(10), + GetTestBlockHash(20), + GetTestBlockHash(30), + GetTestBlockHash(40), + }; + for (size_t i{0}; i < blocks.size(); ++i) { + blocks[i].nHeight = static_cast((i + 1) * 10); + blocks[i].phashBlock = &hashes[i]; + } + + std::vector unsorted_repeated_base_blocks{ + &blocks[2], + &blocks[0], + &blocks[1], + &blocks[1], + }; + BOOST_CHECK(GetLastBaseBlockHash(unsorted_repeated_base_blocks, &blocks[3], false) == hashes[2]); + BOOST_CHECK(GetLastBaseBlockHash(unsorted_repeated_base_blocks, &blocks[1], false) == hashes[1]); + + std::vector sorted_repeated_base_blocks{ + &blocks[0], + &blocks[1], + &blocks[1], + &blocks[2], + }; + BOOST_CHECK(GetLastBaseBlockHash(sorted_repeated_base_blocks, &blocks[3], true) == hashes[2]); + BOOST_CHECK(GetLastBaseBlockHash(sorted_repeated_base_blocks, &blocks[1], true) == hashes[1]); +} + BOOST_AUTO_TEST_CASE(get_quorum_rotation_info_serialization_test) { CGetQuorumRotationInfo getInfo; diff --git a/test/functional/feature_llmq_rotation.py b/test/functional/feature_llmq_rotation.py index f0e3651ddbf5..813016c5b9ef 100755 --- a/test/functional/feature_llmq_rotation.py +++ b/test/functional/feature_llmq_rotation.py @@ -231,6 +231,9 @@ def run_test(self): hmc_base_blockhash = self.nodes[0].getblockhash(block_count - (block_count % 24) - 24 - 8) best_block_hash = self.nodes[0].getbestblockhash() rpc_qr_info = self.nodes[0].quorum("rotationinfo", best_block_hash, False, [hmc_base_blockhash]) + rpc_qr_info_repeated_base = self.nodes[0].quorum("rotationinfo", best_block_hash, False, + [hmc_base_blockhash, hmc_base_blockhash]) + assert_equal(rpc_qr_info_repeated_base, rpc_qr_info) assert_equal(rpc_qr_info["mnListDiffTip"]["blockHash"], best_block_hash) assert_equal(rpc_qr_info["mnListDiffTip"]["baseBlockHash"], rpc_qr_info["mnListDiffH"]["blockHash"]) assert_equal(rpc_qr_info["mnListDiffH"]["baseBlockHash"], rpc_qr_info["mnListDiffAtHMinusC"]["blockHash"])