Как рассчитывается сложность?

Может ли кто-нибудь объяснить мне на простом английском языке, как рассчитывается сложность. У меня есть очень приблизительное представление о том, что он рассчитывается на основе количества хэш-мощности всего биткойн-сообщества за определенный период времени. Но это очень расплывчато.

Также я понимаю, что это может измениться очень быстро. Может только увеличиваться? Есть ли какая-нибудь формула, как его рассчитать или предсказать?

Спасибо за подробный ответ, Мени Розенфельд. Просто чтобы убедиться, что я все правильно понял. Я суммирую все время, которое ушло на генерацию последних 2016 блоков. А затем применить формулу.

Я думаю, что последующие вопросы лучше в качестве комментариев к ответу. В основном да, но суммирование на самом деле не требуется — вы можете просто взять временные метки последнего блока и одного блока 2016 года и вычесть.

Ответы (3)

Сложность биткойна начинается с 1 (и никогда не может опускаться ниже). Затем для каждых 2016 найденных блоков сравниваются временные метки блоков, чтобы узнать, сколько времени ушло на поиск 2016 блоков, назовем его T. Мы хотим, чтобы 2016 блоков заняли 2 недели, поэтому, если T отличается, мы умножаем сложность на (2 недели / T) — таким образом, если хешрейт останется прежним, теперь потребуется 2 недели, чтобы найти 2016 блоков.

Например, если это заняло всего 10 дней, это означает, что сложность слишком низкая и, следовательно, будет увеличена на 40%.

Сложность может увеличиваться или уменьшаться в зависимости от того, потребовалось ли больше или меньше 2 недель, чтобы найти 2016 блоков. Как правило, сложность снижается после падения хешрейта сети.

Если поправочный коэффициент больше 4 (или меньше 1/4), то вместо него используется 4 или 1/4, чтобы изменение не было слишком резким.

В реализации есть ошибка, из-за которой расчет основан на времени поиска последних блоков 2015, а не 2016 года. Для ее исправления потребуется хард-форк, поэтому на данный момент это отложено.

Можно дать приблизительную оценку следующего изменения сложности, основываясь на времени нахождения последних блоков. Никто не может надежно предсказать долгосрочные трудности в будущем, но любой может строить предположения, основываясь на тенденциях обменного курса, законе Мура и других аппаратных достижениях.

