¿Cómo realiza un minero el hashing?

Estoy tratando de seguir mi camino a través del proceso por el cual un minero hace hash.

Digamos que la getworksolicitud devuelve un datacampo de:

0000000244de6ceba49e1c8d438c0d8c584eefd9c8590545bfdfbf380000025c00000000fb3a091de1b4bbe5dc7acfe6bdacbc3fc3bb09bf1030adef8e2854db1b6ac42f5075c0051a057e08456c6f69000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000

Según tengo entendido, el primer paso es calcular el estado medio. Para hacer esto, primero tomamos la primera mitad de la cadena de datos:

0000000244de6ceba49e1c8d438c0d8c584eefd9c8590545bfdfbf380000025c00000000fb3a091de1b4bbe5dc7acfe6bdacbc3fc3bb09bf1030adef8e2854db

Luego invertimos el endian de cada int sin signo de 32 bits (representado como 8 dígitos hexadecimales en la cadena), lo que produce:

02000000eb6cde448d1c9ea48c0d8c43d9ef4e58450559c838bfdfbf5c020000000000001d093afbe5bbb4e1e6cf7adc3fbcacbdbf09bbc3efad3010db54288e

A continuación, transformamos esto en dieciséis entradas sin firmar de 32 bits:

33554432, 3949780548, 2367463076, 2349698115, 3656339032, 1157978568, 952098751, 1543634944, 0, 487144187, 3854284001, 3872357084, 1069329597, 3205086147, 4021104656, 3679725710

Luego ingresamos esta matriz int en la función interna de SHA-256, siendo la segunda entrada los ocho números de 32 bits que se proporcionan en la página 13 de las especificaciones de SHA-256 .

La salida de este hash preliminar produce los siguientes ocho bits de 32 bits como nuestro estado medio:

3045448562, 361056177, 1940413978, 3803584651, 1661283772, 3478943551, 2906109005, 300125848

A partir de este momento, no estoy seguro de cuán correctos son los pasos. ¡Se agradecen mucho las correcciones!

A continuación, observamos la segunda mitad de la cadena de entrada:

1b6ac42f5075c0051a057e08456c6f69000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000

Una vez más, invertimos el endianness, ya que todo es una cadena hexadecimal de 8 caracteres que representa entradas sin firmar de 32 bits:

2fc46a1b05c07550087e051a696f6c45800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000280

Ahora, dividimos esto en dieciséis entradas de 32 bits:801401371, 96499024, 142476570, 1768909893, 2147483648, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 640

El quinto número ( 21474836481) debe ser el nonce, según esta descripción .

(¿Por qué este nonce no es cero?)

Ahora, comenzando en el nonce dado, usamos la función SHA-256 para codificar las dieciséis entradas de 32 bits de la segunda mitad de los datos, usando el estado medio como las otras ocho entradas de entrada. Esto produce:3993002029, 2278477219, 3977673643, 191934125, 2075691039, 4115259165, 601235791, 2598049038

Ahora, ¿qué uso como entradas para la segunda función hash en el "doble hash"? ¿O el cálculo del estado medio contó como el primer cálculo de hash?

Y cuando el nonce se desborda, ¿debo enviar otra getworksolicitud o esperar hasta que haya verificado los nonces en el rango de [0, original_nonce_value)? (¿Suponiendo que mi análisis de que el nonce dado 21474836481es correcto?)

Por último, si nuestro targetvalor de la getworksolicitud es:

ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000

Necesitamos cambiar el endianness de este valor, produciendo:

00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff

Y luego convertimos esto en ocho entradas sin firmar de 32 bits, lo que produce:0, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295, 4294967295

Y creo que después del segundo hash SHA-256 deberíamos tener ocho entradas sin firmar de 32 bits. Por último, debemos comparar estas ocho entradas de salida con nuestras ocho entradas objetivo (de izquierda a derecha en la matriz, por lo que comparamos la salida [0] con el 0 del objetivo, luego la salida [1] con 4294967295, etc.) y si nuestra salida es menos que el objetivo, convertimos nuestros ocho valores int en cadenas hexadecimales, cambiamos el endianness, los concatenamos en el mismo orden (la cadena hexadecimal de salida [0] es el primer conjunto de ocho caracteres) y lo enviamos de nuevo al grupo servidor en una getworkfinalización POST.

¿Cuánto de esto es correcto y dónde estoy malinterpretando el protocolo?

Toda ayuda es apreciada; ¡muchas gracias!

¡Gracias por la edición! Me preguntaba cómo hacer ese formateo...
El siguiente hilo parece que podría ser una respuesta más completa: stackoverflow.com/questions/9245235/…

Respuestas (1)

Esta pregunta es complicada, pero veré qué puedo hacer para responderla. Además, no trataré de abordar el tema de la endianidad, ya que en el caso de Bitcoin me da dolor de cabeza...

Primero, veamos qué tenemos en un encabezado de bloque que nos ha dado getwork. Tomemos el Bloque Génesis como ejemplo.

01000000 - version
0000000000000000000000000000000000000000000000000000000000000000 - prev block
3BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A - merkle root
29AB5F49 - timestamp
FFFF001D - bits
00000000 - nonce (it will be set to 1DAC2B7C later)
00 - number of transactions (always 0, this is the block header)
0000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000 - padding

Para calcular el estado medio, dividimos el encabezado en dos partes que acepta el algoritmo SHA (64 bytes cada una):

0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA
4B1E5E4A29AB5F49FFFF001D00000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000080020000

Cargamos la primera parte en el algoritmo SHA. Guardamos este estado para su uso posterior (estado medio) (perdón por la falta de ejemplos, pero no tengo mis algoritmos hash a mano). Luego cargamos la segunda parte en el algoritmo SHA. Leemos la salida, este es el primer hash. Tomamos esa salida, la volvemos a conectar a una nueva entrada y obtenemos su resultado. Ese es el segundo hash. Suponiendo que obtuvimos el nonce correcto (en nuestro caso, 1DAC2B7C), nuestro resultado debería verse así:

000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f

y compararlo con nuestro objetivo:

00000000ffff0000000000000000000000000000000000000000000000000000

Tomado como un número, ¿cuál es más grande? El objetivo. Esto significa que tenemos el nonce correcto y podemos enviar nuestro encabezado completo como resultado. ¡Lucro!

Por lo que entiendo, intentaste dividir demasiado los números resultantes, en lugar de operar con números realmente grandes como parece estar haciendo Bitcoin. Por otra parte, endianness también es un gran problema con el protocolo y lo que no...

Espero que esto responda a tu problema.