Přeskočit na hlavní obsah
Change page

Serializace rekurzivního délkového prefixu (RLP)

Stránka naposledy aktualizována: 23. února 2026

Serializace rekurzivního délkového prefixu (RLP) se hojně používá v exekučních klientech Etherea. RLP standardizuje přenos dat mezi uzly v prostorově úsporném formátu. Účelem RLP je kódovat libovolně vnořená pole binárních dat a RLP je primární metodou kódování používanou k serializaci objektů v exekuční vrstvě Etherea. Hlavním účelem RLP je kódovat strukturu; s výjimkou kladných celých čísel RLP deleguje kódování specifických datových typů (např. řetězců, čísel s plovoucí desetinnou čárkou) na protokoly vyššího řádu. Kladná celá čísla musí být reprezentována v binární formě big-endian bez úvodních nul (takže celočíselná hodnota nula je ekvivalentní prázdnému poli bajtů). Deserializovaná kladná celá čísla s úvodními nulami musí být jakýmkoli protokolem vyššího řádu používajícím RLP považována za neplatná.

Více informací v Ethereum yellow paper (Dodatek B) (opens in a new tab).

Pro použití RLP ke kódování slovníku jsou dvě navrhované kanonické formy:

  • použijte [[k1,v1],[k2,v2]...] s klíči v lexikografickém pořadí
  • použijte kódování Patricia Tree na vyšší úrovni, tak jak to dělá Ethereum

Definice

Kódovací funkce RLP přijímá položku. Položka je definována následovně:

  • řetězec (tj. pole bajtů) je položka
  • seznam položek je položka
  • kladné celé číslo je položka

Například všechny následující jsou položky:

  • prázdný řetězec;
  • řetězec obsahující slovo "cat";
  • seznam obsahující libovolný počet řetězců;
  • a složitější datové struktury, jako je ["cat", ["puppy", "cow"], "horse", [[]], "pig", [""], "sheep"].
  • číslo 100

Všimněte si, že v kontextu zbytku této stránky „řetězec“ znamená „určitý počet bajtů binárních dat“; nepoužívají se žádná speciální kódování a nepředpokládá se žádná znalost o obsahu řetězců (kromě toho, co vyžaduje pravidlo proti neminimálním kladným celým číslům).

Kódování RLP je definováno následovně:

  • U kladného celého čísla se toto převede na nejkratší pole bajtů, jehož interpretace big-endian je dané celé číslo, a poté se zakóduje jako řetězec podle níže uvedených pravidel.
  • Pro jediný bajt, jehož hodnota je v rozsahu [0x00, 0x7f] (desítkově [0, 127]), je tento bajt svým vlastním kódováním RLP.
  • Jinak, pokud je řetězec dlouhý 0–55 bajtů, kódování RLP se skládá z jednoho bajtu s hodnotou 0x80 (des. 128) plus délka řetězce, po níž následuje samotný řetězec. Rozsah prvního bajtu je tedy [0x80, 0xb7] (des. [128, 183]).
  • Pokud je řetězec delší než 55 bajtů, kódování RLP se skládá z jednoho bajtu s hodnotou 0xb7 (des. 183) plus délka délky řetězce v bajtech v binární formě, následovaná délkou řetězce a samotným řetězcem. Například řetězec dlouhý 1024 bajtů by byl zakódován jako \xb9\x04\x00 (des. 185, 4, 0) a za ním by následoval řetězec. Zde je 0xb9 (183 + 2 = 185) jako první bajt, po němž následují 2 bajty 0x0400 (des. 1024), které označují délku skutečného řetězce. Rozsah prvního bajtu je tedy [0xb8, 0xbf] (des. [184, 191]).
  • Pokud je řetězec dlouhý 2^64 bajtů nebo více, nesmí být kódován.
  • Pokud je celková datová část seznamu (tj. kombinovaná délka všech jeho položek kódovaných pomocí RLP) dlouhá 0–55 bajtů, kódování RLP se skládá z jediného bajtu s hodnotou 0xc0 plus délka datové části, po níž následuje zřetězení kódování RLP jednotlivých položek. Rozsah prvního bajtu je tedy [0xc0, 0xf7] (des. [192, 247]).
  • Pokud je celková datová část seznamu delší než 55 bajtů, kódování RLP se skládá z jednoho bajtu s hodnotou 0xf7 plus délka délky datové části v bajtech v binární podobě, následovaná délkou datové části a zřetězením kódování RLP jednotlivých položek. Rozsah prvního bajtu je tedy [0xf8, 0xff] (des. [248, 255]).

V kódu to vypadá takto:

1def rlp_encode(input):
2 if isinstance(input,str):
3 if len(input) == 1 and ord(input) < 0x80:
4 return input
5 return encode_length(len(input), 0x80) + input
6 elif isinstance(input, list):
7 output = ''
8 for item in input:
9 output += rlp_encode(item)
10 return encode_length(len(output), 0xc0) + output
11
12def encode_length(L, offset):
13 if L < 56:
14 return chr(L + offset)
15 elif L < 256**8:
16 BL = to_binary(L)
17 return chr(len(BL) + offset + 55) + BL
18 raise Exception("input too long")
19
20def to_binary(x):
21 if x == 0:
22 return ''
23 return to_binary(int(x / 256)) + chr(x % 256)
Zobrazit vše

