プロトコル

フィーダー、リレー、クライアントが相互運用するために話す必要がある内容です。リファレンスは Tally リポジトリの wire クレートです。リポジトリ内でプロトコルをエンコード・デコードする唯一のコードであり、すべてのバイナリがこれを使っています。整数はすべてビッグエンディアンです。

トランスポート

すべてのホップは TCP 上の Noise_IK_25519_ChaChaPoly_BLAKE2s です。各 Noise メッセージは 2 バイトの長さに続けて送られ、タグを含めて最大 65,535 バイトで、完全なレコードだけを運びます。

ID は 1 つの Ed25519 鍵です。Noise が認証する X25519 鍵はそこから導出され(libsodium の sk_to_curve25519)、イニシエーターの最初のハンドシェイクメッセージには、イニシエーターの 32 バイトの Ed25519 公開鍵が含まれます。レスポンダーはそれを、ハンドシェイクで証明された鍵と照合します。1 つの鍵が、どこでも 1 本のアンテナを表します。

プリアンブル

ハンドシェイクの前に、イニシエーターは平文で 16 バイトを送ります。これは Noise のプロローグでもあるため、1 バイトでも変わればハンドシェイクは失敗します。また、これによって将来ハンドシェイク自体を変更でき、リレーは鍵のローテーション中に新旧両方の鍵を保持できます。

バイトフィールド意味
0–3マジックASCII 文字の TALY。
4プリアンブルのバージョン1。
5ハンドシェイク1:上記の Noise パターン。
6–7予約ゼロ。
8–15鍵ヒント接続の宛先となるレスポンダーの鍵。その X25519 鍵に対する BLAKE2s-256 の先頭 8 バイトです。

バージョン

続いてイニシエーターは、対応するワイヤーバージョンの最小値と最大値、および自分の役割を載せた Hello を送ります。レスポンダーは、以後双方が使うバージョンを載せた Welcome、または理由と待機時間を載せた Goodbye で応答します。最初のバイトから Welcome までは最大 15 秒で、それ以降の各送信には 30 秒の期限があります。現時点でワイヤーバージョンは 1 だけです。

リレーは、これまでにフィーダーが出荷したすべてのワイヤーバージョンに、永久に応答します。インストール済みのフィーダーは更新されず、プロトコルのほかの部分はすべてこのルールを前提にしています。

レコード

レコードは、種別を表す 1 バイト、2 バイトの本体長、本体で構成されます。ワイヤーバージョン 1 が認識する種別は次のとおりです:

種別レコード本体
0x01Hello最小バージョン、最大バージョン(各 2 バイト)、役割(1 バイト:1 フィーダー、2 購読者、3 リレー、4 MLAT(位置を公開するリレー))。
0x02Welcome以後双方が使うバージョン(2 バイト)。
0x03Batch受信機の署名付きバッチ(後述)。リレーはバイト単位でそのまま転送します。
0x04ReceiverInfo受信機による署名付きの自己記述。位置とその精度、クロッククラス、ソフトウェア、選択したリレーを含みます。
0x05Heartbeat空。生存確認です。
0x06Redirect待機秒数(4 バイト)と、ヒントとしてのリレー。意味は「離れてほしい」だけで、接続先はフィーダーが引き続き自分のルールで選びます。
0x07RelayListこのリレーが把握しているリレー。ヒントとして提示されます。
0x08RateLimit毎秒バイト数とバースト(各 4 バイト)。リレーが望む上限です。フィーダーはこれより低くしてもかまいませんが、所有者が設定した上限を超えることはありません。
0x09Goodbye理由(1 バイト)と待機秒数(4 バイト)。リレーが接続を閉じます。
0x0aSubscribeストリーム(1 バイトのフラグ:1 生データ、2 重複除去済み、4 位置)、件数(2 バイト)、その数の H3 セル(各 8 バイト、最大 64)。購読者の前回の Subscribe を置き換えます。
0x0bRelayBatchリレー自身が署名したバッチ。重複除去済みストリームです。
0x0cPositionsリレーの MLAT が求め、そのリレーが署名した位置。

変更のルール

フィーダーは更新されないため、フィーダーを更新せずにプロトコルを変更するための次のルールがあります:

  • 未知の種別はスキップされます。ただし、最上位ビット(0x80)で重要と示されている場合は、セッションを正常に終了します。したがって新しいレコードは、無視すると不都合が生じる場合を除き、重要とはしません。
  • 本体には、読み手が知っているフィールドの後ろにバイトが続くことがあり、それらは無視されます。フィールドは末尾に追加する形で増やします。
  • 読み手は、知らない列挙値を Other という値として保持し、エラーにはしません。
  • 署名付きの形式は、どのフォーマットバージョンでも同じプレフィックスを保ち、それより前のすべてに対する署名で終わります。そのため、リレーはそれ以外の部分を読めないフォーマットでも、検証、ルーティング、重複除去ができます。
  • 観測データのフォーマットは、1090 MHz では BEAST 自身のタイプバイトです。978 MHz UAT には新しい値を割り当てるため新しいレコードは不要で、リレーは知らないフォーマットもそのまま転送します。

署名付きバッチ

バッチは、1 台の受信機の約 1 秒分の受信データです。フォーマット 1 の構成は次のとおりです:

バイトフィールド意味
1フォーマット1。
32鍵受信機の Ed25519 公開鍵。
8ブート IDフィーダーの起動ごとにランダム。
8シーケンス1 回の起動の中で 0、1、2 と続く番号。下流での欠番は、いずれかのホップが届けなかったデータです。
4カウンターエポック受信機のカウンターが再始動した可能性があるたびに増やします。これにより、再始動の前後のカウンターが混ざることはありません。
8実時間時計フィーダーの時計(Unix ミリ秒)。参考情報であり、正しくない場合があります。
4破棄数前回のバッチ以降、フィーダー自身の上限によって破棄された受信データの数。
32前バッチこの起動での前のバッチのハッシュ。最初のバッチではゼロ。これにより、受信機が 2 つの履歴に署名することはできません。
4件数続く観測データの数。
各 10 + n観測データそれぞれ、フォーマット(1 バイト)、受信機の生の 48 ビットカウンター(6)、信号レベル(1)、長さ(2)、そしてその長さ分の、デコーダーが出力したままのメッセージのバイト列。
64Ed25519 署名それより前のすべてに対する署名。

観測データのフォーマット:1 は Mode A/C(2 バイト)、2 は Mode-S short(7)、3 は Mode-S long(14)、D は 978 MHz UAT のダウンリンク、U は UAT の地上アップリンクで、それぞれ ASCII 文字として書き込みます。

署名の対象は、ASCII テキストの tally batch、ゼロバイト 1 つ、そして署名より前のバッチの全バイトです。リレー自身の重複除去済みバッチは代わりに tally relay batch で署名するため、一方が他方になりすますことはできません。

バッチの ID は、署名を含む全バイトの BLAKE2s-256 ハッシュです。リレーはこれを使って重複を除去し、次のバッチの前バッチフィールドがこれを指します。

先頭の 49 バイト(フォーマット、鍵、ブート ID、シーケンス)は将来のどのフォーマットでも位置を変えず、署名は常に最後に置かれます。

MLAT に渡す前にカウンターを補正することは、誰であっても決してありません。リレーの MLAT が位置を解くには生のカウンターが必要だからです。