What are the equations to convert between bits and difficulty?

10

4

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?

Dan

Posted 2014-09-11T15:42:59.810

Reputation: 371

Answers

20

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

Nick ODell

Posted 2014-09-11T15:42:59.810

Reputation: 26 536

1Thanks 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 2014-09-15T16:17:27.347

@Dan To get the difficulty, divide the maximum target (bits=0x1d00ffff) by the current target.theymos 2014-09-15T19:40:54.447

2

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.

kherwa

Posted 2014-09-11T15:42:59.810

Reputation: 141

1Welcome 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 2018-02-05T11:47:44.410

1

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.

mulllhausen

Posted 2014-09-11T15:42:59.810

Reputation: 1 533