Příklady

  • řetězec "dog" = [ 0x83, 'd', 'o', 'g' ]
  • seznam [ "cat", "dog" ] = [ 0xc8, 0x83, 'c', 'a', 't', 0x83, 'd', 'o', 'g' ]
  • prázdný řetězec ('null') = [ 0x80 ]
  • prázdný seznam = [ 0xc0 ]
  • celé číslo 0 = [ 0x80 ]
  • bajt '\x00' = [ 0x00 ]
  • bajt '\x0f' = [ 0x0f ]
  • bajty '\x04\x00' = [ 0x82, 0x04, 0x00 ]
  • teoreticko-množinová reprezentace (opens in a new tab) trojky, [ [], [[]], [ [], [[]] ] ] = [ 0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0 ]
  • řetězec "Lorem ipsum dolor sit amet, consectetur adipisicing elit" = [ 0xb8, 0x38, 'L', 'o', 'r', 'e', 'm', ' ', ... , 'e', 'l', 'i', 't' ]

Dekódování RLP

Podle pravidel a postupu kódování RLP je vstup pro dekódování RLP považován za pole binárních dat. Proces dekódování RLP je následující:

  1. podle prvního bajtu (tj. prefixu) vstupních dat a dekódování datového typu, délky skutečných dat a offsetu;

  2. podle typu a offsetu dat dekódujte data odpovídajícím způsobem, přičemž respektujte pravidlo minimálního kódování pro kladná celá čísla;

  3. pokračujte v dekódování zbytku vstupu;

Pravidla pro dekódování datových typů a offsetu jsou následující:

  1. data jsou řetězec, pokud je rozsah prvního bajtu (tj. prefixu) [0x00, 0x7f], a řetězec je přesně samotný první bajt;

  2. data jsou řetězec, pokud je rozsah prvního bajtu [0x80, 0xb7] a za prvním bajtem následuje řetězec, jehož délka se rovná prvnímu bajtu mínus 0x80;

  3. data jsou řetězec, pokud je rozsah prvního bajtu [0xb8, 0xbf] a za prvním bajtem následuje délka řetězce, jejíž délka v bajtech se rovná prvnímu bajtu mínus 0xb7, a za délkou řetězce následuje samotný řetězec;

  4. data jsou seznam, pokud je rozsah prvního bajtu [0xc0, 0xf7] a za prvním bajtem následuje zřetězení kódování RLP všech položek seznamu, jejichž celková datová část se rovná prvnímu bajtu mínus 0xc0;

  5. data jsou seznam, pokud je rozsah prvního bajtu [0xf8, 0xff] a za prvním bajtem následuje celková datová část seznamu, jejíž délka se rovná prvnímu bajtu mínus 0xf7, a za celkovou datovou částí seznamu následuje zřetězení kódování RLP všech položek seznamu;

V kódu to vypadá takto:

1def rlp_decode(input):
2 if len(input) == 0:
3 return
4 output = ''
5 (offset, dataLen, type) = decode_length(input)
6 if type is str:
7 output = instantiate_str(substr(input, offset, dataLen))
8 elif type is list:
9 output = instantiate_list(substr(input, offset, dataLen))
10 output += rlp_decode(substr(input, offset + dataLen))
11 return output
12
13def decode_length(input):
14 length = len(input)
15 if length == 0:
16 raise Exception("input is null")
17 prefix = ord(input[0])
18 if prefix <= 0x7f:
19 return (0, 1, str)
20 elif prefix <= 0xb7 and length > prefix - 0x80:
21 strLen = prefix - 0x80
22 return (1, strLen, str)
23 elif prefix <= 0xbf and length > prefix - 0xb7 and length > prefix - 0xb7 + to_integer(substr(input, 1, prefix - 0xb7)):
24 lenOfStrLen = prefix - 0xb7
25 strLen = to_integer(substr(input, 1, lenOfStrLen))
26 return (1 + lenOfStrLen, strLen, str)
27 elif prefix <= 0xf7 and length > prefix - 0xc0:
28 listLen = prefix - 0xc0;
29 return (1, listLen, list)
30 elif prefix <= 0xff and length > prefix - 0xf7 and length > prefix - 0xf7 + to_integer(substr(input, 1, prefix - 0xf7)):
31 lenOfListLen = prefix - 0xf7
32 listLen = to_integer(substr(input, 1, lenOfListLen))
33 return (1 + lenOfListLen, listLen, list)
34 raise Exception("input does not conform to RLP encoding form")
35
36def to_integer(b):
37 length = len(b)
38 if length == 0:
39 raise Exception("input is null")
40 elif length == 1:
41 return ord(b[0])
42 return ord(substr(b, -1)) + to_integer(substr(b, 0, -1)) * 256
Zobrazit vše

Další čtení

Byl tento článek užitečný?