Warum invertieren wir den Hash des Blockheaders?

Nehmen wir dieses Beispiel für Blockheader-Hashing in Python:

from hashlib import sha256
import hashlib
header = "0000002066720b99e07d284bd4fe67ff8c49a5db1dd8514fcdab610000000000000000007829844f4c3a41a537b3131ca992643eaa9d093b2383e4cdc060ad7dc548118751eb505ac1910018de19b302".decode('hex')
print sha256(sha256(header).digest()).digest()[::-1].encode('hex')
// result is 00000000000000000020cf2bdc6563fb25c424af588d5fb7223461e72715e4a9

Ich weiß, dass es Teil des Protokolls ist und ansonsten wird ein Block nicht akzeptiert, aber:

  1. Warum akzeptieren wir keinen Hash, der mit all diesen Nullen endet? Liegt es daran, dass es für ein Programm einfacher zu berechnen ist if hash < expected_hash?
  2. Aber in diesem Fall verstehe ich nicht, warum wir nicht einfach einen Hash akzeptieren sha256(sha256(header).digest()).digest().encode('hex'), der niedriger als der erwartete Hash ist? Die Wahrscheinlichkeit dafür sollte genauso hoch sein wie die umgekehrte.

Was ist also der Grund für die Umkehrung?

Antworten (1)

  1. Warum akzeptieren wir keinen Hash, der mit all diesen Nullen endet? Liegt es daran, dass es für ein Programm einfacher zu berechnen ist if hash < expected_hash?

Das Zählen der Anzahl führender oder nachgestellter Nullen ergibt nicht viel Granularität. Als Hex-Zahl dargestellt, dann gibt es nur 64 mögliche Zielwerte, wenn Sie nur die Anzahl der Nullen zählen. Im Binärformat sind das 256 mögliche Werte. Außerdem bedeutet das Zählen der Nullen, dass Sie die Schwierigkeit nur um eine Potenz von 2 ändern können (in binär muss die Schwierigkeit verdoppelt oder halbiert werden). Es gibt daher nicht viele Werte für das Ziel und dieser Verlust an Granularität ist schlecht.

Umgekehrt bedeutet ein Vergleich der Werte, dass es (theoretisch) 2^256 mögliche Werte für die Schwierigkeit gibt. Dies ist viel detaillierter, und diese Werte sind ganze Zahlen. Anstatt die Schwierigkeit durch Multiplizieren ändern zu müssen, kann die Schwierigkeit durch Addition und Subtraktion geändert werden. Je mehr Werte vorhanden sind, desto weniger wahrscheinlich ist die Schwierigkeit zu schwer oder zu leicht.

  1. Aber in diesem Fall verstehe ich nicht, warum wir nicht einfach einen Hash akzeptieren sha256(sha256(header).digest()).digest().encode('hex'), der niedriger als der erwartete Hash ist? Die Wahrscheinlichkeit dafür sollte genauso hoch sein wie die umgekehrte.

Es ist eigentlich so wie du gesagt hast. Die Umkehrung des Hashs dient nur dazu, wie die Bytes tatsächlich dargestellt werden. Sie werden als Bytes gespeichert und als Little-Endian-256-Bit-Integer interpretiert. Der Vergleich ist immer noch ein ganzzahliger Vergleich und die Datendarstellung ist irrelevant (sie könnten genauso gut als Big-Endian-Ganzzahlen gespeichert und dargestellt werden). Aber wenn sie angezeigt werden, werden sie als Big-Endian-Werte im Hexadezimalformat angezeigt, da Menschen an Big-Endian gewöhnt sind. Der Grund für Little Endian liegt wahrscheinlich darin, dass die x86-Architektur Little Endian zum Speichern von Ganzzahlen verwendet.