Почему мы инвертируем хэш блокхедера?

Давайте возьмем этот пример хеширования блок-заголовков в Python:

from hashlib import sha256
import hashlib
header = "0000002066720b99e07d284bd4fe67ff8c49a5db1dd8514fcdab610000000000000000007829844f4c3a41a537b3131ca992643eaa9d093b2383e4cdc060ad7dc548118751eb505ac1910018de19b302".decode('hex')
print sha256(sha256(header).digest()).digest()[::-1].encode('hex')
// result is 00000000000000000020cf2bdc6563fb25c424af588d5fb7223461e72715e4a9

Я знаю, что это часть протокола, иначе блок не будет принят, но:

  1. Почему мы не принимаем хеш, оканчивающийся всеми этими нулями? Это потому, что программе легче вычислить if hash < expected_hash?
  2. Но в этом случае я не понимаю, почему мы просто не принимаем хэш sha256(sha256(header).digest()).digest().encode('hex')меньше ожидаемого? Вероятность получить это должна быть такой же высокой, как и обратная.

Так в чем причина инвертирования?

Ответы (1)

  1. Почему мы не принимаем хеш, оканчивающийся всеми этими нулями? Это потому, что программе легче вычислить if hash < expected_hash?

Подсчет количества начальных или конечных нулей не дает большой детализации. Если представлено в виде шестнадцатеричного числа, то существует только 64 возможных целевых значения, если вы считаете только количество нулей. Если в двоичном формате, это 256 возможных значений. Кроме того, подсчет количества нулей означает, что вы можете изменить сложность только на некоторую степень двойки (в двоичном формате сложность должна быть удвоена или уменьшена вдвое). Таким образом, для цели не так много значений, и эта потеря детализации — это плохо.

И наоборот, сравнение значения означает, что существует (теоретически) 2 ^ 256 возможных значений сложности. Это намного более детализировано, и эти значения являются целыми числами. Вместо того, чтобы изменять сложность путем умножения, сложность можно изменить с помощью сложения и вычитания. Чем больше значений, тем меньше вероятность того, что сложность будет слишком сложной или слишком легкой.

  1. Но в этом случае я не понимаю, почему мы просто не принимаем хэш sha256(sha256(header).digest()).digest().encode('hex')меньше ожидаемого? Вероятность получить это должна быть такой же высокой, как и обратная.

На самом деле все так, как вы сказали. Инверсия хэша предназначена только для того, как на самом деле представлены байты. Они хранятся в виде байтов и интерпретируются как 256-битное целое число с прямым порядком байтов. Сравнение по-прежнему является сравнением целых чисел, и представление данных не имеет значения (они могут быть так же легко сохранены и представлены как целые числа с обратным порядком байтов). Но когда они отображаются, они отображаются как значения с прямым порядком байтов в шестнадцатеричном формате, потому что люди привыкли к прямому порядку байтов. Причина прямого порядка байтов, вероятно, заключается в том, что архитектура x86 использует прямой порядок байтов для хранения целых чисел.