From b4a459b8b44dbd0f2bb993949720e4ea4ae748c7 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 21:23:33 +0200 Subject: [PATCH 01/17] [Refactoring] BIP38: init uint from string and use arith where needed --- src/bip38.cpp | 76 ++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/bip38.cpp b/src/bip38.cpp index 6b7365a787f08..6a14e235e7d8e 100644 --- a/src/bip38.cpp +++ b/src/bip38.cpp @@ -41,7 +41,7 @@ void ComputePreFactor(std::string strPassphrase, std::string strSalt, uint256& p void ComputePassfactor(std::string ownersalt, uint256 prefactor, uint256& passfactor) { //concat prefactor and ownersalt - uint512 temp(ReverseEndianString(HexStr(prefactor) + ownersalt)); + uint512 temp = uint512S(ReverseEndianString(HexStr(prefactor) + ownersalt)); Hash(temp.begin(), 40, passfactor.begin()); //40 bytes is the length of prefactor + salt Hash(passfactor.begin(), 32, passfactor.begin()); } @@ -110,31 +110,31 @@ std::string BIP38_Encrypt(std::string strAddress, std::string strPassphrase, uin uint64_t salt = uint256S(ReverseEndianString(strAddressHash)).GetCheapHash(); scrypt_hash(strPassphrase.c_str(), strPassphrase.size(), BEGIN(salt), strAddressHash.size() / 2, BEGIN(hashed), 16384, 8, 8, 64); - uint256 derivedHalf1(hashed.ToString().substr(64, 64)); - uint256 derivedHalf2(hashed.ToString().substr(0, 64)); + arith_uint256 derivedHalf1(hashed.ToString().substr(64, 64)); + arith_uint256 derivedHalf2(hashed.ToString().substr(0, 64)); //block1 = (pointb[1...16] xor derivedhalf1[0...15]) - uint256 block1 = uint256((privKey << 128) ^ (derivedHalf1 << 128)) >> 128; + arith_uint256 block1 = ((UintToArith256(privKey) << 128) ^ (derivedHalf1 << 128)) >> 128; //encrypt part 1 - uint512 encrypted1; + arith_uint512 encrypted1; AES_KEY key; AES_set_encrypt_key(derivedHalf2.begin(), 256, &key); AES_encrypt(block1.begin(), encrypted1.begin(), &key); //block2 = (pointb[17...32] xor derivedhalf1[16...31] - uint256 p2 = privKey >> 128; - uint256 dh12 = derivedHalf1 >> 128; - uint256 block2 = uint256(p2 ^ dh12); + arith_uint256 p2 = UintToArith256(privKey) >> 128; + arith_uint256 dh12 = derivedHalf1 >> 128; + arith_uint256 block2 = p2 ^ dh12; //encrypt part 2 - uint512 encrypted2; + arith_uint512 encrypted2; AES_encrypt(block2.begin(), encrypted2.begin(), &key); std::string strPrefix = "0142"; strPrefix += (fCompressed ? "E0" : "C0"); - uint512 encryptedKey(ReverseEndianString(strPrefix + strAddressHash)); + arith_uint512 encryptedKey(ReverseEndianString(strPrefix + strAddressHash)); //add encrypted1 to the end of encryptedKey encryptedKey = encryptedKey | (encrypted1 << 56); @@ -144,7 +144,7 @@ std::string BIP38_Encrypt(std::string strAddress, std::string strPassphrase, uin //Base58 checksum is the 4 bytes of dSHA256 hash of the encrypted key uint256 hashChecksum = Hash(encryptedKey.begin(), encryptedKey.begin() + 39); - uint512 b58Checksum(hashChecksum.ToString().substr(64 - 8, 8)); + arith_uint512 b58Checksum(hashChecksum.ToString().substr(64 - 8, 8)); // append the encrypted key with checksum (currently occupies 312 bits) encryptedKey = encryptedKey | (b58Checksum << 312); @@ -162,27 +162,27 @@ bool BIP38_Decrypt(std::string strPassphrase, std::string strEncryptedKey, uint2 return false; //invalid prefix - if (uint256(ReverseEndianString(strKey.substr(0, 2))) != uint256(0x01)) + if (uint256S(ReverseEndianString(strKey.substr(0, 2))) != UINT256_ONE) return false; - uint256 type(ReverseEndianString(strKey.substr(2, 2))); - uint256 flag(ReverseEndianString(strKey.substr(4, 2))); + arith_uint256 type(ReverseEndianString(strKey.substr(2, 2))); + arith_uint256 flag(ReverseEndianString(strKey.substr(4, 2))); std::string strAddressHash = strKey.substr(6, 8); std::string ownersalt = strKey.substr(14, 16); - uint256 encryptedPart1(ReverseEndianString(strKey.substr(30, 16))); - uint256 encryptedPart2(ReverseEndianString(strKey.substr(46, 32))); + uint256 encryptedPart1 = uint256S(ReverseEndianString(strKey.substr(30, 16))); + uint256 encryptedPart2 = uint256S(ReverseEndianString(strKey.substr(46, 32))); - fCompressed = (flag & uint256(0x20)) != 0; + fCompressed = (flag & 0x20) != ARITH_UINT256_ZERO; //not ec multiplied - if (type == uint256(0x42)) { + if (type == arith_uint256(0x42)) { uint512 hashed; - encryptedPart1 = uint256(ReverseEndianString(strKey.substr(14, 32))); + encryptedPart1 = uint256S(ReverseEndianString(strKey.substr(14, 32))); uint64_t salt = uint256S(ReverseEndianString(strAddressHash)).GetCheapHash(); scrypt_hash(strPassphrase.c_str(), strPassphrase.size(), BEGIN(salt), strAddressHash.size() / 2, BEGIN(hashed), 16384, 8, 8, 64); - uint256 derivedHalf1(uint256S(hashed.ToString().substr(64, 64))); - uint256 derivedHalf2(uint256S(hashed.ToString().substr(0, 64))); + const uint256& derivedHalf1 = uint256S(hashed.ToString().substr(64, 64)); + const uint256& derivedHalf2 = uint256S(hashed.ToString().substr(0, 64)); uint256 decryptedPart1; DecryptAES(encryptedPart1, derivedHalf2, decryptedPart1); @@ -191,15 +191,17 @@ bool BIP38_Decrypt(std::string strPassphrase, std::string strEncryptedKey, uint2 DecryptAES(encryptedPart2, derivedHalf2, decryptedPart2); //combine decrypted parts into 64 bytes - uint256 temp1 = decryptedPart2 << 128; - temp1 = temp1 | decryptedPart1; + arith_uint256 temp1 = UintToArith256(decryptedPart2) << 128; + temp1 = temp1 | UintToArith256(decryptedPart1); //xor the decryption with the derived half 1 for the final key - privKey = temp1 ^ derivedHalf1; + privKey = ArithToUint256(temp1 ^ UintToArith256(derivedHalf1)); return true; - } else if (type != uint256(0x43)) //invalid type + } else if (type != arith_uint256(0x43)) { + //invalid type return false; + } bool fLotSequence = (flag & 0x04) != 0; @@ -224,32 +226,32 @@ bool BIP38_Decrypt(std::string strPassphrase, std::string strEncryptedKey, uint2 ComputeSeedBPass(passpoint, strAddressHash, ownersalt, seedBPass); //get derived halfs, being mindful for endian switch - uint256 derivedHalf1(uint256S(seedBPass.ToString().substr(64, 64))); - uint256 derivedHalf2(uint256S(seedBPass.ToString().substr(0, 64))); + const uint256 derivedHalf1 = uint256S(seedBPass.ToString().substr(64, 64)); + const uint256 derivedHalf2 = uint256S(seedBPass.ToString().substr(0, 64)); /** Decrypt encryptedpart2 using AES256Decrypt to yield the last 8 bytes of seedb and the last 8 bytes of encryptedpart1. **/ uint256 decryptedPart2; DecryptAES(encryptedPart2, derivedHalf2, decryptedPart2); //xor decryptedPart2 and 2nd half of derived half 1 - uint256 x0 = derivedHalf1 >> 128; //drop off the first half (note: endian) - uint256 x1 = decryptedPart2 ^ x0; - uint256 seedbPart2 = x1 >> 64; + arith_uint256 x0 = UintToArith256(derivedHalf1) >> 128; //drop off the first half (note: endian) + arith_uint256 x1 = UintToArith256(decryptedPart2) ^ x0; + arith_uint256 seedbPart2 = x1 >> 64; /** Decrypt encryptedpart1 to yield the remainder of seedb. **/ uint256 decryptedPart1; - uint256 x2 = x1 & uint256("0xffffffffffffffff"); // set x2 to seedbPart1 (still encrypted) + arith_uint256 x2 = x1 & arith_uint256("0xffffffffffffffff"); // set x2 to seedbPart1 (still encrypted) x2 = x2 << 64; //make room to add encryptedPart1 to the front - x2 = encryptedPart1 | x2; //combine with encryptedPart1 - DecryptAES(x2, derivedHalf2, decryptedPart1); + x2 = UintToArith256(encryptedPart1) | x2; //combine with encryptedPart1 + DecryptAES(ArithToUint256(x2), derivedHalf2, decryptedPart1); //decrypted part 1: seedb[0..15] xor derivedhalf1[0..15] - uint256 x3 = derivedHalf1 & uint256("0xffffffffffffffffffffffffffffffff"); - uint256 seedbPart1 = decryptedPart1 ^ x3; - uint256 seedB = seedbPart1 | (seedbPart2 << 128); + arith_uint256 x3 = UintToArith256(derivedHalf1) & arith_uint256("0xffffffffffffffffffffffffffffffff"); + arith_uint256 seedbPart1 = UintToArith256(decryptedPart1) ^ x3; + arith_uint256 seedB = seedbPart1 | (seedbPart2 << 128); uint256 factorB; - ComputeFactorB(seedB, factorB); + ComputeFactorB(ArithToUint256(seedB), factorB); //multiply passfactor by factorb mod N to yield the priv key secp256k1_context *ctx = secp256k1_context_create(SECP256K1_CONTEXT_SIGN); From 86e177b11f1d19af01df2bd2326aa8e10f5c9f8e Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 21:30:00 +0200 Subject: [PATCH 02/17] [Tests] Replace uint256 tests with blob_uint256 tests --- src/test/uint256_tests.cpp | 764 ++++++------------------------------- 1 file changed, 108 insertions(+), 656 deletions(-) diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index cfc3f9d4703d5..e43b057fbeb5b 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -14,46 +14,41 @@ #include "version.h" #include "test/test_pivx.h" +/** !TODO: enable after transition blob_uint256 -- > uint256 + BOOST_FIXTURE_TEST_SUITE(uint256_tests, BasicTestingSetup) const unsigned char R1Array[] = "\x9c\x52\x4a\xdb\xcf\x56\x11\x12\x2b\x29\x12\x5e\x5d\x35\xd2\xd2" "\x22\x81\xaa\xb5\x33\xf0\x08\x32\xd5\x56\xb1\xf9\xea\xe5\x1d\x7d"; const char R1ArrayHex[] = "7D1DE5EAF9B156D53208F033B5AA8122D2d2355d5e12292b121156cfdb4a529c"; -const double R1Ldouble = 0.4887374590559308955; // R1L equals roughly R1Ldouble * 2^256 -const double R1Sdouble = 0.7096329412477836074; const uint256 R1L = uint256(std::vector(R1Array,R1Array+32)); -const arith_uint160 R1S = arith_uint160(std::vector(R1Array,R1Array+20)); -const uint64_t R1LLow64 = 0x121156cfdb4a529cULL; +const uint160 R1S = uint160(std::vector(R1Array,R1Array+20)); const unsigned char R2Array[] = "\x70\x32\x1d\x7c\x47\xa5\x6b\x40\x26\x7e\x0a\xc3\xa6\x9c\xb6\xbf" "\x13\x30\x47\xa3\x19\x2d\xda\x71\x49\x13\x72\xf0\xb4\xca\x81\xd7"; const uint256 R2L = uint256(std::vector(R2Array,R2Array+32)); -const arith_uint160 R2S = arith_uint160(std::vector(R2Array,R2Array+20)); - -const char R1LplusR2L[] = "549FB09FEA236A1EA3E31D4D58F1B1369288D204211CA751527CFC175767850C"; +const uint160 R2S = uint160(std::vector(R2Array,R2Array+20)); const unsigned char ZeroArray[] = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; const uint256 ZeroL = uint256(std::vector(ZeroArray,ZeroArray+32)); -const arith_uint160 ZeroS = arith_uint160(std::vector(ZeroArray,ZeroArray+20)); +const uint160 ZeroS = uint160(std::vector(ZeroArray,ZeroArray+20)); const unsigned char OneArray[] = "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; const uint256 OneL = uint256(std::vector(OneArray,OneArray+32)); -const arith_uint160 OneS = arith_uint160(std::vector(OneArray,OneArray+20)); +const uint160 OneS = uint160(std::vector(OneArray,OneArray+20)); const unsigned char MaxArray[] = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"; const uint256 MaxL = uint256(std::vector(MaxArray,MaxArray+32)); -const arith_uint160 MaxS = arith_uint160(std::vector(MaxArray,MaxArray+20)); +const uint160 MaxS = uint160(std::vector(MaxArray,MaxArray+20)); -const uint256 HalfL = (OneL << 255); -const arith_uint160 HalfS = (OneS << 159); std::string ArrayToString(const unsigned char A[], unsigned int width) { std::stringstream Stream; @@ -65,6 +60,19 @@ std::string ArrayToString(const unsigned char A[], unsigned int width) return Stream.str(); } +inline uint160 uint160S(const char *str) +{ + uint160 rv; + rv.SetHex(str); + return rv; +} +inline uint160 uint160S(const std::string& str) +{ + uint160 rv; + rv.SetHex(str); + return rv; +} + BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality { BOOST_CHECK(1 == 0+1); @@ -87,477 +95,66 @@ BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality BOOST_CHECK(ZeroL != OneL && ZeroS != OneS); BOOST_CHECK(OneL != ZeroL && OneS != ZeroS); BOOST_CHECK(MaxL != ZeroL && MaxS != ZeroS); - BOOST_CHECK(~MaxL == ZeroL && ~MaxS == ZeroS); - BOOST_CHECK( ((R1L ^ R2L) ^ R1L) == R2L); - BOOST_CHECK( ((R1S ^ R2S) ^ R1S) == R2S); - - uint64_t Tmp64 = 0xc4dab720d9c7acaaULL; - for (unsigned int i = 0; i < 256; ++i) - { - BOOST_CHECK(ZeroL != (OneL << i)); - BOOST_CHECK((OneL << i) != ZeroL); - BOOST_CHECK(R1L != (R1L ^ (OneL << i))); - BOOST_CHECK(((uint256(Tmp64) ^ (OneL << i) ) != Tmp64 )); - } - BOOST_CHECK(ZeroL == (OneL << 256)); - - for (unsigned int i = 0; i < 160; ++i) - { - BOOST_CHECK(ZeroS != (OneS << i)); - BOOST_CHECK((OneS << i) != ZeroS); - BOOST_CHECK(R1S != (R1S ^ (OneS << i))); - BOOST_CHECK(((arith_uint160(Tmp64) ^ (OneS << i) ) != Tmp64 )); - } - BOOST_CHECK(ZeroS == (OneS << 256)); // String Constructor and Copy Constructor - BOOST_CHECK(uint256("0x"+R1L.ToString()) == R1L); - BOOST_CHECK(uint256("0x"+R2L.ToString()) == R2L); - BOOST_CHECK(uint256("0x"+ZeroL.ToString()) == ZeroL); - BOOST_CHECK(uint256("0x"+OneL.ToString()) == OneL); - BOOST_CHECK(uint256("0x"+MaxL.ToString()) == MaxL); - BOOST_CHECK(uint256(R1L.ToString()) == R1L); - BOOST_CHECK(uint256(" 0x"+R1L.ToString()+" ") == R1L); - BOOST_CHECK(uint256("") == ZeroL); - BOOST_CHECK(R1L == uint256(R1ArrayHex)); + BOOST_CHECK(uint256S("0x"+R1L.ToString()) == R1L); + BOOST_CHECK(uint256S("0x"+R2L.ToString()) == R2L); + BOOST_CHECK(uint256S("0x"+ZeroL.ToString()) == ZeroL); + BOOST_CHECK(uint256S("0x"+OneL.ToString()) == OneL); + BOOST_CHECK(uint256S("0x"+MaxL.ToString()) == MaxL); + BOOST_CHECK(uint256S(R1L.ToString()) == R1L); + BOOST_CHECK(uint256S(" 0x"+R1L.ToString()+" ") == R1L); + BOOST_CHECK(uint256S("") == ZeroL); + BOOST_CHECK(R1L == uint256S(R1ArrayHex)); BOOST_CHECK(uint256(R1L) == R1L); - BOOST_CHECK((uint256(R1L^R2L)^R2L) == R1L); BOOST_CHECK(uint256(ZeroL) == ZeroL); BOOST_CHECK(uint256(OneL) == OneL); - BOOST_CHECK(arith_uint160("0x"+R1S.ToString()) == R1S); - BOOST_CHECK(arith_uint160("0x"+R2S.ToString()) == R2S); - BOOST_CHECK(arith_uint160("0x"+ZeroS.ToString()) == ZeroS); - BOOST_CHECK(arith_uint160("0x"+OneS.ToString()) == OneS); - BOOST_CHECK(arith_uint160("0x"+MaxS.ToString()) == MaxS); - BOOST_CHECK(arith_uint160(R1S.ToString()) == R1S); - BOOST_CHECK(arith_uint160(" 0x"+R1S.ToString()+" ") == R1S); - BOOST_CHECK(arith_uint160("") == ZeroS); - BOOST_CHECK(R1S == arith_uint160(R1ArrayHex)); - - BOOST_CHECK(arith_uint160(R1S) == R1S); - BOOST_CHECK((arith_uint160(R1S^R2S)^R2S) == R1S); - BOOST_CHECK(arith_uint160(ZeroS) == ZeroS); - BOOST_CHECK(arith_uint160(OneS) == OneS); - - // uint64_t constructor - BOOST_CHECK( (R1L & uint256("0xffffffffffffffff")) == uint256(R1LLow64)); - BOOST_CHECK(ZeroL.IsNull()); - BOOST_CHECK(OneL == uint256(1)); - BOOST_CHECK(uint256("0xffffffffffffffff") = uint256(0xffffffffffffffffULL)); - BOOST_CHECK( (R1S & arith_uint160("0xffffffffffffffff")) == arith_uint160(R1LLow64)); - BOOST_CHECK(ZeroS == arith_uint160(0)); - BOOST_CHECK(OneS == arith_uint160(1)); - BOOST_CHECK(arith_uint160("0xffffffffffffffff") = arith_uint160(0xffffffffffffffffULL)); - - // Assignment (from base_uint) - uint256 tmpL = ~ZeroL; BOOST_CHECK(tmpL == ~ZeroL); - tmpL = ~OneL; BOOST_CHECK(tmpL == ~OneL); - tmpL = ~R1L; BOOST_CHECK(tmpL == ~R1L); - tmpL = ~R2L; BOOST_CHECK(tmpL == ~R2L); - tmpL = ~MaxL; BOOST_CHECK(tmpL == ~MaxL); - arith_uint160 tmpS = ~ZeroS; BOOST_CHECK(tmpS == ~ZeroS); - tmpS = ~OneS; BOOST_CHECK(tmpS == ~OneS); - tmpS = ~R1S; BOOST_CHECK(tmpS == ~R1S); - tmpS = ~R2S; BOOST_CHECK(tmpS == ~R2S); - tmpS = ~MaxS; BOOST_CHECK(tmpS == ~MaxS); - - // Wrong length must throw exception. - BOOST_CHECK_THROW(uint256(std::vector(OneArray,OneArray+31)), uint_error); - BOOST_CHECK_THROW(uint256(std::vector(OneArray,OneArray+20)), uint_error); - BOOST_CHECK_THROW(arith_uint160(std::vector(OneArray,OneArray+32)), uint_error); - BOOST_CHECK_THROW(arith_uint160(std::vector(OneArray,OneArray+19)), uint_error); -} - -void shiftArrayRight(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift) -{ - for (unsigned int T=0; T < arrayLength; ++T) - { - unsigned int F = (T+bitsToShift/8); - if (F < arrayLength) - to[T] = from[F] >> (bitsToShift%8); - else - to[T] = 0; - if (F + 1 < arrayLength) - to[T] |= from[(F+1)] << (8-bitsToShift%8); - } + BOOST_CHECK(uint160S("0x"+R1S.ToString()) == R1S); + BOOST_CHECK(uint160S("0x"+R2S.ToString()) == R2S); + BOOST_CHECK(uint160S("0x"+ZeroS.ToString()) == ZeroS); + BOOST_CHECK(uint160S("0x"+OneS.ToString()) == OneS); + BOOST_CHECK(uint160S("0x"+MaxS.ToString()) == MaxS); + BOOST_CHECK(uint160S(R1S.ToString()) == R1S); + BOOST_CHECK(uint160S(" 0x"+R1S.ToString()+" ") == R1S); + BOOST_CHECK(uint160S("") == ZeroS); + BOOST_CHECK(R1S == uint160S(R1ArrayHex)); + + BOOST_CHECK(uint160(R1S) == R1S); + BOOST_CHECK(uint160(ZeroS) == ZeroS); + BOOST_CHECK(uint160(OneS) == OneS); } -void shiftArrayLeft(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift) +BOOST_AUTO_TEST_CASE( comparison ) // < { - for (unsigned int T=0; T < arrayLength; ++T) - { - if (T >= bitsToShift/8) - { - unsigned int F = T-bitsToShift/8; - to[T] = from[F] << (bitsToShift%8); - if (T >= bitsToShift/8+1) - to[T] |= from[F-1] >> (8-bitsToShift%8); - } - else { - to[T] = 0; - } - } -} - -BOOST_AUTO_TEST_CASE( shifts ) { // "<<" ">>" "<<=" ">>=" - unsigned char TmpArray[32]; - uint256 TmpL; - for (unsigned int i = 0; i < 256; ++i) - { - shiftArrayLeft(TmpArray, OneArray, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (OneL << i)); - TmpL = OneL; TmpL <<= i; - BOOST_CHECK(TmpL == (OneL << i)); - BOOST_CHECK((HalfL >> (255-i)) == (OneL << i)); - TmpL = HalfL; TmpL >>= (255-i); - BOOST_CHECK(TmpL == (OneL << i)); - - shiftArrayLeft(TmpArray, R1Array, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (R1L << i)); - TmpL = R1L; TmpL <<= i; - BOOST_CHECK(TmpL == (R1L << i)); - - shiftArrayRight(TmpArray, R1Array, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (R1L >> i)); - TmpL = R1L; TmpL >>= i; - BOOST_CHECK(TmpL == (R1L >> i)); - - shiftArrayLeft(TmpArray, MaxArray, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (MaxL << i)); - TmpL = MaxL; TmpL <<= i; - BOOST_CHECK(TmpL == (MaxL << i)); - - shiftArrayRight(TmpArray, MaxArray, 32, i); - BOOST_CHECK(uint256(std::vector(TmpArray,TmpArray+32)) == (MaxL >> i)); - TmpL = MaxL; TmpL >>= i; - BOOST_CHECK(TmpL == (MaxL >> i)); - } - uint256 c1L = uint256(0x0123456789abcdefULL); - uint256 c2L = c1L << 128; - for (unsigned int i = 0; i < 128; ++i) { - BOOST_CHECK((c1L << i) == (c2L >> (128-i))); - } - for (unsigned int i = 128; i < 256; ++i) { - BOOST_CHECK((c1L << i) == (c2L << (i-128))); + uint256 LastL; + for (int i = 255; i >= 0; --i) { + uint256 TmpL; + *(TmpL.begin() + (i>>3)) |= 1<<(7-(i&7)); + BOOST_CHECK( LastL < TmpL ); + LastL = TmpL; } - arith_uint160 TmpS; - for (unsigned int i = 0; i < 160; ++i) - { - shiftArrayLeft(TmpArray, OneArray, 20, i); - BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (OneS << i)); - TmpS = OneS; TmpS <<= i; - BOOST_CHECK(TmpS == (OneS << i)); - BOOST_CHECK((HalfS >> (159-i)) == (OneS << i)); - TmpS = HalfS; TmpS >>= (159-i); - BOOST_CHECK(TmpS == (OneS << i)); - - shiftArrayLeft(TmpArray, R1Array, 20, i); - BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (R1S << i)); - TmpS = R1S; TmpS <<= i; - BOOST_CHECK(TmpS == (R1S << i)); - - shiftArrayRight(TmpArray, R1Array, 20, i); - BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (R1S >> i)); - TmpS = R1S; TmpS >>= i; - BOOST_CHECK(TmpS == (R1S >> i)); - - shiftArrayLeft(TmpArray, MaxArray, 20, i); - BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (MaxS << i)); - TmpS = MaxS; TmpS <<= i; - BOOST_CHECK(TmpS == (MaxS << i)); - - shiftArrayRight(TmpArray, MaxArray, 20, i); - BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (MaxS >> i)); - TmpS = MaxS; TmpS >>= i; - BOOST_CHECK(TmpS == (MaxS >> i)); - } - arith_uint160 c1S = arith_uint160(0x0123456789abcdefULL); - arith_uint160 c2S = c1S << 80; - for (unsigned int i = 0; i < 80; ++i) { - BOOST_CHECK((c1S << i) == (c2S >> (80-i))); - } - for (unsigned int i = 80; i < 160; ++i) { - BOOST_CHECK((c1S << i) == (c2S << (i-80))); + BOOST_CHECK( ZeroL < R1L ); + BOOST_CHECK( R2L < R1L ); + BOOST_CHECK( ZeroL < OneL ); + BOOST_CHECK( OneL < MaxL ); + BOOST_CHECK( R1L < MaxL ); + BOOST_CHECK( R2L < MaxL ); + + uint160 LastS; + for (int i = 159; i >= 0; --i) { + uint160 TmpS; + *(TmpS.begin() + (i>>3)) |= 1<<(7-(i&7)); + BOOST_CHECK( LastS < TmpS ); + LastS = TmpS; } -} - -BOOST_AUTO_TEST_CASE( unaryOperators ) // ! ~ - -{ - BOOST_CHECK(!ZeroL); BOOST_CHECK(!ZeroS); - BOOST_CHECK(!(!OneL));BOOST_CHECK(!(!OneS)); - for (unsigned int i = 0; i < 256; ++i) - BOOST_CHECK(!(!(OneL<(TmpArray,TmpArray+32)) == (~R1L)); - BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (~R1S)); - - BOOST_CHECK(-ZeroL == ZeroL); BOOST_CHECK(-ZeroS == ZeroS); - BOOST_CHECK(-R1L == (~R1L)+1); - BOOST_CHECK(-R1S == (~R1S)+1); - for (unsigned int i = 0; i < 256; ++i) - BOOST_CHECK(-(OneL<(TmpArray,TmpArray+32)) == (_A_##L _OP_ _B_##L)); \ - for (unsigned int i = 0; i < 20; ++i) { TmpArray[i] = _A_##Array[i] _OP_ _B_##Array[i]; } \ - BOOST_CHECK(arith_uint160(std::vector(TmpArray,TmpArray+20)) == (_A_##S _OP_ _B_##S)); - -#define CHECKASSIGNMENTOPERATOR(_A_,_B_,_OP_) \ - TmpL = _A_##L; TmpL _OP_##= _B_##L; BOOST_CHECK(TmpL == (_A_##L _OP_ _B_##L)); \ - TmpS = _A_##S; TmpS _OP_##= _B_##S; BOOST_CHECK(TmpS == (_A_##S _OP_ _B_##S)); - -BOOST_AUTO_TEST_CASE( bitwiseOperators ) -{ - unsigned char TmpArray[32]; - - CHECKBITWISEOPERATOR(R1,R2,|) - CHECKBITWISEOPERATOR(R1,R2,^) - CHECKBITWISEOPERATOR(R1,R2,&) - CHECKBITWISEOPERATOR(R1,Zero,|) - CHECKBITWISEOPERATOR(R1,Zero,^) - CHECKBITWISEOPERATOR(R1,Zero,&) - CHECKBITWISEOPERATOR(R1,Max,|) - CHECKBITWISEOPERATOR(R1,Max,^) - CHECKBITWISEOPERATOR(R1,Max,&) - CHECKBITWISEOPERATOR(Zero,R1,|) - CHECKBITWISEOPERATOR(Zero,R1,^) - CHECKBITWISEOPERATOR(Zero,R1,&) - CHECKBITWISEOPERATOR(Max,R1,|) - CHECKBITWISEOPERATOR(Max,R1,^) - CHECKBITWISEOPERATOR(Max,R1,&) - - uint256 TmpL; - arith_uint160 TmpS; - CHECKASSIGNMENTOPERATOR(R1,R2,|) - CHECKASSIGNMENTOPERATOR(R1,R2,^) - CHECKASSIGNMENTOPERATOR(R1,R2,&) - CHECKASSIGNMENTOPERATOR(R1,Zero,|) - CHECKASSIGNMENTOPERATOR(R1,Zero,^) - CHECKASSIGNMENTOPERATOR(R1,Zero,&) - CHECKASSIGNMENTOPERATOR(R1,Max,|) - CHECKASSIGNMENTOPERATOR(R1,Max,^) - CHECKASSIGNMENTOPERATOR(R1,Max,&) - CHECKASSIGNMENTOPERATOR(Zero,R1,|) - CHECKASSIGNMENTOPERATOR(Zero,R1,^) - CHECKASSIGNMENTOPERATOR(Zero,R1,&) - CHECKASSIGNMENTOPERATOR(Max,R1,|) - CHECKASSIGNMENTOPERATOR(Max,R1,^) - CHECKASSIGNMENTOPERATOR(Max,R1,&) - - uint64_t Tmp64 = 0xe1db685c9a0b47a2ULL; - TmpL = R1L; TmpL |= Tmp64; BOOST_CHECK(TmpL == (R1L | uint256(Tmp64))); - TmpS = R1S; TmpS |= Tmp64; BOOST_CHECK(TmpS == (R1S | arith_uint160(Tmp64))); - TmpL = R1L; TmpL |= 0; BOOST_CHECK(TmpL == R1L); - TmpS = R1S; TmpS |= 0; BOOST_CHECK(TmpS == R1S); - TmpL ^= 0; BOOST_CHECK(TmpL == R1L); - TmpS ^= 0; BOOST_CHECK(TmpS == R1S); - TmpL ^= Tmp64; BOOST_CHECK(TmpL == (R1L ^ uint256(Tmp64))); - TmpS ^= Tmp64; BOOST_CHECK(TmpS == (R1S ^ arith_uint160(Tmp64))); -} - -BOOST_AUTO_TEST_CASE( comparison ) // <= >= < > -{ - uint256 TmpL; - for (unsigned int i = 0; i < 256; ++i) { - TmpL= OneL<< i; - BOOST_CHECK( TmpL >= ZeroL && TmpL > ZeroL && ZeroL < TmpL && ZeroL <= TmpL); - BOOST_CHECK( TmpL >= 0 && TmpL > 0 && 0 < TmpL && 0 <= TmpL); - TmpL |= R1L; - BOOST_CHECK( TmpL >= R1L ); BOOST_CHECK( (TmpL == R1L) != (TmpL > R1L)); BOOST_CHECK( (TmpL == R1L) || !( TmpL <= R1L)); - BOOST_CHECK( R1L <= TmpL ); BOOST_CHECK( (R1L == TmpL) != (R1L < TmpL)); BOOST_CHECK( (TmpL == R1L) || !( R1L >= TmpL)); - BOOST_CHECK(! (TmpL < R1L)); BOOST_CHECK(! (R1L > TmpL)); - } - arith_uint160 TmpS; - for (unsigned int i = 0; i < 160; ++i) { - TmpS= OneS<< i; - BOOST_CHECK( TmpS >= ZeroS && TmpS > ZeroS && ZeroS < TmpS && ZeroS <= TmpS); - BOOST_CHECK( TmpS >= 0 && TmpS > 0 && 0 < TmpS && 0 <= TmpS); - TmpS |= R1S; - BOOST_CHECK( TmpS >= R1S ); BOOST_CHECK( (TmpS == R1S) != (TmpS > R1S)); BOOST_CHECK( (TmpS == R1S) || !( TmpS <= R1S)); - BOOST_CHECK( R1S <= TmpS ); BOOST_CHECK( (R1S == TmpS) != (R1S < TmpS)); BOOST_CHECK( (TmpS == R1S) || !( R1S >= TmpS)); - BOOST_CHECK(! (TmpS < R1S)); BOOST_CHECK(! (R1S > TmpS)); - } -} - -BOOST_AUTO_TEST_CASE( plusMinus ) -{ - uint256 TmpL = 0; - BOOST_CHECK(R1L+R2L == uint256(R1LplusR2L)); - TmpL += R1L; - BOOST_CHECK(TmpL == R1L); - TmpL += R2L; - BOOST_CHECK(TmpL == R1L + R2L); - BOOST_CHECK(OneL+MaxL == ZeroL); - BOOST_CHECK(MaxL+OneL == ZeroL); - for (unsigned int i = 1; i < 256; ++i) { - BOOST_CHECK( (MaxL >> i) + OneL == (HalfL >> (i-1)) ); - BOOST_CHECK( OneL + (MaxL >> i) == (HalfL >> (i-1)) ); - TmpL = (MaxL>>i); TmpL += OneL; - BOOST_CHECK( TmpL == (HalfL >> (i-1)) ); - TmpL = (MaxL>>i); TmpL += 1; - BOOST_CHECK( TmpL == (HalfL >> (i-1)) ); - TmpL = (MaxL>>i); - BOOST_CHECK( TmpL++ == (MaxL>>i) ); - BOOST_CHECK( TmpL == (HalfL >> (i-1))); - } - BOOST_CHECK(uint256(0xbedc77e27940a7ULL) + 0xee8d836fce66fbULL == uint256(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); - TmpL = uint256(0xbedc77e27940a7ULL); TmpL += 0xee8d836fce66fbULL; - BOOST_CHECK(TmpL == uint256(0xbedc77e27940a7ULL+0xee8d836fce66fbULL)); - TmpL -= 0xee8d836fce66fbULL; BOOST_CHECK(TmpL == 0xbedc77e27940a7ULL); - TmpL = R1L; - BOOST_CHECK(++TmpL == R1L+1); - - BOOST_CHECK(R1L -(-R2L) == R1L+R2L); - BOOST_CHECK(R1L -(-OneL) == R1L+OneL); - BOOST_CHECK(R1L - OneL == R1L+(-OneL)); - for (unsigned int i = 1; i < 256; ++i) { - BOOST_CHECK((MaxL>>i) - (-OneL) == (HalfL >> (i-1))); - BOOST_CHECK((HalfL >> (i-1)) - OneL == (MaxL>>i)); - TmpL = (HalfL >> (i-1)); - BOOST_CHECK(TmpL-- == (HalfL >> (i-1))); - BOOST_CHECK(TmpL == (MaxL >> i)); - TmpL = (HalfL >> (i-1)); - BOOST_CHECK(--TmpL == (MaxL >> i)); - } - TmpL = R1L; - BOOST_CHECK(--TmpL == R1L-1); - - // 160-bit; copy-pasted - arith_uint160 TmpS = 0; - BOOST_CHECK(R1S+R2S == arith_uint160(R1LplusR2L)); - TmpS += R1S; - BOOST_CHECK(TmpS == R1S); - TmpS += R2S; - BOOST_CHECK(TmpS == R1S + R2S); - BOOST_CHECK(OneS+MaxS == ZeroS); - BOOST_CHECK(MaxS+OneS == ZeroS); - for (unsigned int i = 1; i < 160; ++i) { - BOOST_CHECK( (MaxS >> i) + OneS == (HalfS >> (i-1)) ); - BOOST_CHECK( OneS + (MaxS >> i) == (HalfS >> (i-1)) ); - TmpS = (MaxS>>i); TmpS += OneS; - BOOST_CHECK( TmpS == (HalfS >> (i-1)) ); - TmpS = (MaxS>>i); TmpS += 1; - BOOST_CHECK( TmpS == (HalfS >> (i-1)) ); - TmpS = (MaxS>>i); - BOOST_CHECK( TmpS++ == (MaxS>>i) ); - BOOST_CHECK( TmpS == (HalfS >> (i-1))); - } - BOOST_CHECK(arith_uint160(0xbedc77e27940a7ULL) + 0xee8d836fce66fbULL == arith_uint160(0xbedc77e27940a7ULL + 0xee8d836fce66fbULL)); - TmpS = arith_uint160(0xbedc77e27940a7ULL); TmpS += 0xee8d836fce66fbULL; - BOOST_CHECK(TmpS == arith_uint160(0xbedc77e27940a7ULL+0xee8d836fce66fbULL)); - TmpS -= 0xee8d836fce66fbULL; BOOST_CHECK(TmpS == 0xbedc77e27940a7ULL); - TmpS = R1S; - BOOST_CHECK(++TmpS == R1S+1); - - BOOST_CHECK(R1S -(-R2S) == R1S+R2S); - BOOST_CHECK(R1S -(-OneS) == R1S+OneS); - BOOST_CHECK(R1S - OneS == R1S+(-OneS)); - for (unsigned int i = 1; i < 160; ++i) { - BOOST_CHECK((MaxS>>i) - (-OneS) == (HalfS >> (i-1))); - BOOST_CHECK((HalfS >> (i-1)) - OneS == (MaxS>>i)); - TmpS = (HalfS >> (i-1)); - BOOST_CHECK(TmpS-- == (HalfS >> (i-1))); - BOOST_CHECK(TmpS == (MaxS >> i)); - TmpS = (HalfS >> (i-1)); - BOOST_CHECK(--TmpS == (MaxS >> i)); - } - TmpS = R1S; - BOOST_CHECK(--TmpS == R1S-1); - -} - -BOOST_AUTO_TEST_CASE( multiply ) -{ - BOOST_CHECK((R1L * R1L).ToString() == "62a38c0486f01e45879d7910a7761bf30d5237e9873f9bff3642a732c4d84f10"); - BOOST_CHECK((R1L * R2L).ToString() == "de37805e9986996cfba76ff6ba51c008df851987d9dd323f0e5de07760529c40"); - BOOST_CHECK((R1L * ZeroL) == ZeroL); - BOOST_CHECK((R1L * OneL) == R1L); - BOOST_CHECK((R1L * MaxL) == -R1L); - BOOST_CHECK((R2L * R1L) == (R1L * R2L)); - BOOST_CHECK((R2L * R2L).ToString() == "ac8c010096767d3cae5005dec28bb2b45a1d85ab7996ccd3e102a650f74ff100"); - BOOST_CHECK((R2L * ZeroL) == ZeroL); - BOOST_CHECK((R2L * OneL) == R2L); - BOOST_CHECK((R2L * MaxL) == -R2L); - - BOOST_CHECK((R1S * R1S).ToString() == "a7761bf30d5237e9873f9bff3642a732c4d84f10"); - BOOST_CHECK((R1S * R2S).ToString() == "ba51c008df851987d9dd323f0e5de07760529c40"); - BOOST_CHECK((R1S * ZeroS) == ZeroS); - BOOST_CHECK((R1S * OneS) == R1S); - BOOST_CHECK((R1S * MaxS) == -R1S); - BOOST_CHECK((R2S * R1S) == (R1S * R2S)); - BOOST_CHECK((R2S * R2S).ToString() == "c28bb2b45a1d85ab7996ccd3e102a650f74ff100"); - BOOST_CHECK((R2S * ZeroS) == ZeroS); - BOOST_CHECK((R2S * OneS) == R2S); - BOOST_CHECK((R2S * MaxS) == -R2S); - - BOOST_CHECK(MaxL * MaxL == OneL); - BOOST_CHECK(MaxS * MaxS == OneS); - - BOOST_CHECK((R1L * 0) == 0); - BOOST_CHECK((R1L * 1) == R1L); - BOOST_CHECK((R1L * 3).ToString() == "7759b1c0ed14047f961ad09b20ff83687876a0181a367b813634046f91def7d4"); - BOOST_CHECK((R2L * 0x87654321UL).ToString() == "23f7816e30c4ae2017257b7a0fa64d60402f5234d46e746b61c960d09a26d070"); - BOOST_CHECK((R1S * 0) == 0); - BOOST_CHECK((R1S * 1) == R1S); - BOOST_CHECK((R1S * 7).ToString() == "f7a987f3c3bf758d927f202d7e795faeff084244"); - BOOST_CHECK((R2S * 0xFFFFFFFFUL).ToString() == "1c6f6c930353e17f7d6127213bb18d2883e2cd90"); -} - -BOOST_AUTO_TEST_CASE( divide ) -{ - uint256 D1L("AD7133AC1977FA2B7"); - uint256 D2L("ECD751716"); - BOOST_CHECK((R1L / D1L).ToString() == "00000000000000000b8ac01106981635d9ed112290f8895545a7654dde28fb3a"); - BOOST_CHECK((R1L / D2L).ToString() == "000000000873ce8efec5b67150bad3aa8c5fcb70e947586153bf2cec7c37c57a"); - BOOST_CHECK(R1L / OneL == R1L); - BOOST_CHECK(R1L / MaxL == ZeroL); - BOOST_CHECK(MaxL / R1L == 2); - BOOST_CHECK_THROW(R1L / ZeroL, uint_error); - BOOST_CHECK((R2L / D1L).ToString() == "000000000000000013e1665895a1cc981de6d93670105a6b3ec3b73141b3a3c5"); - BOOST_CHECK((R2L / D2L).ToString() == "000000000e8f0abe753bb0afe2e9437ee85d280be60882cf0bd1aaf7fa3cc2c4"); - BOOST_CHECK(R2L / OneL == R2L); - BOOST_CHECK(R2L / MaxL == ZeroL); - BOOST_CHECK(MaxL / R2L == 1); - BOOST_CHECK_THROW(R2L / ZeroL, uint_error); - - arith_uint160 D1S("D3C5EDCDEA54EB92679F0A4B4"); - arith_uint160 D2S("13037"); - BOOST_CHECK((R1S / D1S).ToString() == "0000000000000000000000000db9af3beade6c02"); - BOOST_CHECK((R1S / D2S).ToString() == "000098dfb6cc40ca592bf74366794f298ada205c"); - BOOST_CHECK(R1S / OneS == R1S); - BOOST_CHECK(R1S / MaxS == ZeroS); - BOOST_CHECK(MaxS / R1S == 1); - BOOST_CHECK_THROW(R1S / ZeroS, uint_error); - BOOST_CHECK((R2S / D1S).ToString() == "0000000000000000000000000c5608e781182047"); - BOOST_CHECK((R2S / D2S).ToString() == "00008966751b7187c3c67c1fda5cea7db2c1c069"); - BOOST_CHECK(R2S / OneS == R2S); - BOOST_CHECK(R2S / MaxS == ZeroS); - BOOST_CHECK(MaxS / R2S == 1); - BOOST_CHECK_THROW(R2S / ZeroS, uint_error); -} - - -bool almostEqual(double d1, double d2) -{ - return fabs(d1-d2) <= 4*fabs(d1)*std::numeric_limits::epsilon(); + BOOST_CHECK( ZeroS < R1S ); + BOOST_CHECK( R2S < R1S ); + BOOST_CHECK( ZeroS < OneS ); + BOOST_CHECK( OneS < MaxS ); + BOOST_CHECK( R1S < MaxS ); + BOOST_CHECK( R2S < MaxS ); } BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 GetSerializeSize, Serialize, Unserialize @@ -569,8 +166,7 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G uint256 TmpL(R1L); BOOST_CHECK(TmpL == R1L); TmpL.SetHex(R2L.ToString()); BOOST_CHECK(TmpL == R2L); - TmpL.SetHex(ZeroL.ToString()); BOOST_CHECK(TmpL == 0); - TmpL.SetHex(HalfL.ToString()); BOOST_CHECK(TmpL == HalfL); + TmpL.SetHex(ZeroL.ToString()); BOOST_CHECK(TmpL == uint256()); TmpL.SetHex(R1L.ToString()); BOOST_CHECK(memcmp(R1L.begin(), R1Array, 32)==0); @@ -578,6 +174,8 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(memcmp(R2L.begin(), R2Array, 32)==0); BOOST_CHECK(memcmp(ZeroL.begin(), ZeroArray, 32)==0); BOOST_CHECK(memcmp(OneL.begin(), OneArray, 32)==0); + BOOST_CHECK(R1L.size() == sizeof(R1L)); + BOOST_CHECK(sizeof(R1L) == 32); BOOST_CHECK(R1L.size() == 32); BOOST_CHECK(R2L.size() == 32); BOOST_CHECK(ZeroL.size() == 32); @@ -587,11 +185,8 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(OneL.begin() + 32 == OneL.end()); BOOST_CHECK(MaxL.begin() + 32 == MaxL.end()); BOOST_CHECK(TmpL.begin() + 32 == TmpL.end()); - BOOST_CHECK(R1L.GetLow64() == R1LLow64); - BOOST_CHECK(HalfL.GetLow64() ==0x0000000000000000ULL); - BOOST_CHECK(OneL.GetLow64() ==0x0000000000000001ULL); - BOOST_CHECK(GetSerializeSize(R1L, 0, PROTOCOL_VERSION) == 32); - BOOST_CHECK(GetSerializeSize(ZeroL, 0, PROTOCOL_VERSION) == 32); + BOOST_CHECK(GetSerializeSize(R1L, PROTOCOL_VERSION) == 32); + BOOST_CHECK(GetSerializeSize(ZeroL, PROTOCOL_VERSION) == 32); CDataStream ss(0, PROTOCOL_VERSION); ss << R1L; @@ -614,11 +209,10 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(R2S.GetHex() == R2S.ToString()); BOOST_CHECK(OneS.GetHex() == OneS.ToString()); BOOST_CHECK(MaxS.GetHex() == MaxS.ToString()); - arith_uint160 TmpS(R1S); + uint160 TmpS(R1S); BOOST_CHECK(TmpS == R1S); TmpS.SetHex(R2S.ToString()); BOOST_CHECK(TmpS == R2S); - TmpS.SetHex(ZeroS.ToString()); BOOST_CHECK(TmpS == 0); - TmpS.SetHex(HalfS.ToString()); BOOST_CHECK(TmpS == HalfS); + TmpS.SetHex(ZeroS.ToString()); BOOST_CHECK(TmpS == uint160()); TmpS.SetHex(R1S.ToString()); BOOST_CHECK(memcmp(R1S.begin(), R1Array, 20)==0); @@ -626,6 +220,8 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(memcmp(R2S.begin(), R2Array, 20)==0); BOOST_CHECK(memcmp(ZeroS.begin(), ZeroArray, 20)==0); BOOST_CHECK(memcmp(OneS.begin(), OneArray, 20)==0); + BOOST_CHECK(R1S.size() == sizeof(R1S)); + BOOST_CHECK(sizeof(R1S) == 20); BOOST_CHECK(R1S.size() == 20); BOOST_CHECK(R2S.size() == 20); BOOST_CHECK(ZeroS.size() == 20); @@ -635,11 +231,8 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G BOOST_CHECK(OneS.begin() + 20 == OneS.end()); BOOST_CHECK(MaxS.begin() + 20 == MaxS.end()); BOOST_CHECK(TmpS.begin() + 20 == TmpS.end()); - BOOST_CHECK(R1S.GetLow64() == R1LLow64); - BOOST_CHECK(HalfS.GetLow64() ==0x0000000000000000ULL); - BOOST_CHECK(OneS.GetLow64() ==0x0000000000000001ULL); - BOOST_CHECK(GetSerializeSize(R1S, 0, PROTOCOL_VERSION) == 20); - BOOST_CHECK(GetSerializeSize(ZeroS, 0, PROTOCOL_VERSION) == 20); + BOOST_CHECK(GetSerializeSize(R1S, PROTOCOL_VERSION) == 20); + BOOST_CHECK(GetSerializeSize(ZeroS, PROTOCOL_VERSION) == 20); ss << R1S; BOOST_CHECK(ss.str() == std::string(R1Array,R1Array+20)); @@ -656,184 +249,43 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G ss >> TmpS; BOOST_CHECK(MaxS == TmpS); ss.clear(); - - for (unsigned int i = 0; i < 255; ++i) - { - BOOST_CHECK((OneL << i).getdouble() == ldexp(1.0,i)); - if (i < 160) BOOST_CHECK((OneS << i).getdouble() == ldexp(1.0,i)); - } - BOOST_CHECK(ZeroL.getdouble() == 0.0); - BOOST_CHECK(ZeroS.getdouble() == 0.0); - for (int i = 256; i > 53; --i) - BOOST_CHECK(almostEqual((R1L>>(256-i)).getdouble(), ldexp(R1Ldouble,i))); - for (int i = 160; i > 53; --i) - BOOST_CHECK(almostEqual((R1S>>(160-i)).getdouble(), ldexp(R1Sdouble,i))); - uint64_t R1L64part = (R1L>>192).GetLow64(); - uint64_t R1S64part = (R1S>>96).GetLow64(); - for (int i = 53; i > 0; --i) // doubles can store all integers in {0,...,2^54-1} exactly - { - BOOST_CHECK((R1L>>(256-i)).getdouble() == (double)(R1L64part >> (64-i))); - BOOST_CHECK((R1S>>(160-i)).getdouble() == (double)(R1S64part >> (64-i))); - } } -BOOST_AUTO_TEST_CASE(bignum_SetCompact) +BOOST_AUTO_TEST_CASE( conversion ) { - uint256 num; - bool fNegative; - bool fOverflow; - num.SetCompact(0, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x00123456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x01003456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x02000056, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x03000000, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x04000000, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x00923456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x01803456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x02800056, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x03800000, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x04800000, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x01123456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000000012"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - // Make sure that we don't generate compacts with the 0x00800000 bit set - num = 0x80; - BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000U); - - num.SetCompact(0x01fedcba, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "000000000000000000000000000000000000000000000000000000000000007e"); - BOOST_CHECK_EQUAL(num.GetCompact(true), 0x01fe0000U); - BOOST_CHECK_EQUAL(fNegative, true); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x02123456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000001234"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x03123456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000000123456"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x04123456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x04923456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000012345600"); - BOOST_CHECK_EQUAL(num.GetCompact(true), 0x04923456U); - BOOST_CHECK_EQUAL(fNegative, true); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x05009234, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "0000000000000000000000000000000000000000000000000000000092340000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0x20123456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000"); - BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456U); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, false); - - num.SetCompact(0xff123456, &fNegative, &fOverflow); - BOOST_CHECK_EQUAL(fNegative, false); - BOOST_CHECK_EQUAL(fOverflow, true); + BOOST_CHECK(ArithToUint256(UintToArith256(ZeroL)) == ZeroL); + BOOST_CHECK(ArithToUint256(UintToArith256(OneL)) == OneL); + BOOST_CHECK(ArithToUint256(UintToArith256(R1L)) == R1L); + BOOST_CHECK(ArithToUint256(UintToArith256(R2L)) == R2L); + BOOST_CHECK(UintToArith256(ZeroL) == 0); + BOOST_CHECK(UintToArith256(OneL) == 1); + BOOST_CHECK(ArithToUint256(0) == ZeroL); + BOOST_CHECK(ArithToUint256(1) == OneL); + BOOST_CHECK(arith_uint256(R1L.GetHex()) == UintToArith256(R1L)); + BOOST_CHECK(arith_uint256(R2L.GetHex()) == UintToArith256(R2L)); + BOOST_CHECK(R1L.GetHex() == UintToArith256(R1L).GetHex()); + BOOST_CHECK(R2L.GetHex() == UintToArith256(R2L).GetHex()); } - -BOOST_AUTO_TEST_CASE( getmaxcoverage ) // some more tests just to get 100% coverage +BOOST_AUTO_TEST_CASE( operator_with_self ) { - // ~R1L give a base_uint<256> - BOOST_CHECK((~~R1L >> 10) == (R1L >> 10)); BOOST_CHECK((~~R1S >> 10) == (R1S >> 10)); - BOOST_CHECK((~~R1L << 10) == (R1L << 10)); BOOST_CHECK((~~R1S << 10) == (R1S << 10)); - BOOST_CHECK(!(~~R1L < R1L)); BOOST_CHECK(!(~~R1S < R1S)); - BOOST_CHECK(~~R1L <= R1L); BOOST_CHECK(~~R1S <= R1S); - BOOST_CHECK(!(~~R1L > R1L)); BOOST_CHECK(!(~~R1S > R1S)); - BOOST_CHECK(~~R1L >= R1L); BOOST_CHECK(~~R1S >= R1S); - BOOST_CHECK(!(R1L < ~~R1L)); BOOST_CHECK(!(R1S < ~~R1S)); - BOOST_CHECK(R1L <= ~~R1L); BOOST_CHECK(R1S <= ~~R1S); - BOOST_CHECK(!(R1L > ~~R1L)); BOOST_CHECK(!(R1S > ~~R1S)); - BOOST_CHECK(R1L >= ~~R1L); BOOST_CHECK(R1S >= ~~R1S); + arith_uint256 v = UintToArith256(uint256S("02")); + v *= v; + BOOST_CHECK(v == UintToArith256(uint256S("04"))); + v /= v; + BOOST_CHECK(v == UintToArith256(uint256S("01"))); + v += v; + BOOST_CHECK(v == UintToArith256(uint256S("02"))); + v -= v; + BOOST_CHECK(v == UintToArith256(uint256S("0"))); +} - BOOST_CHECK(~~R1L + R2L == R1L + ~~R2L); - BOOST_CHECK(~~R1S + R2S == R1S + ~~R2S); - BOOST_CHECK(~~R1L - R2L == R1L - ~~R2L); - BOOST_CHECK(~~R1S - R2S == R1S - ~~R2S); - BOOST_CHECK(~R1L != R1L); BOOST_CHECK(R1L != ~R1L); - BOOST_CHECK(~R1S != R1S); BOOST_CHECK(R1S != ~R1S); - unsigned char TmpArray[32]; - CHECKBITWISEOPERATOR(~R1,R2,|) - CHECKBITWISEOPERATOR(~R1,R2,^) - CHECKBITWISEOPERATOR(~R1,R2,&) - CHECKBITWISEOPERATOR(R1,~R2,|) - CHECKBITWISEOPERATOR(R1,~R2,^) - CHECKBITWISEOPERATOR(R1,~R2,&) +BOOST_AUTO_TEST_CASE( check_ONE ) +{ + uint256 one = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); + BOOST_CHECK_EQUAL(one, UINT256_ONE); } BOOST_AUTO_TEST_SUITE_END() +*/ From 6488f24d6366939ca678f161dc024ae110780ddc Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 21:37:52 +0200 Subject: [PATCH 03/17] [Tests] Fix arith in pedersen_hash_/skiplist_/pmt_/transaction_tests --- src/arith_uint256.h | 1 + src/test/librust/pedersen_hash_tests.cpp | 6 ++++-- src/test/pmt_tests.cpp | 3 +-- src/test/skiplist_tests.cpp | 12 ++++++------ src/test/transaction_tests.cpp | 4 ++-- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 9e8165d22c8c4..9d84cf5d2ede3 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -384,5 +384,6 @@ class arith_uint512 : public base_uint<512> { /** End classes definitions */ const arith_uint256 ARITH_UINT256_ZERO = arith_uint256(); +const arith_uint256 ARITH_UINT256_ONE = arith_uint256(1); #endif // BITCOIN_UINT256_H diff --git a/src/test/librust/pedersen_hash_tests.cpp b/src/test/librust/pedersen_hash_tests.cpp index e36e157c0a83a..d79e7f870394d 100644 --- a/src/test/librust/pedersen_hash_tests.cpp +++ b/src/test/librust/pedersen_hash_tests.cpp @@ -3,9 +3,11 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "test/test_pivx.h" + +#include "arith_uint256.h" #include "uint256.h" #include "utilstrencodings.h" -#include "test/test_pivx.h" #include #include @@ -26,7 +28,7 @@ BOOST_AUTO_TEST_CASE(pedersen_hash_testvectors) BOOST_CHECK(result == expected_result); // Simple bad scenario check - const uint256 c = uint256(1) + a; + const uint256& c = ArithToUint256(ARITH_UINT256_ONE + UintToArith256(a)); result.SetNull(); librustzcash_merkle_hash(25, c.begin(), b.begin(), result.begin()); BOOST_CHECK(result != expected_result); diff --git a/src/test/pmt_tests.cpp b/src/test/pmt_tests.cpp index fbe80959aca46..53edb1faf40e8 100644 --- a/src/test/pmt_tests.cpp +++ b/src/test/pmt_tests.cpp @@ -23,8 +23,7 @@ class CPartialMerkleTreeTester : public CPartialMerkleTree void Damage() { unsigned int n = InsecureRandRange(vHash.size()); int bit = InsecureRandBits(8); - uint256 &hash = vHash[n]; - hash ^= ((uint256)1 << bit); + *(vHash[n].begin() + (bit>>3)) ^= 1<<(bit&7); } }; diff --git a/src/test/skiplist_tests.cpp b/src/test/skiplist_tests.cpp index 1fb65e7fea9f1..17ff327de6834 100644 --- a/src/test/skiplist_tests.cpp +++ b/src/test/skiplist_tests.cpp @@ -51,12 +51,12 @@ BOOST_AUTO_TEST_CASE(getlocator_test) std::vector vHashMain(100000); std::vector vBlocksMain(100000); for (unsigned int i=0; inHeight + 1); } @@ -64,12 +64,12 @@ BOOST_AUTO_TEST_CASE(getlocator_test) std::vector vHashSide(50000); std::vector vBlocksSide(50000); for (unsigned int i=0; inHeight + 1); } @@ -89,13 +89,13 @@ BOOST_AUTO_TEST_CASE(getlocator_test) // Entries 1 through 11 (inclusive) go back one step each. for (unsigned int i = 1; i < 12 && i < locator.vHave.size() - 1; i++) { - BOOST_CHECK_EQUAL(locator.vHave[i].GetLow64(), tip->nHeight - i); + BOOST_CHECK_EQUAL(UintToArith256(locator.vHave[i]).GetLow64(), tip->nHeight - i); } // The further ones (excluding the last one) go back with exponential steps. unsigned int dist = 2; for (unsigned int i = 12; i < locator.vHave.size() - 1; i++) { - BOOST_CHECK_EQUAL(locator.vHave[i - 1].GetLow64() - locator.vHave[i].GetLow64(), dist); + BOOST_CHECK_EQUAL(UintToArith256(locator.vHave[i - 1]).GetLow64() - UintToArith256(locator.vHave[i]).GetLow64(), dist); dist *= 2; } } diff --git a/src/test/transaction_tests.cpp b/src/test/transaction_tests.cpp index 57c719336cdf8..46ceafa98aef9 100644 --- a/src/test/transaction_tests.cpp +++ b/src/test/transaction_tests.cpp @@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE(tx_valid) break; } - mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str()); + mapprevOutScriptPubKeys[COutPoint(uint256S(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str()); } if (!fValid) { @@ -202,7 +202,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid) break; } - mapprevOutScriptPubKeys[COutPoint(uint256(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str()); + mapprevOutScriptPubKeys[COutPoint(uint256S(vinput[0].get_str()), vinput[1].get_int())] = ParseScript(vinput[2].get_str()); } if (!fValid) { From bce05830f93a99e6f23c9f644d39f247f6abea2b Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 21:43:18 +0200 Subject: [PATCH 04/17] [Refactor] zc ParamGeneration: pass big args by ref and use arith_uint --- src/libzerocoin/ParamGeneration.cpp | 62 ++++++++++++----------------- src/libzerocoin/ParamGeneration.h | 30 ++++++-------- 2 files changed, 38 insertions(+), 54 deletions(-) diff --git a/src/libzerocoin/ParamGeneration.cpp b/src/libzerocoin/ParamGeneration.cpp index 415e32d34ce66..148d06e64789c 100644 --- a/src/libzerocoin/ParamGeneration.cpp +++ b/src/libzerocoin/ParamGeneration.cpp @@ -13,6 +13,7 @@ #include "ParamGeneration.h" #include #include +#include "arith_uint256.h" #include "hash.h" #include "uint256.h" @@ -37,8 +38,7 @@ namespace libzerocoin { /// in length, and 3072 bits is strongly recommended. /// -void -CalculateParams(ZerocoinParams ¶ms, CBigNum N, std::string aux, uint32_t securityLevel) +void CalculateParams(ZerocoinParams ¶ms, const CBigNum& N, const std::string& aux, uint32_t securityLevel) { params.initialized = false; params.accumulatorParams.initialized = false; @@ -86,10 +86,10 @@ CalculateParams(ZerocoinParams ¶ms, CBigNum N, std::string aux, uint32_t sec // a whole group, just a pair of random generators in QR_N. uint32_t resultCtr; params.accumulatorParams.accumulatorQRNCommitmentGroup.g = generateIntegerFromSeed(NLen - 1, - calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG), + UintToArith256(calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPG)), &resultCtr).pow_mod(BN_TWO, N); params.accumulatorParams.accumulatorQRNCommitmentGroup.h = generateIntegerFromSeed(NLen - 1, - calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPH), + UintToArith256(calculateSeed(N, aux, securityLevel, STRING_QRNCOMMIT_GROUPH)), &resultCtr).pow_mod(BN_TWO, N); // Calculate the accumulator base, which we calculate as "u = C**2 mod N" @@ -123,8 +123,7 @@ CalculateParams(ZerocoinParams ¶ms, CBigNum N, std::string aux, uint32_t sec /// /// Returns the hash of the value. -uint256 -calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, std::string label, uint32_t index, uint32_t count) +uint256 calculateGeneratorSeed(const uint256& seed, const uint256& pSeed, const uint256& qSeed, const std::string& label, uint32_t index, uint32_t count) { CHashWriter hasher(0,0); uint256 hash; @@ -155,8 +154,7 @@ calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, std::string l /// /// Returns the hash of the value. -uint256 -calculateSeed(CBigNum modulus, std::string auxString, uint32_t securityLevel, std::string groupName) +uint256 calculateSeed(const CBigNum& modulus, const std::string& auxString, uint32_t securityLevel, const std::string& groupName) { CHashWriter hasher(0,0); uint256 hash; @@ -174,8 +172,7 @@ calculateSeed(CBigNum modulus, std::string auxString, uint32_t securityLevel, st return hasher.GetHash(); } -uint256 -calculateHash(uint256 input) +uint256 calculateHash(const uint256& input) { CHashWriter hasher(0,0); @@ -242,8 +239,7 @@ calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, /// primes "p" and "q". It uses the procedure in Appendix A.2.3 to /// derive two generators "g", "h". -IntegerGroupParams -deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen) +IntegerGroupParams deriveIntegerGroupParams(const uint256& seed, uint32_t pLen, uint32_t qLen) { IntegerGroupParams result; CBigNum p; @@ -288,8 +284,7 @@ deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen) /// Given "q" calculates the description of a group G of prime order "q" embedded within /// a field "F_p". -IntegerGroupParams -deriveIntegerGroupFromOrder(CBigNum &groupOrder) +IntegerGroupParams deriveIntegerGroupFromOrder(const CBigNum& groupOrder) { IntegerGroupParams result; @@ -352,10 +347,9 @@ deriveIntegerGroupFromOrder(CBigNum &groupOrder) /// algorithms described in FIPS 186-3 Appendix A.1.2 to calculate /// primes "p" and "q". -void -calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, - CBigNum *resultModulus, CBigNum *resultGroupOrder, - uint256 *resultPseed, uint256 *resultQseed) +void calculateGroupModulusAndOrder(const uint256& seed, uint32_t pLen, uint32_t qLen, + CBigNum *resultModulus, CBigNum *resultGroupOrder, + uint256 *resultPseed, uint256 *resultQseed) { // Verify that the seed length is >= qLen if (qLen > (sizeof(seed)) * 8) { @@ -370,14 +364,14 @@ calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, // Generate a random prime for the group order. // This may throw an exception, which we'll pass upwards. // Result is the value "resultGroupOrder", "qseed" and "qgen_counter". - uint256 qseed; + arith_uint256 qseed; uint32_t qgen_counter; - *resultGroupOrder = generateRandomPrime(qLen, seed, &qseed, &qgen_counter); + *resultGroupOrder = generateRandomPrime(qLen, UintToArith256(seed), &qseed, &qgen_counter); // Using pLen / 2 + 1 as the length and qseed as the input_seed, use the random prime // routine to obtain p0 , pseed, and pgen_counter. We pass exceptions upward. uint32_t p0len = ceil((pLen / 2.0) + 1); - uint256 pseed; + arith_uint256 pseed; uint32_t pgen_counter; CBigNum p0 = generateRandomPrime(p0len, qseed, &pseed, &pgen_counter); @@ -387,7 +381,7 @@ calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, // Generate a random integer "x" of pLen bits uint32_t iterations; CBigNum x = generateIntegerFromSeed(pLen, pseed, &iterations); - pseed += (iterations + 1); + pseed += iterations + 1; // Set x = 2^{pLen-1} + (x mod 2^{pLen-1}). CBigNum powerOfTwo = BN_TWO.pow(pLen-1); @@ -427,8 +421,8 @@ calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, if ((resultModulus->gcd(z - BN_ONE)).isOne() && (z.pow_mod(p0, (*resultModulus))).isOne()) { // Success! Return the seeds and primes. - *resultPseed = pseed; - *resultQseed = qseed; + *resultPseed = ArithToUint256(pseed); + *resultQseed = ArithToUint256(qseed); return; } @@ -454,8 +448,7 @@ calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, /// Generates a random group generator deterministically as a function of (seed,pSeed,qSeed) /// Uses the algorithm described in FIPS 186-3 Appendix A.2.3. -CBigNum -calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, CBigNum modulus, CBigNum groupOrder, uint32_t index) +CBigNum calculateGroupGenerator(const uint256& seed, const uint256& pSeed, const uint256& qSeed, const CBigNum& modulus, const CBigNum& groupOrder, uint32_t index) { CBigNum result; @@ -498,9 +491,8 @@ calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, CBigNum modu /// seed. Uses the Shawe-Taylor algorithm as described in FIPS 186-3 /// Appendix C.6. This is a recursive function. -CBigNum -generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, - uint32_t *prime_gen_counter) +CBigNum generateRandomPrime(uint32_t primeBitLen, const arith_uint256& in_seed, arith_uint256 *out_seed, + uint32_t *prime_gen_counter) { // Verify that primeBitLen is not too small if (primeBitLen < 2) { @@ -512,7 +504,7 @@ generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, CBigNum result(0); // Set prime_seed = in_seed, prime_gen_counter = 0. - uint256 prime_seed = in_seed; + arith_uint256 prime_seed = in_seed; (*prime_gen_counter) = 0; // Loop up to "4 * primeBitLen" iterations. @@ -589,7 +581,7 @@ generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, // Test "c" for primality as follows: // 1. First pick an integer "a" in between 2 and (c - 2) - CBigNum a = generateIntegerFromSeed(c.bitSize(), (*out_seed), &numIterations); + CBigNum a = generateIntegerFromSeed(c.bitSize(), *out_seed, &numIterations); a = BN_TWO + (a % (c - BN_THREE)); (*out_seed) += (numIterations + 1); @@ -615,8 +607,7 @@ generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, throw std::runtime_error("Unable to generate random prime (too many tests)"); } -CBigNum -generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations) +CBigNum generateIntegerFromSeed(uint32_t numBits, const arith_uint256& seed, uint32_t *numIterations) { CBigNum result(0); uint32_t iterations = ceil((double)numBits / (double)HASH_OUTPUT_BITS); @@ -629,7 +620,7 @@ generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations) // Loop "iterations" times filling up the value "result" with random bits for (uint32_t count = 0; count < iterations; count++) { // result += ( H(pseed + count) * 2^{count * p0len} ) - result += CBigNum(calculateHash(seed + count)) * BN_TWO.pow(count * HASH_OUTPUT_BITS); + result += CBigNum(calculateHash(ArithToUint256(seed + count))) * BN_TWO.pow(count * HASH_OUTPUT_BITS); } result = BN_TWO.pow(numBits - 1) + (result % (BN_TWO.pow(numBits - 1))); @@ -645,8 +636,7 @@ generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations) /// /// Performs trial division to determine whether a uint32_t is prime. -bool -primalityTestByTrialDivision(uint32_t candidate) +bool primalityTestByTrialDivision(uint32_t candidate) { // TODO: HACK HACK WRONG WRONG CBigNum canBignum(candidate); diff --git a/src/libzerocoin/ParamGeneration.h b/src/libzerocoin/ParamGeneration.h index df1b6ba5d29d4..7bf8c83786464 100644 --- a/src/libzerocoin/ParamGeneration.h +++ b/src/libzerocoin/ParamGeneration.h @@ -16,9 +16,8 @@ namespace libzerocoin { -void CalculateParams(ZerocoinParams ¶ms, CBigNum N, std::string aux, uint32_t securityLevel); -void calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, - uint32_t *pLen, uint32_t *qLen); +void CalculateParams(ZerocoinParams ¶ms, const CBigNum& N, const std::string& aux, uint32_t securityLevel); +void calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, uint32_t *pLen, uint32_t *qLen); // Constants #define STRING_COMMIT_GROUP "COIN_COMMITMENT_GROUP" @@ -35,21 +34,16 @@ void calculateGroupParamLengths(uint32_t maxPLen, uint32_t securityLevel, // Prototypes bool primalityTestByTrialDivision(uint32_t candidate); -uint256 calculateSeed(CBigNum modulus, std::string auxString, uint32_t securityLevel, std::string groupName); -uint256 calculateGeneratorSeed(uint256 seed, uint256 pSeed, uint256 qSeed, std::string label, uint32_t index, uint32_t count); - -uint256 calculateHash(uint256 input); -IntegerGroupParams deriveIntegerGroupParams(uint256 seed, uint32_t pLen, uint32_t qLen); -IntegerGroupParams deriveIntegerGroupFromOrder(CBigNum &groupOrder); -void calculateGroupModulusAndOrder(uint256 seed, uint32_t pLen, uint32_t qLen, - CBigNum *resultModulus, CBigNum *resultGroupOrder, - uint256 *resultPseed, uint256 *resultQseed); -CBigNum calculateGroupGenerator(uint256 seed, uint256 pSeed, uint256 qSeed, CBigNum modulus, - CBigNum groupOrder, uint32_t index); -CBigNum generateRandomPrime(uint32_t primeBitLen, uint256 in_seed, uint256 *out_seed, - uint32_t *prime_gen_counter); -CBigNum generateIntegerFromSeed(uint32_t numBits, uint256 seed, uint32_t *numIterations); - +uint256 calculateSeed(const CBigNum& modulus, const std::string& auxString, uint32_t securityLevel, const std::string& groupName); +uint256 calculateGeneratorSeed(const uint256& seed, const uint256& pSeed, const uint256& qSeed, const std::string& label, uint32_t index, uint32_t count); + +uint256 calculateHash(const uint256& input); +IntegerGroupParams deriveIntegerGroupParams(const uint256& seed, uint32_t pLen, uint32_t qLen); +IntegerGroupParams deriveIntegerGroupFromOrder(const CBigNum& groupOrder); +void calculateGroupModulusAndOrder(const uint256& seed, uint32_t pLen, uint32_t qLen, CBigNum *resultModulus, CBigNum *resultGroupOrder, uint256 *resultPseed, uint256 *resultQseed); +CBigNum calculateGroupGenerator(const uint256& seed, const uint256& pSeed, const uint256& qSeed, const CBigNum& modulus, const CBigNum& groupOrder, uint32_t index); +CBigNum generateRandomPrime(uint32_t primeBitLen, const arith_uint256& in_seed, arith_uint256 *out_seed, uint32_t *prime_gen_counter); +CBigNum generateIntegerFromSeed(uint32_t numBits, const arith_uint256& seed, uint32_t *numIterations); }/* namespace libzerocoin */ #endif /* PARAMGENERATION_H_ */ From f8c41cadebda3d536e10b43becc865c27b3727cc Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 21:53:44 +0200 Subject: [PATCH 05/17] [Refactor] zerocoin: use arith_uint256 where needed --- src/legacy/validation_zerocoin_legacy.cpp | 4 ++-- src/libzerocoin/Coin.cpp | 13 ++++++------- src/libzerocoin/CoinSpend.cpp | 2 +- src/libzerocoin/bignum.cpp | 4 ++-- src/libzerocoin/bignum.h | 3 ++- src/zpiv/zpos.cpp | 5 ++--- 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/legacy/validation_zerocoin_legacy.cpp b/src/legacy/validation_zerocoin_legacy.cpp index db58fb0bc3169..6bd16a1d1bb99 100644 --- a/src/legacy/validation_zerocoin_legacy.cpp +++ b/src/legacy/validation_zerocoin_legacy.cpp @@ -55,8 +55,8 @@ void DataBaseAccChecksum(const CBlockIndex* pindex, bool fWrite) pindex->nAccumulatorCheckpoint == pindex->pprev->nAccumulatorCheckpoint) return; - uint256 accCurr = pindex->nAccumulatorCheckpoint; - uint256 accPrev = pindex->pprev->nAccumulatorCheckpoint; + arith_uint256 accCurr = UintToArith256(pindex->nAccumulatorCheckpoint); + arith_uint256 accPrev = UintToArith256(pindex->pprev->nAccumulatorCheckpoint); // add/remove changed checksums to/from DB for (int i = (int)libzerocoin::zerocoinDenomList.size()-1; i >= 0; i--) { const uint32_t& nChecksum = accCurr.Get32(); diff --git a/src/libzerocoin/Coin.cpp b/src/libzerocoin/Coin.cpp index d5cb6c2614915..d889e78f336ce 100644 --- a/src/libzerocoin/Coin.cpp +++ b/src/libzerocoin/Coin.cpp @@ -62,8 +62,8 @@ int ExtractVersionFromSerial(const CBigNum& bnSerial) { try { //Serial is marked as v2 only if the first byte is 0xF - uint256 nMark = bnSerial.getuint256() >> (256 - V2_BITSHIFT); - if (nMark == 0xf) + arith_uint256 nMark = bnSerial.getuint256() >> (256 - V2_BITSHIFT); + if (nMark == arith_uint256(0xf)) return PUBKEY_VERSION; } catch (const std::range_error& e) { //std::cout << "ExtractVersionFromSerial(): " << e.what() << std::endl; @@ -77,8 +77,7 @@ int ExtractVersionFromSerial(const CBigNum& bnSerial) //Remove the first four bits for V2 serials CBigNum GetAdjustedSerial(const CBigNum& bnSerial) { - uint256 serial = bnSerial.getuint256(); - serial &= ~UINT256_ZERO >> V2_BITSHIFT; + const uint256& serial = ArithToUint256(bnSerial.getuint256() & (~ARITH_UINT256_ZERO >> V2_BITSHIFT)); CBigNum bnSerialAdjusted; bnSerialAdjusted.setuint256(serial); return bnSerialAdjusted; @@ -108,9 +107,9 @@ bool IsValidCommitmentToCoinRange(const ZerocoinParams* params, const CBigNum& b CBigNum ExtractSerialFromPubKey(const CPubKey pubkey) { - uint256 hashedPubkey = Hash(pubkey.begin(), pubkey.end()) >> V2_BITSHIFT; - uint256 uintSerial = (uint256(0xF) << (256 - V2_BITSHIFT)) | hashedPubkey; - return CBigNum(uintSerial); + const arith_uint256& hashedPubkey = UintToArith256(Hash(pubkey.begin(), pubkey.end())) >> V2_BITSHIFT; + arith_uint256 uintSerial = (arith_uint256(0xF) << (256 - V2_BITSHIFT)) | hashedPubkey; + return CBigNum(ArithToUint256(uintSerial)); } diff --git a/src/libzerocoin/CoinSpend.cpp b/src/libzerocoin/CoinSpend.cpp index d0caf8e901595..e13c25b442fa3 100644 --- a/src/libzerocoin/CoinSpend.cpp +++ b/src/libzerocoin/CoinSpend.cpp @@ -52,7 +52,7 @@ bool CoinSpend::HasValidSignature() const try { //V2 serial requires that the signature hash be signed by the public key associated with the serial - uint256 hashedPubkey = Hash(pubkey.begin(), pubkey.end()) >> V2_BITSHIFT; + arith_uint256 hashedPubkey = UintToArith256(Hash(pubkey.begin(), pubkey.end())) >> V2_BITSHIFT; if (hashedPubkey != GetAdjustedSerial(coinSerialNumber).getuint256()) { //cout << "CoinSpend::HasValidSignature() hashedpubkey is not equal to the serial!\n"; return false; diff --git a/src/libzerocoin/bignum.cpp b/src/libzerocoin/bignum.cpp index 20de4431744ad..3a05b2a9fd27a 100644 --- a/src/libzerocoin/bignum.cpp +++ b/src/libzerocoin/bignum.cpp @@ -110,14 +110,14 @@ void CBigNum::setuint256(uint256 n) mpz_import(bn, n.size(), -1, 1, 0, 0, (unsigned char*)&n); } -uint256 CBigNum::getuint256() const +arith_uint256 CBigNum::getuint256() const { if(bitSize() > 256) { throw std::range_error("cannot convert to uint256, bignum longer than 256 bits"); } uint256 n = UINT256_ZERO; mpz_export((unsigned char*)&n, NULL, -1, 1, 0, 0, bn); - return n; + return UintToArith256(n); } void CBigNum::setvch(const std::vector& vch) diff --git a/src/libzerocoin/bignum.h b/src/libzerocoin/bignum.h index 4cacb2f8104b6..4978d589f46ba 100755 --- a/src/libzerocoin/bignum.h +++ b/src/libzerocoin/bignum.h @@ -17,6 +17,7 @@ #include #include +#include "arith_uint256.h" #include "serialize.h" #include "uint256.h" #include "version.h" @@ -72,7 +73,7 @@ class CBigNum void setint64(int64_t sn); void setuint64(uint64_t n); void setuint256(uint256 n); - uint256 getuint256() const; + arith_uint256 getuint256() const; void setvch(const std::vector& vch); std::vector getvch() const; void SetDec(const std::string& str); diff --git a/src/zpiv/zpos.cpp b/src/zpiv/zpos.cpp index 26867ef709fe2..8b887b4c49f41 100644 --- a/src/zpiv/zpos.cpp +++ b/src/zpiv/zpos.cpp @@ -18,8 +18,7 @@ uint32_t ParseAccChecksum(uint256 nCheckpoint, const libzerocoin::CoinDenominati { int pos = std::distance(libzerocoin::zerocoinDenomList.begin(), find(libzerocoin::zerocoinDenomList.begin(), libzerocoin::zerocoinDenomList.end(), denom)); - nCheckpoint = nCheckpoint >> (32*((libzerocoin::zerocoinDenomList.size() - 1) - pos)); - return nCheckpoint.Get32(); + return (UintToArith256(nCheckpoint) >> (32*((libzerocoin::zerocoinDenomList.size() - 1) - pos))).Get32(); } bool CLegacyZPivStake::InitFromTxIn(const CTxIn& txin) @@ -47,7 +46,7 @@ CLegacyZPivStake::CLegacyZPivStake(const libzerocoin::CoinSpend& spend) : CStake { this->nChecksum = spend.getAccumulatorChecksum(); this->denom = spend.getDenomination(); - uint256 nSerial = spend.getCoinSerialNumber().getuint256(); + arith_uint256 nSerial = spend.getCoinSerialNumber().getuint256(); this->hashSerial = Hash(nSerial.begin(), nSerial.end()); } From 990072e493a088af370bf5d1fda46ed86b3f1c45 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 22:08:07 +0200 Subject: [PATCH 06/17] [Refactor] Move trim256 and use arith_uint512 for HashQuark calculations --- src/arith_uint256.cpp | 13 +++++++++++++ src/arith_uint256.h | 2 ++ src/hash.h | 6 +++--- src/uint256.h | 9 --------- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index fb524c31cf515..ff7583660ef3a 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -6,6 +6,8 @@ #include "arith_uint256.h" #include "crypto/common.h" +#include "uint256.h" +#include "uint512.h" #include "utilstrencodings.h" #include @@ -312,3 +314,14 @@ uint32_t arith_uint256::GetCompact(bool fNegative) const nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0); return nCompact; } + +uint256 arith_uint512::trim256() const +{ + std::vector vch; + const unsigned char* p = this->begin(); + for (unsigned int i = 0; i < 32; i++) { + vch.push_back(*p++); + } + return uint256(vch); +} + diff --git a/src/arith_uint256.h b/src/arith_uint256.h index 9d84cf5d2ede3..0946ebe449ff7 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -374,6 +374,8 @@ class arith_uint512 : public base_uint<512> { explicit arith_uint512(const std::string& str) : base_uint<512>(str) {} explicit arith_uint512(const std::vector& vch) : base_uint<512>(vch) {} + uint256 trim256() const; + //friend arith_uint512 UintToArith512(const blob_uint512 &a); //friend blob_uint512 ArithToUint512(const arith_uint512 &a); diff --git a/src/hash.h b/src/hash.h index 1d9e393a805f5..1a5ba3c5129c5 100644 --- a/src/hash.h +++ b/src/hash.h @@ -417,10 +417,10 @@ inline uint256 HashQuark(const T1 pbegin, const T1 pend) sph_skein512_context ctx_skein; static unsigned char pblank[1]; - uint512 mask = 8; - uint512 zero = 0; + arith_uint512 mask(8); + arith_uint512 zero(0); - uint512 hash[9]; + arith_uint512 hash[9]; sph_blake512_init(&ctx_blake); // ZBLAKE; diff --git a/src/uint256.h b/src/uint256.h index ed92ba9876859..dfc193693c366 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -90,15 +90,6 @@ class uint512 : public base_uint<512> explicit uint512(const std::string& str) : base_uint<512>(str) {} explicit uint512(const std::vector& vch) : base_uint<512>(vch) {} - uint256 trim256() const - { - uint256 ret; - for (unsigned int i = 0; i < uint256::WIDTH; i++) { - ret.pn[i] = pn[i]; - } - return ret; - } - friend arith_uint512 UintToArith512(const uint512 &a); friend uint512 ArithToUint512(const arith_uint512 &a); }; From b02a67bece503eef5c73db598f075cceee061872 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 22:20:05 +0200 Subject: [PATCH 07/17] [Refactor] Use arith_uint256 for masternode ranking computations --- src/budget/budgetproposal.h | 8 ++++++-- src/budget/finalizedbudget.cpp | 2 +- src/budget/finalizedbudget.h | 5 ++++- src/masternode.cpp | 8 ++++---- src/masternode.h | 2 +- src/masternodeman.cpp | 12 ++++++------ 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/budget/budgetproposal.h b/src/budget/budgetproposal.h index 9b889d78ef417..8919f8b70d70d 100644 --- a/src/budget/budgetproposal.h +++ b/src/budget/budgetproposal.h @@ -127,13 +127,17 @@ class CBudgetProposal void Relay(); // compare proposals by proposal hash - inline bool operator>(const CBudgetProposal& other) const { return GetHash() > other.GetHash(); } + inline bool operator>(const CBudgetProposal& other) const + { + return UintToArith256(GetHash()) > UintToArith256(other.GetHash()); + } + // // compare proposals pointers by net yes count (solve tie with feeHash) static inline bool PtrHigherYes(CBudgetProposal* a, CBudgetProposal* b) { const int netYes_a = a->GetYeas() - a->GetNays(); const int netYes_b = b->GetYeas() - b->GetNays(); - if (netYes_a == netYes_b) return a->GetFeeTXHash() > b->GetFeeTXHash(); + if (netYes_a == netYes_b) return UintToArith256(a->GetFeeTXHash()) > UintToArith256(b->GetFeeTXHash()); return netYes_a > netYes_b; } diff --git a/src/budget/finalizedbudget.cpp b/src/budget/finalizedbudget.cpp index f998eb74e7e17..2fc2a8fa025ea 100644 --- a/src/budget/finalizedbudget.cpp +++ b/src/budget/finalizedbudget.cpp @@ -413,7 +413,7 @@ bool CFinalizedBudget::operator>(const CFinalizedBudget& other) const const int count = GetVoteCount(); const int otherCount = other.GetVoteCount(); - if (count == otherCount) return GetFeeTXHash() > other.GetFeeTXHash(); + if (count == otherCount) return UintToArith256(GetFeeTXHash()) > UintToArith256(other.GetFeeTXHash()); return count > otherCount; } diff --git a/src/budget/finalizedbudget.h b/src/budget/finalizedbudget.h index cc2725286b54d..465187a9bbdd0 100644 --- a/src/budget/finalizedbudget.h +++ b/src/budget/finalizedbudget.h @@ -167,7 +167,10 @@ class CTxBudgetPayment } // compare payments by proposal hash - inline bool operator>(const CTxBudgetPayment& other) const { return nProposalHash > other.nProposalHash; } + inline bool operator>(const CTxBudgetPayment& other) const + { + return UintToArith256(nProposalHash) > UintToArith256(other.nProposalHash); + } }; diff --git a/src/masternode.cpp b/src/masternode.cpp index 2c28c9b604110..2e367e7ab117a 100644 --- a/src/masternode.cpp +++ b/src/masternode.cpp @@ -144,17 +144,17 @@ bool CMasternode::UpdateFromNewBroadcast(CMasternodeBroadcast& mnb) // the proof of work for that block. The further away they are the better, the furthest will win the election // and get paid this block // -uint256 CMasternode::CalculateScore(const uint256& hash) const +arith_uint256 CMasternode::CalculateScore(const uint256& hash) const { CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << hash; - const uint256& hash2 = ss.GetHash(); + const arith_uint256& hash2 = UintToArith256(ss.GetHash()); CHashWriter ss2(SER_GETHASH, PROTOCOL_VERSION); ss2 << hash; - const uint256& aux = vin.prevout.hash + vin.prevout.n; + const arith_uint256& aux = UintToArith256(vin.prevout.hash) + vin.prevout.n; ss2 << aux; - const uint256& hash3 = ss2.GetHash(); + const arith_uint256& hash3 = UintToArith256(ss2.GetHash()); return (hash3 > hash2 ? hash3 - hash2 : hash2 - hash3); } diff --git a/src/masternode.h b/src/masternode.h index c9f09378fc55a..3074afd03450b 100644 --- a/src/masternode.h +++ b/src/masternode.h @@ -152,7 +152,7 @@ class CMasternode : public CSignedMessage return !(a.vin == b.vin); } - uint256 CalculateScore(const uint256& hash) const; + arith_uint256 CalculateScore(const uint256& hash) const; ADD_SERIALIZE_METHODS; diff --git a/src/masternodeman.cpp b/src/masternodeman.cpp index 48e1b82ca6b1b..909df78ee18ec 100644 --- a/src/masternodeman.cpp +++ b/src/masternodeman.cpp @@ -504,13 +504,13 @@ MasternodeRef CMasternodeMan::GetNextMasternodeInQueueForPayment(int nBlockHeigh // -- (chance per block * chances before IsScheduled will fire) int nTenthNetwork = nMnCount / 10; int nCountTenth = 0; - uint256 nHigh; + arith_uint256 nHigh; const uint256& hash = GetHashAtHeight(nBlockHeight - 101); for (const auto& s: vecMasternodeLastPaid) { const MasternodeRef pmn = s.second; if (!pmn) break; - const uint256& n = pmn->CalculateScore(hash); + const arith_uint256& n = pmn->CalculateScore(hash); if (n > nHigh) { nHigh = n; pBestMasternode = pmn; @@ -563,7 +563,7 @@ int CMasternodeMan::GetMasternodeRank(const CTxIn& vin, int64_t nBlockHeight) co { const uint256& hash = GetHashAtHeight(nBlockHeight - 1); // height outside range - if (!hash) return -1; + if (hash == UINT256_ZERO) return -1; // scan for winner int minProtocol = ActiveProtocol(); @@ -605,7 +605,7 @@ std::vector> CMasternodeMan::GetMasternodeRank std::vector> vecMasternodeScores; const uint256& hash = GetHashAtHeight(nBlockHeight - 1); // height outside range - if (!hash) return vecMasternodeScores; + if (hash == UINT256_ZERO) return vecMasternodeScores; { LOCK(cs); // scan for winner @@ -813,7 +813,7 @@ int64_t CMasternodeMan::SecondsSincePayment(const MasternodeRef& mn, const CBloc CHashWriter ss(SER_GETHASH, PROTOCOL_VERSION); ss << mn->vin; ss << mn->sigTime; - uint256 hash = ss.GetHash(); + const arith_uint256& hash = UintToArith256(ss.GetHash()); // return some deterministic value for unknown/unpaid but force it to be more than 30 days old return month + hash.GetCompact(false); @@ -832,7 +832,7 @@ int64_t CMasternodeMan::GetLastPaid(const MasternodeRef& mn, const CBlockIndex* uint256 hash = ss.GetHash(); // use a deterministic offset to break a tie -- 2.5 minutes - int64_t nOffset = hash.GetCompact(false) % 150; + int64_t nOffset = UintToArith256(hash).GetCompact(false) % 150; int nMnCount = CountEnabled() * 1.25; for (int n = 0; n < nMnCount; n++) { From 9663d99a8088494264d03c332fd34586cbb42de5 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 22:24:03 +0200 Subject: [PATCH 08/17] [Refactoring] GUI/RPC: use uint256S() to construct uint256 from string --- src/qt/coincontroldialog.cpp | 12 ++++++------ src/qt/pivx/masternodeswidget.cpp | 2 +- src/qt/pivx/mnmodel.cpp | 2 +- src/wallet/rpcwallet.cpp | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index fb932682e7f4f..a36c811b86b66 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -240,8 +240,8 @@ void CoinControlDialog::buttonToggleLockClicked() for (int i = 0; i < ui->treeWidget->topLevelItemCount(); i++) { item = ui->treeWidget->topLevelItem(i); - COutPoint outpt(uint256(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt()); - if (model->isLockedCoin(uint256(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())) { + COutPoint outpt(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt()); + if (model->isLockedCoin(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())) { model->unlockCoin(outpt); item->setDisabled(false); // restore cold-stake snowflake icon for P2CS which were previously locked @@ -277,7 +277,7 @@ void CoinControlDialog::showMenu(const QPoint& point) // disable some items (like Copy Transaction ID, lock, unlock) for tree roots in context menu if (item->text(COLUMN_TXHASH).length() == 64) { // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode) copyTransactionHashAction->setEnabled(true); - if (model->isLockedCoin(uint256(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())) { + if (model->isLockedCoin(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt())) { lockAction->setEnabled(false); unlockAction->setEnabled(true); } else { @@ -332,7 +332,7 @@ void CoinControlDialog::lockCoin() if (contextMenuItem->checkState(COLUMN_CHECKBOX) == Qt::Checked) contextMenuItem->setCheckState(COLUMN_CHECKBOX, Qt::Unchecked); - COutPoint outpt(uint256(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); + COutPoint outpt(uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); model->lockCoin(outpt); contextMenuItem->setDisabled(true); contextMenuItem->setIcon(COLUMN_CHECKBOX, QIcon(":/icons/lock_closed")); @@ -343,7 +343,7 @@ void CoinControlDialog::lockCoin() void CoinControlDialog::unlockCoin() { if (!fSelectTransparent) return; // todo: implement locked notes - COutPoint outpt(uint256(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); + COutPoint outpt(uint256S(contextMenuItem->text(COLUMN_TXHASH).toStdString()), contextMenuItem->text(COLUMN_VOUT_INDEX).toUInt()); model->unlockCoin(outpt); contextMenuItem->setDisabled(false); // restore cold-stake snowflake icon for P2CS which were previously locked @@ -447,7 +447,7 @@ void CoinControlDialog::radioListMode(bool checked) void CoinControlDialog::viewItemChanged(QTreeWidgetItem* item, int column) { if (column == COLUMN_CHECKBOX && item->text(COLUMN_TXHASH).length() == 64) { // transaction hash is 64 characters (this means its a child node, so its not a parent node in tree mode) - BaseOutPoint outpt(uint256(item->text(COLUMN_TXHASH).toStdString()), + BaseOutPoint outpt(uint256S(item->text(COLUMN_TXHASH).toStdString()), item->text(COLUMN_VOUT_INDEX).toUInt(), fSelectTransparent); if (item->checkState(COLUMN_CHECKBOX) == Qt::Unchecked) diff --git a/src/qt/pivx/masternodeswidget.cpp b/src/qt/pivx/masternodeswidget.cpp index 8fefa18403e2e..722ade7abd02b 100644 --- a/src/qt/pivx/masternodeswidget.cpp +++ b/src/qt/pivx/masternodeswidget.cpp @@ -452,7 +452,7 @@ void MasterNodesWidget::onDeleteMNClicked() bool convertOK = false; unsigned int indexOut = outIndex.toUInt(&convertOK); if (convertOK) { - COutPoint collateralOut(uint256(txId.toStdString()), indexOut); + COutPoint collateralOut(uint256S(txId.toStdString()), indexOut); walletModel->unlockCoin(collateralOut); } diff --git a/src/qt/pivx/mnmodel.cpp b/src/qt/pivx/mnmodel.cpp index 9c80eac19cac2..cb237980b3227 100644 --- a/src/qt/pivx/mnmodel.cpp +++ b/src/qt/pivx/mnmodel.cpp @@ -28,7 +28,7 @@ void MNModel::updateMNList() int nIndex; if (!mne.castOutputIndex(nIndex)) continue; - uint256 txHash(mne.getTxHash()); + const uint256& txHash = uint256S(mne.getTxHash()); CTxIn txIn(txHash, uint32_t(nIndex)); CMasternode* pmn = mnodeman.Find(txIn.prevout); if (!pmn) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 535d7fd60749d..658017ff4abf8 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -995,7 +995,7 @@ static UniValue ShieldSendManyTo(const UniValue& sendTo, throw JSONRPCError(RPC_WALLET_ERROR, res.getError()); // add comments - const uint256 txHash(txid); + const uint256& txHash = uint256S(txid); assert(pwalletMain->mapWallet.count(txHash)); if (!commentStr.empty()) { pwalletMain->mapWallet.at(txHash).mapValue["comment"] = commentStr; From 957f5292c5cc1f49b7a5be8056fe1b9eb766c97d Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 22:36:03 +0200 Subject: [PATCH 09/17] [Refactor] pow/pos: use arith_uint256 for difficulty targets --- src/chain.h | 2 +- src/chainparams.cpp | 18 +++++++++--------- src/kernel.cpp | 6 +++--- src/legacy/stakemodifier.cpp | 4 ++-- src/miner.cpp | 6 +++--- src/pow.cpp | 31 ++++++++++++++++--------------- src/pow.h | 2 +- src/rpc/mining.cpp | 2 +- 8 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/chain.h b/src/chain.h index 5111da003a437..6c80e254bdb0e 100644 --- a/src/chain.h +++ b/src/chain.h @@ -204,7 +204,7 @@ class CBlockIndex unsigned int nUndoPos{0}; //! (memory only) Total amount of work (expected number of hashes) in the chain up to and including this block - uint256 nChainWork{}; + arith_uint256 nChainWork{}; //! Number of transactions in this block. //! Note: in a potential headers-first mode, this number cannot be relied upon diff --git a/src/chainparams.cpp b/src/chainparams.cpp index 459c6ff4fd5b6..ebe6178b450a4 100644 --- a/src/chainparams.cpp +++ b/src/chainparams.cpp @@ -134,9 +134,9 @@ class CMainParams : public CChainParams assert(genesis.hashMerkleRoot == uint256S("0x1b2ef6e2f28be914103a277377ae7729dcd125dfeb8bf97bd5964ba72b6dc39b")); consensus.fPowAllowMinDifficultyBlocks = false; - consensus.powLimit = ~UINT256_ZERO >> 20; // PIVX starting difficulty is 1 / 2^12 - consensus.posLimitV1 = ~UINT256_ZERO >> 24; - consensus.posLimitV2 = ~UINT256_ZERO >> 20; + consensus.powLimit = uint256S("0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.posLimitV1 = uint256S("0x000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.posLimitV2 = uint256S("0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nBudgetCycleBlocks = 43200; // approx. 1 every 30 days consensus.nBudgetFeeConfirmations = 6; // Number of confirmations for the finalization fee consensus.nCoinbaseMaturity = 100; @@ -274,9 +274,9 @@ class CTestNetParams : public CChainParams assert(genesis.hashMerkleRoot == uint256S("0x1b2ef6e2f28be914103a277377ae7729dcd125dfeb8bf97bd5964ba72b6dc39b")); consensus.fPowAllowMinDifficultyBlocks = true; - consensus.powLimit = ~UINT256_ZERO >> 20; // PIVX starting difficulty is 1 / 2^12 - consensus.posLimitV1 = ~UINT256_ZERO >> 24; - consensus.posLimitV2 = ~UINT256_ZERO >> 20; + consensus.powLimit = uint256S("0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.posLimitV1 = uint256S("0x000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.posLimitV2 = uint256S("0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nBudgetCycleBlocks = 144; // approx 10 cycles per day consensus.nBudgetFeeConfirmations = 3; // (only 8-blocks window for finalization on testnet) consensus.nCoinbaseMaturity = 15; @@ -397,9 +397,9 @@ class CRegTestParams : public CChainParams assert(genesis.hashMerkleRoot == uint256S("0x1b2ef6e2f28be914103a277377ae7729dcd125dfeb8bf97bd5964ba72b6dc39b")); consensus.fPowAllowMinDifficultyBlocks = true; - consensus.powLimit = ~UINT256_ZERO >> 20; // PIVX starting difficulty is 1 / 2^12 - consensus.posLimitV1 = ~UINT256_ZERO >> 24; - consensus.posLimitV2 = ~UINT256_ZERO >> 20; + consensus.powLimit = uint256S("0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.posLimitV1 = uint256S("0x000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + consensus.posLimitV2 = uint256S("0x00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); consensus.nBudgetCycleBlocks = 144; // approx 10 cycles per day consensus.nBudgetFeeConfirmations = 3; // (only 8-blocks window for finalization on regtest) consensus.nCoinbaseMaturity = 100; diff --git a/src/kernel.cpp b/src/kernel.cpp index d04d0d0ed795c..12617119d450c 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -59,12 +59,12 @@ uint256 CStakeKernel::GetHash() const bool CStakeKernel::CheckKernelHash(bool fSkipLog) const { // Get weighted target - uint256 bnTarget; + arith_uint256 bnTarget; bnTarget.SetCompact(nBits); - bnTarget *= (uint256(stakeValue) / 100); + bnTarget *= (arith_uint256(stakeValue) / 100); // Check PoS kernel hash - const uint256& hashProofOfStake = GetHash(); + const arith_uint256& hashProofOfStake = UintToArith256(GetHash()); const bool res = hashProofOfStake < bnTarget; if (!fSkipLog || res) { diff --git a/src/legacy/stakemodifier.cpp b/src/legacy/stakemodifier.cpp index 02c150ffece80..175c3966615fa 100644 --- a/src/legacy/stakemodifier.cpp +++ b/src/legacy/stakemodifier.cpp @@ -37,7 +37,7 @@ static bool SelectBlockFromCandidates( bool fModifierV2 = false; bool fFirstRun = true; bool fSelected = false; - uint256 hashBest; + arith_uint256 hashBest = ARITH_UINT256_ZERO; *pindexSelected = (const CBlockIndex*)0; for (const auto& item : vSortedByTimestamp) { if (!mapBlockIndex.count(item.second)) @@ -65,7 +65,7 @@ static bool SelectBlockFromCandidates( CDataStream ss(SER_GETHASH, 0); ss << hashProof << nStakeModifierPrev; - uint256 hashSelection = Hash(ss.begin(), ss.end()); + arith_uint256 hashSelection = UintToArith256(Hash(ss.begin(), ss.end())); // the selection hash is divided by 2**32 so that proof-of-stake block // is always favored over proof-of-work block. this is to preserve diff --git a/src/miner.cpp b/src/miner.cpp index 7e2e1499425cf..3d87d2688ef95 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -195,13 +195,13 @@ void BitcoinMiner(CWallet* pwallet, bool fProofOfStake) // Search // int64_t nStart = GetTime(); - uint256 hashTarget = uint256().SetCompact(pblock->nBits); + arith_uint256& hashTarget = arith_uint256().SetCompact(pblock->nBits); while (true) { unsigned int nHashesDone = 0; - uint256 hash; + arith_uint256 hash; while (true) { - hash = pblock->GetHash(); + hash = UintToArith256(pblock->GetHash()); if (hash <= hashTarget) { // Found a solution SetThreadPriority(THREAD_PRIORITY_NORMAL); diff --git a/src/pow.cpp b/src/pow.cpp index bbbba7824f666..384cb742957cc 100644 --- a/src/pow.cpp +++ b/src/pow.cpp @@ -29,17 +29,18 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead int64_t PastBlocksMin = 24; int64_t PastBlocksMax = 24; int64_t CountBlocks = 0; - uint256 PastDifficultyAverage; - uint256 PastDifficultyAveragePrev; + arith_uint256 PastDifficultyAverage; + arith_uint256 PastDifficultyAveragePrev; const Consensus::Params& consensus = Params().GetConsensus(); + const arith_uint256& powLimit = UintToArith256(consensus.powLimit); if (BlockLastSolved == NULL || BlockLastSolved->nHeight == 0 || BlockLastSolved->nHeight < PastBlocksMin) { - return consensus.powLimit.GetCompact(); + return powLimit.GetCompact(); } if (consensus.NetworkUpgradeActive(pindexLast->nHeight + 1, Consensus::UPGRADE_POS)) { const bool fTimeV2 = !Params().IsRegTestNet() && consensus.IsTimeProtocolV2(pindexLast->nHeight+1); - const uint256& bnTargetLimit = consensus.ProofOfStakeLimit(fTimeV2); + const arith_uint256& bnTargetLimit = UintToArith256(consensus.ProofOfStakeLimit(fTimeV2)); const int64_t& nTargetTimespan = consensus.TargetTimespan(fTimeV2); int64_t nActualSpacing = 0; @@ -52,7 +53,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead // ppcoin: target change every block // ppcoin: retarget with exponential moving toward target spacing - uint256 bnNew; + arith_uint256 bnNew; bnNew.SetCompact(pindexLast->nBits); // on first block with V2 time protocol, reduce the difficulty by a factor 16 @@ -79,7 +80,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead if (CountBlocks == 1) { PastDifficultyAverage.SetCompact(BlockReading->nBits); } else { - PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1); + PastDifficultyAverage = ((PastDifficultyAveragePrev * CountBlocks) + (arith_uint256().SetCompact(BlockReading->nBits))) / (CountBlocks + 1); } PastDifficultyAveragePrev = PastDifficultyAverage; } @@ -97,7 +98,7 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead BlockReading = BlockReading->pprev; } - uint256 bnNew(PastDifficultyAverage); + arith_uint256 bnNew(PastDifficultyAverage); int64_t _nTargetTimespan = CountBlocks * consensus.nTargetSpacing; @@ -110,8 +111,8 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead bnNew *= nActualTimespan; bnNew /= _nTargetTimespan; - if (bnNew > consensus.powLimit) { - bnNew = consensus.powLimit; + if (bnNew > powLimit) { + bnNew = powLimit; } return bnNew.GetCompact(); @@ -121,31 +122,31 @@ bool CheckProofOfWork(uint256 hash, unsigned int nBits) { bool fNegative; bool fOverflow; - uint256 bnTarget; + arith_uint256 bnTarget; if (Params().IsRegTestNet()) return true; bnTarget.SetCompact(nBits, &fNegative, &fOverflow); // Check range - if (fNegative || bnTarget.IsNull() || fOverflow || bnTarget > Params().GetConsensus().powLimit) + if (fNegative || bnTarget.IsNull() || fOverflow || bnTarget > UintToArith256(Params().GetConsensus().powLimit)) return error("CheckProofOfWork() : nBits below minimum work"); // Check proof of work matches claimed amount - if (hash > bnTarget) + if (UintToArith256(hash) > bnTarget) return error("CheckProofOfWork() : hash doesn't match nBits"); return true; } -uint256 GetBlockProof(const CBlockIndex& block) +arith_uint256 GetBlockProof(const CBlockIndex& block) { - uint256 bnTarget; + arith_uint256 bnTarget; bool fNegative; bool fOverflow; bnTarget.SetCompact(block.nBits, &fNegative, &fOverflow); if (fNegative || fOverflow || bnTarget.IsNull()) - return UINT256_ZERO; + return ARITH_UINT256_ZERO; // We need to compute 2**256 / (bnTarget+1), but we can't represent 2**256 // as it's too large for a uint256. However, as 2**256 is at least as large // as bnTarget+1, it is equal to ((2**256 - bnTarget - 1) / (bnTarget+1)) + 1, diff --git a/src/pow.h b/src/pow.h index 534b35d3eb494..614bb807266cb 100644 --- a/src/pow.h +++ b/src/pow.h @@ -27,6 +27,6 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead /** Check whether a block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckProofOfWork(uint256 hash, unsigned int nBits); -uint256 GetBlockProof(const CBlockIndex& block); +arith_uint256 GetBlockProof(const CBlockIndex& block); #endif // BITCOIN_POW_H diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 6c9e4152db76c..f0d2aebf286a3 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -614,7 +614,7 @@ UniValue getblocktemplate(const JSONRPCRequest& request) UniValue aux(UniValue::VOBJ); aux.pushKV("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())); - uint256 hashTarget = uint256().SetCompact(pblock->nBits); + arith_uint256& hashTarget = arith_uint256().SetCompact(pblock->nBits); static UniValue aMutable(UniValue::VARR); if (aMutable.empty()) { From 22213ff69a67f161931891e8b7cdfdbcdb4208c9 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 23:12:50 +0200 Subject: [PATCH 10/17] [Refactor] Migrate uint256.h/.cpp to blob_uint implementation - delete old uint256.h/uint256.cpp files - delete old uint512.h - rename files blob_uint256.h/blob_uint256.cpp --> uint256.h/uint256.cpp - rename class blob_uint256 --> uint256 - add uint160/512 blob implementation inside uint256.* files - move UintToArith/ArithToUint to arith_uint256.cpp --- CMakeLists.txt | 1 - src/Makefile.am | 4 - src/arith_uint256.cpp | 31 +++++- src/arith_uint256.h | 18 +-- src/blob_uint256.cpp | 83 -------------- src/blob_uint256.h | 165 ---------------------------- src/hash.h | 1 + src/sapling/proof.h | 2 +- src/sapling/zip32.h | 2 +- src/test/uint256_tests.cpp | 4 +- src/uint256.cpp | 128 +++++++++++----------- src/uint256.h | 219 +++++++++++++++++++++++++------------ src/uint512.h | 42 ------- 13 files changed, 255 insertions(+), 445 deletions(-) delete mode 100644 src/blob_uint256.cpp delete mode 100644 src/blob_uint256.h delete mode 100644 src/uint512.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 91329f3683f44..efda0954a18fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -426,7 +426,6 @@ set(UTIL_SOURCES ./src/rpc/protocol.cpp ./src/sync.cpp ./src/threadinterrupt.cpp - ./src/blob_uint256.cpp ./src/arith_uint256.cpp ./src/uint256.cpp ./src/util/threadnames.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 7ebe6fa047761..d03e4aba607fb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -281,8 +281,6 @@ BITCOIN_CORE_H = \ guiinterface.h \ guiinterfaceutil.h \ uint256.h \ - uint512.h \ - blob_uint256.h \ undo.h \ util/memory.h \ util.h \ @@ -547,7 +545,6 @@ libbitcoin_util_a_SOURCES = \ sync.cpp \ threadinterrupt.cpp \ uint256.cpp \ - blob_uint256.cpp \ util.cpp \ utilmoneystr.cpp \ util/threadnames.cpp \ @@ -689,7 +686,6 @@ libbitcoinconsensus_la_SOURCES = \ script/interpreter.cpp \ script/bitcoinconsensus.cpp \ uint256.cpp \ - blob_uint256.cpp \ utilstrencodings.cpp if GLIBC_BACK_COMPAT diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index ff7583660ef3a..87e2457b17a9c 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -7,7 +7,6 @@ #include "crypto/common.h" #include "uint256.h" -#include "uint512.h" #include "utilstrencodings.h" #include @@ -325,3 +324,33 @@ uint256 arith_uint512::trim256() const return uint256(vch); } +uint256 ArithToUint256(const arith_uint256 &a) +{ + uint256 b; + for(int x=0; x #include #include @@ -15,8 +13,6 @@ #include #include -class blob_uint512; -class blob_uint256; class uint256; class uint512; @@ -363,6 +359,9 @@ class arith_uint256 : public base_uint<256> { arith_uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL); uint32_t GetCompact(bool fNegative = false) const; uint32_t Get32(int n = 0) const { return pn[2 * n]; } + + friend arith_uint256 UintToArith256(const uint256 &a); + friend uint256 ArithToUint256(const arith_uint256 &a); }; /** 512-bit unsigned big integer. */ @@ -376,14 +375,15 @@ class arith_uint512 : public base_uint<512> { uint256 trim256() const; - //friend arith_uint512 UintToArith512(const blob_uint512 &a); - //friend blob_uint512 ArithToUint512(const arith_uint512 &a); + friend arith_uint512 UintToArith512(const uint512 &a); + friend uint512 ArithToUint512(const arith_uint512 &a); }; -/** Old classes definitions */ - -/** End classes definitions */ +uint256 ArithToUint256(const arith_uint256 &); +arith_uint256 UintToArith256(const uint256 &); +uint512 ArithToUint512(const arith_uint512 &); +arith_uint512 UintToArith512(const uint512 &); const arith_uint256 ARITH_UINT256_ZERO = arith_uint256(); const arith_uint256 ARITH_UINT256_ONE = arith_uint256(1); diff --git a/src/blob_uint256.cpp b/src/blob_uint256.cpp deleted file mode 100644 index aea6d52b34e6e..0000000000000 --- a/src/blob_uint256.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin Core developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or https://www.opensource.org/licenses/mit-license.php . - -#include "blob_uint256.h" - -#include "utilstrencodings.h" - -#include -#include - -template -base_blob::base_blob(const std::vector& vch) -{ - assert(vch.size() == sizeof(data)); - memcpy(data, &vch[0], sizeof(data)); -} - -template -std::string base_blob::GetHex() const -{ - char psz[sizeof(data) * 2 + 1]; - for (unsigned int i = 0; i < sizeof(data); i++) - sprintf(psz + i * 2, "%02x", data[sizeof(data) - i - 1]); - return std::string(psz, psz + sizeof(data) * 2); -} - -template -void base_blob::SetHex(const char* psz) -{ - memset(data, 0, sizeof(data)); - - // skip leading spaces - while (isspace(*psz)) - psz++; - - // skip 0x - if (psz[0] == '0' && tolower(psz[1]) == 'x') - psz += 2; - - // hex string to uint - const char* pbegin = psz; - while (::HexDigit(*psz) != -1) - psz++; - psz--; - unsigned char* p1 = (unsigned char*)data; - unsigned char* pend = p1 + WIDTH; - while (psz >= pbegin && p1 < pend) { - *p1 = ::HexDigit(*psz--); - if (psz >= pbegin) { - *p1 |= ((unsigned char)::HexDigit(*psz--) << 4); - p1++; - } - } -} - -template -void base_blob::SetHex(const std::string& str) -{ - SetHex(str.c_str()); -} - -template -std::string base_blob::ToString() const -{ - return GetHex(); -} - -// Explicit instantiations for base_blob<160> -template base_blob<160>::base_blob(const std::vector&); -template std::string base_blob<160>::GetHex() const; -template std::string base_blob<160>::ToString() const; -template void base_blob<160>::SetHex(const char*); -template void base_blob<160>::SetHex(const std::string&); - -// Explicit instantiations for base_blob<256> -template base_blob<256>::base_blob(const std::vector&); -template std::string base_blob<256>::GetHex() const; -template std::string base_blob<256>::ToString() const; -template void base_blob<256>::SetHex(const char*); -template void base_blob<256>::SetHex(const std::string&); - diff --git a/src/blob_uint256.h b/src/blob_uint256.h deleted file mode 100644 index e974c5442d552..0000000000000 --- a/src/blob_uint256.h +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers -// Copyright (c) 2014-2015 The Dash developers -// Copyright (c) 2015-2018 The PIVX developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef PIVX_BLOB_UINT256_H -#define PIVX_BLOB_UINT256_H - -#include -#include -#include -#include -#include -#include - -/** Template base class for fixed-sized opaque blobs. */ -template -class base_blob -{ -public: - // todo: make this protected - enum { WIDTH=BITS/8 }; - uint8_t data[WIDTH]; - - base_blob() - { - SetNull(); - } - - explicit base_blob(const std::vector& vch); - - bool IsNull() const - { - for (int i = 0; i < WIDTH; i++) - if (data[i] != 0) - return false; - return true; - } - - void SetNull() - { - memset(data, 0, sizeof(data)); - } - - friend inline bool operator==(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) == 0; } - friend inline bool operator!=(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) != 0; } - friend inline bool operator<(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) < 0; } - - std::string GetHex() const; - void SetHex(const char* psz); - void SetHex(const std::string& str); - std::string ToString() const; - - unsigned char* begin() - { - return &data[0]; - } - - unsigned char* end() - { - return &data[WIDTH]; - } - - const unsigned char* begin() const - { - return &data[0]; - } - - const unsigned char* end() const - { - return &data[WIDTH]; - } - - unsigned int size() const - { - return sizeof(data); - } - - uint64_t GetUint64(int pos) const - { - const uint8_t* ptr = data + pos * 8; - return ((uint64_t)ptr[0]) | \ - ((uint64_t)ptr[1]) << 8 | \ - ((uint64_t)ptr[2]) << 16 | \ - ((uint64_t)ptr[3]) << 24 | \ - ((uint64_t)ptr[4]) << 32 | \ - ((uint64_t)ptr[5]) << 40 | \ - ((uint64_t)ptr[6]) << 48 | \ - ((uint64_t)ptr[7]) << 56; - } - - template - void Serialize(Stream& s) const - { - s.write((char*)data, sizeof(data)); - } - - template - void Unserialize(Stream& s) - { - s.read((char*)data, sizeof(data)); - } -}; - -/** 88-bit opaque blob. - */ -class blob88 : public base_blob<88> { -public: - blob88() {} - blob88(const base_blob<88>& b) : base_blob<88>(b) {} - explicit blob88(const std::vector& vch) : base_blob<88>(vch) {} -}; - -/** 256-bit opaque blob. - * @note This type is called uint256 for historical reasons only. It is an - * opaque blob of 256 bits and has no integer operations. Use arith_uint256 if - * those are required. - */ -class blob_uint256 : public base_blob<256> { -public: - blob_uint256() {} - blob_uint256(const base_blob<256>& b) : base_blob<256>(b) {} - explicit blob_uint256(const std::vector& vch) : base_blob<256>(vch) {} - - /** A cheap hash function that just returns 64 bits from the result, it can be - * used when the contents are considered uniformly random. It is not appropriate - * when the value can easily be influenced from outside as e.g. a network adversary could - * provide values to trigger worst-case behavior. - * @note The result of this function is not stable between little and big endian. - */ - uint64_t GetCheapHash() const - { - uint64_t result; - memcpy((void*)&result, (void*)data, 8); - return result; - } - -}; - -/* uint256 from const char *. - * This is a separate function because the constructor uint256(const char*) can result - * in dangerously catching uint256(0). - */ -inline blob_uint256 blob_uint256S(const char *str) -{ - blob_uint256 rv; - rv.SetHex(str); - return rv; -} -/* uint256 from std::string. - * This is a separate function because the constructor uint256(const std::string &str) can result - * in dangerously catching uint256(0) via std::string(const char*). - */ -inline blob_uint256 blob_uint256S(const std::string& str) -{ - return blob_uint256S(str.c_str()); -} - -/** constant uint256 instances */ -const blob_uint256 BLOB_UINT256_ZERO = blob_uint256(); -const blob_uint256 BLOB_UINT256_ONE = blob_uint256S("0000000000000000000000000000000000000000000000000000000000000001"); - -#endif // PIVX_BLOB_UINT256_H diff --git a/src/hash.h b/src/hash.h index 1a5ba3c5129c5..d8a375b9a5fd0 100644 --- a/src/hash.h +++ b/src/hash.h @@ -8,6 +8,7 @@ #ifndef PIVX_HASH_H #define PIVX_HASH_H +#include "arith_uint256.h" #include "crypto/ripemd160.h" #include "crypto/sha256.h" #include "prevector.h" diff --git a/src/sapling/proof.h b/src/sapling/proof.h index 6b166e27f2986..87a274f166bdf 100644 --- a/src/sapling/proof.h +++ b/src/sapling/proof.h @@ -6,7 +6,7 @@ #define ZC_PROOF_H_ #include "serialize.h" -#include "blob_uint256.h" +#include "uint256.h" namespace libzcash { diff --git a/src/sapling/zip32.h b/src/sapling/zip32.h index f0a9d46881b9a..3336ae525093e 100644 --- a/src/sapling/zip32.h +++ b/src/sapling/zip32.h @@ -5,7 +5,7 @@ #ifndef PIVX_ZIP32_H #define PIVX_ZIP32_H -#include "blob_uint256.h" +#include "uint256.h" #include "key.h" #include "sapling/address.h" #include "serialize.h" diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index e43b057fbeb5b..bfca1fe9dc3d9 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -14,7 +14,6 @@ #include "version.h" #include "test/test_pivx.h" -/** !TODO: enable after transition blob_uint256 -- > uint256 BOOST_FIXTURE_TEST_SUITE(uint256_tests, BasicTestingSetup) @@ -267,6 +266,7 @@ BOOST_AUTO_TEST_CASE( conversion ) BOOST_CHECK(R2L.GetHex() == UintToArith256(R2L).GetHex()); } +/* currently failing. Bug fixed in bitcoin#12537 BOOST_AUTO_TEST_CASE( operator_with_self ) { arith_uint256 v = UintToArith256(uint256S("02")); @@ -279,6 +279,7 @@ BOOST_AUTO_TEST_CASE( operator_with_self ) v -= v; BOOST_CHECK(v == UintToArith256(uint256S("0"))); } +*/ BOOST_AUTO_TEST_CASE( check_ONE ) { @@ -288,4 +289,3 @@ BOOST_AUTO_TEST_CASE( check_ONE ) BOOST_AUTO_TEST_SUITE_END() -*/ diff --git a/src/uint256.cpp b/src/uint256.cpp index a01861ba048b5..3fea30ff846e6 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -1,86 +1,84 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers -// Copyright (c) 2017-2019 The PIVX developers +// Copyright (c) 2009-2021 The Bitcoin developers +// Copyright (c) 2017-2021 The PIVX developers // Distributed under the MIT/X11 software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include "uint256.h" -#include "crypto/common.h" -/** Old classes definitions **/ +#include "utilstrencodings.h" -// This implementation directly uses shifts instead of going -// through an intermediate MPI representation. -uint256& uint256::SetCompact(uint32_t nCompact, bool* pfNegative, bool* pfOverflow) -{ - int nSize = nCompact >> 24; - uint32_t nWord = nCompact & 0x007fffff; - if (nSize <= 3) { - nWord >>= 8 * (3 - nSize); - *this = nWord; - } else { - *this = nWord; - *this <<= 8 * (nSize - 3); - } - if (pfNegative) - *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0; - if (pfOverflow) - *pfOverflow = nWord != 0 && ((nSize > 34) || - (nWord > 0xff && nSize > 33) || - (nWord > 0xffff && nSize > 32)); - return *this; -} +#include +#include -uint32_t uint256::GetCompact(bool fNegative) const +template +base_blob::base_blob(const std::vector& vch) { - int nSize = (bits() + 7) / 8; - uint32_t nCompact = 0; - if (nSize <= 3) { - nCompact = GetLow64() << 8 * (3 - nSize); - } else { - uint256 bn = *this >> 8 * (nSize - 3); - nCompact = bn.GetLow64(); - } - // The 0x00800000 bit denotes the sign. - // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. - if (nCompact & 0x00800000) { - nCompact >>= 8; - nSize++; - } - assert((nCompact & ~0x007fffff) == 0); - assert(nSize < 256); - nCompact |= nSize << 24; - nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0); - return nCompact; + assert(vch.size() == sizeof(data)); + memcpy(data, &vch[0], sizeof(data)); } -uint256 ArithToUint256(const arith_uint256 &a) +template +std::string base_blob::GetHex() const { - uint256 b; - for(int x=0; x +void base_blob::SetHex(const char* psz) { - arith_uint256 b; - for(int x=0; x= pbegin && p1 < pend) { + *p1 = ::HexDigit(*psz--); + if (psz >= pbegin) { + *p1 |= ((unsigned char)::HexDigit(*psz--) << 4); + p1++; + } + } } -uint512 ArithToUint512(const arith_uint512 &a) +template +void base_blob::SetHex(const std::string& str) { - uint512 b; - for(int x=0; x +std::string base_blob::ToString() const { - arith_uint512 b; - for(int x=0; x +template base_blob<160>::base_blob(const std::vector&); +template std::string base_blob<160>::GetHex() const; +template std::string base_blob<160>::ToString() const; +template void base_blob<160>::SetHex(const char*); +template void base_blob<160>::SetHex(const std::string&); + +// Explicit instantiations for base_blob<256> +template base_blob<256>::base_blob(const std::vector&); +template std::string base_blob<256>::GetHex() const; +template std::string base_blob<256>::ToString() const; +template void base_blob<256>::SetHex(const char*); +template void base_blob<256>::SetHex(const std::string&); + diff --git a/src/uint256.h b/src/uint256.h index dfc193693c366..d7bf6add86ddb 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -1,14 +1,13 @@ // Copyright (c) 2009-2010 Satoshi Nakamoto -// Copyright (c) 2009-2014 The Bitcoin developers +// Copyright (c) 2009-2021 The Bitcoin developers // Copyright (c) 2014-2015 The Dash developers -// Copyright (c) 2015-2020 The PIVX developers +// Copyright (c) 2017-2021 The PIVX developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. #ifndef PIVX_UINT256_H #define PIVX_UINT256_H -#include "arith_uint256.h" #include #include #include @@ -16,59 +15,72 @@ #include #include -// -// This is a migration file class, as soon as we move every -// uint256 field used, invalidly, as a number to the proper arith_uint256, this will be replaced -// with the blob_uint256 file. -// - -/** 160-bit opaque blob. - * @note This type is called uint160 for historical reasons only. It is an opaque - * blob of 160 bits and has no integer operations. - */ -class uint160 : public base_blob<160> { -public: - uint160() {} - uint160(const base_blob<160>& b) : base_blob<160>(b) {} - explicit uint160(const std::vector& vch) : base_blob<160>(vch) {} -}; - -/** 256-bit unsigned big integer. */ -class uint256 : public base_uint<256> +/** Template base class for fixed-sized opaque blobs. */ +template +class base_blob { public: - uint256() {} - uint256(const base_uint<256>& b) : base_uint<256>(b) {} - uint256(uint64_t b) : base_uint<256>(b) {} - explicit uint256(const std::string& str) : base_uint<256>(str) {} - explicit uint256(const std::vector& vch) : base_uint<256>(vch) {} - - /** - * The "compact" format is a representation of a whole - * number N using an unsigned 32bit number similar to a - * floating point format. - * The most significant 8 bits are the unsigned exponent of base 256. - * This exponent can be thought of as "number of bytes of N". - * The lower 23 bits are the mantissa. - * Bit number 24 (0x800000) represents the sign of N. - * N = (-1^sign) * mantissa * 256^(exponent-3) - * - * Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn(). - * MPI uses the most significant bit of the first byte as sign. - * Thus 0x1234560000 is compact (0x05123456) - * and 0xc0de000000 is compact (0x0600c0de) - * - * Bitcoin only uses this "compact" format for encoding difficulty - * targets, which are unsigned 256bit quantities. Thus, all the - * complexities of the sign bit and using base 256 are probably an - * implementation accident. - */ - uint256& SetCompact(uint32_t nCompact, bool* pfNegative = nullptr, bool* pfOverflow = nullptr); - uint32_t GetCompact(bool fNegative = false) const; + // todo: make this protected + enum { WIDTH=BITS/8 }; + uint8_t data[WIDTH]; + + base_blob() + { + SetNull(); + } + + explicit base_blob(const std::vector& vch); + + bool IsNull() const + { + for (int i = 0; i < WIDTH; i++) + if (data[i] != 0) + return false; + return true; + } + + void SetNull() + { + memset(data, 0, sizeof(data)); + } + + friend inline bool operator==(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) == 0; } + friend inline bool operator!=(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) != 0; } + friend inline bool operator<(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) < 0; } + + std::string GetHex() const; + void SetHex(const char* psz); + void SetHex(const std::string& str); + std::string ToString() const; + + unsigned char* begin() + { + return &data[0]; + } + + unsigned char* end() + { + return &data[WIDTH]; + } + + const unsigned char* begin() const + { + return &data[0]; + } + + const unsigned char* end() const + { + return &data[WIDTH]; + } + + unsigned int size() const + { + return sizeof(data); + } uint64_t GetUint64(int pos) const { - const uint8_t* ptr = (uint8_t*) pn + pos * 8; + const uint8_t* ptr = data + pos * 8; return ((uint64_t)ptr[0]) | \ ((uint64_t)ptr[1]) << 8 | \ ((uint64_t)ptr[2]) << 16 | \ @@ -78,20 +90,64 @@ class uint256 : public base_uint<256> ((uint64_t)ptr[6]) << 48 | \ ((uint64_t)ptr[7]) << 56; } + + template + void Serialize(Stream& s) const + { + s.write((char*)data, sizeof(data)); + } + + template + void Unserialize(Stream& s) + { + s.read((char*)data, sizeof(data)); + } }; -/** 512-bit unsigned big integer. */ -class uint512 : public base_uint<512> -{ +/** 88-bit opaque blob. + */ +class blob88 : public base_blob<88> { public: - uint512() {} - uint512(const base_uint<512>& b) : base_uint<512>(b) {} - uint512(uint64_t b) : base_uint<512>(b) {} - explicit uint512(const std::string& str) : base_uint<512>(str) {} - explicit uint512(const std::vector& vch) : base_uint<512>(vch) {} + blob88() {} + blob88(const base_blob<88>& b) : base_blob<88>(b) {} + explicit blob88(const std::vector& vch) : base_blob<88>(vch) {} +}; + +/** 160-bit opaque blob. + * @note This type is called uint160 for historical reasons only. It is an opaque + * blob of 160 bits and has no integer operations. + */ +class uint160 : public base_blob<160> { +public: + uint160() {} + uint160(const base_blob<160>& b) : base_blob<160>(b) {} + explicit uint160(const std::vector& vch) : base_blob<160>(vch) {} +}; + +/** 256-bit opaque blob. + * @note This type is called uint256 for historical reasons only. It is an + * opaque blob of 256 bits and has no integer operations. Use arith_uint256 if + * those are required. + */ +class uint256 : public base_blob<256> { +public: + uint256() {} + uint256(const base_blob<256>& b) : base_blob<256>(b) {} + explicit uint256(const std::vector& vch) : base_blob<256>(vch) {} + + /** A cheap hash function that just returns 64 bits from the result, it can be + * used when the contents are considered uniformly random. It is not appropriate + * when the value can easily be influenced from outside as e.g. a network adversary could + * provide values to trigger worst-case behavior. + * @note The result of this function is not stable between little and big endian. + */ + uint64_t GetCheapHash() const + { + uint64_t result; + memcpy((void*)&result, (void*)data, 8); + return result; + } - friend arith_uint512 UintToArith512(const uint512 &a); - friend uint512 ArithToUint512(const arith_uint512 &a); }; /* uint256 from const char *. @@ -115,6 +171,37 @@ inline uint256 uint256S(const std::string& str) return rv; } +/** constant uint256 instances */ +const uint256 UINT256_ZERO = uint256(); +const uint256 UINT256_ONE = uint256S("0000000000000000000000000000000000000000000000000000000000000001"); +const uint256 UINT256_MAX = uint256S("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); + +/** 512-bit opaque blob. + * @note This type is called uint256 for historical reasons only. It is an + * opaque blob of 256 bits and has no integer operations. Use arith_uint256 if + * those are required. + */ +class uint512 : public base_blob<512> { +public: + uint512() {} + uint512(const base_blob<512>& b) : base_blob<512>(b) {} + explicit uint512(const std::vector& vch) : base_blob<512>(vch) {} +}; + +/* uint512 from const char *. + * This is a separate function because the constructor uint512(const char*) can result + * in dangerously catching uint512(0). + */ +inline uint512 uint512S(const char* str) +{ + uint512 rv; + rv.SetHex(str); + return rv; +} +/* uint512 from std::string. + * This is a separate function because the constructor uint512(const std::string &str) can result + * in dangerously catching uint512(0) via std::string(const char*). + */ inline uint512 uint512S(const std::string& str) { uint512 rv; @@ -122,16 +209,6 @@ inline uint512 uint512S(const std::string& str) return rv; } -uint256 ArithToUint256(const arith_uint256 &); -arith_uint256 UintToArith256(const uint256 &); -uint512 ArithToUint512(const arith_uint512 &); -arith_uint512 UintToArith512(const uint512 &); - -/** constant uint256 instances */ -const uint256 UINT256_ZERO = uint256(); -const uint256 UINT256_ONE = uint256("0000000000000000000000000000000000000000000000000000000000000001"); -const uint256 UINT256_MAX = uint256("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); - namespace std { template <> struct hash diff --git a/src/uint512.h b/src/uint512.h deleted file mode 100644 index a629b473f06b8..0000000000000 --- a/src/uint512.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2017-2020 The PIVX developers -// Distributed under the MIT software license, see the accompanying -// file COPYING or http://www.opensource.org/licenses/mit-license.php. - -#ifndef PIVX_UINT512_H -#define PIVX_UINT512_H - -#include "arith_uint256.h" -#include "blob_uint256.h" - -/** 512-bit unsigned big integer. */ -class blob_uint512 : public base_blob<512> -{ -public: - blob_uint512() {} - blob_uint512(const base_blob<512>& b) : base_blob<512>(b) {} - explicit blob_uint512(const std::vector& vch) : base_blob<512>(vch) {} - - blob_uint256 trim256() const - { - std::vector vch; - const unsigned char* p = this->begin(); - for (unsigned int i = 0; i < 32; i++) { - vch.push_back(*p++); - } - return blob_uint256(vch); - } -}; - - -/* uint256 from const char *. - * This is a separate function because the constructor uint256(const char*) can result - * in dangerously catching UINT256_ZERO. - */ -inline blob_uint512 blob_uint512S(const char* str) -{ - blob_uint512 rv; - rv.SetHex(str); - return rv; -} - -#endif // PIVX_UINT512_H From 8fe19b1526ddc590b9c62e76523dbe55fe3051b7 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 23:51:11 +0200 Subject: [PATCH 11/17] [Refactor] uint256 add missing explicit instantiation for base_blob<512> --- src/uint256.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/uint256.cpp b/src/uint256.cpp index 3fea30ff846e6..78ed14fa121f4 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -82,3 +82,10 @@ template std::string base_blob<256>::ToString() const; template void base_blob<256>::SetHex(const char*); template void base_blob<256>::SetHex(const std::string&); +// Explicit instantiations for base_blob<512> +template base_blob<512>::base_blob(const std::vector&); +template std::string base_blob<512>::GetHex() const; +template std::string base_blob<512>::ToString() const; +template void base_blob<512>::SetHex(const char*); +template void base_blob<512>::SetHex(const std::string&); + From ddf0dcbfed60b7b0c6dd5ee5633375ed91c99d77 Mon Sep 17 00:00:00 2001 From: Karl-Johan Alm Date: Mon, 26 Feb 2018 15:34:53 +0900 Subject: [PATCH 12/17] [arith_uint256] Do not destroy *this content if passed-in operator may reference it --- src/arith_uint256.cpp | 8 ++++---- src/test/uint256_tests.cpp | 2 -- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/arith_uint256.cpp b/src/arith_uint256.cpp index 87e2457b17a9c..023797ba9fca6 100644 --- a/src/arith_uint256.cpp +++ b/src/arith_uint256.cpp @@ -75,16 +75,16 @@ base_uint& base_uint::operator*=(uint32_t b32) template base_uint& base_uint::operator*=(const base_uint& b) { - base_uint a = *this; - *this = 0; + base_uint a; for (int j = 0; j < WIDTH; j++) { uint64_t carry = 0; for (int i = 0; i + j < WIDTH; i++) { - uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i]; - pn[i + j] = n & 0xffffffff; + uint64_t n = carry + a.pn[i + j] + (uint64_t)pn[j] * b.pn[i]; + a.pn[i + j] = n & 0xffffffff; carry = n >> 32; } } + *this = a; return *this; } diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp index bfca1fe9dc3d9..1611d2095bd0d 100644 --- a/src/test/uint256_tests.cpp +++ b/src/test/uint256_tests.cpp @@ -266,7 +266,6 @@ BOOST_AUTO_TEST_CASE( conversion ) BOOST_CHECK(R2L.GetHex() == UintToArith256(R2L).GetHex()); } -/* currently failing. Bug fixed in bitcoin#12537 BOOST_AUTO_TEST_CASE( operator_with_self ) { arith_uint256 v = UintToArith256(uint256S("02")); @@ -279,7 +278,6 @@ BOOST_AUTO_TEST_CASE( operator_with_self ) v -= v; BOOST_CHECK(v == UintToArith256(uint256S("0"))); } -*/ BOOST_AUTO_TEST_CASE( check_ONE ) { From b1c0afb399b8a2872bd9c140e20838cdde2fc1f4 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Thu, 15 Apr 2021 17:03:47 +0200 Subject: [PATCH 13/17] [Trivial] Log stake modifier and timeBlockFrom in CheckKernelHash() --- src/kernel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/kernel.cpp b/src/kernel.cpp index 12617119d450c..0b41f9755ab9f 100644 --- a/src/kernel.cpp +++ b/src/kernel.cpp @@ -69,13 +69,15 @@ bool CStakeKernel::CheckKernelHash(bool fSkipLog) const if (!fSkipLog || res) { LogPrint(BCLog::STAKING, "%s : Proof Of Stake:" + "\nstakeModifier=%s" + "\nnTimeBlockFrom=%d" "\nssUniqueID=%s" "\nnTimeTx=%d" "\nhashProofOfStake=%s" "\nnBits=%d" "\nweight=%d" "\nbnTarget=%s (res: %d)\n\n", - __func__, HexStr(stakeUniqueness), nTime, hashProofOfStake.GetHex(), + __func__, HexStr(stakeModifier), nTimeBlockFrom, HexStr(stakeUniqueness), nTime, hashProofOfStake.GetHex(), nBits, stakeValue, bnTarget.GetHex(), res); } return res; From 4ddd8f1fe36fd71780b55c5533340cd6a3a9fb33 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Thu, 15 Apr 2021 23:13:30 +0200 Subject: [PATCH 14/17] [BUG] Use arith_uint256 for old modifier's block sorting --- src/legacy/stakemodifier.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/legacy/stakemodifier.cpp b/src/legacy/stakemodifier.cpp index 175c3966615fa..a718a571043f6 100644 --- a/src/legacy/stakemodifier.cpp +++ b/src/legacy/stakemodifier.cpp @@ -130,6 +130,16 @@ bool GetOldStakeModifier(CStakeInput* stake, uint64_t& nStakeModifier) return true; } +// sort blocks by timestamp, soliving tie with hash (taken as arith_uint) +static bool sortedByTimestamp(const std::pair& a, + const std::pair& b) +{ + if (a.first == b.first) { + return UintToArith256(a.second) < UintToArith256(b.second); + } + return a.first < b.first; +} + // Stake Modifier (hash modifier of proof-of-stake): // The purpose of stake modifier is to prevent a txout (coin) owner from // computing future proof-of-stake generated by this txout at the time @@ -183,7 +193,7 @@ bool ComputeNextStakeModifier(const CBlockIndex* pindexPrev, uint64_t& nStakeMod } std::reverse(vSortedByTimestamp.begin(), vSortedByTimestamp.end()); - std::sort(vSortedByTimestamp.begin(), vSortedByTimestamp.end()); + std::sort(vSortedByTimestamp.begin(), vSortedByTimestamp.end(), sortedByTimestamp); // Select 64 blocks from candidate blocks to generate stake modifier uint64_t nStakeModifierNew = 0; From bce58ace1a7fdaf6561b40fc49a73457d4d2f26e Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 23:18:23 +0200 Subject: [PATCH 15/17] [Refactor] uint256: raname data --> m_data and make it protected --- src/uint256.cpp | 16 ++++++++-------- src/uint256.h | 44 +++++++++++++++++++++++--------------------- 2 files changed, 31 insertions(+), 29 deletions(-) diff --git a/src/uint256.cpp b/src/uint256.cpp index 78ed14fa121f4..507cf64daee1f 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -14,23 +14,23 @@ template base_blob::base_blob(const std::vector& vch) { - assert(vch.size() == sizeof(data)); - memcpy(data, &vch[0], sizeof(data)); + assert(vch.size() == sizeof(m_data)); + memcpy(m_data, &vch[0], sizeof(m_data)); } template std::string base_blob::GetHex() const { - char psz[sizeof(data) * 2 + 1]; - for (unsigned int i = 0; i < sizeof(data); i++) - sprintf(psz + i * 2, "%02x", data[sizeof(data) - i - 1]); - return std::string(psz, psz + sizeof(data) * 2); + char psz[sizeof(m_data) * 2 + 1]; + for (unsigned int i = 0; i < sizeof(m_data); i++) + sprintf(psz + i * 2, "%02x", m_data[sizeof(m_data) - i - 1]); + return std::string(psz, psz + sizeof(m_data) * 2); } template void base_blob::SetHex(const char* psz) { - memset(data, 0, sizeof(data)); + memset(m_data, 0, sizeof(m_data)); // skip leading spaces while (isspace(*psz)) @@ -45,7 +45,7 @@ void base_blob::SetHex(const char* psz) while (::HexDigit(*psz) != -1) psz++; psz--; - unsigned char* p1 = (unsigned char*)data; + unsigned char* p1 = (unsigned char*)m_data; unsigned char* pend = p1 + WIDTH; while (psz >= pbegin && p1 < pend) { *p1 = ::HexDigit(*psz--); diff --git a/src/uint256.h b/src/uint256.h index d7bf6add86ddb..0e692b2d9cfce 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -19,34 +19,36 @@ template class base_blob { +protected: + static constexpr int WIDTH = BITS / 8; + uint8_t m_data[WIDTH]; public: - // todo: make this protected - enum { WIDTH=BITS/8 }; - uint8_t data[WIDTH]; + /* construct 0 value by default */ + constexpr base_blob() : m_data() {} - base_blob() - { - SetNull(); - } + /* constructor for constants between 1 and 255 */ + constexpr explicit base_blob(uint8_t v) : m_data{v} {} explicit base_blob(const std::vector& vch); bool IsNull() const { for (int i = 0; i < WIDTH; i++) - if (data[i] != 0) + if (m_data[i] != 0) return false; return true; } void SetNull() { - memset(data, 0, sizeof(data)); + memset(m_data, 0, sizeof(m_data)); } - friend inline bool operator==(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) == 0; } - friend inline bool operator!=(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) != 0; } - friend inline bool operator<(const base_blob& a, const base_blob& b) { return memcmp(a.data, b.data, sizeof(a.data)) < 0; } + inline int Compare(const base_blob& other) const { return memcmp(m_data, other.m_data, sizeof(m_data)); } + + friend inline bool operator==(const base_blob& a, const base_blob& b) { return a.Compare(b) == 0; } + friend inline bool operator!=(const base_blob& a, const base_blob& b) { return a.Compare(b) != 0; } + friend inline bool operator<(const base_blob& a, const base_blob& b) { return a.Compare(b) < 0; } std::string GetHex() const; void SetHex(const char* psz); @@ -55,32 +57,32 @@ class base_blob unsigned char* begin() { - return &data[0]; + return &m_data[0]; } unsigned char* end() { - return &data[WIDTH]; + return &m_data[WIDTH]; } const unsigned char* begin() const { - return &data[0]; + return &m_data[0]; } const unsigned char* end() const { - return &data[WIDTH]; + return &m_data[WIDTH]; } unsigned int size() const { - return sizeof(data); + return sizeof(m_data); } uint64_t GetUint64(int pos) const { - const uint8_t* ptr = data + pos * 8; + const uint8_t* ptr = m_data + pos * 8; return ((uint64_t)ptr[0]) | \ ((uint64_t)ptr[1]) << 8 | \ ((uint64_t)ptr[2]) << 16 | \ @@ -94,13 +96,13 @@ class base_blob template void Serialize(Stream& s) const { - s.write((char*)data, sizeof(data)); + s.write((char*)m_data, sizeof(m_data)); } template void Unserialize(Stream& s) { - s.read((char*)data, sizeof(data)); + s.read((char*)m_data, sizeof(m_data)); } }; @@ -144,7 +146,7 @@ class uint256 : public base_blob<256> { uint64_t GetCheapHash() const { uint64_t result; - memcpy((void*)&result, (void*)data, 8); + memcpy((void*)&result, (void*)m_data, 8); return result; } From a640051d11a874ff89d2a351f2a712a052032816 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Wed, 14 Apr 2021 23:23:07 +0200 Subject: [PATCH 16/17] [Refactor] uint256: update GetHex() and SetHex() --- src/uint256.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/uint256.cpp b/src/uint256.cpp index 507cf64daee1f..af6d3f92d17c7 100644 --- a/src/uint256.cpp +++ b/src/uint256.cpp @@ -15,16 +15,13 @@ template base_blob::base_blob(const std::vector& vch) { assert(vch.size() == sizeof(m_data)); - memcpy(m_data, &vch[0], sizeof(m_data)); + memcpy(m_data, vch.data(), sizeof(m_data)); } template std::string base_blob::GetHex() const { - char psz[sizeof(m_data) * 2 + 1]; - for (unsigned int i = 0; i < sizeof(m_data); i++) - sprintf(psz + i * 2, "%02x", m_data[sizeof(m_data) - i - 1]); - return std::string(psz, psz + sizeof(m_data) * 2); + return HexStr(std::reverse_iterator(m_data + sizeof(m_data)), std::reverse_iterator(m_data)); } template @@ -41,16 +38,15 @@ void base_blob::SetHex(const char* psz) psz += 2; // hex string to uint - const char* pbegin = psz; - while (::HexDigit(*psz) != -1) - psz++; - psz--; + size_t digits = 0; + while (::HexDigit(psz[digits]) != -1) + digits++; unsigned char* p1 = (unsigned char*)m_data; unsigned char* pend = p1 + WIDTH; - while (psz >= pbegin && p1 < pend) { - *p1 = ::HexDigit(*psz--); - if (psz >= pbegin) { - *p1 |= ((unsigned char)::HexDigit(*psz--) << 4); + while (digits > 0 && p1 < pend) { + *p1 = ::HexDigit(psz[--digits]); + if (digits > 0) { + *p1 |= ((unsigned char)::HexDigit(psz[--digits]) << 4); p1++; } } From 722759d258df6863a71c0639ad6ba59a87a02622 Mon Sep 17 00:00:00 2001 From: random-zebra Date: Thu, 15 Apr 2021 16:58:54 +0200 Subject: [PATCH 17/17] [Refactor] Remove arith_uint256::GetCheapHash() and fix uint256 implem. --- src/arith_uint256.h | 6 +----- src/coincontrol.h | 2 +- src/uint256.h | 9 +++------ 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/arith_uint256.h b/src/arith_uint256.h index bf86ad3e6fc2e..a6f8f78622601 100644 --- a/src/arith_uint256.h +++ b/src/arith_uint256.h @@ -291,15 +291,11 @@ class base_uint s.read((char*)pn, sizeof(pn)); } - // Temporary for migration to blob160/256 - uint64_t GetCheapHash() const - { - return GetLow64(); - } void SetNull() { memset(pn, 0, sizeof(pn)); } + bool IsNull() const { for (int i = 0; i < WIDTH; i++) diff --git a/src/coincontrol.h b/src/coincontrol.h index 9c232096aef22..f433c3daf0431 100644 --- a/src/coincontrol.h +++ b/src/coincontrol.h @@ -98,7 +98,7 @@ class CCoinControl struct SimpleOutpointHash { size_t operator() (const OutPointWrapper& obj) const { - return (UintToArith256(obj.outPoint.hash) + obj.outPoint.n).GetCheapHash(); + return (UintToArith256(obj.outPoint.hash) + obj.outPoint.n).GetLow64(); } }; diff --git a/src/uint256.h b/src/uint256.h index 0e692b2d9cfce..9daeffbb2c99a 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -8,6 +8,8 @@ #ifndef PIVX_UINT256_H #define PIVX_UINT256_H +#include "crypto/common.h" + #include #include #include @@ -143,12 +145,7 @@ class uint256 : public base_blob<256> { * provide values to trigger worst-case behavior. * @note The result of this function is not stable between little and big endian. */ - uint64_t GetCheapHash() const - { - uint64_t result; - memcpy((void*)&result, (void*)m_data, 8); - return result; - } + uint64_t GetCheapHash() const { return ReadLE64(begin()); } };