Этот баг еще есть? Разве не должна быть проблема GitHub для этого, чтобы люди могли отслеживать статус... С такими ошибками в протоколе экосистеме Биткойн будет трудно отойти от ситуации, в которой разработчики клиента Satoshi установили все правила.
@StevenRoose: Насколько я знаю, это так, но я оставлю это людям, которые более вовлечены в основной код, чтобы комментировать ... Этого достаточно для отдельного вопроса SE.
Хороший ответ, но ускользает один маленький, но важный момент: как узлы в сети соглашаются, в чем сложность?
@deadalnix: сложность блока — это детерминированный расчет, основанный на данных предыдущих блоков. Все узлы независимо делают один и тот же расчет и получают одинаковый результат.
@MeniRosenfeld спасибо за этот ответ. Но для меня это просто перемещает проблему. Как я понимаю, вы отвечаете, вычисление производится по метке времени, доступной в блоках. Но тогда как сеть p2p согласовывает отметку времени?
@deadalnix: временная метка является частью блока, а это означает, что тот, кто нашел блок, решает, что в него вставить. Временная метка должна быть не раньше медианы последних 11 блоков. Кроме того, если узел получает блок с отметкой времени более чем через 2 часа в будущем, он отклонит его и не будет распространять.
Буду очень признателен за ссылки на спецификации или кодовую базу Биткойн. Настоятельно предпочтительнее пересматривать свой ответ, чем вставлять вещи в комментарии.
@Indolering: Материал в комментариях не является частью основного ответа. Это ответы на конкретные уточняющие вопросы.
@Meni, так что, если я хочу рассчитать завершение раунда, я должен сделать CURRENT_BLOCK_COUNT_IN_THIS_ROUND/2015 вместо CURRENT_BLOCK_COUNT_IN_THIS_ROUND/2016 ???
@mixdev: «Раунд» (перенацеливание на сложность) выполняется каждые 2016 блоков. Но в настоящее время пересчет выполняется не в prev_target TIME_FOR_LAST_2016_Blocks/1209600, а в prev_target TIME_FOR_LAST_2015_Blocks/1209600.
Таким образом, это в основном означает, что ошибки будут складываться каждый раз, когда рассматривается только время последней эпохи? Это означало бы, что заявление о том, что последний биткойн будет добыт в 2140 году, неверно, поскольку это может произойти за годы или даже десятилетия до этого.
@tobi: ошибка «отклонение на один» приводит к тому, что блоки обнаруживаются в среднем на 0,05% медленнее, чем «официальный» 2016 год за две недели. Есть отдельная проблема, которая вызывает еще одно замедление на 0,05%. Вместе они составляют всего 1 месяц замедления за столетие. Однако есть отдельный эффект, который заставляет блоки находить быстрее за счет увеличения хешрейта. Это более важно, и из-за этого последняя монета будет добыта, вероятно, на 1-2 года раньше срока.
@tobi: общее ускорение из-за увеличения хешрейта можно рассчитать примерно как log (сложность) * 2 недели. Это основная причина, по которой вечеринки по халвингу блоков каждый раз проводятся в разные даты — ноябрь 2012 года, июль 2016 года и т. д.
да, я имел в виду ускорение из-за увеличения хешрейта, а не ошибку блоков 2015 года
@tobi: О, хорошо. Предыдущие комментарии были об ошибке, а «ошибки» намекали на то, что это ошибка, поэтому я предположил, что мы говорим об этом. Так да. Если мы предположим, что к 2140 году хешрейт будет около *1 млрд, как сейчас, график будет опережать на 96 недель, или почти на два года. Но есть еще один эффект — задержка, вызванная тем, что в начале сложность была 1, хотя хэшрейта было недостаточно, чтобы ее оправдать.

Мени ответ хороший. Я просто хочу дать несколько практических подробных методов расчета сложности, которые, возможно, будут полезны для будущих взглядов на ответ на этот вопрос.

Давайте взглянем на заголовок генезисного блока Сатоши (часть связанной информации):

$ bitcoin-cli getblockhash 0
000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f

$ bitcoin-cli getblockheader 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
{
  ...
  "height": 0,
  ...
  "bits": "1d00ffff",
  "difficulty": 1,
  ...
}

Как мы видим выше, блок генезиса имеет сложность «1» и биты «1d00ffff». Биткойн - биты означают «целевое» хеш-значение, новый сгенерированный блок должен соответствовать условию: двойное хеш-значение SHA-256 заголовка блока должно быть меньше этого «целевого» значения.

Значение битов «1d00ffff» в блоке генезиса означает «целевое» значение:

[0x00000000,0xffff,{0x00..0x00}]
                   {0x00..0x00} at above has 26 bytes 0x00.

Затем, чтобы найти новый блок, вы должны искать это 32-битное значение nNonce (а также nTimes и hashMerkleRoot) до тех пор, пока хеш-значение блока не будет начинаться с 4 байтов, равных нулю. Кстати, nNonce — это одно из полей в структуре заголовка блока:

 struct header_structure{            // BYTES   NAME
     uint32_t nVersion;              // 4       version
     uint8_t hashPrevBlock[32];      // 32      previous block header hash
     uint8_t hashMerkleRoot[32];     // 32      merkle root hash
     uint32_t nTime;                 // 4       time
     uint32_t nBits;                 // 4       target
     uint32_t nNonce;                // 4       nonce
 };

Поскольку алгоритм SHA-256 (как и любой криптографически безопасный хеш-алгоритм) выдает результат, который будет выглядеть как равномерно случайная последовательность , практический метод «проб и ошибок» — единственный способ найти новый блок, отвечающий условию. Вероятность найти блок с нулевым начальным хеш-значением из 4 байтов равна 1/(2^32), что означает, что среднее количество проб и ошибок равно 2^32 (т.е. 4G).

