]> Git Repo - VerusCoin.git/commitdiff
Move {Get,Set}Compact from bignum to uint256
authorPieter Wuille <[email protected]>
Sun, 20 Apr 2014 01:19:20 +0000 (03:19 +0200)
committerPieter Wuille <[email protected]>
Fri, 9 May 2014 14:44:59 +0000 (16:44 +0200)
13 files changed:
src/bignum.h
src/chainparams.cpp
src/chainparams.h
src/main.cpp
src/main.h
src/miner.cpp
src/rpcmining.cpp
src/test/DoS_tests.cpp
src/test/bignum_tests.cpp
src/test/uint256_tests.cpp
src/txdb.cpp
src/txdb.h
src/uint256.h

index 0259338b319d70f65d5a1d1c69c7a7001573ec46..6b77462d838b9736ff9142f336f6fca96eef4be7 100644 (file)
@@ -269,71 +269,6 @@ public:
         return 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)
-    // (0x05c0de00) would be -0x40de000000
-    //
-    // 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.
-    //
-    // This implementation directly uses shifts instead of going
-    // through an intermediate MPI representation.
-    CBigNum& SetCompact(unsigned int nCompact)
-    {
-        unsigned int nSize = nCompact >> 24;
-        bool fNegative     =(nCompact & 0x00800000) != 0;
-        unsigned int nWord = nCompact & 0x007fffff;
-        if (nSize <= 3)
-        {
-            nWord >>= 8*(3-nSize);
-            BN_set_word(this, nWord);
-        }
-        else
-        {
-            BN_set_word(this, nWord);
-            BN_lshift(this, this, 8*(nSize-3));
-        }
-        BN_set_negative(this, fNegative);
-        return *this;
-    }
-
-    unsigned int GetCompact() const
-    {
-        unsigned int nSize = BN_num_bytes(this);
-        unsigned int nCompact = 0;
-        if (nSize <= 3)
-            nCompact = BN_get_word(this) << 8*(3-nSize);
-        else
-        {
-            CBigNum bn;
-            BN_rshift(&bn, this, 8*(nSize-3));
-            nCompact = BN_get_word(&bn);
-        }
-        // 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++;
-        }
-        nCompact |= nSize << 24;
-        nCompact |= (BN_is_negative(this) ? 0x00800000 : 0);
-        return nCompact;
-    }
-
     void SetHex(const std::string& str)
     {
         // skip 0x
index eb56800b92fb95b9a4374cb3519bc08d0aaf82a1..f5cf846a01b0a0feb6efd466b19226ea2331e9f2 100644 (file)
@@ -110,7 +110,7 @@ public:
         vAlertPubKey = ParseHex("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284");
         nDefaultPort = 8333;
         nRPCPort = 8332;
-        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 32);
+        bnProofOfWorkLimit = ~uint256(0) >> 32;
         nSubsidyHalvingInterval = 210000;
 
         // Build the genesis block. Note that the output of the genesis coinbase cannot
@@ -233,7 +233,7 @@ public:
         pchMessageStart[2] = 0xb5;
         pchMessageStart[3] = 0xda;
         nSubsidyHalvingInterval = 150;
-        bnProofOfWorkLimit = CBigNum(~uint256(0) >> 1);
+        bnProofOfWorkLimit = ~uint256(0) >> 1;
         genesis.nTime = 1296688602;
         genesis.nBits = 0x207fffff;
         genesis.nNonce = 2;
index 542afeaf92bd514491d77bddbc2d587d95b17b16..f3f24efd9922f692e2d7f1829883f5bd12fd18a6 100644 (file)
@@ -56,7 +56,7 @@ public:
     const MessageStartChars& MessageStart() const { return pchMessageStart; }
     const vector<unsigned char>& AlertKey() const { return vAlertPubKey; }
     int GetDefaultPort() const { return nDefaultPort; }
