# What is most efficient way to validate bitcoin target (difficulty) value in C++

I have two values

``````1. h = hash of the block (32 bytes long in memory representation - not hex)
2. bits (uint32_t)
``````

To make the calculation easier we create a function difficulty such that:

``````auto d = difficulty(bits)
``````

Now what is the best way to create such a difficulty function that, I believe should, return a 256 bit value?

Then I am thinking casting both h and d values into an array of type uint64_t and compare all 4 elements from msb (bit 255) to make sure the condition holds.

Is there a better way for comparing as well?

Bitcoin Core has its own `arith_uint256` class for calculations on 256-bit unsigned integers. Its code to convert "bits" (so-called compact format) to `arith_uint256` can be found in `arith_uint256::SetCompact` in the file `arith_uint256.cpp`.

So you could always just use its code directly. This might be a good idea because if your version differs in any way from their behavior (e.g. rounding errors), you could disagree with Bitcoin Core on the validity of a block. If your version is in a widely-used client, this would fork the block chain.

I have come up with following version that seems to be working correctly for few test cases I have defined.

First we need a helper function that prints hex value given binary data:

``````void hexdump(unsigned char *data, int len)
{
int c = 0;
while (c < len)
{
cout << hex << std::setw(2) << std::setfill('0') << static_cast<int>(data[c++]);
}
printf("\n");
}
``````

Now lets define the actual function that takes block.bits and converts it to 256 bit value in memory:

``````bool convert_bits(uint32_t bits, uint64_t* value, int val_len = 4)
{
assert(val_len == 4);
assert(value != NULL);

if (val_len != 4 || value == NULL)
{
return false;
}

// if bits =  0x1b0404cb, hex target = 0x0404cb * 2**(8*(0x1b - 3))
uint32_t x = 8 * ((bits >> 24) - 3); // number of zero bits on right
uint64_t val = bits & 0x00FFFFFF;

// Number of maximum bits required for val is 24.
assert(x <= (256 - 24));
if (x > (256 - 24))
{
return false;
}

int startq = (3 - int(x / 64));
int endq = (3 - int((x + 24) / 64));

int shift = ((3 + endq) * 64 - x);
if (startq != endq)
{
shift = 64 - shift;
}

value[startq] = htobe64(val << shift);
value[endq] = htobe64(val >> shift);

return true;
}
``````

Now lets test the above function:

``````int main()
{
uint64_t num[4] = { 0, 0, 0, 0 };
if(convert_bits(0x1b0404cb, num))
{
hexdump((unsigned char *)num, sizeof(uint64_t) * 4);
}
return 0;
}
``````

This prints: 00000000000404cb000000000000000000000000000000000000000000000000

• `htobe64` is particularly slow (about 50 executions in a single thread with my i5-1240P). Apr 28, 2023 at 16:31
• I ended up using gist.github.com/Ending2015a/70373b2f6f665a765b4d0b0c427f052b Apr 28, 2023 at 17:16
• Bytes shift don't need us to pay attention to the endianness. Endianness must be taken in account iff the code is copying integers with memcpy. Aug 16, 2023 at 7:25