Чтобы человеку было легче понять это «целевое» хеш-значение, мы определяем термин «сложность», который означает среднее количество проб и ошибок, чтобы найти блок, соответствующий «целевому» условию. И мы определяем единицу «сложности». : 1 "сложность" = хэши 4G

Затем, до сегодняшнего дня, высота блокчейна биткойнов достигает 501509, давайте взглянем на его заголовок:

$ bitcoin-cli getblockheader 0000000000000000006c5532f4fd9ee03e07f94df165c556b89c495e97680147
{
  ...
  "height": 501509,
  ...
  "bits": "18009645",
  "difficulty": 1873105475221.611,
  ...
}

Биты блока 501509 = 0x18009645, это компактный формат 256-битного целого числа, его 256-битный формат:

[0x00000000,0x00000000,0x009645,{0x00..0x00}]
                                {0x00..0x00} at above has 21 bytes 0x00.
that is  0x009645 * (256 ^ 21) 
The genesis block's target is  ( 0x00ffff * 256 ^ 26 )which is the difficulty unit '1.0'.
So, the difficulty 
= (0x00ffff * 256 ^ 26)/ (0x009645 * 256 ^ 21)
= 65535/38469 * (256^5)
= 1.703579505575918 * 2^40
= 1873105475221.611

Пока у вас есть все подробности о том, как рассчитать «сложность». В некоторых случаях мы также используем простой формат 1.7T , чтобы указать сложность, в приведенном выше примере:

 (1.703579505575918 * 2^40) = 1.703579505575918T
 1T = 2^40 = 1024^4
1d — это 29 декабря (не 26). ШС это ША
спасибо @BorisIvanov, опечатка SHSисправлена. Но 1dна самом деле это означает 26 байтов с нулевым хвостом вместо 29, пожалуйста, прочитайте детали примера, показанные выше.
о да. значимость

Я хотел бы дать здесь свои 2 цента, указав взаимосвязь между вероятностью майнинга блока с учетом текущей цели tи соответствующей сложностью d, которая рассчитывается в ядре биткойнов.

Таким образом, криптографические хеш-функции идеализируются абстракцией случайного оракула [ https://en.wikipedia.org/wiki/Random_oracle] . Таким образом, мы можем смоделировать выходные doubleSHA256данные хеш-функции, используемой в PoW, как универсальную переменную в пространстве {0,1}^256, то есть массивы из 256 бит. Таким образом, вероятность того, что единственный хэш hявляется действительным хешем, равна:

p = P(h < t) = t /( 2^{256} - 1 )

С другой стороны d, вычисляется следующим образом, как объяснял @gary ранее, только преобразуется в десятичные числа:

d = ( (2^{16} - 1) * 2^{8*26} ) / t = ( (2^{16} -1) * 2^{208} ) / t

Реализация находится в [ https://github.com/bitcoin/bitcoin/blob/master/src/rpc/blockchain.cpp] , строка 60, функция GetDifficulty. На самом деле, если бы кто-то мог объяснить, как именно код соответствует приведенной выше формуле, это было бы полезно. Комбинируя эти две формулы, мы получаем:

d = ( (2^{16} -1) * 2^{208} ) / ( p * (2^{256} - 1) ) ~ 2^{-32} / p

При анализе этого последнего выражения трудность представляет собой отношение между вероятностью получения хэш-значения ниже 2^{224}(это наименьшее десятичное число, имеющее двоичное представление с использованием 256 битов, начиная с 32 нулевых битов) и вероятностью получения действительного хэш-значения на основе текущая цель t. Это прямое следствие определения в блоке генезиса сложности 1 , связанной с шестнадцатеричной целью 0x1d00ffff , выраженной в том, что я думаю называется 32-битной компактной формой для 256-битных чисел.

Хороший вопрос, на мой взгляд, заключается в том, почему именно эта компактная форма была выбрана для представления цели.

Проголосовал! Компактная форма предоставляет 3 старших байта для цели, в минимальной сложности 3 старших байта — 00ffff.