-    const CBigNum& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
+    const uint256& ProofOfWorkLimit() const { return bnProofOfWorkLimit; }
     int SubsidyHalvingInterval() const { return nSubsidyHalvingInterval; }
     virtual const CBlock& GenesisBlock() const = 0;
     virtual bool RequireRPCPassword() const { return true; }
@@ -75,7 +75,7 @@ protected:
     vector<unsigned char> vAlertPubKey;
     int nDefaultPort;
     int nRPCPort;
-    CBigNum bnProofOfWorkLimit;
+    uint256 bnProofOfWorkLimit;
     int nSubsidyHalvingInterval;
     string strDataDir;
     vector<CDNSSeedData> vSeeds;
index a0f4f40cb13d86223d28b2dd3f53cbd44037657c..6a7bb9206c958d1305320d4208e37eb256fd424e 100644 (file)
@@ -1209,13 +1209,13 @@ static const int64_t nInterval = nTargetTimespan / nTargetSpacing;
 //
 unsigned int ComputeMinWork(unsigned int nBase, int64_t nTime)
 {
-    const CBigNum &bnLimit = Params().ProofOfWorkLimit();
+    const uint256 &bnLimit = Params().ProofOfWorkLimit();
     // Testnet has min-difficulty blocks
     // after nTargetSpacing*2 time between blocks:
     if (TestNet() && nTime > nTargetSpacing*2)
         return bnLimit.GetCompact();
 
-    CBigNum bnResult;
+    uint256 bnResult;
     bnResult.SetCompact(nBase);
     while (nTime > 0 && bnResult < bnLimit)
     {
@@ -1274,8 +1274,10 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
         nActualTimespan = nTargetTimespan*4;
 
     // Retarget
-    CBigNum bnNew;
+    uint256 bnNew;
+    uint256 bnOld;
     bnNew.SetCompact(pindexLast->nBits);
+    bnOld = bnNew;
     bnNew *= nActualTimespan;
     bnNew /= nTargetTimespan;
 
@@ -1285,23 +1287,25 @@ unsigned int GetNextWorkRequired(const CBlockIndex* pindexLast, const CBlockHead
     /// debug print
     LogPrintf("GetNextWorkRequired RETARGET\n");
     LogPrintf("nTargetTimespan = %d    nActualTimespan = %d\n", nTargetTimespan, nActualTimespan);
-    LogPrintf("Before: %08x  %s\n", pindexLast->nBits, CBigNum().SetCompact(pindexLast->nBits).getuint256().ToString());
-    LogPrintf("After:  %08x  %s\n", bnNew.GetCompact(), bnNew.getuint256().ToString());
+    LogPrintf("Before: %08x  %s\n", pindexLast->nBits, bnOld.ToString());
+    LogPrintf("After:  %08x  %s\n", bnNew.GetCompact(), bnNew.ToString());
 
     return bnNew.GetCompact();
 }
 
 bool CheckProofOfWork(uint256 hash, unsigned int nBits)
 {
-    CBigNum bnTarget;
-    bnTarget.SetCompact(nBits);
+    bool fNegative;
+    bool fOverflow;
+    uint256 bnTarget;
+    bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
 
     // Check range
-    if (bnTarget <= 0 || bnTarget > Params().ProofOfWorkLimit())
+    if (fNegative || bnTarget == 0 || fOverflow || bnTarget > Params().ProofOfWorkLimit())
         return error("CheckProofOfWork() : nBits below minimum work");
 
     // Check proof of work matches claimed amount
-    if (hash > bnTarget.getuint256())
+    if (hash > bnTarget)
         return error("CheckProofOfWork() : hash doesn't match nBits");
 
     return true;
@@ -1346,7 +1350,7 @@ void CheckForkWarningConditions()
     if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 72)
         pindexBestForkTip = NULL;
 
-    if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (chainActive.Tip()->GetBlockWork() * 6).getuint256()))
+    if (pindexBestForkTip || (pindexBestInvalid && pindexBestInvalid->nChainWork > chainActive.Tip()->nChainWork + (chainActive.Tip()->GetBlockWork() * 6)))
     {
         if (!fLargeWorkForkFound)
         {
@@ -1402,7 +1406,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
     // We define it this way because it allows us to only store the highest fork tip (+ base) which meets
     // the 7-block condition and from this always have the most-likely-to-cause-warning fork
     if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) &&
-            pindexNewForkTip->nChainWork - pfork->nChainWork > (pfork->GetBlockWork() * 7).getuint256() &&
+            pindexNewForkTip->nChainWork - pfork->nChainWork > (pfork->GetBlockWork() * 7) &&
             chainActive.Height() - pindexNewForkTip->nHeight < 72)
     {
         pindexBestForkTip = pindexNewForkTip;
@@ -1436,10 +1440,6 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
     if (!pindexBestInvalid || pindexNew->nChainWork > pindexBestInvalid->nChainWork)
     {
         pindexBestInvalid = pindexNew;
-        // The current code doesn't actually read the BestInvalidWork entry in
-        // the block database anymore, as it is derived from the flags in block
-        // index entry. We only write it for backward compatibility.
-        pblocktree->WriteBestInvalidWork(CBigNum(pindexBestInvalid->nChainWork));
         uiInterface.NotifyBlocksChanged();
     }
     LogPrintf("InvalidChainFound: invalid block=%s  height=%d  log2_work=%.8g  date=%s\n",
@@ -2182,7 +2182,7 @@ CBlockIndex* AddToBlockIndex(CBlockHeader& block)
         pindexNew->pprev = (*miPrev).second;
         pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
     }
-    pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork().getuint256();
+    pindexNew->nChainWork = (pindexNew->pprev ? pindexNew->pprev->nChainWork : 0) + pindexNew->GetBlockWork();
     pindexNew->RaiseValidity(BLOCK_VALID_TREE);
 
     return pindexNew;
@@ -2359,11 +2359,12 @@ bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool f
             return state.DoS(100, error("CheckBlockHeader() : block with timestamp before last checkpoint"),
                              REJECT_CHECKPOINT, "time-too-old");
         }
