LCOV - code coverage report
Current view: top level - src/test - llmq_params_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 110 110 100.0 %
Date: 2026-06-25 07:23:43 Functions: 53 53 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2025 The Dash Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #include <test/util/llmq_tests.h>
       6             : #include <test/util/setup_common.h>
       7             : 
       8             : #include <consensus/params.h>
       9             : #include <llmq/params.h>
      10             : 
      11             : #include <boost/test/unit_test.hpp>
      12             : 
      13             : #include <limits>
      14             : 
      15             : using namespace llmq;
      16             : using namespace llmq::testutils;
      17             : using namespace Consensus;
      18             : 
      19         146 : BOOST_FIXTURE_TEST_SUITE(llmq_params_tests, BasicTestingSetup)
      20             : 
      21             : // Get test params for use in tests
      22         146 : static const Consensus::LLMQParams& TEST_PARAMS_BASE = GetLLMQParams(Consensus::LLMQType::LLMQ_TEST_V17);
      23             : 
      24         149 : BOOST_AUTO_TEST_CASE(llmq_params_max_cycles_test)
      25             : {
      26             :     // Test non-rotated quorum
      27           1 :     LLMQParams nonRotated = TEST_PARAMS_BASE;
      28           1 :     nonRotated.useRotation = false;
      29           1 :     nonRotated.signingActiveQuorumCount = 2;
      30             : 
      31             :     // For non-rotated: max_cycles = quorums_count
      32           1 :     BOOST_CHECK_EQUAL(nonRotated.max_cycles(10), 10);
      33           1 :     BOOST_CHECK_EQUAL(nonRotated.max_cycles(100), 100);
      34           1 :     BOOST_CHECK_EQUAL(nonRotated.max_cycles(1), 1);
      35           1 :     BOOST_CHECK_EQUAL(nonRotated.max_cycles(0), 0);
      36             : 
      37             :     // Test rotated quorum
      38           1 :     LLMQParams rotated = TEST_PARAMS_BASE;
      39           1 :     rotated.useRotation = true;
      40           1 :     rotated.signingActiveQuorumCount = 2;
      41             : 
      42             :     // For rotated: max_cycles = quorums_count / signingActiveQuorumCount
      43           1 :     BOOST_CHECK_EQUAL(rotated.max_cycles(10), 5);
      44           1 :     BOOST_CHECK_EQUAL(rotated.max_cycles(100), 50);
      45           1 :     BOOST_CHECK_EQUAL(rotated.max_cycles(1), 0); // Integer division
      46           1 :     BOOST_CHECK_EQUAL(rotated.max_cycles(0), 0);
      47             : 
      48             :     // Test with different signingActiveQuorumCount
      49           1 :     rotated.signingActiveQuorumCount = 4;
      50           1 :     BOOST_CHECK_EQUAL(rotated.max_cycles(100), 25);
      51           1 :     BOOST_CHECK_EQUAL(rotated.max_cycles(16), 4);
      52           1 :     BOOST_CHECK_EQUAL(rotated.max_cycles(15), 3); // Integer division
      53           1 : }
      54             : 
      55         149 : BOOST_AUTO_TEST_CASE(llmq_params_max_store_depth_test)
      56             : {
      57           1 :     LLMQParams params = TEST_PARAMS_BASE;
      58           1 :     params.dkgInterval = 24;
      59           1 :     params.signingActiveQuorumCount = 2;
      60           1 :     params.keepOldKeys = 10;
      61             : 
      62             :     // max_store_depth = max_cycles(keepOldKeys) * dkgInterval
      63             : 
      64             :     // Test non-rotated
      65           1 :     params.useRotation = false;
      66             :     // max_cycles(10) = 10 for non-rotated
      67           1 :     BOOST_CHECK_EQUAL(params.max_store_depth(), 10 * 24); // 240
      68             : 
      69             :     // Test rotated
      70           1 :     params.useRotation = true;
      71             :     // max_cycles(10) = 10/2 = 5 for rotated
      72           1 :     BOOST_CHECK_EQUAL(params.max_store_depth(), 5 * 24); // 120
      73             : 
      74             :     // Test with different values
      75           1 :     params.keepOldKeys = 20;
      76           1 :     params.dkgInterval = 48;
      77           1 :     params.signingActiveQuorumCount = 4;
      78             :     // max_cycles(20) = 20/4 = 5 for rotated
      79           1 :     BOOST_CHECK_EQUAL(params.max_store_depth(), 5 * 48); // 240
      80             : 
      81             :     // Test edge cases
      82           1 :     params.keepOldKeys = 0;
      83           1 :     BOOST_CHECK_EQUAL(params.max_store_depth(), 0);
      84             : 
      85           1 :     params.keepOldKeys = 1;
      86           1 :     params.dkgInterval = 1;
      87           1 :     params.signingActiveQuorumCount = 1;
      88           1 :     BOOST_CHECK_EQUAL(params.max_store_depth(), 1);
      89           1 : }
      90             : 
      91         149 : BOOST_AUTO_TEST_CASE(llmq_params_validation_test)
      92             : {
      93             :     // Test parameter constraints and relationships
      94           1 :     LLMQParams params = TEST_PARAMS_BASE;
      95             : 
      96             :     // minSize should be less than or equal to size
      97           1 :     BOOST_CHECK_LE(params.minSize, params.size);
      98             : 
      99             :     // threshold should be less than or equal to size
     100           1 :     BOOST_CHECK_LE(params.threshold, params.size);
     101             : 
     102             :     // threshold should typically be > 50% of size for security
     103           1 :     BOOST_CHECK_GT(params.threshold * 2, params.size);
     104             : 
     105             :     // dkgMiningWindowStart should be after DKG phases complete
     106             :     // Typically should be >= 5 * dkgPhaseBlocks
     107           1 :     BOOST_CHECK_GE(params.dkgMiningWindowStart, 5 * params.dkgPhaseBlocks);
     108             : 
     109             :     // dkgMiningWindowEnd should be after dkgMiningWindowStart
     110           1 :     BOOST_CHECK_GT(params.dkgMiningWindowEnd, params.dkgMiningWindowStart);
     111             : 
     112             :     // dkgMiningWindowEnd should be within dkgInterval
     113           1 :     BOOST_CHECK_LT(params.dkgMiningWindowEnd, params.dkgInterval);
     114           1 : }
     115             : 
     116         149 : BOOST_AUTO_TEST_CASE(llmq_params_types_test)
     117             : {
     118             :     // Test that LLMQ types are properly defined
     119           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_NONE), 0xff);
     120           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_50_60), 1);
     121           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_400_60), 2);
     122           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_400_85), 3);
     123           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_100_67), 4);
     124           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_60_75), 5);
     125           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_25_67), 6);
     126             : 
     127             :     // Test special types
     128           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_TEST), 100);
     129           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_DEVNET), 101);
     130           1 :     BOOST_CHECK_EQUAL(static_cast<uint8_t>(LLMQType::LLMQ_TEST_V17), 102);
     131           1 : }
     132             : 
     133         149 : BOOST_AUTO_TEST_CASE(llmq_params_edge_calculations_test)
     134             : {
     135           1 :     LLMQParams params;
     136             : 
     137             :     // Test with maximum values
     138           1 :     params.useRotation = true;
     139           1 :     params.signingActiveQuorumCount = 1;
     140           1 :     params.keepOldKeys = std::numeric_limits<int>::max() / 2; // Avoid overflow
     141           1 :     params.dkgInterval = 2;
     142             : 
     143             :     // Should not overflow
     144           1 :     int depth = params.max_store_depth();
     145           1 :     BOOST_CHECK_GT(depth, 0);
     146             : 
     147             :     // Test division by zero protection
     148           1 :     params.signingActiveQuorumCount = 0;
     149             :     // This would cause division by zero in max_cycles if not handled
     150             :     // The implementation should handle this gracefully or it's a bug
     151             : 
     152             :     // Test with all zeros
     153           1 :     params.useRotation = false;
     154           1 :     params.keepOldKeys = 0;
     155           1 :     params.dkgInterval = 0;
     156           1 :     BOOST_CHECK_EQUAL(params.max_store_depth(), 0);
     157           1 : }
     158             : 
     159         149 : BOOST_AUTO_TEST_CASE(llmq_params_rotation_consistency_test)
     160             : {
     161             :     // Test that rotation parameters are consistent
     162           1 :     LLMQParams rotatedParams;
     163           1 :     rotatedParams.useRotation = true;
     164           1 :     rotatedParams.signingActiveQuorumCount = 4;
     165           1 :     rotatedParams.keepOldConnections = 8; // Should be 2x active for rotated
     166           1 :     rotatedParams.keepOldKeys = 8;
     167           1 :     rotatedParams.dkgInterval = 24;
     168             : 
     169             :     // For rotated quorums, keepOldConnections should typically be 2x signingActiveQuorumCount
     170           1 :     BOOST_CHECK_EQUAL(rotatedParams.keepOldConnections, 2 * rotatedParams.signingActiveQuorumCount);
     171             : 
     172           1 :     LLMQParams nonRotatedParams;
     173           1 :     nonRotatedParams.useRotation = false;
     174           1 :     nonRotatedParams.signingActiveQuorumCount = 4;
     175           1 :     nonRotatedParams.keepOldConnections = 5; // Should be at least active + 1 for non-rotated
     176           1 :     nonRotatedParams.keepOldKeys = 8;
     177           1 :     nonRotatedParams.dkgInterval = 24;
     178             : 
     179             :     // For non-rotated quorums, keepOldConnections should be > signingActiveQuorumCount
     180           1 :     BOOST_CHECK_GT(nonRotatedParams.keepOldConnections, nonRotatedParams.signingActiveQuorumCount);
     181           1 : }
     182             : 
     183         149 : BOOST_AUTO_TEST_CASE(llmq_params_calculations_overflow_test)
     184             : {
     185           1 :     LLMQParams params;
     186           1 :     params.useRotation = false;
     187           1 :     params.signingActiveQuorumCount = 1;
     188             : 
     189             :     // Test max_cycles with large values
     190           1 :     int largeQuorumCount = std::numeric_limits<int>::max();
     191           1 :     int cycles = params.max_cycles(largeQuorumCount);
     192           1 :     BOOST_CHECK_EQUAL(cycles, largeQuorumCount); // Non-rotated returns input
     193             : 
     194             :     // Test potential overflow in max_store_depth
     195           1 :     params.keepOldKeys = std::numeric_limits<int>::max() / 100;
     196           1 :     params.dkgInterval = 100;
     197             : 
     198             :     // This should not crash or overflow
     199           1 :     int depth = params.max_store_depth();
     200           1 :     BOOST_CHECK_GE(depth, 0); // Result should be valid
     201             : 
     202             :     // Test with rotation and potential division issues
     203           1 :     params.useRotation = true;
     204           1 :     params.signingActiveQuorumCount = std::numeric_limits<int>::max();
     205           1 :     cycles = params.max_cycles(1000);
     206           1 :     BOOST_CHECK_EQUAL(cycles, 0); // 1000 / max_int = 0
     207           1 : }
     208             : 
     209         146 : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 1.16