イーサー坊のRLPコード

5674 ワード

文章は2部分に分けて、第1部分は既存の資料を総合的に整理して生成した参考文書で、第2部分はpython版の太坊コードの中のソースコードで分析を実現する.
RLPの概要
RLP(再帰長接頭辞)は、任意のバイナリデータ配列の符号化に適用される.イーサー坊におけるデータのシーケンス化/逆シーケンス化の主な方法であり、ブロック、トランザクションなどのデータ構造は、ネットワーク転送や永続化の際にRLP符号化を経てデータベースに格納される.
json符号化に比べてRLP符号化の占有空間は小さく,冗長情報はほとんどない.
RLP符号化の定義は、2種類のデータのみを処理する.
  • バイナリデータの配列(文字列、バイト配列、整形など)
  • リスト(バイナリデータの配列の配列、すなわちネストされた再帰構造であり、文字列とリストを含むことができる)は、例えば
    ["cat",["puppy","cow"],"horse",[[]],"pig",[""],"sheep"]
    
    
    が複雑なリストである.

  • 他のタイプのデータは、structがリストに変換されてもよいし、intが文字列に変換されてもよいし、回転されなくてもよいし、辞書が例えば[[k1,v1],[k2,v2]...]に変換されてもよい.
    RLP符号化規則
    全体として、 (シングルバイト)、 + (総長<55)、または + + (総長>55)と概括することができる.
  • ルール1(内容).[0 x 00,0 x 7 f]の範囲の であり、RLP符号化コンテンツはバイトコンテンツそのものである.

  • 例:
  • ‘a’ = 0x61
  • 整数15('\x0f') = 0x0f
  • ルール2(プレフィックス+コンテンツ).0-55バイト長の文字列、RLP符号化は (0x80+len( ))+
  • 例:
  • abc符号化結果は0 x 83 0 x 61 0 x 62 0 x 63であり、0 x 83=0 x 80+len(「abc」)である.
  • 整数1024('x 0400')=[0 x 82,0 x 04,0 x 00]
  • 空白文字列"=0 x 80
  • 文字列"dog" = [0x83, 'd', 'o', 'g' ]
  • ルール3(接頭辞+長さ+内容).>55バイト長文字列、RLP符号化 (0xb7+len(len( )))+len( )+
  • 例:
  • 文字列「Lorem ipsum dolor sit amet,consectetur adipisicing elit」=[0 xb 8,0 x 38,'L','o','r','e','m',...,'e','l','i','t']
  • ルール4(プレフィックス+コンテンツ).リストの合計長さ(リストの合計長さとは、含まれる項目の数と含まれる各項目の長さの和を指す)は0~55バイトであり、RLP符号化は (0xc0+len( ))+ RLP であり、接頭辞の値範囲は[0xc0, 0xf7]である.

  • 例:
  • リスト["cate","dog"] = [0xc9, 0x84, 'c', 'a', 't', 'e',0x83, 'd', 'o', 'g' ] 0xc9=0 xc 0+1+4+1+3(1:文字列長の長さ、4:文字列長、1:文字列長の長さ、3:文字列長)
  • リスト[ [], [[]], [ [], [[]] ] ] = [0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0]
  • ルール5(接頭辞+長さ+内容).**リストの全長は55バイトより大きく、RLP符号化は (0xf7+len(len( )))+len( )+ RLP であり、プレフィックス値範囲は[0xf8, 0xff]である.例:
  • リスト["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"] = [0xf8 0x58 0xb3 'T','h','e',... 0 xf 8=0 xf 7+1(1:リスト全長の長さ)0 x 58=0 x 56+1+1(0 x 56:リスト全長1+1:2文字列長さの長さ)0 xb 3=0 x 80+0 x 33(33:文字列長)

  • 統合符号化の例:["abc",["The length of this sentence is more than 55 bytes, ", "I know it because I pre-designed it"]] = [0xf8 0x5e 0x83 0x61 98 99 248 88 179 84 104 101 32 108 101 110 103 116 104 32 111 102 32 116 104 105 115 32 115 101 110 116 101 110 99 101 32 105 115 32 109 111 114 101 32 116 104 97 110 32 53 53 32 98 121 116 101 115 44 32 163 73 32 107 110 111 119 32 105 116 32 98 101 99 97 117 115 101 32 73 32 112 114 101 45 100 101 115 105 103 110 101 100 32 105 116]
    0 xf 8=0 xf 7+1(1:リスト全長の長さ)
    0 x 5 e=90+1+2+1(90:文字列全長1:1番目の文字列接頭辞2:2番目の文字列接頭辞+長さ1:3番目の文字列接頭辞)
    RLP復号規則
  • f∈[0128]の場合、それはバイト自体です.
  • 2.f∈[128,184]の場合、配列の長さはl=f-128の長さ55を超えないbyte配列である.
    3.f∈[184192]の場合、長さが55を超える配列であり、長さ自体の符号化長がll=f-183であり、2バイト目から長さがllのbytesが読み出され、BigEndianに従って整数l、lが配列の長さとなるように符号化される.
    4.f∈(192247)の場合、符号化後の全長が55を超えないリストであり、リスト長はl=f-192である.再帰的にはルール1~4を用いて復号する.
    5.f∈(247256)の場合、符号化後の長さが55より大きいリストであり、その長さ自体の符号化長がll=f-247であり、その後、2バイト目から長さがllのbytesを読み出し、BigEndianで整数l、lであるサブリスト長に符号化する.その後、復号規則に従って復号する.
    イーサー坊のRLPコーデック
    python版イーサー坊では、RLPコーデックについて独立した専門プロジェクトが作成されています.https://github.com/ethereum/pyrlp
    主なプロセスは、シーケンス化と符号化、および**復号化と逆シーケンス化を含む.**
    合計エントリ:
  • encode(obj,sedes=None,infer_serializer=True)obj:符号化対象オブジェクトsedes:符号化対象オブジェクトタイプ(binary,listなど)infer_を明示的に指定することを示すserializer:objタイプに基づいてデフォルトで自動的にシーケンス化され、falseに設定すると、オブジェクトに対してrlp符号化が直接行われることを示す
  • decode(rlp, sedes=None, strict=True, **kwargs)

  • プロジェクトはいくつかの機能モジュールに分けられ、実行プロセスに従って以下の通りである.
  • codec/lazy:RLP符号化復号を実現するインタフェースの定義と実現
  • encodeプロセス
  • objタイプに従ってシーケンス化:item = infer_sedes(obj).serialize(obj)
  • infer_sedesはRLP符号化をサポートするタイプ:big_endian_int; binary; Listを返し、dictである場合は先にListタイプに変換する必要がある.詳しくは以下を参照してください.
  • serializeは、対応するタイプのシーケンス化インターフェースを呼び出し、シーケンス化を実行する.詳しくは以下を参照してください.
  • 符号化:encode_raw(item)、符号化規則は前述の通りである.リストタイプについては、各要素を再帰的に符号化する:payload = b''.join(encode_raw(x) for x in item)
  • 長さに基づいて符号化プレフィックスを生成する:prefix = length_prefix(len(payload), prefix_offset)、規則は前述の通りである.
  • は、プレフィックスおよび符号化コンテンツを返す:return prefix + payload

  • sedes:シーケンス化/逆シーケンス化可能なオブジェクトタイプを定義し、それぞれのシーケンス化/逆シーケンス化の方法の1つにします.
  • Binary:長さを決定するバイナリデータシーケンス化方法:str_to_bytes(obj)
  • BigEndianInt:長さを決定するマクロバイナリデータシーケンス化方法:b'\x00' * max(0, - len(int_to_big_endian(obj))) + int_to_big_endian(obj)
  • List:各メンバーがシーケンス化方法をサポートする必要がある:[sedes.serialize(element) for element, sedes in zip(obj, self)]
  • utils:データ型間の相互変換インタフェース
  • decode_Hex(s):16進数符号化バイト配列列を文字列に変換する例:"616263" => "abc"
  • encode_Hex(s):文字列を16進符号化バイト配列列に変換します.たとえば、"abc" => "616263"
  • int_to_big_endian(value):整形データを大端バイト符号化文字列
  • に変換する
  • big_endian_to_int(value):大端バイト符号化文字列を整形データ
  • に変換する