我正在尝试将使用按位运算的 C++ 函数移植到 C#,但遇到了问题。即当输入是0x01123456
C# 时返回零,但它应该是12
BN_set_word 和其他 BN_* 函数在 OpenSSL 中。这些函数做了什么(详细)......是否有一个大整数的.NET等价物?
什么是 MPI 表示?(谷歌没用)
我应该担心这里评论中提到的班次计数中的掩蔽吗?
C++ 原版
// 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;
}
C# 尝试的端口
internal static System.Numerics.BigInteger SetCompact(uint numToCompact)
{
//
//
// SetCompact
// Extract the number from bits 0..23
uint nWord = numToCompact & 0x007fffff;
BigInteger ret = new BigInteger(nWord);
// Add zeroes to the left according to bits 25..32
var ttt = ret.ToByteArray();
uint size = numToCompact >> 24;
uint amountToShift = 0;
if (size <= 3)
{
amountToShift = 8 * (3 - size);
ret = ret >> (int)amountToShift;
}
else
{
ret = ret << (int)amountToShift;
amountToShift = 8 * (size - 3);
}
// Set the value negative if required per bit 24
UInt32 isNegative = 0x00800000 & numToCompact;
if (isNegative != 0)
ret =BigInteger.Negate(ret);
var test = ret.ToByteArray();
Console.WriteLine();
Console.WriteLine(ret.ToString("X"));
return ret;
}