Inversión de bit de encabezado de bloque de minería

Mientras trato de comprender el proceso de minería y verifico en python ... estoy desconcertado con qué información desde / hacia el grupo está en Little Endian, cuál necesita revertirse en la construcción del encabezado del bloque + hashing y cuál no. ??

Por ejemplo... Comencemos conectándonos a solo.ckpool.org la respuesta a mining.authorize me da... job_id,prevhash,coinb1,coinb2,merkle_branch,version,nbits,ntime,clean_jobs =

{'id': None, 'method': 'mining.notify', 'params': ['59bc8dfc0000029f',
        '0eba48f47bc0ab4bb35b230849868bf1d79aeb19006eed460000000000000000',
        '01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff35039a6807000404d5bc5904fc873d140c',
        '0a636b706f6f6c112f736f6c6f2e636b706f6f6c2e6f72672fffffffff03c4626c4e000000001976a914fc6123f4bfd3a840b4387ab90e9801e98fb17cf888acb1caca00000000001976a914f4cbe6c6bb3a8535c963169c22963d3a20e7686988ac0000000000000000266a24aa21a9edab3b87f3963e55a23f3cea5e4435bf6637328fd5e329bb8fdac7d31c3a01d26200000000',
        ['c251d18568d2cdb07c376d5f3304a2161e3d09d289d1a7e53737199171d73ae6',
         '4f9bcac3ec00fc8238db04b7758a1b673bdf38b93e48159678b60b51517dd563',
         '2aadad2c9c8e6df5c71264524b090cdf89830f12949527f7872c243bc1dc552c',
         '8c5edf39c0d85c9853308eef3ce6f9b71c8d6584ca4120d411bc75987bb2f254',
         '48751c2ae0ddc05f5d504a3d6039e7d5afb3d5f2a6aaac93bd5822e5f8efc328',
         '3e9b5c6b986c2ddc09bf8604eb2bd2a3b49b46f11042c282331a206dadb4296e',
         'c65f502b11b325abc0fac847e8fc5cd300169160e7244b29dd5acc3d0e4b8605',
         'afe7d2287020c4291f609a772adbeafc952a8de0ced38a7346acb6c7103bec6d',
         '0caa545ae63de39d47baea100ea15a18061235d7e1a372fbca88edf9ca5ac797',
         'c5bfff15b4dd64e7faac98f1bba118fb11990e4ff146cb45c7f4af6b93e2ea03',
         'a8805201e8152c1f5835c9aa024752fb34aeb7fa55dd3af0ae6109918f328dbb'],
        '20000000',
        '1801310b',
        '59bcd504',
        True]}

Basado en la respuesta del grupo... Puedo construir la base de monedas con solo

coinbase = coinb1 + extranonce1 + extranonce2 + coinb2 
coinbase_hash_bin = hashlib.sha256(hashlib.sha256(binascii.unhexlify(coinbase)).digest()).digest()

y lo mismo para incluir en merkle tree con hashing para obtener merkle_root. No estoy seguro si necesito invertir los bits aquí.

Pero para construir un encabezado de bloque ... ¿debería hacer esto?

header = version + prevhash + merkle_root + ntime + nbits + nonce

o esto..

header = binascii.hexlify(binascii.unhexlify(version)[::-1]).decode('utf-8') + \
prevhash + \
merkle_root + \
binascii.hexlify(binascii.unhexlify(ntime)[::-1]).decode('utf-8') + \
binascii.hexlify(binascii.unhexlify(nbits)[::-1]).decode('utf-8') + \
binascii.hexlify(binascii.unhexlify(nonce)[::-1]).decode('utf-8')

encabezado de bloque: 000000200eba48f47bc0ab4bb35b230849868bf1d79aeb19006eed460000000000000000fb68998fe1dd4cc22fa1225c2592c27df5331d40d9b33ffce99b26c0baead50bc1ef4ef1ef408

¿Puede alguien publicar un ejemplo de un ENCABEZADO DE BLOQUE reciente? ¡Creo que estoy haciendo algo mal!

Estoy comparando este hash

hash = hashlib.sha256(hashlib.sha256(binascii.unhexlify(header)).digest()).digest()[::-1]

con el objetivo "000000000001310b0000000000000000000000000000000000000000000000000"

Respuestas (2)

Echemos un vistazo a este bloque, porque solo tiene una transacción (la base de monedas): 000000000000000000eb2d0ed97a7b2cff7f1408417dca83908004beb6fd9b95

Tomemos los datos hexadecimales sin procesar:

0000002053f7ebc735f54ac8d4ebcc1eeb3d3bdea89603bdd27431000000000000000000ff964ec70ea5a5356a04fdb044ca6c59ffda2dd6be02c63d9ea58fb6d46e01991a22bb590b310118f6df26f801010000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff3103b46707244d696e656420627920416e74506f6f6c6b2f4542312f4144362f4e59412f332059bb221ab8080000615c0300ffffffff02807c814a000000001976a914660371326d3a2e064c278b20107a65dad847e8a988ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000

Hay 6 cosas que componen el encabezado del bloque:

  1. Primero tenemos la versión (4 bytes) 00000020, que son bytes invertidos de 0x20000000.
  2. Luego tenemos el hash del bloque anterior (32 bytes), también en orden inverso de bytes, 53f7ebc735f54ac8d4ebcc1eeb3d3bdea89603bdd27431000000000000000000que es este bloque .
  3. A continuación tenemos la raíz Merkle de las transacciones (32 bytes), en orden de bytes inverso, ff964ec70ea5a5356a04fdb044ca6c59ffda2dd6be02c63d9ea58fb6d46e0199. Debido a que solo hay una transacción, la transacción coinbase, la raíz de merkle es igual a esa transacción txid.
  4. Luego tenemos la marca de tiempo (4 bytes), en orden de bytes inverso, 1a22bb59que es 0x59bb221ahexadecimal o 1505436186decimal.
  5. Luego tenemos los bytes invertidos del campo 'bits' (4 bytes), 0b310118que es0x1801310b
  6. Y luego el nonce (4 bytes), f6df26f8que es0xf826dff6

