Verificando la raíz de Merkle para el bloque #100000

El siguiente texto se copia de la Referencia de desarrollador de Bitcoin en bitcoin.org:

Si un bloque tiene tres o más transacciones, se forman filas intermedias de árboles Merkle. Los TXID se colocan en orden y se emparejan, comenzando con el TXID de la transacción de coinbase. Cada par se concatena como 64 bytes sin procesar y SHA256 (SHA256()) se codifica para formar una segunda fila de hash. Si hay un número impar (no par) de TXID, el último TXID se concatena con una copia de sí mismo y se codifica. Si hay más de dos hashes en la segunda fila, el proceso se repite para crear una tercera fila (y, si es necesario, se repite para crear filas adicionales). Una vez que se obtiene una fila con solo dos hashes, esos hashes se concatenan y se procesan para producir la raíz merkle.

Estoy tratando de usar esta lógica para recrear la raíz de merkle para el bloque #100000. Hay 4 transacciones en este bloque. Comienzo copiando el hash de la transacción para la transacción coinbase y la siguiente en una calculadora Sha256 para obtener el hash. Luego hago el hash una vez más: Sha256(sha256()). Repito ese procedimiento una vez más con las segundas dos transacciones en el bloque. Finalmente, vuelvo a repetir el procedimiento usando los hashes resultantes para obtener el Merkle Root. Desafortunadamente, esto no se relaciona con Merkle Root que se muestra en el encabezado del bloque en blockchain.info.

¿Alguien puede explicar dónde me equivoqué?

Gracias.

¿Quizás incluya los hashes intermedios que está obteniendo? Eso puede darle a la gente una pista de dónde se equivocó.
Sospecho que está codificando el ID de la transacción como una cadena en lugar de como bytes
Sí, @MeshCollider tienes razón. ¿Hay alguna manera de convertir fácilmente a bytes?
Dudo que haya sitios web que tomen bytes de entrada a sha256, el mejor enfoque es usar python u otro idioma y convertir la cadena a bytes antes de ingresar a sha256

Respuestas (2)

Debe intercambiar bytes en los ID de transacción antes de aplicarles hash, aplicar hash a cada nodo secundario e intercambiar bytes al valor hexadecimal hash final.

Transacción 1 (Transacción Coibase) 8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87

Para Byteswap puedes usar:

a = "8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87" "".join(reversed([a[i:i+2] for i in range(0, len(a), 2)])) @Greg Hewgill

Bytes intercambiados = 876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148c

Transacción 2 fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4 Bytes intercambiados = c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d40318295bff

Desea concatenar los valores de transacción de intercambio de bytes de 1 y 2. La transacción 1 va primero.

876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148cc40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff

Para codificar esta cadena hexadecimal, puede usar el siguiente código ejecutando Python en su terminal de comando:

importar hashlib

transacción12_hex = "876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148cc40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff"

transacción12_bin = transacción12_hex.decode('hex')

hash = hashlib.sha256(hashlib.sha256(transacción12_bin).digest()).digest()

hash.encode('hex_codec')

15b88c5107195bf09eb9da89b83d95b3d070079a3c5c5d3d17d0dcd873fbdacc

Transacción 3 6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4 Bytes intercambiados = c46e239ab7d28e2c019b6d66ad8fae98a56ef1f21aeecb94d1b1718186f05963

Transacción 4 e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d Bytes intercambiados = 1d0cb83721529a062d9675b98d6e5c587e4a770fc84ed00abc6a5a6e049

Si hace lo mismo para las transacciones 3 y 4, el hash final es: 49aef42d78e3e9999c9e6ec9e1dddd6cb880bf3b076a03be1318ca789089308e

Nuestro último paso es combinar el valor hash final de 1 y 2 y 3 y 4 y duplicarlo e intercambiar bytes.

Nuestra respuesta es f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766 la raíz de Merkle.

No llega mi respuesta. Convertí esto 876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148cc40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ffa binario y le hice doble hash usando passwordsgenerator.net/sha256-hash-generator
Desafortunadamente, el uso de un generador SHA en línea no parece funcionar para el hash doble y estoy tratando de averiguar por qué. Te mantendré informado. Creo que tiene que ver con cómo codifica y decodifica los datos.
porque tal vez no lo hagan por bytes, 87, es un byte, y sha 256 por bytes de entrada, pero podrían convertir 8 en un byte (ya que es un carácter) y así sucesivamente.
Eso muy bien podría ser: acabo de preguntar y lancé la pregunta a las masas y estoy esperando una respuesta.... bitcoin.stackexchange.com/questions/77208/…
@ Suraj Jain bitcoin.stackexchange.com/questions/5671/… ... si va a usar un generador en línea, use anyhash.com/sha256?hello ... y marque la casilla hexadecimal. No entendí completamente la respuesta más formal.

Creo que los errores son la construcción correcta del hash y tuve el mismo problema, ahora quiero compartir mi experiencia.

Para compilar el hash he usado esta buena biblioteca c++/java .

Intentaré explicarme con un código simple.

Este es el hash de la transacción del bloque génesis.

string versionRawTransaction = "01000000";
string numbarTransactionInput = "01";
string output = "0000000000000000000000000000000000000000000000000000000000000000ffffffff";
string scriptLenght = "4d";
string scriptSing = "04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73";
string sequences = "ffffffff";
string numbarTransactionOutput = "01";
string cAmmount = "00f2052a01000000";
string publicKeyScriptLenght = "43";
string publicKeyScript = "4104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac";
string lockTime = "00000000";

El hash completo es01000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000

Cuando calculas el hash. ¿Puedo obtener este hash?4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b

hasta aqui todo es sencillo

El valor bitcoin se convierte a la convención big endian, pero cuando se calcula el hash, el tipo único se convierte a little endian.

¿Cuál es la transacción de forma real? ¿Puedo ejecutar este pasaje?

  1. convertir el valor de big-endian a little-endian
  2. Convierte el valor en hexadecimal
  3. unir todas las propiedades en forma hexadecimal en el orden correcto
  4. Convierta a la forma binaria la cadena grande
  5. Aplicar el sha256
  6. convertir el resultado a big-endian

Usé el C++ y esta operación lograron hacerlo gracias a las bibliotecas de bitcoin, pero si usaste python, puedes usar este ejemplo para calcular el hash.

para construir el árbol, los pasos son simples, solo asegúrese de calcular el hash correctamente, por lo que le sugiero que pruebe primero las funciones hash y luego la construcción del árbol, para evitar pérdidas de tiempo innecesarias en errores triviales

pd: si tiene el script de transacción en formato sin procesar (si lee la información de los archivos blk), ya están convertidos a little-endian y, por lo tanto, no deben convertirse más. (depende de su proceso de deserialización)