-        CBigNum bnNewBlock;
-        bnNewBlock.SetCompact(block.nBits);
-        CBigNum bnRequired;
+        bool fOverflow = false;
+        uint256 bnNewBlock;
+        bnNewBlock.SetCompact(block.nBits, NULL, &fOverflow);
+        uint256 bnRequired;
         bnRequired.SetCompact(ComputeMinWork(pcheckpoint->nBits, deltaTime));
-        if (bnNewBlock > bnRequired)
+        if (fOverflow || bnNewBlock > bnRequired)
         {
             return state.DoS(100, error("CheckBlockHeader() : block with too little proof-of-work"),
                              REJECT_INVALID, "bad-diffbits");
@@ -2934,7 +2935,7 @@ bool static LoadBlockIndexDB()
     BOOST_FOREACH(const PAIRTYPE(int, CBlockIndex*)& item, vSortedByHeight)
     {
         CBlockIndex* pindex = item.second;
-        pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + pindex->GetBlockWork().getuint256();
+        pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + pindex->GetBlockWork();
         pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
         if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS))
             setBlockIndexValid.insert(pindex);
index c69e0d2a3c30833f9c08ca6408134f88230b6166..796a3031c9714778cab81899f1ff8fec72f52598 100644 (file)
@@ -10,7 +10,6 @@
 #include "bitcoin-config.h"
 #endif
 
-#include "bignum.h"
 #include "chainparams.h"
 #include "coins.h"
 #include "core.h"
@@ -816,13 +815,19 @@ public:
         return (int64_t)nTime;
     }
 
-    CBigNum GetBlockWork() const
+    uint256 GetBlockWork() const
     {
-        CBigNum bnTarget;
-        bnTarget.SetCompact(nBits);
-        if (bnTarget <= 0)
+        uint256 bnTarget;
+        bool fNegative;
+        bool fOverflow;
+        bnTarget.SetCompact(nBits, &fNegative, &fOverflow);
+        if (fNegative || fOverflow || bnTarget == 0)
             return 0;
-        return (CBigNum(1)<<256) / (bnTarget+1);
+        // 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,
+        // or ~bnTarget / (nTarget+1) + 1.
+        return (~bnTarget / (bnTarget + 1)) + 1;
     }
 
     bool CheckIndex() const
