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 <streams.h> 9 : #include <util/strencodings.h> 10 : 11 : #include <chainlock/chainlock.h> 12 : 13 : #include <boost/test/unit_test.hpp> 14 : 15 : using chainlock::ChainLockSig; 16 : using namespace llmq; 17 : using namespace llmq::testutils; 18 : 19 146 : BOOST_FIXTURE_TEST_SUITE(llmq_chainlock_tests, BasicTestingSetup) 20 : 21 149 : BOOST_AUTO_TEST_CASE(chainlock_construction_test) 22 : { 23 : // Test default constructor 24 1 : ChainLockSig clsig1; 25 1 : BOOST_CHECK(clsig1.IsNull()); 26 1 : BOOST_CHECK_EQUAL(clsig1.getHeight(), -1); 27 1 : BOOST_CHECK(clsig1.getBlockHash().IsNull()); 28 1 : BOOST_CHECK(!clsig1.getSig().IsValid()); 29 : 30 : // Test parameterized constructor 31 1 : int32_t height = 12345; 32 1 : uint256 blockHash = GetTestBlockHash(1); 33 1 : CBLSSignature sig = CreateRandomBLSSignature(); 34 : 35 1 : ChainLockSig clsig2(height, blockHash, sig); 36 1 : BOOST_CHECK(!clsig2.IsNull()); 37 1 : BOOST_CHECK_EQUAL(clsig2.getHeight(), height); 38 1 : BOOST_CHECK(clsig2.getBlockHash() == blockHash); 39 1 : BOOST_CHECK(clsig2.getSig() == sig); 40 1 : } 41 : 42 149 : BOOST_AUTO_TEST_CASE(chainlock_null_test) 43 : { 44 1 : ChainLockSig clsig; 45 : 46 : // Default constructed should be null 47 1 : BOOST_CHECK(clsig.IsNull()); 48 : 49 : // With height set but null hash, should not be null 50 1 : clsig = ChainLockSig(100, uint256(), CBLSSignature()); 51 1 : BOOST_CHECK(!clsig.IsNull()); 52 : 53 : // With valid data should not be null 54 1 : clsig = CreateChainLock(100, GetTestBlockHash(1)); 55 1 : BOOST_CHECK(!clsig.IsNull()); 56 1 : } 57 : 58 149 : BOOST_AUTO_TEST_CASE(chainlock_serialization_test) 59 : { 60 : // Test with valid chainlock 61 1 : ChainLockSig clsig = CreateChainLock(67890, GetTestBlockHash(42)); 62 : 63 : // Test serialization preserves all fields 64 1 : CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); 65 1 : ss << clsig; 66 : 67 1 : ChainLockSig deserialized; 68 1 : ss >> deserialized; 69 : 70 1 : BOOST_CHECK_EQUAL(clsig.getHeight(), deserialized.getHeight()); 71 1 : BOOST_CHECK(clsig.getBlockHash() == deserialized.getBlockHash()); 72 1 : BOOST_CHECK(clsig.getSig() == deserialized.getSig()); 73 1 : BOOST_CHECK_EQUAL(clsig.IsNull(), deserialized.IsNull()); 74 1 : } 75 : 76 149 : BOOST_AUTO_TEST_CASE(chainlock_tostring_test) 77 : { 78 : // Test null chainlock 79 1 : ChainLockSig nullClsig; 80 1 : std::string nullStr = nullClsig.ToString(); 81 1 : BOOST_CHECK(!nullStr.empty()); 82 : 83 : // Test valid chainlock 84 1 : int32_t height = 123456; 85 1 : uint256 blockHash = GetTestBlockHash(789); 86 1 : ChainLockSig clsig = CreateChainLock(height, blockHash); 87 : 88 1 : std::string str = clsig.ToString(); 89 1 : BOOST_CHECK(!str.empty()); 90 : 91 : // ToString should contain height and hash info 92 1 : BOOST_CHECK(str.find(strprintf("%d", height)) != std::string::npos); 93 1 : BOOST_CHECK(str.find(blockHash.ToString().substr(0, 10)) != std::string::npos); 94 1 : } 95 : 96 149 : BOOST_AUTO_TEST_CASE(chainlock_edge_cases_test) 97 : { 98 : // Test with edge case heights 99 1 : ChainLockSig clsig1 = CreateChainLock(0, GetTestBlockHash(1)); 100 1 : BOOST_CHECK_EQUAL(clsig1.getHeight(), 0); 101 1 : BOOST_CHECK(!clsig1.IsNull()); 102 : 103 1 : ChainLockSig clsig2 = CreateChainLock(std::numeric_limits<int32_t>::max(), GetTestBlockHash(2)); 104 1 : BOOST_CHECK_EQUAL(clsig2.getHeight(), std::numeric_limits<int32_t>::max()); 105 : 106 : // Test serialization with extreme values 107 1 : CDataStream ss1(SER_NETWORK, PROTOCOL_VERSION); 108 1 : ss1 << clsig1; 109 1 : ChainLockSig clsig1_deserialized; 110 1 : ss1 >> clsig1_deserialized; 111 1 : BOOST_CHECK_EQUAL(clsig1.getHeight(), clsig1_deserialized.getHeight()); 112 : 113 1 : CDataStream ss2(SER_NETWORK, PROTOCOL_VERSION); 114 1 : ss2 << clsig2; 115 1 : ChainLockSig clsig2_deserialized; 116 1 : ss2 >> clsig2_deserialized; 117 1 : BOOST_CHECK_EQUAL(clsig2.getHeight(), clsig2_deserialized.getHeight()); 118 1 : } 119 : 120 149 : BOOST_AUTO_TEST_CASE(chainlock_comparison_test) 121 : { 122 : // Create identical chainlocks 123 1 : int32_t height = 5000; 124 1 : uint256 blockHash = GetTestBlockHash(10); 125 1 : CBLSSignature sig = CreateRandomBLSSignature(); 126 : 127 1 : ChainLockSig clsig1(height, blockHash, sig); 128 1 : ChainLockSig clsig2(height, blockHash, sig); 129 : 130 : // Verify getters return same values 131 1 : BOOST_CHECK_EQUAL(clsig1.getHeight(), clsig2.getHeight()); 132 1 : BOOST_CHECK(clsig1.getBlockHash() == clsig2.getBlockHash()); 133 1 : BOOST_CHECK(clsig1.getSig() == clsig2.getSig()); 134 : 135 : // Different chainlocks 136 1 : ChainLockSig clsig3(height + 1, blockHash, sig); 137 1 : BOOST_CHECK(clsig1.getHeight() != clsig3.getHeight()); 138 : 139 1 : ChainLockSig clsig4(height, GetTestBlockHash(11), sig); 140 1 : BOOST_CHECK(clsig1.getBlockHash() != clsig4.getBlockHash()); 141 1 : } 142 : 143 149 : BOOST_AUTO_TEST_CASE(chainlock_malformed_data_test) 144 : { 145 : // Test deserialization of truncated data 146 1 : ChainLockSig clsig = CreateChainLock(1000, GetTestBlockHash(5)); 147 : 148 1 : CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); 149 1 : ss << clsig; 150 : 151 : // Truncate the stream 152 1 : std::string data = ss.str(); 153 15 : for (size_t truncateAt = 1; truncateAt < data.size(); truncateAt += 10) { 154 14 : CDataStream truncated(std::vector<unsigned char>(data.begin(), data.begin() + truncateAt), SER_NETWORK, 155 : PROTOCOL_VERSION); 156 : 157 14 : ChainLockSig deserialized; 158 : try { 159 14 : truncated >> deserialized; 160 : // If no exception, verify it's either complete or default 161 0 : if (truncateAt < sizeof(int32_t)) { 162 0 : BOOST_CHECK(deserialized.IsNull()); 163 0 : } 164 14 : } catch (const std::exception&) { 165 : // Expected for most truncation points 166 14 : } 167 14 : } 168 15 : } 169 : 170 146 : BOOST_AUTO_TEST_SUITE_END()