Сложность

Материал из Bitcoin Wiki
Перейти к: навигация, поиск

Сложность (англ, "Difficulty") — это единица измерения, которая показывает, насколько сложно найти хеш, который будет ниже предложенной системой цели (таргета).

Принципы функционирования

В сети Bitcoin для всех блоков существует глобальная сложность. Блок, для того, что бы считаться корректным, должен иметь хеш ниже заявленной цели (таргета).

Сложность в сети Bitcoin меняется каждые 2016 блоков. Она рассчитывается по следующей формуле:

difficulty = difficulty_1_target / current_target

где difficulty – сложность, а target – 256 битное число.

Difficulty_1_target может принимать различные значения. Традиционно это хеш, 32 первых бита которого являются 0, остальную часть составляют единицы (это также называется pdiff или pool difficulty). Bitcoin протокол представляет цель (target), как тип с плавающей точкой и ограниченной точностью. Зачастую, именно основываясь на этих данных, Bitcoin клиенты определяют сложность.

Хранение сложности в блоках

Каждый блок хранит в себе запакованную версию (называемую “Bits” или «Биты») шестнадцатеричной цели.

Используя следующую формулу, из каждого блока можно получить его цель. Например, если запакованная цель в блоке имеет вид 0x1b0404cb, то ее шестнадцатеричная версия будет выглядеть следующим образом:

0x0404cb * 2**(8*(0x1b - 3)) = 0x00000000000404CB000000000000000000000000000000000000000000000000

Максимальное значение для этого поля - 0x7fffff, минимальное же составляет 0x008000.

Максимально возможная цель (при сложности 1) определена как 0x1d00ffff, что в шестнадцатеричном варианте имеет вид:

0x00ffff * 2**(8*(0x1d - 3)) = 0x00000000FFFF0000000000000000000000000000000000000000000000000000

Ниже представлен быстрый способ вычисления сложности сети Bitcoin. Для логарифмирования он использует измененную версию ряда Тейлора и основывается на логах для преобразования вычисления сложности.

#include <iostream>
#include <cmath>
 
inline float fast_log(float val)
{
   int * const exp_ptr = reinterpret_cast <int *>(&val);
   int x = *exp_ptr;
   const int log_2 = ((x >> 23) & 255) - 128;
   x &= ~(255 << 23);
   x += 127 << 23;
   *exp_ptr = x;
 
   val = ((-1.0f/3) * val + 2) * val - 2.0f/3;
   return ((val + log_2) * 0.69314718f);
}
 
float difficulty(unsigned int bits)
{
    static double max_body = fast_log(0x00ffff), scaland = fast_log(256);
    return exp(max_body - fast_log(bits & 0x00ffffff) + scaland * (0x1d - ((bits & 0xff000000) >> 24)));
}
 
int main()
{
    std::cout << difficulty(0x1b0404cb) << std::endl;
    return 0;
}

Максимальная, текущая и минимальная сложности

Текущую сложность можно узнать воспользовавшись Bitcoin-командой getDifficulty.

Ввиду того, что не существует минимальной цели (target), примерно рассчитать максимальную сложность можно следующим образом: maximum_target / 1 (т.к. 0 приведет уравнение к бесконечности), что является невообразимым числом (~ 2 в 224 степени).

Минимальная же сложность равняется 1.

Изменение сложности

Сложность меняется каждые 2016 блоков, основываясь на времени, которое потребовалось для нахождения предыдущих 2016 блоков. Если блок будет находиться каждые 10 минут (как это задумывалось изначально для равномерной эмиссии), нахождение 2016 блоков займет ровно 2 недели. Если предыдущие 2016 блоков были найдены за срок более 2х недель – сложность будет уменьшена, если меньше – сложность будет увеличена. Чем больше (или меньше) времени было затрачено на нахождение предыдущих 2016 блоков, тем больше уменьшится (или увеличится) сложность.

Для нахождения блока хеш должен быть меньше цели (принцип работы proof-of-work). Хеш является случайным числом от 0 до 2*256-1.

Смещение для сложности 1: 0xffff * 2**208
Для сложности D: (0xffff * 2**208)/D
Количество хешей, которое необходимо рассчитать для нахождения блока со сложность D: D * 2**256 / (0xffff * 2**208)
Или просто: D * 2**48 / 0xffff

Сложность заявлена таким образом, как будто мы находили предыдущие 2016 блоков с периодичностью раз в 10 минут.

Соответственно мы рассчитывали (D * 2**48 / 0xffff) хешей за 600 секунд.
Хешрейт нашей сети за предыдущие 2016 блоков составит: D * 2**48 / 0xffff / 600
Без особой потери точности можно упростить до: D * 2**32 / 600.
На сложности 1 это примерно 7 Mhash в секунду.

Среднее время нахождения блока в одиночку рассчитывается по формуле: time = difficulty * 2**32 / hashrate, где difficulty это текущая сложность сети Bitcoin, hashrate это количество хешей, которое ваш майнер находит в секунду и time это среднее время (в секундах) между нахождением вами блока.

См. также

Ссылки