13

If we take block hash 0000000000000006770c3806960539ca83a24facbd99ea212f37f2a0e6a5629a for example.

The difficulty as a 32 bit float is 50810339.04827648. The difficulty in bits as an unsigned 32 bit integer is 424970034?

What are the equations to go from difficulty -> bits and bits -> difficulty?

1

3 Answers 3

23

Answer shamelessly stolen from stackexchange:

Difficulty encoding is thoroughly described here.

Hexadecimal representation like 0x182815ee consists of two parts:

  • 0x18 -- number of bytes in a target
  • 0x2815ee -- target prefix

This means that valid hash should be less than 0x2815ee000000000000000000000000000000000000000000 (it is exactly 0x18 = 24 bytes long).

Floating point representation of difficulty shows how much current target is harder than the one used in the genesis block.

Satoshi decided to use 0x1d00ffff as a difficulty for the genesis block, so the target was 0x00ffff0000000000000000000000000000000000000000000000000000.

And 50810339.04827648 is how much current target is greater than the initial one.

How the Bitcoin client converts from bits -> difficulty:

uint256& uint256::SetCompact(uint32_t nCompact, bool *pfNegative, bool *pfOverflow)
{
    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;
}

How the Bitcoin client converts from difficulty -> bits:

uint32_t uint256::GetCompact(bool fNegative) 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;
}

Converting from target to difficulty, in shell. Create file target-to-difficulty.sh:

#!/bin/bash
echo "ibase=16;FFFF0000000000000000000000000000000000000000000000000000 / $1" | bc -l

Usage:

$ ./target-to-difficulty.sh 000000000000000024DBE9000000000000000000000000000000000000000000
29829733124.04041574884510759883
4
  • 1
    Thanks for the code. However it only seems to convert between the 256 bit and 32 bit compact representation of bits. Not the floating point value of difficulty I am looking for. So I believe this is only part of the solution.
    – Dan
    Sep 15, 2014 at 16:17
  • @Dan To get the difficulty, divide the maximum target (bits=0x1d00ffff) by the current target.
    – theymos
    Sep 15, 2014 at 19:40
  • I know this is old, but what is pfNegative and pfOverflow?
    – chriscrutt
    Sep 12, 2022 at 23:38
  • @chriscrutt pf = pointer to flag. It means that the function checks whether the compact number is negative, or has an overflow (the exponent is so large that the result cannot fit in 256 bits.)
    – Nick ODell
    Sep 13, 2022 at 16:43
4

There are 3 representations of the same thing (with varying degrees of precision) in Bitcoin:

  • bits - unsigned int 32-bit
  • target - unsigned int 256-bit
  • difficulty - double-precision float (64-bit)

and 6 methods are necessary to convert between any two of these:

  • bits -> target (SetCompact() in bitcoin/src/arith_uint256.cpp)
  • bits -> difficulty (GetDifficulty() in bitcoin/src/rpc/blockchain.cpp)
  • target -> bits (GetCompact() in bitcoin/src/arith_uint256.cpp)
  • target -> difficulty (same as target -> bits -> difficulty)
  • difficulty -> bits (not done in bitcoin/src)
  • difficulty -> target (same as difficulty -> bits -> target)

The Bitcoin source code can do the conversion from bits -> difficulty as asked in the question, but cannot do the conversion from difficulty -> bits as also asked in the question.

I have written my own implementation of the difficulty -> bits conversion in vanilla Javascript by mimicking the target -> bits conversion where possible, plus some additional checks:

function difficulty2bits(difficulty) { 
    if (difficulty < 0) throw 'difficulty cannot be negative';
    if (!isFinite(difficulty)) throw 'difficulty cannot be infinite';
    for (var shiftBytes = 1; true; shiftBytes++) {
        var word = (0x00ffff * Math.pow(0x100, shiftBytes)) / difficulty;
        if (word >= 0xffff) break;
    }
    word &= 0xffffff; // convert to int < 0xffffff
    var size = 0x1d - shiftBytes;
    // the 0x00800000 bit denotes the sign, so if it is already set, divide the
    // mantissa by 0x100 and increase the size by a byte
    if (word & 0x800000) {
        word >>= 8;
        size++;
    }
    if ((word & ~0x007fffff) != 0) throw 'the \'bits\' \'word\' is out of bounds';
    if (size > 0xff) throw 'the \'bits\' \'size\' is out of bounds';
    var bits = (size << 24) | word;
    return bits;
}

It is possible to validate that the above function gives correct answers by doing the following conversion:

bits -> difficulty -> bits

Where bits -> difficulty is done using Bitcoin's GetDifficulty() and difficulty -> bits is done using difficulty2bits() above. If we arrive back at the same bits value then the difficulty2bits() function is correct. The only exception is when (bits & 0x00800000) != 0, since this means that bits is a negative number, whereas difficulty is always a positive number in Bitcoin.

I have tested the above difficulty2bits() function and it does return the same result as the original bits value. If you want to do the tests yourself then I have created a live conversion tool on my blog where you can do any of the 6 conversions listed above in real time (I have transcribed Bitcoin's SetCompact(), GetDifficulty() and GetCompact() into Javascript): https://analysis.null.place/how-do-the-bitcoin-mining-algorithms-work/#form7

Note that numbers in Javascript are IEEE 754 double precision - the same precision as the difficulty in the Bitcoin source, so Javascript is as accurate as the Bitcoin source for all bits/difficulty/target conversions. However, to assuage scepticism I have also included the relevant unit tests from Bitcoin's bitcoin/src/test/blockchain_tests.cpp and bitcoin/src/test/arith_uint256_tests.cpp files on the blog just below the aforementioned tool - all tests pass.

3

I have written javascript code to understand Target, Difficulty and Avg Network Hashrate and how they are interlinked.

Difficulty = Difficulty_1_target / Current Target;

Difficulty_1_target is target when difficulty was 1, so its also called max target. which is defined in genesis block as a 4-byte number "1d00ffff". Target is found in block header as 4-byte number which is compact base256 notation, where first byte is exponent, and last three bytes are mantissa;

Next Difficulty = current difficulty * 2 weeks / T ( Time in which previous 2016 blocks found ).

So, if we know Difficulty, from the above equation we can find Current Target, using bignumber.js:

var base = new BigNumber(256);
var hTargetCompact = '1d00ffff';
var e = hTargetCompact.slice(0,2); //First Byte 
var exponent = new BigNumber(e,16);
exponent = exponent.minus(3); 

var m = hTargetCompact.slice(2); //Three Significant Bytes
var mantissa = new BigNumber(m,16);
var hTarget = mantissa.times(base.toPower(exponent));
var d = new BigNumber('2.87467423441594e12'); // Current Difficulty 2874674234415.94

var cTarget = hTarget.div(d).ceil();

// Output Current Target in Hex
console.log(cTarget.toString(16));  

// Current Target in compact format
mantissa = cTarget.toString(16).slice(0,6); // Most Significant three bytes
exponent = (cTarget.toString(16).length / 2).toString(16) // Exponent

var cTargetCompact = exponent + mantissa;
console.log(cTargetCompact);

http://blog.kherwa.com/2017/10/25/blockchain-difficulty-network-hashrate/

Javascript code is on JSBin, you can try your combination also.

1
  • 2
    Welcome to Bitcoin.SE! A useful answer! I see you have already done the work here, but your answer can still be improved if you edit it to include some examples of how the equations work.
    – Willtech
    Feb 5, 2018 at 11:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.