Zum Hauptinhalt springen
Change page

Recursive-Length Prefix (RLP) Serialisierung

Die Recursive-Length Prefix (RLP) Serialisierung wird in den Ausführungs-Clients von Ethereum umfassend verwendet. RLP standardisiert den Transfer von Daten zwischen Knoten in einem platzsparenden Format. Der Zweck von RLP ist es, beliebig verschachtelte Arrays von Binärdaten zu codieren, und RLP ist die primäre Codierungsmethode, die zur Serialisierung von Objekten in der Ausführungsschicht von Ethereum verwendet wird. Der Hauptzweck von RLP ist die Codierung von Struktur; mit Ausnahme von positiven Ganzzahlen delegiert RLP die Codierung spezifischer Datentypen (z. B. Strings, Floats) an Protokolle höherer Ordnung. Positive Ganzzahlen müssen in Big-Endian-Binärform ohne führende Nullen dargestellt werden (wodurch der ganzzahlige Wert Null dem leeren Byte-Array entspricht). Deserialisierte positive Ganzzahlen mit führenden Nullen müssen von jedem Protokoll höherer Ordnung, das RLP verwendet, als ungültig behandelt werden.

Weitere Informationen finden Sie im Ethereum Yellow Paper (Anhang B) (opens in a new tab).

Um RLP zur Codierung eines Wörterbuchs (Dictionary) zu verwenden, sind die beiden vorgeschlagenen kanonischen Formen:

  • Verwendung von [[k1,v1],[k2,v2]...] mit Schlüsseln in lexikografischer Reihenfolge
  • Verwendung der übergeordneten Patricia-Tree-Codierung, wie es Ethereum tut

Definition

Die RLP-Codierungsfunktion nimmt ein Element (Item) auf. Ein Element ist wie folgt definiert:

  • ein String (d. h. ein Byte-Array) ist ein Element
  • eine Liste von Elementen ist ein Element
  • eine positive Ganzzahl ist ein Element

Zum Beispiel sind alle folgenden Dinge Elemente:

  • ein leerer String;
  • der String, der das Wort "cat" enthält;
  • eine Liste, die eine beliebige Anzahl von Strings enthält;
  • und komplexere Datenstrukturen wie ["cat", ["puppy", "cow"], "horse", [[]], "pig", [""], "sheep"].
  • die Zahl 100

Beachten Sie, dass im Kontext des Rests dieser Seite "String" bedeutet: "eine bestimmte Anzahl von Bytes an Binärdaten"; es werden keine speziellen Codierungen verwendet, und es wird kein Wissen über den Inhalt der Strings vorausgesetzt (außer wie durch die Regel gegen nicht-minimale positive Ganzzahlen gefordert).

Die RLP-Codierung ist wie folgt definiert:

  • Eine positive Ganzzahl wird in das kürzeste Byte-Array umgewandelt, dessen Big-Endian-Interpretation die Ganzzahl ist, und dann gemäß den unten stehenden Regeln als String codiert.
  • Für ein einzelnes Byte, dessen Wert im Bereich [0x00, 0x7f] (dezimal [0, 127]) liegt, ist dieses Byte seine eigene RLP-Codierung.
  • Andernfalls, wenn ein String 0-55 Bytes lang ist, besteht die RLP-Codierung aus einem einzelnen Byte mit dem Wert 0x80 (dez. 128) plus der Länge des Strings, gefolgt von dem String. Der Bereich des ersten Bytes ist somit [0x80, 0xb7] (dez. [128, 183]).
  • Wenn ein String mehr als 55 Bytes lang ist, besteht die RLP-Codierung aus einem einzelnen Byte mit dem Wert 0xb7 (dez. 183) plus der Länge in Bytes der Länge des Strings in Binärform, gefolgt von der Länge des Strings, gefolgt von dem String. Zum Beispiel würde ein 1024 Byte langer String als \xb9\x04\x00 (dez. 185, 4, 0) gefolgt von dem String codiert werden. Hier ist 0xb9 (183 + 2 = 185) das erste Byte, gefolgt von den 2 Bytes 0x0400 (dez. 1024), die die Länge des eigentlichen Strings angeben. Der Bereich des ersten Bytes ist somit [0xb8, 0xbf] (dez. [184, 191]).
  • Wenn ein String 2^64 Bytes lang oder länger ist, darf er nicht codiert werden.
  • Wenn die gesamte Nutzlast (Payload) einer Liste (d. h. die kombinierte Länge aller ihrer RLP-codierten Elemente) 0-55 Bytes lang ist, besteht die RLP-Codierung aus einem einzelnen Byte mit dem Wert 0xc0 plus der Länge der Nutzlast, gefolgt von der Verkettung der RLP-Codierungen der Elemente. Der Bereich des ersten Bytes ist somit [0xc0, 0xf7] (dez. [192, 247]).
  • Wenn die gesamte Nutzlast einer Liste mehr als 55 Bytes lang ist, besteht die RLP-Codierung aus einem einzelnen Byte mit dem Wert 0xf7 plus der Länge in Bytes der Länge der Nutzlast in Binärform, gefolgt von der Länge der Nutzlast, gefolgt von der Verkettung der RLP-Codierungen der Elemente. Der Bereich des ersten Bytes ist somit [0xf8, 0xff] (dez. [248, 255]).

