Überprüfung der Merkle-Root für Block #100000

Der folgende Text wurde aus der Bitcoin Developer Reference auf bitcoin.org kopiert:

Wenn ein Block drei oder mehr Transaktionen hat, werden dazwischenliegende Merkle-Tree-Zeilen gebildet. Die TXIDs werden geordnet und gepaart, beginnend mit der TXID der Coinbase-Transaktion. Jedes Paar wird als 64 Rohbytes verkettet und SHA256(SHA256()) gehasht, um eine zweite Reihe von Hashes zu bilden. Wenn es eine ungerade (nicht gerade) Anzahl von TXIDs gibt, wird die letzte TXID mit einer Kopie von sich selbst verkettet und gehasht. Wenn mehr als zwei Hashes in der zweiten Zeile vorhanden sind, wird der Vorgang wiederholt, um eine dritte Zeile zu erstellen (und, falls erforderlich, weiter wiederholt, um zusätzliche Zeilen zu erstellen). Sobald eine Zeile mit nur zwei Hashes erhalten wurde, werden diese Hashes verkettet und gehasht, um die Merkle-Wurzel zu erzeugen.

Ich versuche, diese Logik zu verwenden, um die Merkle-Wurzel für Block # 100000 neu zu erstellen. Es gibt 4 Transaktionen in diesem Block. Ich beginne damit, den Transaktions-Hash für die Coinbase-Transaktion und die folgende nacheinander in einen Sha256-Rechner zu kopieren, um den Hash zu erhalten. Dann hash ich diesen Hash noch einmal: Sha256(sha256()). Ich wiederhole diesen Vorgang noch einmal mit den zweiten beiden Transaktionen im Block. Abschließend wiederhole ich den Vorgang erneut mit den resultierenden Hashes, um die Merkle-Root zu erhalten. Leider knüpft dies nicht an die Merkle Root an, die im Blockheader bei blockchain.info angezeigt wird.

Kann jemand erklären, wo ich falsch gelaufen bin?

Vielen Dank.

Fügen Sie vielleicht die Zwischen-Hashes hinzu, die Sie erhalten? Das kann den Leuten einen Hinweis geben, wo Sie einen Fehler gemacht haben.
Ich vermute, Sie hashen die Transaktions-ID als Zeichenfolge und nicht als Bytes
Ja, @MeshCollider, du hast recht. Gibt es eine Möglichkeit, einfach in Bytes umzuwandeln?
Ich bezweifle, dass es Websites gibt, die Byte-Eingaben für sha256 verwenden. Der beste Ansatz besteht darin, Python oder eine andere Sprache zu verwenden und die Zeichenfolge vor der Eingabe in sha256 in Bytes zu konvertieren

Antworten (2)

Sie müssen die Transaktions-IDs byte-tauschen, bevor Sie sie hashen, jeden untergeordneten Knoten hashen und den endgültigen gehashten Hex-Wert byte-tauschen.

Transaktion 1 (Coibase-Transaktion) 8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87

Zum Byteswap können Sie Folgendes verwenden:

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

Vertauschte Bytes = 876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148c

Transaktion 2 fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4 Bytetausch = c40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b5231895b52292d02d4031895b52292d02d4031895b52d

Sie möchten die Byte-ausgetauschten Transaktionswerte von 1 und 2 verketten. Transaktion 1 geht zuerst.

876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148cc40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff

Um diese Hex-Zeichenfolge zu hashen, können Sie den folgenden Code verwenden, der Python in Ihrem Befehlsterminal ausführt:

Hashlib importieren

transaction12_hex = "876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148cc40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff"

transaktion12_bin = transaktion12_hex.decode('hex')

hash = hashlib.sha256(hashlib.sha256(transaction12_bin).digest()).digest()

hash.encode('hex_codec')

15b88c5107195bf09eb9da89b83d95b3d070079a3c5c5d3d17d0dcd873fbdacc

Transaktion 3 6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4 Byteswapped = c46e239ab7d28e2c019b6d66ad8fae98a56ef1f21aeecb94d1b1718186f05963

