Merge pull request #4076
397668e
Deduplicate uint* comparison operator logic (Pieter Wuille)df9eb5e
Move {Get,Set}Compact from bignum to uint256 (Pieter Wuille)a703150
Add multiplication and division to uint160/uint256 (Pieter Wuille)4d480c8
Exception instead of assigning 0 in case of wrong vector length (Pieter Wuille)eb2cbd7
Deduplicate shared code between uint160 and uint256 (Pieter Wuille)
This commit is contained in:
commit
8bcfccbc2d
13 changed files with 477 additions and 512 deletions
65
src/bignum.h
65
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
43
src/main.cpp
43
src/main.cpp
|
@ -1207,13 +1207,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)
|
||||
{
|
||||
|
@ -1272,8 +1272,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;
|
||||
|
||||
|
@ -1283,23 +1285,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;
|
||||
|
@ -1338,7 +1342,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)
|
||||
{
|
||||
|
@ -1394,7 +1398,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;
|
||||
|
@ -1428,10 +1432,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",
|
||||
|
@ -2174,7 +2174,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;
|
||||
|
@ -2351,11 +2351,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");
|
||||
|
@ -2926,7 +2927,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);
|
||||
|
|
17
src/main.h
17
src/main.h
|
@ -10,7 +10,6 @@
|
|||
#include "bitcoin-config.h"
|
||||
#endif
|
||||
|
||||
#include "bignum.h"
|
||||
#include "chainparams.h"
|
||||
#include "coins.h"
|
||||
#include "core.h"
|
||||
|
@ -814,13 +813,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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
} }
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -160,11 +160,11 @@ BOOST_AUTO_TEST_CASE( basics ) // constructors, equality, inequality
|
|||
tmpS = ~R2S; BOOST_CHECK(tmpS == ~R2S);
|
||||
tmpS = ~MaxS; BOOST_CHECK(tmpS == ~MaxS);
|
||||
|
||||
// Wrong length must give 0
|
||||
BOOST_CHECK(uint256(std::vector<unsigned char>(OneArray,OneArray+31)) == 0);
|
||||
BOOST_CHECK(uint256(std::vector<unsigned char>(OneArray,OneArray+20)) == 0);
|
||||
BOOST_CHECK(uint160(std::vector<unsigned char>(OneArray,OneArray+32)) == 0);
|
||||
BOOST_CHECK(uint160(std::vector<unsigned char>(OneArray,OneArray+19)) == 0);
|
||||
// Wrong length must throw exception.
|
||||
BOOST_CHECK_THROW(uint256(std::vector<unsigned char>(OneArray,OneArray+31)), uint_error);
|
||||
BOOST_CHECK_THROW(uint256(std::vector<unsigned char>(OneArray,OneArray+20)), uint_error);
|
||||
BOOST_CHECK_THROW(uint160(std::vector<unsigned char>(OneArray,OneArray+32)), uint_error);
|
||||
BOOST_CHECK_THROW(uint160(std::vector<unsigned char>(OneArray,OneArray+19)), uint_error);
|
||||
}
|
||||
|
||||
void shiftArrayRight(unsigned char* to, const unsigned char* from, unsigned int arrayLength, unsigned int bitsToShift)
|
||||
|
@ -482,6 +482,77 @@ BOOST_AUTO_TEST_CASE( plusMinus )
|
|||
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
uint160 D1S("D3C5EDCDEA54EB92679F0A4B4");
|
||||
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<double>::epsilon();
|
||||
|
@ -604,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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
536
src/uint256.h
536
src/uint256.h
|
@ -1,11 +1,13 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2013 The Bitcoin developers
|
||||
// Copyright (c) 2009-2014 The Bitcoin developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef BITCOIN_UINT256_H
|
||||
#define BITCOIN_UINT256_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdexcept>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
@ -19,17 +21,59 @@ inline signed char HexDigit(char c)
|
|||
return p_util_hexdigit[(unsigned char)c];
|
||||
}
|
||||
|
||||
/** Base class without constructors for uint256 and uint160.
|
||||
* This makes the compiler let you use it in a union.
|
||||
*/
|
||||
class uint_error : public std::runtime_error {
|
||||
public:
|
||||
explicit uint_error(const std::string& str) : std::runtime_error(str) {}
|
||||
};
|
||||
|
||||
/** Template base class for unsigned big integers. */
|
||||
template<unsigned int BITS>
|
||||
class base_uint
|
||||
{
|
||||
protected:
|
||||
private:
|
||||
enum { WIDTH=BITS/32 };
|
||||
uint32_t pn[WIDTH];
|
||||
public:
|
||||
|
||||
base_uint()
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
base_uint(const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
}
|
||||
|
||||
base_uint& operator=(const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint(uint64_t b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
explicit base_uint(const std::string& str)
|
||||
{
|
||||
SetHex(str);
|
||||
}
|
||||
|
||||
explicit base_uint(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
if (vch.size() != sizeof(pn))
|
||||
throw uint_error("Converting vector of wrong size to base_uint");
|
||||
memcpy(pn, &vch[0], sizeof(pn));
|
||||
}
|
||||
|
||||
bool operator!() const
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
|
@ -178,6 +222,57 @@ public:
|
|||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator*=(uint32_t b32)
|
||||
{
|
||||
uint64_t carry = 0;
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
{
|
||||
uint64_t n = carry + (uint64_t)b32 * pn[i];
|
||||
pn[i] = n & 0xffffffff;
|
||||
carry = n >> 32;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator*=(const base_uint& b)
|
||||
{
|
||||
base_uint a = *this;
|
||||
*this = 0;
|
||||
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;
|
||||
carry = n >> 32;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator/=(const base_uint& b)
|
||||
{
|
||||
base_uint div = b; // make a copy, so we can shift.
|
||||
base_uint num = *this; // make a copy, so we can subtract.
|
||||
*this = 0; // the quotient.
|
||||
int num_bits = num.bits();
|
||||
int div_bits = div.bits();
|
||||
if (div_bits == 0)
|
||||
throw uint_error("Division by zero");
|
||||
if (div_bits > num_bits) // the result is certainly 0.
|
||||
return *this;
|
||||
int shift = num_bits - div_bits;
|
||||
div <<= shift; // shift so that div and nun align.
|
||||
while (shift >= 0) {
|
||||
if (num >= div) {
|
||||
num -= div;
|
||||
pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result.
|
||||
}
|
||||
div >>= 1; // shift back.
|
||||
shift--;
|
||||
}
|
||||
// num now contains the remainder of the division.
|
||||
return *this;
|
||||
}
|
||||
|
||||
base_uint& operator++()
|
||||
{
|
||||
|
@ -213,86 +308,46 @@ public:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int CompareTo(const base_uint& b) const {
|
||||
for (int i = base_uint::WIDTH-1; i >= 0; i--) {
|
||||
if (pn[i] < b.pn[i])
|
||||
return -1;
|
||||
if (pn[i] > b.pn[i])
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
friend inline bool operator<(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = base_uint::WIDTH-1; i >= 0; i--)
|
||||
{
|
||||
if (a.pn[i] < b.pn[i])
|
||||
return true;
|
||||
else if (a.pn[i] > b.pn[i])
|
||||
bool EqualTo(uint64_t b) const {
|
||||
for (int i = base_uint::WIDTH-1; i >= 2; i--) {
|
||||
if (pn[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
friend inline bool operator<=(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = base_uint::WIDTH-1; i >= 0; i--)
|
||||
{
|
||||
if (a.pn[i] < b.pn[i])
|
||||
return true;
|
||||
else if (a.pn[i] > b.pn[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
friend inline bool operator>(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = base_uint::WIDTH-1; i >= 0; i--)
|
||||
{
|
||||
if (a.pn[i] > b.pn[i])
|
||||
return true;
|
||||
else if (a.pn[i] < b.pn[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
friend inline bool operator>=(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = base_uint::WIDTH-1; i >= 0; i--)
|
||||
{
|
||||
if (a.pn[i] > b.pn[i])
|
||||
return true;
|
||||
else if (a.pn[i] < b.pn[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
friend inline bool operator==(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
for (int i = 0; i < base_uint::WIDTH; i++)
|
||||
if (a.pn[i] != b.pn[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
friend inline bool operator==(const base_uint& a, uint64_t b)
|
||||
{
|
||||
if (a.pn[0] != (unsigned int)b)
|
||||
if (pn[1] != (b >> 32))
|
||||
return false;
|
||||
if (a.pn[1] != (unsigned int)(b >> 32))
|
||||
if (pn[0] != (b & 0xfffffffful))
|
||||
return false;
|
||||
for (int i = 2; i < base_uint::WIDTH; i++)
|
||||
if (a.pn[i] != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
friend inline bool operator!=(const base_uint& a, const base_uint& b)
|
||||
{
|
||||
return (!(a == b));
|
||||
}
|
||||
|
||||
friend inline bool operator!=(const base_uint& a, uint64_t b)
|
||||
{
|
||||
return (!(a == b));
|
||||
}
|
||||
|
||||
|
||||
friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; }
|
||||
friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; }
|
||||
friend inline const base_uint operator*(const base_uint& a, const base_uint& b) { return base_uint(a) *= b; }
|
||||
friend inline const base_uint operator/(const base_uint& a, const base_uint& b) { return base_uint(a) /= b; }
|
||||
friend inline const base_uint operator|(const base_uint& a, const base_uint& b) { return base_uint(a) |= b; }
|
||||
friend inline const base_uint operator&(const base_uint& a, const base_uint& b) { return base_uint(a) &= b; }
|
||||
friend inline const base_uint operator^(const base_uint& a, const base_uint& b) { return base_uint(a) ^= b; }
|
||||
friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; }
|
||||
friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; }
|
||||
friend inline const base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; }
|
||||
friend inline bool operator==(const base_uint& a, const base_uint& b) { return a.CompareTo(b) == 0; }
|
||||
friend inline bool operator!=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) != 0; }
|
||||
friend inline bool operator>(const base_uint& a, const base_uint& b) { return a.CompareTo(b) > 0; }
|
||||
friend inline bool operator<(const base_uint& a, const base_uint& b) { return a.CompareTo(b) < 0; }
|
||||
friend inline bool operator>=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) >= 0; }
|
||||
friend inline bool operator<=(const base_uint& a, const base_uint& b) { return a.CompareTo(b) <= 0; }
|
||||
friend inline bool operator==(const base_uint& a, uint64_t b) { return a.EqualTo(b); }
|
||||
friend inline bool operator!=(const base_uint& a, uint64_t b) { return !a.EqualTo(b); }
|
||||
|
||||
std::string GetHex() const
|
||||
{
|
||||
|
@ -367,269 +422,134 @@ public:
|
|||
return sizeof(pn);
|
||||
}
|
||||
|
||||
// Returns the position of the highest bit set plus one, or zero if the
|
||||
// value is zero.
|
||||
unsigned int bits() const
|
||||
{
|
||||
for (int pos = WIDTH-1; pos >= 0; pos--) {
|
||||
if (pn[pos]) {
|
||||
for (int bits = 31; bits > 0; bits--) {
|
||||
if (pn[pos] & 1<<bits)
|
||||
return 32*pos + bits + 1;
|
||||
}
|
||||
return 32*pos + 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t GetLow64() const
|
||||
{
|
||||
assert(WIDTH >= 2);
|
||||
return pn[0] | (uint64_t)pn[1] << 32;
|
||||
}
|
||||
|
||||
// unsigned int GetSerializeSize(int nType=0, int nVersion=PROTOCOL_VERSION) const
|
||||
unsigned int GetSerializeSize(int nType, int nVersion) const
|
||||
{
|
||||
return sizeof(pn);
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
// void Serialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION) const
|
||||
void Serialize(Stream& s, int nType, int nVersion) const
|
||||
{
|
||||
s.write((char*)pn, sizeof(pn));
|
||||
}
|
||||
|
||||
template<typename Stream>
|
||||
// void Unserialize(Stream& s, int nType=0, int nVersion=PROTOCOL_VERSION)
|
||||
void Unserialize(Stream& s, int nType, int nVersion)
|
||||
{
|
||||
s.read((char*)pn, sizeof(pn));
|
||||
}
|
||||
|
||||
|
||||
friend class uint160;
|
||||
friend class uint256;
|
||||
};
|
||||
|
||||
typedef base_uint<160> base_uint160;
|
||||
typedef base_uint<256> base_uint256;
|
||||
|
||||
|
||||
|
||||
//
|
||||
// uint160 and uint256 could be implemented as templates, but to keep
|
||||
// compile errors and debugging cleaner, they're copy and pasted.
|
||||
//
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uint160
|
||||
//
|
||||
|
||||
/** 160-bit unsigned integer */
|
||||
class uint160 : public base_uint160
|
||||
{
|
||||
/** 160-bit unsigned big integer. */
|
||||
class uint160 : public base_uint<160> {
|
||||
public:
|
||||
typedef base_uint160 basetype;
|
||||
|
||||
uint160()
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
uint160(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
}
|
||||
|
||||
uint160& operator=(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint160(uint64_t b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
uint160& operator=(uint64_t b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit uint160(const std::string& str)
|
||||
{
|
||||
SetHex(str);
|
||||
}
|
||||
|
||||
explicit uint160(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
if (vch.size() == sizeof(pn))
|
||||
memcpy(pn, &vch[0], sizeof(pn));
|
||||
else
|
||||
*this = 0;
|
||||
}
|
||||
uint160() {}
|
||||
uint160(const base_uint<160>& b) : base_uint<160>(b) {}
|
||||
uint160(uint64_t b) : base_uint<160>(b) {}
|
||||
explicit uint160(const std::string& str) : base_uint<160>(str) {}
|
||||
explicit uint160(const std::vector<unsigned char>& vch) : base_uint<160>(vch) {}
|
||||
};
|
||||
|
||||
inline bool operator==(const uint160& a, uint64_t b) { return (base_uint160)a == b; }
|
||||
inline bool operator!=(const uint160& a, uint64_t b) { return (base_uint160)a != b; }
|
||||
inline const uint160 operator<<(const base_uint160& a, unsigned int shift) { return uint160(a) <<= shift; }
|
||||
inline const uint160 operator>>(const base_uint160& a, unsigned int shift) { return uint160(a) >>= shift; }
|
||||
inline const uint160 operator<<(const uint160& a, unsigned int shift) { return uint160(a) <<= shift; }
|
||||
inline const uint160 operator>>(const uint160& a, unsigned int shift) { return uint160(a) >>= shift; }
|
||||
|
||||
inline const uint160 operator^(const base_uint160& a, const base_uint160& b) { return uint160(a) ^= b; }
|
||||
inline const uint160 operator&(const base_uint160& a, const base_uint160& b) { return uint160(a) &= b; }
|
||||
inline const uint160 operator|(const base_uint160& a, const base_uint160& b) { return uint160(a) |= b; }
|
||||
inline const uint160 operator+(const base_uint160& a, const base_uint160& b) { return uint160(a) += b; }
|
||||
inline const uint160 operator-(const base_uint160& a, const base_uint160& b) { return uint160(a) -= b; }
|
||||
|
||||
inline bool operator<(const base_uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; }
|
||||
inline bool operator<=(const base_uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; }
|
||||
inline bool operator>(const base_uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; }
|
||||
inline bool operator>=(const base_uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; }
|
||||
inline bool operator==(const base_uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; }
|
||||
inline bool operator!=(const base_uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; }
|
||||
inline const uint160 operator^(const base_uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; }
|
||||
inline const uint160 operator&(const base_uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; }
|
||||
inline const uint160 operator|(const base_uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; }
|
||||
inline const uint160 operator+(const base_uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; }
|
||||
inline const uint160 operator-(const base_uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; }
|
||||
|
||||
inline bool operator<(const uint160& a, const base_uint160& b) { return (base_uint160)a < (base_uint160)b; }
|
||||
inline bool operator<=(const uint160& a, const base_uint160& b) { return (base_uint160)a <= (base_uint160)b; }
|
||||
inline bool operator>(const uint160& a, const base_uint160& b) { return (base_uint160)a > (base_uint160)b; }
|
||||
inline bool operator>=(const uint160& a, const base_uint160& b) { return (base_uint160)a >= (base_uint160)b; }
|
||||
inline bool operator==(const uint160& a, const base_uint160& b) { return (base_uint160)a == (base_uint160)b; }
|
||||
inline bool operator!=(const uint160& a, const base_uint160& b) { return (base_uint160)a != (base_uint160)b; }
|
||||
inline const uint160 operator^(const uint160& a, const base_uint160& b) { return (base_uint160)a ^ (base_uint160)b; }
|
||||
inline const uint160 operator&(const uint160& a, const base_uint160& b) { return (base_uint160)a & (base_uint160)b; }
|
||||
inline const uint160 operator|(const uint160& a, const base_uint160& b) { return (base_uint160)a | (base_uint160)b; }
|
||||
inline const uint160 operator+(const uint160& a, const base_uint160& b) { return (base_uint160)a + (base_uint160)b; }
|
||||
inline const uint160 operator-(const uint160& a, const base_uint160& b) { return (base_uint160)a - (base_uint160)b; }
|
||||
|
||||
inline bool operator<(const uint160& a, const uint160& b) { return (base_uint160)a < (base_uint160)b; }
|
||||
inline bool operator<=(const uint160& a, const uint160& b) { return (base_uint160)a <= (base_uint160)b; }
|
||||
inline bool operator>(const uint160& a, const uint160& b) { return (base_uint160)a > (base_uint160)b; }
|
||||
inline bool operator>=(const uint160& a, const uint160& b) { return (base_uint160)a >= (base_uint160)b; }
|
||||
inline bool operator==(const uint160& a, const uint160& b) { return (base_uint160)a == (base_uint160)b; }
|
||||
inline bool operator!=(const uint160& a, const uint160& b) { return (base_uint160)a != (base_uint160)b; }
|
||||
inline const uint160 operator^(const uint160& a, const uint160& b) { return (base_uint160)a ^ (base_uint160)b; }
|
||||
inline const uint160 operator&(const uint160& a, const uint160& b) { return (base_uint160)a & (base_uint160)b; }
|
||||
inline const uint160 operator|(const uint160& a, const uint160& b) { return (base_uint160)a | (base_uint160)b; }
|
||||
inline const uint160 operator+(const uint160& a, const uint160& b) { return (base_uint160)a + (base_uint160)b; }
|
||||
inline const uint160 operator-(const uint160& a, const uint160& b) { return (base_uint160)a - (base_uint160)b; }
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// uint256
|
||||
//
|
||||
|
||||
/** 256-bit unsigned integer */
|
||||
class uint256 : public base_uint256
|
||||
{
|
||||
/** 256-bit unsigned big integer. */
|
||||
class uint256 : public base_uint<256> {
|
||||
public:
|
||||
typedef base_uint256 basetype;
|
||||
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<unsigned char>& vch) : base_uint<256>(vch) {}
|
||||
|
||||
uint256()
|
||||
// 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)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
uint256(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
}
|
||||
|
||||
uint256& operator=(const basetype& b)
|
||||
{
|
||||
for (int i = 0; i < WIDTH; i++)
|
||||
pn[i] = b.pn[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint256(uint64_t b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
}
|
||||
|
||||
uint256& operator=(uint64_t b)
|
||||
{
|
||||
pn[0] = (unsigned int)b;
|
||||
pn[1] = (unsigned int)(b >> 32);
|
||||
for (int i = 2; i < WIDTH; i++)
|
||||
pn[i] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit uint256(const std::string& str)
|
||||
{
|
||||
SetHex(str);
|
||||
}
|
||||
|
||||
explicit uint256(const std::vector<unsigned char>& vch)
|
||||
{
|
||||
if (vch.size() == sizeof(pn))
|
||||
memcpy(pn, &vch[0], sizeof(pn));
|
||||
int nSize = nCompact >> 24;
|
||||
uint32_t nWord = nCompact & 0x007fffff;
|
||||
if (nSize <= 3)
|
||||
{
|
||||
nWord >>= 8*(3-nSize);
|
||||
*this = nWord;
|
||||
}
|
||||
else
|
||||
*this = 0;
|
||||
{
|
||||
*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;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator==(const uint256& a, uint64_t b) { return (base_uint256)a == b; }
|
||||
inline bool operator!=(const uint256& a, uint64_t b) { return (base_uint256)a != b; }
|
||||
inline const uint256 operator<<(const base_uint256& a, unsigned int shift) { return uint256(a) <<= shift; }
|
||||
inline const uint256 operator>>(const base_uint256& a, unsigned int shift) { return uint256(a) >>= shift; }
|
||||
inline const uint256 operator<<(const uint256& a, unsigned int shift) { return uint256(a) <<= shift; }
|
||||
inline const uint256 operator>>(const uint256& a, unsigned int shift) { return uint256(a) >>= shift; }
|
||||
|
||||
inline const uint256 operator^(const base_uint256& a, const base_uint256& b) { return uint256(a) ^= b; }
|
||||
inline const uint256 operator&(const base_uint256& a, const base_uint256& b) { return uint256(a) &= b; }
|
||||
inline const uint256 operator|(const base_uint256& a, const base_uint256& b) { return uint256(a) |= b; }
|
||||
inline const uint256 operator+(const base_uint256& a, const base_uint256& b) { return uint256(a) += b; }
|
||||
inline const uint256 operator-(const base_uint256& a, const base_uint256& b) { return uint256(a) -= b; }
|
||||
|
||||
inline bool operator<(const base_uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; }
|
||||
inline bool operator<=(const base_uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; }
|
||||
inline bool operator>(const base_uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; }
|
||||
inline bool operator>=(const base_uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; }
|
||||
inline bool operator==(const base_uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; }
|
||||
inline bool operator!=(const base_uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; }
|
||||
inline const uint256 operator^(const base_uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
|
||||
inline const uint256 operator&(const base_uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; }
|
||||
inline const uint256 operator|(const base_uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; }
|
||||
inline const uint256 operator+(const base_uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; }
|
||||
inline const uint256 operator-(const base_uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; }
|
||||
|
||||
inline bool operator<(const uint256& a, const base_uint256& b) { return (base_uint256)a < (base_uint256)b; }
|
||||
inline bool operator<=(const uint256& a, const base_uint256& b) { return (base_uint256)a <= (base_uint256)b; }
|
||||
inline bool operator>(const uint256& a, const base_uint256& b) { return (base_uint256)a > (base_uint256)b; }
|
||||
inline bool operator>=(const uint256& a, const base_uint256& b) { return (base_uint256)a >= (base_uint256)b; }
|
||||
inline bool operator==(const uint256& a, const base_uint256& b) { return (base_uint256)a == (base_uint256)b; }
|
||||
inline bool operator!=(const uint256& a, const base_uint256& b) { return (base_uint256)a != (base_uint256)b; }
|
||||
inline const uint256 operator^(const uint256& a, const base_uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
|
||||
inline const uint256 operator&(const uint256& a, const base_uint256& b) { return (base_uint256)a & (base_uint256)b; }
|
||||
inline const uint256 operator|(const uint256& a, const base_uint256& b) { return (base_uint256)a | (base_uint256)b; }
|
||||
inline const uint256 operator+(const uint256& a, const base_uint256& b) { return (base_uint256)a + (base_uint256)b; }
|
||||
inline const uint256 operator-(const uint256& a, const base_uint256& b) { return (base_uint256)a - (base_uint256)b; }
|
||||
|
||||
inline bool operator<(const uint256& a, const uint256& b) { return (base_uint256)a < (base_uint256)b; }
|
||||
inline bool operator<=(const uint256& a, const uint256& b) { return (base_uint256)a <= (base_uint256)b; }
|
||||
inline bool operator>(const uint256& a, const uint256& b) { return (base_uint256)a > (base_uint256)b; }
|
||||
inline bool operator>=(const uint256& a, const uint256& b) { return (base_uint256)a >= (base_uint256)b; }
|
||||
inline bool operator==(const uint256& a, const uint256& b) { return (base_uint256)a == (base_uint256)b; }
|
||||
inline bool operator!=(const uint256& a, const uint256& b) { return (base_uint256)a != (base_uint256)b; }
|
||||
inline const uint256 operator^(const uint256& a, const uint256& b) { return (base_uint256)a ^ (base_uint256)b; }
|
||||
inline const uint256 operator&(const uint256& a, const uint256& b) { return (base_uint256)a & (base_uint256)b; }
|
||||
inline const uint256 operator|(const uint256& a, const uint256& b) { return (base_uint256)a | (base_uint256)b; }
|
||||
inline const uint256 operator+(const uint256& a, const uint256& b) { return (base_uint256)a + (base_uint256)b; }
|
||||
inline const uint256 operator-(const uint256& a, const uint256& b) { return (base_uint256)a - (base_uint256)b; }
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue