mirror of
https://github.com/dashpay/dash.git
synced 2024-12-28 13:32:47 +01:00
commit
d339da70e5
68
src/bignum.h
68
src/bignum.h
@ -262,28 +262,68 @@ public:
|
|||||||
return vch;
|
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)
|
CBigNum& SetCompact(unsigned int nCompact)
|
||||||
{
|
{
|
||||||
unsigned int nSize = nCompact >> 24;
|
unsigned int nSize = nCompact >> 24;
|
||||||
std::vector<unsigned char> vch(4 + nSize);
|
bool fNegative =(nCompact & 0x00800000) != 0;
|
||||||
vch[3] = nSize;
|
unsigned int nWord = nCompact & 0x007fffff;
|
||||||
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
|
if (nSize <= 3)
|
||||||
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
|
{
|
||||||
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
|
nWord >>= 8*(3-nSize);
|
||||||
BN_mpi2bn(&vch[0], vch.size(), this);
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int GetCompact() const
|
unsigned int GetCompact() const
|
||||||
{
|
{
|
||||||
unsigned int nSize = BN_bn2mpi(this, NULL);
|
unsigned int nSize = BN_num_bytes(this);
|
||||||
std::vector<unsigned char> vch(nSize);
|
unsigned int nCompact = 0;
|
||||||
nSize -= 4;
|
if (nSize <= 3)
|
||||||
BN_bn2mpi(this, &vch[0]);
|
nCompact = BN_get_word(this) << 8*(3-nSize);
|
||||||
unsigned int nCompact = nSize << 24;
|
else
|
||||||
if (nSize >= 1) nCompact |= (vch[4] << 16);
|
{
|
||||||
if (nSize >= 2) nCompact |= (vch[5] << 8);
|
CBigNum bn;
|
||||||
if (nSize >= 3) nCompact |= (vch[6] << 0);
|
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;
|
return nCompact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,4 +122,57 @@ 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(), 0);
|
||||||
|
|
||||||
|
num.SetCompact(0x00123456);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "0");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0);
|
||||||
|
|
||||||
|
num.SetCompact(0x01123456);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "12");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0x01120000);
|
||||||
|
|
||||||
|
// Make sure that we don't generate compacts with the 0x00800000 bit set
|
||||||
|
num = 0x80;
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0x02008000);
|
||||||
|
|
||||||
|
num.SetCompact(0x01fedcba);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "-7e");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0x01fe0000);
|
||||||
|
|
||||||
|
num.SetCompact(0x02123456);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "1234");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0x02123400);
|
||||||
|
|
||||||
|
num.SetCompact(0x03123456);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "123456");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0x03123456);
|
||||||
|
|
||||||
|
num.SetCompact(0x04123456);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "12345600");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0x04123456);
|
||||||
|
|
||||||
|
num.SetCompact(0x04923456);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "-12345600");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0x04923456);
|
||||||
|
|
||||||
|
num.SetCompact(0x05009234);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "92340000");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0x05009234);
|
||||||
|
|
||||||
|
num.SetCompact(0x20123456);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "1234560000000000000000000000000000000000000000000000000000000000");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0x20123456);
|
||||||
|
|
||||||
|
num.SetCompact(0xff123456);
|
||||||
|
BOOST_CHECK_EQUAL(num.GetHex(), "123456000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
|
||||||
|
BOOST_CHECK_EQUAL(num.GetCompact(), 0xff123456);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_SUITE_END()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
Loading…
Reference in New Issue
Block a user