Develop with pleasure!

福岡でCloudとかBlockchainとか。

ProtocolのバージョンとUser Agentを分離したBIP-014

作られたのは2011年とだいぶ前のBIPだけど、あまりPeer ServiceレイヤーのBIPを見てなかったので見てみる。
昔はプロトコルのバージョンとクライアントのバージョンが同じだったのね。

bips/bip-0014.mediawiki at master · bitcoin/bips · GitHub

動機

BitcoinプロトコルはSatoshiクライアントから始まったが、現在ではコミュニティも多様化し、様々な言語(Java, Python, Javascript, C++)で書かれた独自のコードベースを持つクライアントが、独自の機能セットを急速に開発 している。

プロトコルにはバージョンが埋め込まれている。このバージョン番号は主にversionメッセージとgetblocksメッセージ、ブロックを作成したソフトウェアのバージョンを示すblockメッセージに含まれている。現在このバージョン番号はクライアントのバージョン番号と同じである。このBIPでは、プロトコルのバージョン番号とクライアントのバージョン番号を分離するための提案である。

論拠

バージョン番号が分離されていないと、Satoshiクライアントのリリースの度に内部のバージョン番号がインクリメントされることになり、こうなると他の全てのクライアントもSatoshiのバージョン番号に追いつく必要が出てくる。Bitcoin開発者のあるグループのリリーススケジュールに全てのソフトウェアのリリースを合わせるといったことになり、これはBitcoinが本来持つ分散型の特性とは異なる。

バージョンのバンプは非互換性を生み、ネットワークを破壊する可能性もある。ネットワークの健全性が維持されるためには、プロトコルの開発とプロトコルの実装は分けて考える必要がある。全てのグループの代表者と共にプロトコルの舵をきるニュートラルな第3のエンティティの存在が、Bitcoinが最小のリスクで積極的に成長する機会を提供することになる。

プロトコルバージョンを利用することで、ネットワーク上の全ての実装に共通の標準を設定することができ、何がプロトコルで何が実装依存なのかの境界について誰もが同意できるようになる。User Agentの文字列はクライアントがネットワーク内で自分自身を識別するためのvanity-plateとして提供される。

ネットワークプロトコルを実装から分離し、参加者間の相互合意によりプロトコルを開発するということは、議論によって合意が困難な場合にはこの民主的な意思決定は不利益をもたらす。この問題を軽減するためには強力なコミュニケーションチャネルと迅速なリリーススケジュールが必要となるが、それについてはこのBIPの範囲外。

User Agentは、使っているクライアントの実装や共通のアーキテクチャ/OSなどのネットワークデータを把握するのに便利な余分なトラッキング情報を提供する。稀に、ネットワークの健全性を脅かすクライアントを排除するための緊急の方法として利用されることも考えられるが、これは基本的に推奨される使い方ではない。User Agentは異なるクライアントの実装をワークアラウンドに動作させるための方法ではない(そういう使い方をするとプロトコルの破壊に繋がる)。

まとめると

  • Protocol version
    異なる動作をするノードを区別する方法
  • User Agent
    シンプルな情報ツール(User Agentに応じてプロトコルを変更しないこと)

ブラウザのUser-Agents

RFC 1945ではUser Agentを製品の文字列にオプションのコメントを付けて曖昧に指定している。

Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.6) Gecko/20100127 Gentoo Shiretoko/3.5.6

User Agentは人間よりコンピュータによって解析されることの方が多い。スペースで区切るフォーマットでは簡単、高速にまた効率的に解析することができない。またデータにはその階層を示す構造は含まれていない。

情報の最も直接的な部分には、ブラウザの製品名、レンダリングエンジンおよびビルド(Gentoo Shiretoko)とバージョン番号がある。デスクトップ環境やプラットフォーム、言語、ビルドのリビジョン番号などさまざまな情報はコメントに含まれる。

仕様

versiongetblocksパケットのversionフィールドは、プロトコルのバージョン番号になる。blocksのバージョン番号は、そのブロックが作成されたときのプロトコルのバージョンを反映する。

versionパケットの現在使われていないsub_version_numフィールドが新しいUser Agentの文字列となる。

BitcoinのUser Agentは、パースしやすく一貫性のあるデータを構成するためブラウザのUser Agentに変更を加えたものになる。Bitcoinでは、ソフトウェアは通常、コアのcode-baseからGUIまでのスタックで構成されている。そのためUser Agentの文字列でこの関連をコード化する。

基本フォーマットが↓

/Name:Version/Name:Version/.../

サンプル

/Satoshi:5.64/bitcoin-qt:0.4/
/Satoshi:5.12/Spesmilo:0.8/

ここでbitcoin-qtとSpesmiloはプロトコルバージョン5.0を使うが、両者が使っている内部のコードベースは同じソフトウェアの異なるバージョンになっている。バージョン番号には厳密なフォーマットは定義されてないが、このガイドでは以下を推奨する。

  • バージョン番号は、メジャー.マイナー.リビジョン(例:2.6.41)というフォーマットを使う
  • リポジトリビルドにはYYYYMMDD(例:20110128)というフォーマットのデータを使う

gitリポジトリのビルドの場合、リビジョンビルドにgitのcommitを使用することも可能だが、先行するリポジトリがなければすぐには明らかにならないという問題もある。そのため上記の日付のフォーマットを推奨するが、これは決して要件ではない。

オプションで-r1-r2をUser Agentのバージョン番号に付与できる。これは推奨事項だが必須要件ではない。User Agentの構文エラーとなる():/を含めない限り、バージョン番号は任意のフォーマットで指定できる。

バージョン番号の後にオプションのコメントフィールドを設けることも可能。その際コメントは()で区切ること。コメント内の区切り文字としてはセミコロンの使用を推奨している。

サンプル

/BitcoinJ:0.2(iPad; U; CPU OS 3_2_1)/AndroidBuild:0.8/

従って予約シンボルは/:()

  • /
    code-stackのデリミタ
  • :
    特定のスタックの実装バージョンを指定するのに使用
  • ()
    コメントのデリミタ(オプションでコメント内のデータのデリミタとして;

タイムライン

このBIPが公開された時点でBitcoinプロトコルとSatoshiクライアントのバージョンは0.5で、開発が行われている。この変更の対応における影響を最小限にするため、次のプロトコルバージョン0.6はクライアントバージョンから除外された。2012年1月からプロトコルと実装(クライアント)のバージョン番号はそれぞれ異なる値になっている。

プロトコルのバージョン遷移は↓に記載されていて、0.6.0からこのBIPのルールがて適用されている。

https://bitcoin.org/en/developer-reference#protocol-versions

現在のバージョンはBIP-152をサポートにより70014が最新みたい。

311→31402にガッツリ上がってるのは何があったのか?