BOLT #1 : Base Protocol

Overview


このプロトコルは、個々のメッセージのフレーミングを処理する、基盤となる認証および順序付けされたトランスポートメカニズムを想定している。 BOLT#8 は、Lightning で使用される正規のトランスポート層を指定するが、上記の保証を満たす任意のトランスポートで置き換えることができる。(デフォルトの TCP ポート番号:9735、16進数:0x2607)

Connection Handling and Multiplexing


実装ではピアごとに単一の接続を使用しなければならない(チャンネルメッセージ(チャンネル ID を含む)はこの単一接続上を通して多重化してしている)。

Lightning Message Format


復号後、Lightning メッセージは以下のような形式になっている。

Table1

Field Size Description
type 2-byte メッセージのタイプ
payload variable メッセージタイプのフォーマットに適したメッセージ内容
extension ? オプションの TLV ストリーム

type フィールドは payload をどのように解釈するかを示している。個々のタイプのフォーマットはこのリポジトリの仕様書によって定義されている。タイプは「奇数ならばOK」というルールに従っているため、ノードは受信者の理解を確認せずに奇数タイプを送る可能性がある。メッセージは論理的に5つのグループに分けることができ、設定されている最上位ビットの順に並べられる。

Table2

Function Type-num Description
Setup & Control 0-31 接続セットアップ、制御、サポート機能、エラーレポートに関するメッセージ(後述)
Channel 32-127 マイクロペイメントチャネルのセットアップと削除用メッセージ(BOLT #2)
Commitment 128-255 現在のコミットメントトランザクションのアップデートに関連したメッセージ(手数料の更新と署名の交換と同様に HTLC の追加、廃止、清算を含む)(BOLT #2)
Routing 256-511 アクティブルートの探索、ノードとチャネルの通知を含むメッセージ(BOLT #7)
Custom 32768-65535 実験用またはアプリケーション専用メッセージ

メッセージの最大サイズはトランスポート層より 65535 bytes である。

送信ノード:

受信ノード:

Rationale

SHA2 と Bitcoin 公開鍵はデフォルトでビッグエンディアンであるため、他のフィールドで異なるエンディアンを使うのは一般的ではない。暗号学的ラッピングによって長さが 65535 bytes に制限されているため、プロトコルでのメッセージはいずれもその長さ以下である。

「奇数ならOK」というルールは将来のクライアントに交渉や特別なコーディングなしで任意の拡張を可能にする。拡張フィールドもまた同様に送信者が TLV データを追加することで将来の拡張を可能にする。

Type-Length-Value Format


プロトコル全体で TLV(Typr-Length-Value)フォーマットは既存のメッセージタイプに下位互換性のある新しいフィールドを追加可能にするために使われる。

tlv_record は単一のフィールドを表し以下のフォームにエンコードされる。

tlv_stream は(ゼロの可能性もある)tlv_records のシリーズであり、エンコードされた tlv_records の連続として表されている。既存のメッセージを拡張するために使用するとき、tlv_stream は一般的には現在定義されている全てのフィールドの後に置かれる。

その type は BigSize フォーマットを使用してエンコードされている。それはメッセージ固有に機能し、tlv_record の 64-bit 識別子はコンテンツの値をどのようにデコードするべきかを決定している。2^16 以下の type 識別子はこの仕様書の中で予約されているため、2^16 以上の識別子をカスタムレコードに使用可能である。ここで定義されていないレコードはカスタムレコードとして見なされる。lengthvalue のサイズをバイト単位で通知する BigSize フォーマットを使用してエンコードされる。

Requirements

送信ノード:

受信ノード:

Rationale

TLV を使用する主な利点は、各フィールドはエンコードされた要素のぴったりのサイズを運ぶため読み手が知らない新しいフィールドを無視することができることである。TLV がない場合、ノードが特定のフィールドを使用したくない場合でも、ノードは後続のフィールドのオフセットを決定するために、そのフィールドの解析ロジックを追加する必要がある。

厳格な単調性制約は全ての type は一意であり最大で一度だけ現れることを保証する。複雑なオブジェクトにマップするフィールド(ベクトル、マップ、構造体など)は、オブジェクトが単一の tlv_record 内でシリアル化されるようにエンコーディングを定義することにより、そうする必要がある。 一意性制約は、以下の最適化を可能にする。

大きいサイズの typelength の使用は小さい type や短い value の空間を節約することが可能になる。これにより、回線上または onion ペイロードにアプリケーションデータ用のより多くのスペースが残る可能性がある。

全ての type は、根本にある tlv_record の正規エンコーディングを作成するために昇順に表示する必要がある。これは、検証者が署名者のように同じメッセージダイジェストを再計算できることを保証するので、tlv_stream で署名を計算する時に極めて重要である。

書き手は長さを2回計算することになり、外側の長さの計算が複雑にならないようにするため tlv_record において冗長で可変長なエンコーディングの使用をさけるべきである。例えば、可変長のバイト列を書く時、tlv_record はすでに後続のバイト数を持っているため、その値は生バイトのみに含まれており追加の内部長は含まれていない。つまり、tlv_record が複数の可変長要素が含まれていると、これは冗長とは見なされず value から個々の要素を解析することを受け手に許可する必要がある。

Fundamental Types


様々な基本的タイプはメッセージ仕様書において言及される:

単一の値を含む TLV レコード内では、整数の先行ゼロを省略できる:

以下の便利なタイプも定義されている:

Setup Messages


The init Message

一度認証が完了すると最初のメッセージは、たとえこれが再接続であってもこのノードによってサポートされているもしくは要求されている特徴を明らかにする。BOLT #9 は特徴のリストを記している。各特徴は一般的に 2 bits で表されており、最下位ビットの番号は0(偶数)で、次の最上位ビットの番号は1(奇数)である。歴史的理由によって、特徴はグローバルとローカルビットマスクに分けられる。

features はバイトまでゼロでパッディングされなければならない。

任意の networks はそのノードが挿入されているチェーンを示している。

Requirements

送信ノード:

受信ノード:

Rationale

ここでは2つの機能ビットフィールドが使われているが、下位互換性のためにそれらは1つに結合されている。このセマンティクスにより、将来の互換性のない変更と下位互換性のある変更の両方が可能になる。オプションの機能が後で強制的になるようにするために、ビットは通常ペアで割り当てる必要がある。ノードは特徴に互換性がないとき、エラー診断書を単純化するために他の特徴の受信を待つ。

(ほとんどの実装では単一のネットワークしかサポートしていないが)全ての networks で同じポートを共有しているため、その networks フィールドは、ノードが優先ネットワークに関する更新を受信する、またはチャネルを開くことができると誤って信じるノードを回避する。