uint256_tests.cpp
1 // Copyright (c) 2011-present The Bitcoin 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 <primitives/transaction_identifier.h> 6 #include <streams.h> 7 #include <test/util/common.h> 8 #include <uint256.h> 9 #include <util/strencodings.h> 10 11 #include <boost/test/unit_test.hpp> 12 13 #include <iomanip> 14 #include <sstream> 15 #include <string> 16 #include <string_view> 17 #include <vector> 18 19 BOOST_AUTO_TEST_SUITE(uint256_tests) 20 21 const unsigned char R1Array[] = 22 "\x9c\x52\x4a\xdb\xcf\x56\x11\x12\x2b\x29\x12\x5e\x5d\x35\xd2\xd2" 23 "\x22\x81\xaa\xb5\x33\xf0\x08\x32\xd5\x56\xb1\xf9\xea\xe5\x1d\x7d"; 24 const char R1ArrayHex[] = "7D1DE5EAF9B156D53208F033B5AA8122D2d2355d5e12292b121156cfdb4a529c"; 25 const uint256 R1L = uint256(std::vector<unsigned char>(R1Array,R1Array+32)); 26 const uint160 R1S = uint160(std::vector<unsigned char>(R1Array,R1Array+20)); 27 28 const unsigned char R2Array[] = 29 "\x70\x32\x1d\x7c\x47\xa5\x6b\x40\x26\x7e\x0a\xc3\xa6\x9c\xb6\xbf" 30 "\x13\x30\x47\xa3\x19\x2d\xda\x71\x49\x13\x72\xf0\xb4\xca\x81\xd7"; 31 const uint256 R2L = uint256(std::vector<unsigned char>(R2Array,R2Array+32)); 32 const uint160 R2S = uint160(std::vector<unsigned char>(R2Array,R2Array+20)); 33 34 const unsigned char ZeroArray[] = 35 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 36 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; 37 const uint256 ZeroL = uint256(std::vector<unsigned char>(ZeroArray,ZeroArray+32)); 38 const uint160 ZeroS = uint160(std::vector<unsigned char>(ZeroArray,ZeroArray+20)); 39 40 const unsigned char OneArray[] = 41 "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 42 "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; 43 const uint256 OneL = uint256(std::vector<unsigned char>(OneArray,OneArray+32)); 44 const uint160 OneS = uint160(std::vector<unsigned char>(OneArray,OneArray+20)); 45 46 const unsigned char MaxArray[] = 47 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" 48 "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; 49 const uint256 MaxL = uint256(std::vector<unsigned char>(MaxArray,MaxArray+32)); 50 const uint160 MaxS = uint160(std::vector<unsigned char>(MaxArray,MaxArray+20)); 51 52 static std::string ArrayToString(const unsigned char A[], unsigned int width) 53 { 54 std::stringstream Stream; 55 Stream << std::hex; 56 for (unsigned int i = 0; i < width; ++i) 57 { 58 Stream<<std::setw(2)<<std::setfill('0')<<(unsigned int)A[width-i-1]; 59 } 60 return Stream.str(); 61 } 62 63 BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality 64 { 65 // constructor uint256(vector<char>): 66 BOOST_CHECK_EQUAL(R1L.ToString(), ArrayToString(R1Array,32)); 67 BOOST_CHECK_EQUAL(R1S.ToString(), ArrayToString(R1Array,20)); 68 BOOST_CHECK_EQUAL(R2L.ToString(), ArrayToString(R2Array,32)); 69 BOOST_CHECK_EQUAL(R2S.ToString(), ArrayToString(R2Array,20)); 70 BOOST_CHECK_EQUAL(ZeroL.ToString(), ArrayToString(ZeroArray,32)); 71 BOOST_CHECK_EQUAL(ZeroS.ToString(), ArrayToString(ZeroArray,20)); 72 BOOST_CHECK_EQUAL(OneL.ToString(), ArrayToString(OneArray,32)); 73 BOOST_CHECK_EQUAL(OneS.ToString(), ArrayToString(OneArray,20)); 74 BOOST_CHECK_EQUAL(MaxL.ToString(), ArrayToString(MaxArray,32)); 75 BOOST_CHECK_EQUAL(MaxS.ToString(), ArrayToString(MaxArray,20)); 76 BOOST_CHECK_NE(OneL.ToString(), ArrayToString(ZeroArray,32)); 77 BOOST_CHECK_NE(OneS.ToString(), ArrayToString(ZeroArray,20)); 78 79 // == and != 80 BOOST_CHECK_NE(R1L, R2L); BOOST_CHECK_NE(R1S, R2S); 81 BOOST_CHECK_NE(ZeroL, OneL); BOOST_CHECK_NE(ZeroS, OneS); 82 BOOST_CHECK_NE(OneL, ZeroL); BOOST_CHECK_NE(OneS, ZeroS); 83 BOOST_CHECK_NE(MaxL, ZeroL); BOOST_CHECK_NE(MaxS, ZeroS); 84 85 // String Constructor and Copy Constructor 86 BOOST_CHECK_EQUAL(uint256::FromHex(R1L.ToString()).value(), R1L); 87 BOOST_CHECK_EQUAL(uint256::FromHex(R2L.ToString()).value(), R2L); 88 BOOST_CHECK_EQUAL(uint256::FromHex(ZeroL.ToString()).value(), ZeroL); 89 BOOST_CHECK_EQUAL(uint256::FromHex(OneL.ToString()).value(), OneL); 90 BOOST_CHECK_EQUAL(uint256::FromHex(MaxL.ToString()).value(), MaxL); 91 BOOST_CHECK_EQUAL(uint256::FromHex(R1ArrayHex).value(), R1L); 92 BOOST_CHECK_EQUAL(uint256(R1L), R1L); 93 BOOST_CHECK_EQUAL(uint256(ZeroL), ZeroL); 94 BOOST_CHECK_EQUAL(uint256(OneL), OneL); 95 96 BOOST_CHECK_EQUAL(uint160::FromHex(R1S.ToString()).value(), R1S); 97 BOOST_CHECK_EQUAL(uint160::FromHex(R2S.ToString()).value(), R2S); 98 BOOST_CHECK_EQUAL(uint160::FromHex(ZeroS.ToString()).value(), ZeroS); 99 BOOST_CHECK_EQUAL(uint160::FromHex(OneS.ToString()).value(), OneS); 100 BOOST_CHECK_EQUAL(uint160::FromHex(MaxS.ToString()).value(), MaxS); 101 BOOST_CHECK_EQUAL(uint160::FromHex(std::string_view{R1ArrayHex + 24, 40}).value(), R1S); 102 103 BOOST_CHECK_EQUAL(uint160(R1S), R1S); 104 BOOST_CHECK_EQUAL(uint160(ZeroS), ZeroS); 105 BOOST_CHECK_EQUAL(uint160(OneS), OneS); 106 } 107 108 BOOST_AUTO_TEST_CASE( comparison ) // <= >= < > 109 { 110 uint256 LastL; 111 for (int i = 255; i >= 0; --i) { 112 uint256 TmpL; 113 *(TmpL.begin() + (i>>3)) |= 1<<(7-(i&7)); 114 BOOST_CHECK_LT(LastL, TmpL); 115 LastL = TmpL; 116 } 117 118 BOOST_CHECK_LT(ZeroL, R1L); 119 BOOST_CHECK_LT(R2L, R1L); 120 BOOST_CHECK_LT(ZeroL, OneL); 121 BOOST_CHECK_LT(OneL, MaxL); 122 BOOST_CHECK_LT(R1L, MaxL); 123 BOOST_CHECK_LT(R2L, MaxL); 124 125 uint160 LastS; 126 for (int i = 159; i >= 0; --i) { 127 uint160 TmpS; 128 *(TmpS.begin() + (i>>3)) |= 1<<(7-(i&7)); 129 BOOST_CHECK_LT(LastS, TmpS); 130 LastS = TmpS; 131 } 132 BOOST_CHECK_LT(ZeroS, R1S); 133 BOOST_CHECK_LT(R2S, R1S); 134 BOOST_CHECK_LT(ZeroS, OneS); 135 BOOST_CHECK_LT(OneS, MaxS); 136 BOOST_CHECK_LT(R1S, MaxS); 137 BOOST_CHECK_LT(R2S, MaxS); 138 139 // Non-arithmetic uint256s compare from the beginning of their inner arrays: 140 BOOST_CHECK_LT(R2L, R1L); 141 // Ensure first element comparisons give the same order as above: 142 BOOST_CHECK_LT(*R2L.begin(), *R1L.begin()); 143 // Ensure last element comparisons give a different result (swapped params): 144 BOOST_CHECK_LT(*(R1L.end()-1), *(R2L.end()-1)); 145 // Hex strings represent reverse-encoded bytes, with lexicographic ordering: 146 BOOST_CHECK_LT(uint256{"1000000000000000000000000000000000000000000000000000000000000000"}, 147 uint256{"0000000000000000000000000000000000000000000000000000000000000001"}); 148 } 149 150 BOOST_AUTO_TEST_CASE(methods) // GetHex FromHex begin() end() size() GetLow64 GetSerializeSize, Serialize, Unserialize 151 { 152 BOOST_CHECK_EQUAL(R1L.GetHex(), R1L.ToString()); 153 BOOST_CHECK_EQUAL(R2L.GetHex(), R2L.ToString()); 154 BOOST_CHECK_EQUAL(OneL.GetHex(), OneL.ToString()); 155 BOOST_CHECK_EQUAL(MaxL.GetHex(), MaxL.ToString()); 156 uint256 TmpL(R1L); 157 BOOST_CHECK_EQUAL(TmpL, R1L); 158 BOOST_CHECK_EQUAL(uint256::FromHex(R2L.ToString()).value(), R2L); 159 BOOST_CHECK_EQUAL(uint256::FromHex(ZeroL.ToString()).value(), uint256()); 160 161 TmpL = uint256::FromHex(R1L.ToString()).value(); 162 BOOST_CHECK_EQUAL_COLLECTIONS(R1L.begin(), R1L.end(), R1Array, R1Array + uint256::size()); 163 BOOST_CHECK_EQUAL_COLLECTIONS(TmpL.begin(), TmpL.end(), R1Array, R1Array + uint256::size()); 164 BOOST_CHECK_EQUAL_COLLECTIONS(R2L.begin(), R2L.end(), R2Array, R2Array + uint256::size()); 165 BOOST_CHECK_EQUAL_COLLECTIONS(ZeroL.begin(), ZeroL.end(), ZeroArray, ZeroArray + uint256::size()); 166 BOOST_CHECK_EQUAL_COLLECTIONS(OneL.begin(), OneL.end(), OneArray, OneArray + uint256::size()); 167 BOOST_CHECK_EQUAL(R1L.size(), sizeof(R1L)); 168 BOOST_CHECK_EQUAL(sizeof(R1L), 32); 169 BOOST_CHECK_EQUAL(R1L.size(), 32); 170 BOOST_CHECK_EQUAL(R2L.size(), 32); 171 BOOST_CHECK_EQUAL(ZeroL.size(), 32); 172 BOOST_CHECK_EQUAL(MaxL.size(), 32); 173 BOOST_CHECK_EQUAL(R1L.begin() + 32, R1L.end()); 174 BOOST_CHECK_EQUAL(R2L.begin() + 32, R2L.end()); 175 BOOST_CHECK_EQUAL(OneL.begin() + 32, OneL.end()); 176 BOOST_CHECK_EQUAL(MaxL.begin() + 32, MaxL.end()); 177 BOOST_CHECK_EQUAL(TmpL.begin() + 32, TmpL.end()); 178 BOOST_CHECK_EQUAL(GetSerializeSize(R1L), 32); 179 BOOST_CHECK_EQUAL(GetSerializeSize(ZeroL), 32); 180 181 DataStream ss{}; 182 ss << R1L; 183 BOOST_CHECK_EQUAL(ss.str(), std::string(R1Array,R1Array+32)); 184 ss >> TmpL; 185 BOOST_CHECK_EQUAL(R1L, TmpL); 186 ss.clear(); 187 ss << ZeroL; 188 BOOST_CHECK_EQUAL(ss.str(), std::string(ZeroArray,ZeroArray+32)); 189 ss >> TmpL; 190 BOOST_CHECK_EQUAL(ZeroL, TmpL); 191 ss.clear(); 192 ss << MaxL; 193 BOOST_CHECK_EQUAL(ss.str(), std::string(MaxArray,MaxArray+32)); 194 ss >> TmpL; 195 BOOST_CHECK_EQUAL(MaxL, TmpL); 196 ss.clear(); 197 198 BOOST_CHECK_EQUAL(R1S.GetHex(), R1S.ToString()); 199 BOOST_CHECK_EQUAL(R2S.GetHex(), R2S.ToString()); 200 BOOST_CHECK_EQUAL(OneS.GetHex(), OneS.ToString()); 201 BOOST_CHECK_EQUAL(MaxS.GetHex(), MaxS.ToString()); 202 uint160 TmpS(R1S); 203 BOOST_CHECK_EQUAL(TmpS, R1S); 204 BOOST_CHECK_EQUAL(uint160::FromHex(R2S.ToString()).value(), R2S); 205 BOOST_CHECK_EQUAL(uint160::FromHex(ZeroS.ToString()).value(), uint160()); 206 207 TmpS = uint160::FromHex(R1S.ToString()).value(); 208 BOOST_CHECK_EQUAL_COLLECTIONS(R1S.begin(), R1S.end(), R1Array, R1Array + uint160::size()); 209 BOOST_CHECK_EQUAL_COLLECTIONS(TmpS.begin(), TmpS.end(), R1Array, R1Array + uint160::size()); 210 BOOST_CHECK_EQUAL_COLLECTIONS(R2S.begin(), R2S.end(), R2Array, R2Array + uint160::size()); 211 BOOST_CHECK_EQUAL_COLLECTIONS(ZeroS.begin(), ZeroS.end(), ZeroArray, ZeroArray + uint160::size()); 212 BOOST_CHECK_EQUAL_COLLECTIONS(OneS.begin(), OneS.end(), OneArray, OneArray + uint160::size()); 213 BOOST_CHECK_EQUAL(R1S.size(), sizeof(R1S)); 214 BOOST_CHECK_EQUAL(sizeof(R1S), 20); 215 BOOST_CHECK_EQUAL(R1S.size(), 20); 216 BOOST_CHECK_EQUAL(R2S.size(), 20); 217 BOOST_CHECK_EQUAL(ZeroS.size(), 20); 218 BOOST_CHECK_EQUAL(MaxS.size(), 20); 219 BOOST_CHECK_EQUAL(R1S.begin() + 20, R1S.end()); 220 BOOST_CHECK_EQUAL(R2S.begin() + 20, R2S.end()); 221 BOOST_CHECK_EQUAL(OneS.begin() + 20, OneS.end()); 222 BOOST_CHECK_EQUAL(MaxS.begin() + 20, MaxS.end()); 223 BOOST_CHECK_EQUAL(TmpS.begin() + 20, TmpS.end()); 224 BOOST_CHECK_EQUAL(GetSerializeSize(R1S), 20); 225 BOOST_CHECK_EQUAL(GetSerializeSize(ZeroS), 20); 226 227 ss << R1S; 228 BOOST_CHECK_EQUAL(ss.str(), std::string(R1Array,R1Array+20)); 229 ss >> TmpS; 230 BOOST_CHECK_EQUAL(R1S, TmpS); 231 ss.clear(); 232 ss << ZeroS; 233 BOOST_CHECK_EQUAL(ss.str(), std::string(ZeroArray,ZeroArray+20)); 234 ss >> TmpS; 235 BOOST_CHECK_EQUAL(ZeroS, TmpS); 236 ss.clear(); 237 ss << MaxS; 238 BOOST_CHECK_EQUAL(ss.str(), std::string(MaxArray,MaxArray+20)); 239 ss >> TmpS; 240 BOOST_CHECK_EQUAL(MaxS, TmpS); 241 ss.clear(); 242 } 243 244 /** 245 * Implemented as a templated function so it can be reused by other classes that have a FromHex() 246 * method that wraps base_blob::FromHex(), such as transaction_identifier::FromHex(). 247 */ 248 template <typename T> 249 void TestFromHex() 250 { 251 constexpr unsigned int num_chars{T::size() * 2}; 252 static_assert(num_chars <= 64); // this test needs to be modified to allow for more than 64 hex chars 253 const std::string valid_64char_input{"0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDEF"}; 254 const auto valid_input{valid_64char_input.substr(0, num_chars)}; 255 { 256 // check that lower and upper case hex characters are accepted 257 auto valid_result{T::FromHex(valid_input)}; 258 BOOST_REQUIRE(valid_result); 259 BOOST_CHECK_EQUAL(valid_result->ToString(), ToLower(valid_input)); 260 } 261 { 262 // check that only strings of size num_chars are accepted 263 BOOST_CHECK(!T::FromHex("")); 264 BOOST_CHECK(!T::FromHex("0")); 265 BOOST_CHECK(!T::FromHex(valid_input.substr(0, num_chars / 2))); 266 BOOST_CHECK(!T::FromHex(valid_input.substr(0, num_chars - 1))); 267 BOOST_CHECK(!T::FromHex(valid_input + "0")); 268 } 269 { 270 // check that non-hex characters are not accepted 271 std::string invalid_chars{R"( !"#$%&'()*+,-./:;<=>?@GHIJKLMNOPQRSTUVWXYZ[\]^_`ghijklmnopqrstuvwxyz{|}~)"}; 272 for (auto c : invalid_chars) { 273 BOOST_CHECK(!T::FromHex(valid_input.substr(0, num_chars - 1) + c)); 274 } 275 // 0x prefixes are invalid 276 std::string invalid_prefix{"0x" + valid_input}; 277 BOOST_CHECK(!T::FromHex(std::string_view(invalid_prefix.data(), num_chars))); 278 BOOST_CHECK(!T::FromHex(invalid_prefix)); 279 } 280 { 281 // check that string_view length is respected 282 std::string chars_68{valid_64char_input + "0123"}; 283 BOOST_CHECK_EQUAL(T::FromHex(std::string_view(chars_68.data(), num_chars)).value().ToString(), ToLower(valid_input)); 284 BOOST_CHECK(!T::FromHex(std::string_view(chars_68.data(), num_chars - 1))); // too short 285 BOOST_CHECK(!T::FromHex(std::string_view(chars_68.data(), num_chars + 1))); // too long 286 } 287 } 288 289 BOOST_AUTO_TEST_CASE(from_hex) 290 { 291 TestFromHex<uint160>(); 292 TestFromHex<uint256>(); 293 TestFromHex<Txid>(); 294 TestFromHex<Wtxid>(); 295 } 296 297 BOOST_AUTO_TEST_CASE(from_user_hex) 298 { 299 BOOST_CHECK_EQUAL(uint256::FromUserHex(""), uint256::ZERO); 300 BOOST_CHECK_EQUAL(uint256::FromUserHex("0x"), uint256::ZERO); 301 BOOST_CHECK_EQUAL(uint256::FromUserHex("0"), uint256::ZERO); 302 BOOST_CHECK_EQUAL(uint256::FromUserHex("00"), uint256::ZERO); 303 BOOST_CHECK_EQUAL(uint256::FromUserHex("1"), uint256::ONE); 304 BOOST_CHECK_EQUAL(uint256::FromUserHex("0x10"), uint256{0x10}); 305 BOOST_CHECK_EQUAL(uint256::FromUserHex("10"), uint256{0x10}); 306 BOOST_CHECK_EQUAL(uint256::FromUserHex("0xFf"), uint256{0xff}); 307 BOOST_CHECK_EQUAL(uint256::FromUserHex("Ff"), uint256{0xff}); 308 const std::string valid_hex_64{"0x0123456789abcdef0123456789abcdef0123456789ABDCEF0123456789ABCDEF"}; 309 BOOST_REQUIRE_EQUAL(valid_hex_64.size(), 2 + 64); // 0x prefix and 64 hex digits 310 BOOST_CHECK_EQUAL(uint256::FromUserHex(valid_hex_64.substr(2)).value().ToString(), ToLower(valid_hex_64.substr(2))); 311 BOOST_CHECK_EQUAL(uint256::FromUserHex(valid_hex_64.substr(0)).value().ToString(), ToLower(valid_hex_64.substr(2))); 312 313 BOOST_CHECK(!uint256::FromUserHex("0x0 ")); // no spaces at end, 314 BOOST_CHECK(!uint256::FromUserHex(" 0x0")); // or beginning, 315 BOOST_CHECK(!uint256::FromUserHex("0x 0")); // or middle, 316 BOOST_CHECK(!uint256::FromUserHex(" ")); // etc. 317 BOOST_CHECK(!uint256::FromUserHex("0x0ga")); // invalid character 318 BOOST_CHECK(!uint256::FromUserHex("x0")); // broken prefix 319 BOOST_CHECK(!uint256::FromUserHex("0x0x00")); // two prefixes not allowed 320 BOOST_CHECK(!uint256::FromUserHex(valid_hex_64.substr(2) + "0")); // 1 hex digit too many 321 BOOST_CHECK(!uint256::FromUserHex(valid_hex_64 + "a")); // 1 hex digit too many 322 BOOST_CHECK(!uint256::FromUserHex(valid_hex_64 + " ")); // whitespace after max length 323 BOOST_CHECK(!uint256::FromUserHex(valid_hex_64 + "z")); // invalid character after max length 324 } 325 326 BOOST_AUTO_TEST_CASE( check_ONE ) 327 { 328 uint256 one = uint256{"0000000000000000000000000000000000000000000000000000000000000001"}; 329 BOOST_CHECK_EQUAL(one, uint256::ONE); 330 } 331 332 BOOST_AUTO_TEST_CASE(FromHex_vs_uint256) 333 { 334 auto runtime_uint{uint256::FromHex("4A5E1E4BAAB89F3A32518A88C31BC87F618f76673e2cc77ab2127b7afdeda33b")}; 335 constexpr uint256 consteval_uint{ "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"}; 336 BOOST_CHECK_EQUAL(consteval_uint, runtime_uint); 337 } 338 339 BOOST_AUTO_TEST_SUITE_END()