Luego, después del encabezado, tenemos el byte 01que significa que hay una transacción, que sigue. Esa única transacción es solo la transacción de base de monedas codificada, como puede ver aquí .

Por supuesto, solo se debe codificar el encabezado del bloque, no las transacciones también.

¡Esto es impresionante! Gracias... Todo está muy claro ahora... excepto la raíz de merkle. binascii.hexlify(hashlib.sha256(hashlib.sha256(binascii.unhexlify('0100000000010100000000..........4e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000')).digest()).digest()) This gives me "cb7ac0ad06517d90cd5a936aebb8b32205fefec268ac6970c04b528313f3ce26" and not "99016ed4b68fa59e3dc602bed62ddaff596cca44b0fd046a35a5a50ec74e96ff"
Esa es una transacción testigo, por lo que debe modificarla un poco antes de codificarla para encontrar el txid (actualmente encontró el wtxid). Pero esa es una pregunta aparte, recuerda aceptar mi respuesta a tu pregunta si te satisface por cierto :)
Sí, tu respuesta es perfecta, lo que estaba buscando.
Entonces, ¿todo en el encabezado enviado del bloque está invertido en bytes del valor real? En otras palabras, si desea conocer la versión del encabezado del bloque, invierta el byte y obtendrá el valor. Este diseño es tan innecesariamente confuso.

La respuesta de MeshCollider es increíble. Quiero agregar una nota. ¿Por qué el hash de encabezado de bloque anterior y el hash de raíz de Merkle necesitan revertir bytes? ¿Y por qué otros campos no lo necesitan?

En realidad, si desea el hash de cualquier transacción, debe duplicar el hash sha256. Entonces, el punto es: si algunos datos necesitan un resumen sha256, y los almacenes de resumen en la computadora son little-endian, algunos casos deben transformarse a big int en big-endian, así que invierta los bytes. Y obtienes el hash doble-sha256 en bitcoin. En algunos casos, el big-endian es necesario. por ejemplo, big-int(block-header-hash) < ¿Objetivo de minería?

Si necesita hash de transacción, el resultado también es big-endian.

Por ejemplo, un hexadecimal de transacción sin procesar es:

0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000

entonces, necesita hash de transacción:

>>> import hashlib
>>> d = '0100000001c997a5e56e104102fa209c6a852dd90660a20b2d9c352423edce25857fcd3704000000004847304402204e45e16932b8af514961a1d3a1a25fdf3f4f7732e9d624c6c61548ab5fb8cd410220181522ec8eca07de4860a4acdd12909d831cc56cbbac4622082221a8768d1d0901ffffffff0200ca9a3b00000000434104ae1a62fe09c5f51b13905f07f06b99a2f7159b2225f374cd378d71302fa28414e7aab37397f554a7df5f142c21c1b7303b8a0626f1baded5c72a704f7e6cd84cac00286bee0000000043410411db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b412a3ac00000000'
>>> hashlib.sha256(bytes.fromhex(d)).hexdigest()
'240cf324ec3cf59609733e2a45e1408673306be8dcd4caf3067aa9355a0269e3'
>>> hashlib.sha256(bytes.fromhex('240cf324ec3cf59609733e2a45e1408673306be8dcd4caf3067aa9355a0269e3')).hexdigest()
'169e1e83e930853391bc6f35f605c6754cfead57cf8387639d3b4096c54f18f4'

169e1e83e930853391bc6f35f605c6754cfead57cf8387639d3b4096c54f18f4es hash little-endian, en bitcoin, todo el hash doble-sha256 es big-endian.

De hecho, el identificador de esta transacción es hash big-endian: f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16.

Cuando necesite encontrar información sobre esta transacción, debe ingresar el hash big-endian: https://www.blockchain.com/btc/tx/f4184fc596403b9d638783cf57adfe4c75c605f6356fbc91338530e9831e9e16

y hash little-endian no puedes encontrar nada.

¿Lo obtuviste?

  • El hash del encabezado del bloque anterior necesita revertir los bytes, porque Bitcoin necesita big-endian.
  • El hash del encabezado del bloque actual necesita revertir los bytes, porque Bitcoin necesita big-endian.
  • el hash de transacción necesita invertir bytes, porque bitcoin necesita big-endian.
  • Merkle root hash necesita invertir bytes, porque bitcoin necesita big-endian.

¡DIOS MÍO! ¿por qué? Descubrí que el desarrollador del núcleo de bitcoin no sabía el motivo.

Debido a un accidente histórico, los hashes de tx y de bloque que utiliza el núcleo de bitcoin se invierten en bytes. No estoy completamente seguro de por qué. Puede ser algo así como usar openssl bignum para almacenar hashes o algo así, y luego imprimirlos como un número.

referencia: http://learnmeabitcoin.com/glossary/txid

No habría necesidad de verificar endianes grandes/pequeños y hacer una inversión de bytes si todos los datos se almacenaran como bytes en lugar de algunos como uint32. Por ejemplo, getblocktemplate proporciona el campo de bits como una cadena hexadecimal; podrían haber hecho lo mismo para la versión, curtime/ntime. Este diseño carece de simplicidad y está retorcido innecesariamente. Es estúpido. No puedo creer que Bitcoin valga algo.