aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2014-04-20 03:19:20 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2014-05-09 16:44:59 +0200
commitdf9eb5e14fa8072bc8a82b59e712c2ba36f13f4c (patch)
tree64c961273c28988b9be4138490e6db570a3b66d0
parenta7031507e647da0723bf289dadba10ef1a50f278 (diff)
Move {Get,Set}Compact from bignum to uint256
-rw-r--r--src/bignum.h65
-rw-r--r--src/chainparams.cpp4
-rw-r--r--src/chainparams.h4
-rw-r--r--src/main.cpp43
-rw-r--r--src/main.h17
-rw-r--r--src/miner.cpp6
-rw-r--r--src/rpcmining.cpp4
-rw-r--r--src/test/DoS_tests.cpp4
-rw-r--r--src/test/bignum_tests.cpp88
-rw-r--r--src/test/uint256_tests.cpp129
-rw-r--r--src/txdb.cpp6
-rw-r--r--src/txdb.h2
-rw-r--r--src/uint256.h70
13 files changed, 243 insertions, 199 deletions
diff --git a/src/bignum.h b/src/bignum.h
index 0259338b31..6b77462d83 100644
--- a/src/bignum.h
+++ b/src/bignum.h
@@ -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
diff --git a/src/chainparams.cpp b/src/chainparams.cpp
index eb56800b92..f5cf846a01 100644
--- a/src/chainparams.cpp
+++ b/src/chainparams.cpp
@@ -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;
diff --git a/src/chainparams.h b/src/chainparams.h
index 542afeaf92..f3f24efd99 100644
--- a/src/chainparams.h
+++ b/src/chainparams.h
@@ -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;
diff --git a/src/main.cpp b/src/main.cpp
index a0f4f40cb1..6a7bb9206c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -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);
diff --git a/src/main.h b/src/main.h
index c69e0d2a3c..796a3031c9 100644
--- a/src/main.h
+++ b/src/main.h
@@ -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
diff --git a/src/miner.cpp b/src/miner.cpp
index 01fc56601b..50be4fad40 100644
--- a/src/miner.cpp
+++ b/src/miner.cpp
@@ -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);
}
}
} }
diff --git a/src/rpcmining.cpp b/src/rpcmining.cpp
index 070cf1cb2a..cb903b585a 100644
--- a/src/rpcmining.cpp
+++ b/src/rpcmining.cpp
@@ -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())
diff --git a/src/test/DoS_tests.cpp b/src/test/DoS_tests.cpp
index d86cc7a290..897fb87e46 100644
--- a/src/test/DoS_tests.cpp
+++ b/src/test/DoS_tests.cpp
@@ -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);
}
diff --git a/src/test/bignum_tests.cpp b/src/test/bignum_tests.cpp
index d5ee8c9778..01967c7684 100644
--- a/src/test/bignum_tests.cpp
+++ b/src/test/bignum_tests.cpp
@@ -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";
diff --git a/src/test/uint256_tests.cpp b/src/test/uint256_tests.cpp
index 226d737def..4b1a2ae58f 100644
--- a/src/test/uint256_tests.cpp
+++ b/src/test/uint256_tests.cpp
@@ -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>
diff --git a/src/txdb.cpp b/src/txdb.cpp
index cb92922a35..4eab8525a5 100644
--- a/src/txdb.cpp
+++ b/src/txdb.cpp
@@ -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);
}
diff --git a/src/txdb.h b/src/txdb.h
index 5eb5731db3..7257b0dd21 100644
--- a/src/txdb.h
+++ b/src/txdb.h
@@ -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);
diff --git a/src/uint256.h b/src/uint256.h
index 7b17694eb2..10c6657c76 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -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