In knapper Form:

BereichByte 1Byte 2...Byte 9Byte 10Bedeutung
0x00-0x7f0pppppppEinzel-Byte-String
0x80-0xb710nnnnnnpppppppp...kurzer String (0-55 Bytes)
0xb8-0xbf10111NNNnnnnnnnn...nnnnnnnn/pppppppppppppppplanger String, N+1 Bytes für Länge, dann Nutzlast
0xc0-0xf711nnnnnnpppppppp...kurze Liste (0-55 Bytes)
0xf8-0xff11111NNNnnnnnnnn...nnnnnnnn/pppppppppppppppplange Liste, N+1 Bytes für Länge, dann Nutzlast
  • p = Nutzlast (Payload)
  • n = Länge (Anzahl der Nutzlast-Bytes)
  • N = Länge-der-Länge-Offset (N+1 n Bytes folgen)

Im Code sieht das so aus:

Beispiele

  • der String "dog" = [ 0x83, 'd', 'o', 'g' ]
  • die Liste [ "cat", "dog" ] = [ 0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g' ]
  • der leere String ('null') = [ 0x80 ]
  • die leere Liste = [ 0xc0 ]
  • die Ganzzahl 0 = [ 0x80 ]
  • das Byte '\x00' = [ 0x00 ]
  • das Byte '\x0f' = [ 0x0f ]
  • die Bytes '\x04\x00' = [ 0x82, 0x04, 0x00 ]
  • die mengentheoretische Darstellung (opens in a new tab) von drei, [ [], [[]], [ [], [[]] ] ] = [ 0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0 ]
  • der String "Lorem ipsum dolor sit amet, consectetur adipisicing elit" = [ 0xb8, 0x38, 'L', 'o', 'r', 'e', 'm', ' ', ... , 'e', 'l', 'i', 't' ]

RLP-Decodierung

Gemäß den Regeln und dem Prozess der RLP-Codierung wird die Eingabe der RLP-Decodierung als ein Array von Binärdaten betrachtet. Der RLP-Decodierungsprozess läuft wie folgt ab:

  1. Anhand des ersten Bytes (d. h. des Präfixes) der Eingabedaten werden der Datentyp, die Länge der eigentlichen Daten und der Offset decodiert;

  2. Entsprechend dem Typ und dem Offset der Daten werden die Daten entsprechend decodiert, wobei die Regel der minimalen Codierung für positive Ganzzahlen beachtet wird;

  3. Fahren Sie mit der Decodierung des Rests der Eingabe fort;

Dabei lauten die Regeln zur Decodierung von Datentypen und Offsets wie folgt:

  1. Die Daten sind ein String, wenn der Bereich des ersten Bytes (d. h. des Präfixes) [0x00, 0x7f] ist, und der String ist exakt das erste Byte selbst;

  2. Die Daten sind ein String, wenn der Bereich des ersten Bytes [0x80, 0xb7] ist, und der String, dessen Länge gleich dem ersten Byte minus 0x80 ist, folgt auf das erste Byte;

  3. Die Daten sind ein String, wenn der Bereich des ersten Bytes [0xb8, 0xbf] ist, und die Länge des Strings, dessen Länge in Bytes gleich dem ersten Byte minus 0xb7 ist, folgt auf das erste Byte, und der String folgt auf die Länge des Strings;

  4. Die Daten sind eine Liste, wenn der Bereich des ersten Bytes [0xc0, 0xf7] ist, und die Verkettung der RLP-Codierungen aller Elemente der Liste, deren gesamte Nutzlast gleich dem ersten Byte minus 0xc0 ist, folgt auf das erste Byte;

  5. Die Daten sind eine Liste, wenn der Bereich des ersten Bytes [0xf8, 0xff] ist, und die gesamte Nutzlast der Liste, deren Länge gleich dem ersten Byte minus 0xf7 ist, folgt auf das erste Byte, und die Verkettung der RLP-Codierungen aller Elemente der Liste folgt auf die gesamte Nutzlast der Liste;

Im Code sieht das so aus:

Weiterführende Literatur