Quería ayudar a la comunidad y crear una aplicación C pura independiente del cliente de referencia, que, dada una marca de tiempo y una clave pública, produzca una raíz Merkle para la creación de un bloque de génesis.
Mi conocimiento de C++ es muy poco o nada. Después de mirar el código fuente, este es el código relevante
const char* pszTimestamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks";
CTransaction txNew;
txNew.vin.resize(1);
txNew.vout.resize(1);
txNew.vin[0].scriptSig = CScript() << 486604799 << CBigNum(4) << vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
txNew.vout[0].nValue = 50 * COIN;
txNew.vout[0].scriptPubKey = CScript() << ParseHex("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f") << OP_CHECKSIG;
Que produce este merkle hash
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
No estoy seguro de si CScript() << 486604799 << CBigNum(4) <<... está cambiando todo esto, o simplemente escribiéndolo en .scriptSig. Y voy a suponer que CScript() es el constructor que inicializa .scriptSig.
Mientras profundizaba en el código fuente y siguiendo las llamadas de BuildMerkleTree, terminé en
template<typename T>
uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
{
CHashWriter ss(nType, nVersion);
ss << obj;
return ss.GetHash();
}
Así que comencé a seguir a ChashWriter y terminé en
template<typename T>
CHashWriter& operator<<(const T& obj) {
// Serialize to this stream
::Serialize(*this, obj, nType, nVersion);
return (*this);
}
Y me perdí allí. Pero lo más cerca que estuve fue duplicar SHA256 en esto
04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73 5000000000 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG after supposedly converting to a byte array.
Y obviamente me equivoqué al respecto, ya que el resultado no fue correcto.
Aparentemente, Bitcoin usa algo conocido como Serialización para serializar las variables del objeto, tal vez concatenarlas, pero desafortunadamente debido a mi inexperiencia con C++ no pude entender qué variables, en qué orden, etc. Básicamente, el código fuente de Bitcoin era más complejo de lo que había imaginado.
Entonces, mi pregunta es cómo puedo producir un hash Merkle para un bloque de génesis, sin usar serialización y en C.
En lugar de mirar el código fuente, eche un vistazo a la página wiki correspondiente .
Como revelará blockexplorer , la raíz merkle del bloque de génesis es igual al hash de la transacción en él . Esto se debe a que construir un árbol hash de una transacción simplemente dará como resultado esa transacción, y el hash de ese árbol será el mismo que el hash de esa transacción.
Cuando se trate de más transacciones, simplemente colóquelas en un árbol y córtelas de abajo hacia arriba, como se menciona en la página wiki.
granja
Tom van der Woerdt
granja
Tom van der Woerdt
granja
Tom van der Woerdt
tx
comando. Eltx
comando se describe aquí . Allí se incluye una transacción de ejemplo.