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/commitment.h>
10 : #include <llmq/utils.h>
11 :
12 : #include <boost/test/unit_test.hpp>
13 :
14 : #include <vector>
15 :
16 : using namespace llmq;
17 : using namespace llmq::testutils;
18 :
19 146 : BOOST_FIXTURE_TEST_SUITE(llmq_hash_tests, BasicTestingSetup)
20 :
21 : // Get test params for use in tests
22 146 : static const Consensus::LLMQParams& TEST_PARAMS = GetLLMQParams(Consensus::LLMQType::LLMQ_TEST_V17);
23 146 : static const Consensus::LLMQParams& TEST_PARAMS_ALT = GetLLMQParams(Consensus::LLMQType::LLMQ_TEST);
24 :
25 149 : BOOST_AUTO_TEST_CASE(build_commitment_hash_deterministic_test)
26 : {
27 : // Setup test data
28 1 : Consensus::LLMQType llmqType = TEST_PARAMS.type;
29 1 : uint256 quorumHash = GetTestQuorumHash(1);
30 1 : std::vector<bool> validMembers = CreateBitVector(5, {0, 1, 2, 3});
31 1 : CBLSPublicKey quorumPubKey = CreateRandomBLSPublicKey();
32 1 : uint256 vvecHash = GetTestQuorumHash(2);
33 :
34 : // Generate hash multiple times with same inputs
35 1 : uint256 hash1 = BuildCommitmentHash(llmqType, quorumHash, validMembers, quorumPubKey, vvecHash);
36 1 : uint256 hash2 = BuildCommitmentHash(llmqType, quorumHash, validMembers, quorumPubKey, vvecHash);
37 1 : uint256 hash3 = BuildCommitmentHash(llmqType, quorumHash, validMembers, quorumPubKey, vvecHash);
38 :
39 : // All hashes should be identical (deterministic)
40 1 : BOOST_CHECK(hash1 == hash2);
41 1 : BOOST_CHECK(hash2 == hash3);
42 1 : BOOST_CHECK(!hash1.IsNull());
43 1 : }
44 :
45 149 : BOOST_AUTO_TEST_CASE(build_commitment_hash_sensitivity_test)
46 : {
47 : // Base test data
48 1 : Consensus::LLMQType llmqType = TEST_PARAMS.type;
49 1 : uint256 quorumHash = GetTestQuorumHash(1);
50 1 : std::vector<bool> validMembers = CreateBitVector(5, {0, 1, 2, 3});
51 1 : CBLSPublicKey quorumPubKey = CreateRandomBLSPublicKey();
52 1 : uint256 vvecHash = GetTestQuorumHash(2);
53 :
54 1 : uint256 baseHash = BuildCommitmentHash(llmqType, quorumHash, validMembers, quorumPubKey, vvecHash);
55 :
56 : // Test sensitivity to llmqType change
57 1 : uint256 hashDiffType = BuildCommitmentHash(TEST_PARAMS_ALT.type, // Different type
58 : quorumHash, validMembers, quorumPubKey, vvecHash);
59 1 : BOOST_CHECK(baseHash != hashDiffType);
60 :
61 : // Test sensitivity to quorumHash change
62 1 : uint256 hashDiffQuorum = BuildCommitmentHash(llmqType,
63 1 : GetTestQuorumHash(99), // Different quorum hash
64 : validMembers, quorumPubKey, vvecHash);
65 1 : BOOST_CHECK(baseHash != hashDiffQuorum);
66 :
67 : // Test sensitivity to validMembers change
68 1 : std::vector<bool> differentMembers = CreateBitVector(5, {0, 1, 2}); // One less member
69 1 : uint256 hashDiffMembers = BuildCommitmentHash(llmqType, quorumHash,
70 : differentMembers, // Different valid members
71 : quorumPubKey, vvecHash);
72 1 : BOOST_CHECK(baseHash != hashDiffMembers);
73 :
74 : // Test sensitivity to quorumPubKey change
75 1 : CBLSPublicKey differentPubKey = CreateRandomBLSPublicKey();
76 1 : uint256 hashDiffPubKey = BuildCommitmentHash(llmqType, quorumHash, validMembers,
77 : differentPubKey, // Different public key
78 : vvecHash);
79 1 : BOOST_CHECK(baseHash != hashDiffPubKey);
80 :
81 : // Test sensitivity to vvecHash change
82 1 : uint256 hashDiffVvec = BuildCommitmentHash(llmqType, quorumHash, validMembers, quorumPubKey,
83 1 : GetTestQuorumHash(99) // Different vvec hash
84 : );
85 1 : BOOST_CHECK(baseHash != hashDiffVvec);
86 1 : }
87 :
88 149 : BOOST_AUTO_TEST_CASE(build_commitment_hash_edge_cases_test)
89 : {
90 : // Test with empty valid members
91 1 : std::vector<bool> emptyMembers;
92 2 : uint256 hashEmpty = BuildCommitmentHash(TEST_PARAMS.type, GetTestQuorumHash(1), emptyMembers,
93 1 : CreateRandomBLSPublicKey(), GetTestQuorumHash(2));
94 1 : BOOST_CHECK(!hashEmpty.IsNull());
95 :
96 : // Test with all members valid
97 1 : std::vector<bool> allValid(100, true);
98 2 : uint256 hashAllValid = BuildCommitmentHash(TEST_PARAMS.type, GetTestQuorumHash(1), allValid,
99 1 : CreateRandomBLSPublicKey(), GetTestQuorumHash(2));
100 1 : BOOST_CHECK(!hashAllValid.IsNull());
101 :
102 : // Test with no members valid
103 1 : std::vector<bool> noneValid(100, false);
104 2 : uint256 hashNoneValid = BuildCommitmentHash(TEST_PARAMS.type, GetTestQuorumHash(1), noneValid,
105 1 : CreateRandomBLSPublicKey(), GetTestQuorumHash(2));
106 1 : BOOST_CHECK(!hashNoneValid.IsNull());
107 :
108 : // All three should produce different hashes
109 1 : BOOST_CHECK(hashEmpty != hashAllValid);
110 1 : BOOST_CHECK(hashEmpty != hashNoneValid);
111 1 : BOOST_CHECK(hashAllValid != hashNoneValid);
112 1 : }
113 :
114 149 : BOOST_AUTO_TEST_CASE(build_commitment_hash_null_inputs_test)
115 : {
116 : // Test with null quorum hash
117 2 : uint256 hashNullQuorum = BuildCommitmentHash(TEST_PARAMS.type,
118 1 : uint256(), // Null hash
119 1 : CreateBitVector(5, {0, 1, 2}), CreateRandomBLSPublicKey(),
120 1 : GetTestQuorumHash(1));
121 1 : BOOST_CHECK(!hashNullQuorum.IsNull());
122 :
123 : // Test with invalid (but serializable) public key
124 1 : CBLSPublicKey invalidPubKey;
125 2 : uint256 hashInvalidKey = BuildCommitmentHash(TEST_PARAMS.type, GetTestQuorumHash(1), CreateBitVector(5, {0, 1, 2}),
126 : invalidPubKey, // Invalid key
127 1 : GetTestQuorumHash(2));
128 1 : BOOST_CHECK(!hashInvalidKey.IsNull());
129 :
130 : // Test with null vvec hash
131 2 : uint256 hashNullVvec = BuildCommitmentHash(TEST_PARAMS.type, GetTestQuorumHash(1), CreateBitVector(5, {0, 1, 2}),
132 1 : CreateRandomBLSPublicKey(),
133 1 : uint256() // Null hash
134 : );
135 1 : BOOST_CHECK(!hashNullVvec.IsNull());
136 :
137 : // All should produce different hashes
138 1 : BOOST_CHECK(hashNullQuorum != hashInvalidKey);
139 1 : BOOST_CHECK(hashNullQuorum != hashNullVvec);
140 1 : BOOST_CHECK(hashInvalidKey != hashNullVvec);
141 1 : }
142 :
143 149 : BOOST_AUTO_TEST_CASE(build_commitment_hash_large_data_test)
144 : {
145 : // Test with maximum expected quorum size
146 1 : std::vector<bool> largeValidMembers(400, true); // Max quorum size
147 :
148 : // Create pattern in valid members
149 135 : for (size_t i = 0; i < largeValidMembers.size(); i += 3) {
150 134 : largeValidMembers[i] = false;
151 134 : }
152 :
153 2 : uint256 hashLarge = BuildCommitmentHash(TEST_PARAMS.type, GetTestQuorumHash(1), largeValidMembers,
154 1 : CreateRandomBLSPublicKey(), GetTestQuorumHash(2));
155 :
156 1 : BOOST_CHECK(!hashLarge.IsNull());
157 :
158 : // Slightly different pattern should produce different hash
159 1 : largeValidMembers[0] = !largeValidMembers[0];
160 2 : uint256 hashLargeDiff = BuildCommitmentHash(TEST_PARAMS.type, GetTestQuorumHash(1), largeValidMembers,
161 1 : CreateRandomBLSPublicKey(), GetTestQuorumHash(2));
162 :
163 1 : BOOST_CHECK(!hashLargeDiff.IsNull());
164 1 : BOOST_CHECK(hashLarge != hashLargeDiff);
165 1 : }
166 :
167 149 : BOOST_AUTO_TEST_CASE(build_commitment_hash_bit_pattern_test)
168 : {
169 : // Test that different bit patterns produce different hashes
170 1 : Consensus::LLMQType llmqType = TEST_PARAMS_ALT.type;
171 1 : uint256 quorumHash = GetTestQuorumHash(1);
172 1 : CBLSPublicKey quorumPubKey = CreateRandomBLSPublicKey();
173 1 : uint256 vvecHash = GetTestQuorumHash(2);
174 :
175 : // Create various bit patterns
176 6 : std::vector<std::vector<bool>> patterns = {
177 1 : CreateBitVector(10, {}), // All false
178 1 : CreateBitVector(10, {0}), // First only
179 1 : CreateBitVector(10, {9}), // Last only
180 1 : CreateBitVector(10, {0, 9}), // First and last
181 1 : CreateBitVector(10, {1, 3, 5, 7}), // Alternating
182 1 : CreateBitVector(10, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}), // All true
183 : };
184 :
185 1 : std::vector<uint256> hashes;
186 7 : for (const auto& pattern : patterns) {
187 6 : uint256 hash = BuildCommitmentHash(llmqType, quorumHash, pattern, quorumPubKey, vvecHash);
188 6 : hashes.push_back(hash);
189 6 : BOOST_CHECK(!hash.IsNull());
190 : }
191 :
192 : // All hashes should be unique
193 7 : for (size_t i = 0; i < hashes.size(); ++i) {
194 21 : for (size_t j = i + 1; j < hashes.size(); ++j) {
195 15 : BOOST_CHECK(hashes[i] != hashes[j]);
196 15 : }
197 6 : }
198 1 : }
199 :
200 146 : BOOST_AUTO_TEST_SUITE_END()
|