Ich wollte der Community helfen und eine reine C-Anwendung unabhängig vom Referenzclient erstellen, die mit einem Zeitstempel und einem öffentlichen Schlüssel eine Merkle-Root für die Erstellung eines Genesis-Blocks erzeugt.
Meine Kenntnisse in C++ sind sehr gering bis gar nicht vorhanden. Nach dem Betrachten des Quellcodes ist dies der relevante Code
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;
Was diesen Merkle-Hash produziert
4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b
Ich bin mir nicht sicher, ob CScript() << 486604799 << CBigNum(4) <<... all dies bitshifting oder es einfach in .scriptSig schreibt. Und ich gehe davon aus, dass CScript() der Konstruktor ist, der .scriptSig initialisiert.
Als ich mich in den Quellcode vertiefte und den Aufrufen von BuildMerkleTree folgte, landete ich darin
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();
}
Also fing ich an, ChashWriter zu folgen, und landete bei
template<typename T>
CHashWriter& operator<<(const T& obj) {
// Serialize to this stream
::Serialize(*this, obj, nType, nVersion);
return (*this);
}
Und ich habe mich dort verlaufen. Aber das, was mir am nächsten kam, war doppeltes SHA256-ing
04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73 5000000000 04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f OP_CHECKSIG after supposedly converting to a byte array.
Und ich habe mich offensichtlich geirrt, da das Ergebnis nicht korrekt war.
Anscheinend verwendet Bitcoin etwas, das als Serialisierung bekannt ist, um die Variablen des Objekts zu serialisieren, vielleicht zu verketten, aber leider konnte ich aufgrund meiner Unerfahrenheit mit C++ nicht verstehen, welche Variablen in welcher Reihenfolge und so weiter. Im Grunde war der Bitcoin-Quellcode komplexer, als ich es mir vorgestellt hatte.
Meine Frage ist also, wie ich einen Merkle-Hash für einen Genesis-Block erzeugen kann, ohne Serialisierung und in C zu verwenden?
Anstatt den Quellcode zu betrachten, werfen Sie einen Blick auf die entsprechende Wiki-Seite .
Wie der Blockexplorer zeigen wird, ist die Merkle-Wurzel des Genesis-Blocks gleich dem Hash der darin enthaltenen Transaktion . Dies liegt daran, dass das Erstellen eines Hash-Baums einer Transaktion einfach zu dieser einen Transaktion führt und der Hash dieses Baums derselbe ist wie der Hash dieser einen Transaktion.
Wenn Sie sich mit mehr Transaktionen befassen, legen Sie sie einfach in einen Baum und hashen Sie sie von unten nach oben, wie auf der Wiki-Seite erwähnt.
farmdve
Tom van der Woerdt
farmdve
Tom van der Woerdt
farmdve
Tom van der Woerdt
tx
Befehl gesendet wird. Dertx
Befehl ist hier beschrieben . Dort ist eine Beispieltransaktion enthalten.