Wie behandelt man unvollständige Blöcke beim Lesen von blk*.dat-Dateien?

Ich versuche, einen Parser für blk*.dat-Dateien von Grund auf neu zu schreiben. Im Moment kann ich Blöcke lesen, die Header-Felder extrahieren und den korrekten Block-Hash basierend auf den Header-Feldern berechnen.

Ich habe gerade versucht, den Parser durch alle blk-Dateien laufen zu lassen, und es ist fehlgeschlagen, nachdem ich die ersten ~ 300 blk-Dateien erfolgreich gelesen hatte. Als ich die fehlerhafte Datei mit einem Hex-Editor untersuchte, fand ich zwei "Magic-Byte-Felder", die nur durch 4 andere Bytes getrennt waren.

Geben Sie hier die Bildbeschreibung ein

Da der obligatorische Block-Header 80 Bytes lang sein soll, bin ich jetzt ziemlich verwirrt.

Ich habe drei wahrscheinlich verwandte Fragen gefunden:

  1. blk-Dateifehler beim Lesen - hat sich etwas am Format geändert?
  2. Wie können Sie feststellen, ob Sie am Ende einer unvollständigen blk*.dat-Datei sind?
  3. Nullen in blk00*.dat-Dateien

Meine Vermutung, basierend auf diesen anderen Fragen, ist die folgende:

  • Dies ist ein "unvollständiger Block"
  • Dies geschieht, wenn ein Block nur teilweise heruntergeladen oder auf die Festplatte geschrieben werden kann.
  • Das Löschen der betroffenen blk-Dateien und das erneute Herunterladen von Teilen der Blockchain ist nicht sinnvoll, da damit gerechnet werden kann, dass dies erneut geschieht.
  • Der Parser sollte in der Lage sein, diese Blöcke zu überspringen.
  • Der gesamten blk-Datei fehlen keine tatsächlichen Daten und sie ist nicht beschädigt.
  • Der 'unvollständige Block' wird heruntergeladen und weiter unten in der blk-Datei (oder in einer anderen blk-Datei) wieder geschrieben.

Welche meiner Annahmen sind richtig? .. Welche nicht sind? Übersehe ich etwas?

Der Knoten wurde wahrscheinlich beim Schreiben auf die Festplatte beendet.
Wenn Sie 0xd0 Bytes weiter gehen, gibt es weitere magische 4-Bytes? Theoretisch könnte f9beb4d9 in den Daten des Blocks selbst vorkommen, sodass Sie nicht sicher sein können, dass irgendein Vorkommen den Beginn eines Blocks markiert. Sie sollten die Längen verwenden. Obwohl die ersten Bytes des Blocks die Versionsnummer sein sollten, denke ich, und ich bin mir nicht sicher, ob f9beb4d9 dort gültig wäre.
@eponymous Ich habe alle blk-Dateien gelöscht und erneut heruntergeladen. Dieses Mal habe ich dafür gesorgt, dass der Knoten kein einziges Mal angehalten hat. Danach hatte ich keine Probleme beim Lesen aller blk-Dateien. Das stützt deine Theorie.
Ja. Meine Dateien befinden sich aufgrund vieler erzwungener Knotenneustarts während IBD in einem seltsamen Zustand. Die Software ist damit einverstanden, da es eine externe Datenbank mit Zeigern auf die Blöcke auf der Festplatte gibt, die die Beschädigung einfach überspringen können.
@NateEldredge Nein, gibt es nicht. Es ist auch sehr unwahrscheinlich, dass diese 4 Bytes in den Daten vorkommen. bitcoin.stackexchange.com/questions/2337/…
Es ist vielleicht unwahrscheinlich, dass es zufällig auftritt, aber nichts hindert irgendjemanden daran, diese 4 Bytes absichtlich in eine Transaktion einzufügen (z. B. über OP_RETURN). Ein Miner, der sich unwohl fühlte, konnte auch an der Coinbase-Transaktion herumspielen, bis diese Bytes in der Merkle-Wurzel auftauchten; es würde etwas in der Größenordnung von 100 Millionen Versuchen erfordern, was nicht viel ist. In diesem Fall würden Sie diese Bytes im Blockheader sehen.
Angesichts Ihrer zusätzlichen Beschreibung stimme ich zu, dass dies hier wahrscheinlich nicht das Problem ist, aber es zeigt, dass Ihr Code diesen Fall unbedingt richtig behandeln muss.
Danke @NateEldredge, ich habe nicht daran gedacht, dass jemand diese Bytes absichtlich generiert. Ich frage mich, ob das schon versucht wurde? Du hast aber vollkommen Recht. Mein Parser muss damit richtig umgehen.
@forgemo: Ich wäre irgendwie überrascht, wenn dies nicht der Fall wäre. Vielleicht suche ich irgendwann mal in der Blockchain nach. Wenn es noch keiner gemacht hat, werde ich es vielleicht tun :-)
@NateEldredge Ich konnte nicht widerstehen, danach zu suchen. :) Wie Sie bereits erraten haben, hat es jemand getan. Der folgende Block aus dem Jahr 2012 scheint einen solchen Fall zu enthalten. blockchain.info/block/… Dies unterstreicht Ihren Vorschlag, diese Fälle ordnungsgemäß zu behandeln, weiter.

Antworten (1)

Ich werde meine eigene Frage beantworten. Dies sind meine Schlussfolgerungen basierend auf den Kommentaren von Nade Eldrege und namensgebend.

Annahme 1: Dies ist ein 'unvollständiger Block'

Ja, das ist ein unvollständiger Block. Genauer gesagt ist es nicht Teil des blk-Dateiformats.

Annahme 2: Dies geschieht, wenn ein Block nur teilweise heruntergeladen oder auf die Festplatte geschrieben werden kann.

Ja, es gibt Hinweise darauf, dass dies passiert, wenn die Bitcoin beim Schreiben auf die Festplatte unterbrochen / getötet wird. Wenn es neu gestartet wird, fährt es einfach fort, neue Blöcke herunterzuladen und in die blk-Datei zu schreiben. Unvollständige Blöcke werden nicht bereinigt.

Annahme 3: Das Löschen der betroffenen blk-Dateien und das erneute Herunterladen von Teilen der Blockchain ist nicht sinnvoll, da damit zu rechnen ist, dass dies erneut passieren wird.

Ja und nein. Ja, denn das Löschen und erneute Herunterladen der blk-Dateien ohne Unterbrechungen löst das Problem. Beim Schreiben eines blk-Parsers sollte dieser jedoch in der Lage sein, mit diesen unvollständigen Blöcken umzugehen. Zum Beispiel durch Springen zum nächsten gültigen Block.

Annahme 4: Der Parser soll diese Blöcke überspringen können.

Ja. Siehe Nr. 3

Annahme 5: Der gesamten blk-Datei fehlen keine aktuellen Daten und sie ist nicht beschädigt.

Ich bin mir nicht sicher, aber da der Bitcoin einfach mit dem Herunterladen von Blöcken fortfährt und ohne Probleme funktioniert, kann man davon ausgehen, dass der unvollständige Block danach einfach erneut heruntergeladen wird.

Annahme 6: Der 'unvollständige Block' wird heruntergeladen und weiter unten in die blk-Datei (oder in eine andere blk-Datei) wieder geschrieben.

Es scheint so. Siehe Nr. 5