index 01fc56601b28bf241cd39355291da50724d3a8df..50be4fad40ff0f006007a4ac644ab680f937beb1 100644 (file)
@@ -466,7 +466,7 @@ CBlockTemplate* CreateNewBlockWithKey(CReserveKey& reservekey)
 bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
 {
     uint256 hash = pblock->GetHash();
-    uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
+    uint256 hashTarget = uint256().SetCompact(pblock->nBits);
 
     if (hash > hashTarget)
         return false;
@@ -552,7 +552,7 @@ void static BitcoinMiner(CWallet *pwallet)
         // Search
         //
         int64_t nStart = GetTime();
-        uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
+        uint256 hashTarget = uint256().SetCompact(pblock->nBits);
         uint256 hashbuf[2];
         uint256& hash = *alignup<16>(hashbuf);
         while (true)
@@ -636,7 +636,7 @@ void static BitcoinMiner(CWallet *pwallet)
             {
                 // Changing pblock->nTime can change work required on testnet:
                 nBlockBits = ByteReverse(pblock->nBits);
-                hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
+                hashTarget.SetCompact(pblock->nBits);
             }
         }
     } }
index 070cf1cb2a3a5e846dd114f8336283662c7792e0..cb903b585ab3fcc38be707f614bce9641b50369e 100644 (file)
@@ -363,7 +363,7 @@ Value getwork(const Array& params, bool fHelp)
         char phash1[64];
         FormatHashBuffers(pblock, pmidstate, pdata, phash1);
 
-        uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
+        uint256 hashTarget = uint256().SetCompact(pblock->nBits);
 
         Object result;
         result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); // deprecated
@@ -559,7 +559,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
     Object aux;
     aux.push_back(Pair("flags", HexStr(COINBASE_FLAGS.begin(), COINBASE_FLAGS.end())));
 
-    uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256();
+    uint256 hashTarget = uint256().SetCompact(pblock->nBits);
 
     static Array aMutable;
     if (aMutable.empty())
index d86cc7a290eb6dc81e6860ed010af0719a58a1a7..897fb87e4622d28210c198b06ce48356cc389f5e 100644 (file)
@@ -106,9 +106,9 @@ static bool CheckNBits(unsigned int nbits1, int64_t time1, unsigned int nbits2,
         return CheckNBits(nbits2, time2, nbits1, time1);
     int64_t deltaTime = time2-time1;
 
-    CBigNum required;
+    uint256 required;
     required.SetCompact(ComputeMinWork(nbits1, deltaTime));
-    CBigNum have;
+    uint256 have;
     have.SetCompact(nbits2);
     return (have <= required);
 }
index d5ee8c9778c3b59a11ed07793c27cc125da9453e..01967c76847211d6ede0fb1df0ecdf8d26a186c0 100644 (file)
@@ -125,94 +125,6 @@ BOOST_AUTO_TEST_CASE(bignum_setint64)
 }
 
 
