¿Cómo puedo verificar que mi función raíz de Merkle es correcta?

Empecé a jugar con Bitcoin en un nivel más técnico recientemente (soy un desarrollador de software experimentado, pero hasta ahora solo soy un usuario de Bitcoin). Estoy tratando de implementar una función para calcular una raíz Merkle, como se describe en la documentación del protocolo aquí . Creo que he implementado una función como se describe, pero no estoy muy seguro de cómo verificar lo que he hecho. Idealmente, me gustaría escribir algunas pruebas unitarias, pero necesito algunos valores de entrada y una salida esperada.

¿Alguien sabe dónde podría encontrar un conjunto de hash de transacciones, junto con la raíz merkle correcta que debería generarse desde allí? Realmente estoy buscando entradas y salidas de ejemplo que pueda usar para verificar la corrección de mi función.

Intenté copiar y pegar los hashes de transacción del bloque Bitcoin 96001 , pero la raíz de Merkle que estoy calculando no coincide con lo que se muestra en blockchain.info. Lo extraño es que, cuando introduzco los mismos hashes de transacción en la función de raíz de merkle en BitcoinJS-lib , produce la misma raíz de merkle que mi función. ¿Mi función y BitcoinJS-lib son incorrectas? ¿Esta mal blockchain.info? ¿O es que pasa algo más aquí?

var sha256 = (buffer) => {
  return crypto.createHash('sha256')
    .update(buffer)
    .digest()
}

var doubleSha256 = (buffer) => sha256(sha256(buffer))

var merkleRoot = (hashes) => {
  if (hashes.length == 1)
    return hashes[0]

  return merkleRoot(
    _.chain(hashes)
      .chunk(2)
      .each(tuple => tuple[1] = tuple[1] || tuple[0])
      .map(tuple => Buffer.concat(tuple))
      .map(doubleSha256)
      .value()
  )
}

// Transaction hashes from block 96001:
var tx1 = Buffer.from('dcc95c8740525e27d87333558e5d0a288d0eac9062598c86c77e75dcde7178d2', 'hex')
var tx2 = Buffer.from('043cd1d9166cf16a4cc02d4385667657056cbe23f7058877c7fde09ef7de904a', 'hex')
var tx3 = Buffer.from('88b058d7e3e7b6d174d0f5a76a209a3107de65c01b010cda72ee64b22c980998', 'hex')

console.log(merkleRoot([tx1, tx2, tx3].sort()).toString('hex'));

// expected 'e7ae478c684e965d730e72b9cac644fd1ebeb1517fe69cc458d9d4070b9de8d8'
// output   'b2f52e4efbbab7653489b83d5ad331f1ada1b7e5959ac63b8aa45a786ae90279'

Respuestas (1)

Lo más probable es que tenga algunos problemas de endianidad. Recuerde que la raíz de merkle publicada está en little-endian y también lo están los hashes de transacción. Tendrás que invertirlos y luego calcular los cálculos de Merkle.

Puede echar un vistazo a los detalles de un bloque con los hash tx aquí:

https://webbtc.com/block/000000000000000000375c25e5af8f3b2310585ad6a7c264d66398018ce4c6a41.json

Hay una clave muy útil en esa carga útil json llamada "mrkl_tree" que le indica todos los nodos del árbol merkle (por lo que el padre de dos nodos de hoja adyacentes está en ese conjunto). Probablemente sea más fácil construir pruebas alrededor de eso.