¿Por qué invertimos el hash del blockheader?

Elijamos este ejemplo de hash de encabezado de bloque en Python:

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

Sé que es parte del protocolo y de lo contrario, no se aceptará un bloque, pero:

  1. ¿Por qué no aceptamos un hash que termine con todos esos ceros? ¿Es porque es más fácil de calcular para un programa if hash < expected_hash?
  2. Pero en este caso, no entiendo por qué no aceptamos simplemente un hash sha256(sha256(header).digest()).digest().encode('hex')que es más bajo que el hash esperado. La probabilidad de obtener eso debería ser tan alta como la inversa.

Entonces, ¿cuál es la razón de invertirlo?

Respuestas (1)

  1. ¿Por qué no aceptamos un hash que termine con todos esos ceros? ¿Es porque es más fácil de calcular para un programa if hash < expected_hash?

Contar el número de ceros al principio o al final no da mucha granularidad. Si se representa como un número hexadecimal, solo hay 64 valores objetivo posibles si cuenta solo la cantidad de ceros. Si es binario, son 256 valores posibles. Además, contar el número de ceros significa que solo puedes cambiar la dificultad por alguna potencia de 2 (en binario, la dificultad debe duplicarse o reducirse a la mitad). Por lo tanto, no hay muchos valores para el objetivo y esta pérdida de granularidad es mala.

Por el contrario, comparar el valor significa que hay (en teoría) 2^256 valores posibles para la dificultad. Esto es mucho más granular, y estos valores son números enteros. En lugar de tener que cambiar la dificultad multiplicando, la dificultad se puede cambiar sumando y restando. Al tener más valores, será menos probable que la dificultad sea demasiado difícil o demasiado fácil.

  1. Pero en este caso, no entiendo por qué no aceptamos simplemente un hash sha256(sha256(header).digest()).digest().encode('hex')que es más bajo que el hash esperado. La probabilidad de obtener eso debería ser tan alta como la inversa.

En realidad es como dijiste. La inversión del hash es solo por cómo se representan realmente los bytes. Se almacenan como bytes y se interpretan como un entero little endian de 256 bits. La comparación sigue siendo una comparación de enteros y la representación de datos es irrelevante (podrían almacenarse y representarse fácilmente como enteros big endian). Pero cuando se muestran, se muestran como valores big endian en hexadecimal porque los humanos están acostumbrados al big endian. El motivo de little endian es probablemente porque la arquitectura x86 usa little endian para almacenar números enteros.