-BOOST_AUTO_TEST_CASE(bignum_SetCompact)
-{
-    CBigNum num;
-    num.SetCompact(0);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x00123456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x01003456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x02000056);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x03000000);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x04000000);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x00923456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x01803456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x02800056);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x03800000);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-    
-    num.SetCompact(0x04800000);
-    BOOST_CHECK_EQUAL(num.GetHex(), "0");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0U);
-
-    num.SetCompact(0x01123456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "12");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000U);
-
-    // Make sure that we don't generate compacts with the 0x00800000 bit set
-    num = 0x80;
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000U);
-
-    num.SetCompact(0x01fedcba);
-    BOOST_CHECK_EQUAL(num.GetHex(), "-7e");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0x01fe0000U);
-
-    num.SetCompact(0x02123456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "1234");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400U);
-
-    num.SetCompact(0x03123456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "123456");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456U);
-
-    num.SetCompact(0x04123456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "12345600");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456U);
-
-    num.SetCompact(0x04923456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "-12345600");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0x04923456U);
-
-    num.SetCompact(0x05009234);
-    BOOST_CHECK_EQUAL(num.GetHex(), "92340000");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234U);
-
-    num.SetCompact(0x20123456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456U);
-
-    num.SetCompact(0xff123456);
-    BOOST_CHECK_EQUAL(num.GetHex(), "123456000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
-    BOOST_CHECK_EQUAL(num.GetCompact(), 0xff123456U);
-}
-
 BOOST_AUTO_TEST_CASE(bignum_SetHex)
 {
     std::string hexStr = "deecf97fd890808b9cc0f1b6a3e7a60b400f52710e6ad075b1340755bfa58cc9";
index 226d737defd9d2f4dddfc2f017d07857a3459def..4b1a2ae58f4b9083f3fbc94cac5a4800d44dcbbc 100644 (file)
@@ -675,6 +675,135 @@ BOOST_AUTO_TEST_CASE( methods ) // GetHex SetHex begin() end() size() GetLow64 G
     }
 }
 
+BOOST_AUTO_TEST_CASE(bignum_SetCompact)
+{
+    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_AUTO_TEST_CASE( getmaxcoverage ) // some more tests just to get 100% coverage
 {
     // ~R1L give a base_uint<256>
index cb92922a357d7b2396b840787f060a54e84fa32b..4eab8525a5cee113c4bf0faba53da517be7238ce 100644 (file)
@@ -73,12 +73,6 @@ bool CBlockTreeDB::WriteBlockIndex(const CDiskBlockIndex& blockindex)
     return Write(make_pair('b', blockindex.GetBlockHash()), blockindex);
 }
 
-bool CBlockTreeDB::WriteBestInvalidWork(const CBigNum& bnBestInvalidWork)
-{
-    // Obsolete; only written for backward compatibility.
-    return Write('I', bnBestInvalidWork);
-}
-
 bool CBlockTreeDB::WriteBlockFileInfo(int nFile, const CBlockFileInfo &info) {
     return Write(make_pair('f', nFile), info);
 }
index 5eb5731db3d6dd37b134b4c25876bc995ae94e77..7257b0dd2176d3a30087c3261a5c9ee20a6d3435 100644 (file)
@@ -14,7 +14,6 @@
 #include <utility>
 #include <vector>
 
-class CBigNum;
 class CCoins;
 class uint256;
 
@@ -52,7 +51,6 @@ private:
     void operator=(const CBlockTreeDB&);
 public:
     bool WriteBlockIndex(const CDiskBlockIndex& blockindex);
-    bool WriteBestInvalidWork(const CBigNum& bnBestInvalidWork);
     bool ReadBlockFileInfo(int nFile, CBlockFileInfo &fileinfo);
     bool WriteBlockFileInfo(int nFile, const CBlockFileInfo &fileinfo);
     bool ReadLastBlockFile(int &nFile);
index 7b17694eb2d601fe15f70565654af76789d3eac2..10c6657c763aebc9d1045879c2ddf7065ae9aeec 100644 (file)
@@ -529,6 +529,76 @@ public:
     uint256(uint64_t b) : base_uint<256>(b) {}
     explicit uint256(const std::string& str) : base_uint<256>(str) {}
     explicit uint256(const std::vector<unsigned char>& 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)
+    // (0x05c0de00) would be -0x40de000000
+    //
+    // 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.
+    //
+    // This implementation directly uses shifts instead of going
+    // through an intermediate MPI representation.
+    uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL)
+    {
+        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;
+    }
+
+    uint32_t GetCompact(bool fNegative = false) const
+    {
+        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;
+    }
 };
 
 #endif
This page took 0.053196 seconds and 4 git commands to generate.