Transaktion 4 e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d Byteswapped = 1d0cb83721529a062d9675b98d6e5c587e4a770fc84ed00abc5a5de6e0458

Wenn Sie dasselbe für Transaktion 3 und 4 tun, lautet der endgültige Hash: 49aef42d78e3e9999c9e6ec9e1dddd6cb880bf3b076a03be1318ca789089308e

Unser letzter Schritt besteht darin, den endgültigen Hash-Wert von 1 & 2 und 3 & 4 zu kombinieren und ihn doppelt zu hashen und per Byte auszutauschen.

Unsere Antwort ist f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766 die Merkle Root.

Meine Antwort kommt nicht. Ich habe dies in Binär konvertiert und mit passwordsgenerator.net/sha256-hash-generator876dd0a3ef4a2816ffd1c12ab649825a958b0ff3bb3d6f3e1250f13ddbf0148cc40297f730dd7b5a99567eb8d27b78758f607507c52292d02d4031895b52f2ff doppelt gehasht
Leider scheint die Verwendung eines Online-SHA-Generators nicht für doppeltes Hashing zu funktionieren, und ich versuche herauszufinden, warum. Ich werde Sie auf dem Laufenden halten. Ich denke, es hat damit zu tun, wie es Daten kodiert und dekodiert.
weil sie es vielleicht nicht byteweise machen, 87 ist ein Byte und sha 256 geben sie byteweise ein, aber sie könnten 8 in ein Byte umwandeln (da es ein Zeichen ist) und so weiter.
Das könnte sehr gut sein - ich habe gerade die Frage an die Massen gestellt und warte auf eine Antwort .... bitcoin.stackexchange.com/questions/77208/…
@ Suraj Jain bitcoin.stackexchange.com/questions/5671/… ... wenn Sie einen Online-Generator verwenden möchten, verwenden Sie anyhash.com/sha256?hello ... und markieren Sie das Hex-Kästchen. Ich habe die formellere Antwort nicht ganz verstanden.

Ich denke, die Fehler sind das korrekte Erstellen des Hashs, und ich hatte das gleiche Problem, jetzt möchte ich meine Erfahrung teilen.

Zum Erstellen des Hashs habe ich diese gute Bibliothek c++/java verwendet .

Ich werde versuchen, mich mit einfachem Code zu erklären.

Dies ist der Transaktions-Hash des Genesis-Blocks

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";

Der vollständige Hash ist01000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000

Wenn Sie den Hash berechnen. kann ich diesen hash bekommen4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b

bis hierher ist alles einfach

Der Wert Bitcoin wird in die Big-Endian-Konvention konvertiert, aber wenn der Hash berechnet wird, wurde der einzelne Typ in Little Endian konvertiert.

Während der Realform-Transaktion kann ich diese Passage ausführen

  1. Wandeln Sie den Wert von Big-Endian in Little-Endian um
  2. Wandeln Sie den Wert in Hex um
  3. Verbinden Sie alle Propieties Hex-Form in der korrekten Reihenfolge
  4. Wandeln Sie den großen String in die Binärform um
  5. Wenden Sie die sha256 an
  6. Wandeln Sie das Ergebnis in Big-Endian um

Ich habe C++ verwendet und diese Operation haben sie dank der Bitcoin-Bibliotheken geschafft, aber wenn Sie Python verwendet haben, können Sie dieses Beispiel zur Berechnung des Hashs verwenden.

Um den Baum zu erstellen, sind die Schritte einfach, stellen Sie nur sicher, dass Sie den Hash korrekt berechnen, daher schlage ich vor, dass Sie zuerst die Hash-Funktionen und dann die Baumkonstruktion testen, um unnötigen Zeitverlust durch triviale Fehler zu vermeiden

ps: Wenn Sie das Transaktionsskript im Rohformat haben (wenn Sie die Informationen aus den blk-Dateien lesen), sind sie bereits in Little-Endian konvertiert und sollten daher nicht weiter konvertiert werden. (hängt von Ihrem Deserialisierungsprozess ab)