Zum Inhalt springen
buybitcoinsmart

Glossar / Entwicklerreferenz

CompactSize

Auch bekannt als Compact size unsigned integer, VarInt.

Was ist CompactSize?
CompactSize ist die Ganzzahl mit variabler Länge, mit der Bitcoin in serialisierten Daten Zählwerte und Längen einleitet; sie kostet ein Byte für Werte unter 253 und bis zu neun für den Rest.

Die binären Formate von Bitcoin tragen keine Feldnamen, ein Parser muss also wissen, wie viele Eingaben folgen und wie lang jedes Skript ist. CompactSize antwortet mit nur einem Byte: 0 bis 252 ist dieses Byte allein, und größere Werte brauchen eine Kennung plus zwei, vier oder acht weitere. Jede Zahlung, die Sie senden, enthält mindestens vier davon.

So funktioniert es

CompactSize liest sein eigenes erstes Byte, um zu entscheiden, wie viel von sich selbst noch übrig ist.

Ein erstes Byte unter 0xfd ist der Wert, Zählwerte von 0 bis 252 belegen also ein Byte und sonst nichts. Ein erstes Byte von 0xfd bedeutet, dass der Wert in den nächsten zwei Bytes steht, 0xfe bedeutet die nächsten vier und 0xff die nächsten acht. Alle diese Folgenummern sind Little Endian. Die längste mögliche Kodierung ist neun Bytes und kann einen Wert über 18 Trillionen ausdrücken, was keine reale Struktur auch nur annähernd braucht.

Kodierungen müssen minimal sein. Die Zahl 5 als 0xfd 0x05 0x00 zu schreiben ist arithmetisch identisch mit 0x05, und Bitcoin Core lehnt sie ab und wirft beim Deserialisieren einen Fehler wegen nicht kanonischer Kodierung. Ohne diese Regel könnte dieselbe Transaktion auf mehrere Arten geschrieben werden, jede mit einer anderen Kennung, was ein Problem der Malleabilität ist und nicht der Ordentlichkeit.

Es gibt eine praktische Obergrenze weit unter der arithmetischen. Bitcoin Core weigert sich, für ein deserialisiertes Objekt Speicher zu reservieren, das angibt, größer als 0x02000000 Bytes zu sein, etwa 33,5 Megabyte, und das Peer-Protokoll begrenzt eine Nachricht separat auf 4.000.000 Bytes. Ein feindlicher Peer kann Ihren Node daher nicht dazu bringen, Gigabyte an Speicher zu reservieren, indem er eine Transaktion mit einer Trillion Eingaben ankündigt.

Eine Namensfalle ist erwähnenswert. Die Dokumentation des Übertragungsformats nennt dies var_int, Wallet-Bibliotheken nennen es meist VarInt, und der Quellcode von Bitcoin Core selbst verwendet den Namen VarInt für eine völlig andere und unabhängige Kodierung, die nur in seinen Datenbank- und Undo-Dateien vorkommt. Wenn Sie Code lesen, prüfen Sie, welche der beiden Sie vor sich haben.

Wo es auftritt

CompactSize ist die am häufigsten anzutreffende Struktur in Bitcoin, die überhaupt keinen für Nutzer sichtbaren Namen hat.

In einer rohen Transaktion steht sie unmittelbar nach der vier Byte langen Version, oder nach dem SegWit-Marker und -Flag, wenn diese vorhanden sind, und enthält die Anzahl der Eingaben. Sie erscheint erneut vor jedem Skript, um dessen Länge anzugeben, und nochmals vor der Anzahl der Ausgaben. In einem serialisierten Block trägt sie die Anzahl der Transaktionen. Im Peer-Protokoll eröffnet sie die Nutzlast der Nachrichten inv, getdata, addr und headers.

Die Nachricht headers zeigt die Kodierung in ihrer seltsamsten Form. Auf jeden 80 Byte langen Header folgt eine CompactSize-Anzahl von null Transaktionen, ein Eintrag belegt also 81 Bytes statt 80, und ein voller Stapel von 2.000 Headern kommt auf 162.000 Bytes im Netz. Die Anzahl ist immer null, weil eine headers-Nachricht nie Transaktionen enthält. Das Feld existiert, damit derselbe Parsercode einen Header lesen kann, ob ihm ein Blockkörper folgt oder nicht.

Wenn Sie eine rohe Transaktion von Hand dekodieren und die Felder mitten in der Transaktion keinen Sinn mehr ergeben, ist ein falsch gelesener CompactSize-Wert fast immer die Ursache. Lesen Sie ein Byte zu wenig, ist alles danach verschoben.

Häufig gestellte Fragen

Warum verwendet Bitcoin überhaupt eine Ganzzahl mit variabler Länge?

Weil fast jeder Zählwert in Bitcoin klein ist. Eine Transaktion hat meist eine oder zwei Eingaben, und vier oder acht Bytes auf jedem Feld jeder jemals erstellten Transaktion dafür auszugeben, hätte eine große Menge dauerhaften Gewichts für nichts hinzugefügt.

Ist CompactSize dasselbe wie das VarInt von Bitcoin Core?

Nein, trotz des gemeinsamen Spitznamens. CompactSize ist das hier beschriebene Format im Netz und auf der Festplatte, während die in Bitcoin Core VarInt genannte Klasse eine separate kompakte Kodierung ist, die nur innerhalb seiner eigenen Datenbank- und Undo-Dateien verwendet wird.

Verwandte Begriffe

Mehr zum Thema Entwicklerreferenz

Diese Seite auf Englisch lesen