Bitcoinのdifficultyを決めるnBitsを理解する

仮想通貨全般

マイニングする際の理解を深めようと思い、マイニング難易度(difficulty)を決めるnBitsについて理解を深めてみます。

マイニングする際におなじみの stratum protcol で難易度を表すnBitsが返却されます。

上記stackoverflowでわかりやすい投稿があったのでこちらを元に理解を深めます。

Sponsored Link


difficultyの具体的な数値の求め方

上記の記事でnBitsが1b3cc366のとき、なぜdifficultyが 1078.52975077 になるかわからない、と投稿者はいっています。

0x1b3cc366

を以下のように分解します。

– 0x1b (ターゲットのバイト数)
– 0x3cc366 (ターゲットのバイト)

上記を踏まえて有効なhashが以下になります。

0x3cc366000000000000000000000000000000000000000000000000
(0x1bが27bytesなので、3cから末尾の0まで54個ある。16進数なので1桁4byte)

そしてsatochiは 0x1d00ffff を genesis blockで使う事にきめたので
targetは 0x00ffff0000000000000000000000000000000000000000000000000000 になります。
そして、difficultyの求め方は以下になると。

$ echo 'ibase=16;FFFF0000000000000000000000000000000000000000000000000000 / 3CC366000000000000000000000000000000000000000000000000' | bc -l
1078.52975077482646448605

Bitcoinの関数 GetDifficultyを見てみる

では具体的にソースではどのようになっているか見て見ます。

double GetDifficulty(const CBlockIndex* blockindex)
{
    if (blockindex == nullptr)
    {
        return 1.0;
    }

    int nShift = (blockindex->nBits >> 24) & 0xff;
    double dDiff =
        (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);

    while (nShift < 29)
    {
        dDiff *= 256.0;
        nShift++;
    }
    while (nShift > 29)
    {
        dDiff /= 256.0;
        nShift--;
    }

    return dDiff;
}

が全体のソース。
例としてあげた値は 0x1b3cc366 とします。

int nShift = (blockindex->nBits >> 24) & 0xff;

この部分で、シフトする数を求めていると。24bitシフトしていますが、hexでいくと6(24bit/4bit)個シフトします。
0x1b3cc366
なので、6個右にずらすと3cc366の部分がなくなり 0x1b。

    double dDiff =
        (double)0x0000ffff / (double)(blockindex->nBits & 0x00ffffff);

まず、0x0000ffffはgenesisblockで取り決めた 0x1d00ffff の shift部分 1d を00にして求めてます。
blockindex->nBitsは、現状のnBitsで、0x00ffffff(shiftする数の情報を無効にする。先頭の00がそれ)をかけることによって0x003cc366になります。

    while (nShift < 29)
    {
        dDiff *= 256.0;
        nShift++;
    }
    while (nShift > 29)
    {
        dDiff /= 256.0;
        nShift--;
    }

そして最後のこの部分。この例だと nShiftは0x1bであり27なので

    while (nShift < 29)
    {
        dDiff *= 256.0;
        nShift++;
    }

の部分で処理されます。
ちなみに条件式の29は何か?というと、0x1d00ffff の 1dの部分が29になります。
ようはdifficultyの閾値で、nShiftがこの値より大きければdifficultyを小さくして、nShiftがこの値より小さければdifficultyを大きくします。

そして今回はnShiftは0x1bであり27なので
dDiffに256をかけていきます。27,28とループして256を2回かけることになりますね。

256をかけるとなると、16進数で左に2個shiftします。
0x00001 = 1
0x00100 = 256
0x10000 = 65536
こんな感じですね。

これでdifficultyを求めています。

まとめ

具体的な数値とソースを見つつdifficultyを求めて見ました。
何かの参考になれば幸いです。

Sponsored Link
コメントはまだありません

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA


仮想通貨全般
TendermintをDocker使って起動してみる

以前、勉強会に行ってきた際にTendermintの事を聞いて ブロックチェーンプロトコルが実装できる …

仮想通貨全般
EOS Night Meetupにいってきた

今回は、以前からEOSに興味があったので EOS Night Meetupにいってきました。 暗号通 …

仮想通貨全般
ビットコインとか勉強会#21 にいってきた

に参加してきたのでメモ。 Sponsored Link Contents1 DAppsの現状とイーサ …