[翻訳] GitTorrentを発表 - 分散型GitHub -
#ヤク中 この投稿はChris Ball氏による次の投稿を翻訳したものです。
Chris Ball » Announcing GitTorrent: A Decentralized GitHub
すべての権利は彼に帰属します。あと私はまだ大学生なのでちょっと翻訳が汚いです。 原文より口調が強いといったこともあるかもしれません。まあこまけえことは気にせず読みな!
##本文 (この投稿は2015年の5月にData Terra Nemoのカンファレンスで行ったトークの意欲に溢れた原稿です。 私が_実際に_行ったものと同じトークをよりゆっくりと話したものの動画が近いうちに公開されます。)
私は分散型GitHubの構築に取り組んでいるのですが、このことが何を意味し、 なぜ重要なのかということについて、そしてもっと重要なことである、それがどのようにして成され、 これまでに実装してきたGitTorrentの本当のコードがどうなっているのかをここでお見せしたいと思います。
##なぜ分散型GitHubを? まず、実際問題として、GitHubはハックされたりして信頼できなくなるかもしれないということがあります。 あるいは―私がこのプロジェクトに取り組んでいるときに起こった 中国によるDDOS を受けるなんてこともあるかもしれません。その瞬間からGitHubが多くの対応を行ってくれているようであることを知っていましたが、 ベンチャーキャピタル投資によって1億ドルの資金を得た会社が使用者の意思に強く反する決定をし始めることはしばしばあることなのです。
信条に関する理由もあります。GitHubはクローズドソースであり、私たち自身によってそれをより良くすることはできません。 Mako Hillはフリーソフトウェアを制作するにあたってプロプライエタリ・ソフトウェアに依存する際の問題を Free Software Needs Free Tools というエッセイに書いています。私は彼のいうことはもっともだと感じています。他の言い方もできるでしょう。 オープンソースプロジェクトを取り巻く私達の共同作業はGitHubが決めた改変不可能なツールによって制限されてしまっているのです。
これらが実際問題と信条における理由です。3つ目の理由は「皮肉」とでも呼びましょうか。 CVSやSubversionプロトコルを利用した多くのサーバーから分散型であるGitプロトコルによる対話を行うひとつの集中サーバーに移行したというのは大きな皮肉でしょう。 Google Codeは数か月前に 終了を発表しました。 その根拠には「みんな気にせずGitHubを使っているから、もう僕はいらないんだよね」といったことがあるのは明白です。 私達はあっという間にひとつの集中型サービスに世界中のソースコードを向かわせるようになってしまったということです。
そういったことを踏まえ、特にこのカンファレンスでは、このレベルの集中が浅はかなことであるということに関して私に同意してくれるものとします。
##Gitはすでに分散型ではないのか? GitHubは集中型である一方で、Gitプロトコルは分散型ではないか、リポジトリをクローンすればそのコピーは他の人と同じにになる。 それで十分じゃないか?そう考えているかもしれません。
私はそうは思いません。FTPがあるからBitTorrentなしでもやっていけるというのを想像してみてください。 別にBitTorrentをFTPで置き換えようというのでもありませんし、全く意味のないことではないですか? まず―どのホストがFTPでどのファイルを共有しているのか示すインデックスはありません。 そのためどこを探せばよいのかわからなくなります。次に―たとえ欲しがっているコピーを誰が持っているかわかっていても、 こういったコンピューターは匿名FTPサーバーを動かそうとするようなことはありあせん。
ちょうどGitと同じように、FTPはP2Pプロトコルがするような、クライアントをサーバーに変えるようなことはしません。 これがGitが_既に_GitHubを分散しているとは言えない理由です。どこに何があるのか知ることはできませんし、 仮に出来たとしても、そういったコンピューターはあなたが対話できるGitサーバーを実行してはいません。 私はこの状況は改善できると考えます。
##リポジトリをGitTorrentしよう! GitTorrentのデモでGitTorrentの世界に飛び込んでみましょう。次の例では、 BitTorrentでホストされているGitリポジトリをクローンします。
λ git clone gittorrent://github.com/cjb/recursers
Cloning into 'recursers'...
Okay, we want to get: 5fbfea8de70ddc686dafdd24b690893f98eb9475
Adding swarm peer: 192.34.86.36:30000
Downloading git pack with infohash: 9d98510a9fee5d3f603e08dcb565f0675bd4b6a2
Receiving objects: 100% (47/47), 11.47 KiB | 0 bytes/s, done.
Resolving deltas: 100% (10/10), done.
Checking connectivity... done.
皆さん!たった今BitTorrentでGitリポジトリをクローンしました!それでは、 行ごとにこれを追って見てみましょう。
1-2行目: Gitは実際に、内蔵されているネットワーク・プロトコルを拡張する仕組みを持っています。
これは私のgit clone
コマンドを「git-remote-gittorrent
コマンドを実行しURLを引数として渡す」
と読み替えることで実現されます。つまり実際のダウンロードをしたいようにすることができ、
gitオブジェクトを新しいディレクトリに書き込みGitに終わったことを教えることになります。
これを作るのにGitを弄る必要は全くありません。
ここからgit-remote-gittorrent
が仕事を引き受けます。まずGitHubに接続してこのリポジトリの最新のリビジョンを突き止め、
何が必要なのか理解します。GitHubは5fbfea8de..
と教えてくれます。
4-6行目: それからBitTorrentと同じようにハッシュテーブルが配布されているGitTorrentネットワークに乗り出し、
誰か5fbdea8de..
コミットのコピーを持っていないか聞きます。誰かがYes!と答えました。
彼らとBitTorrent接続を行います。BitTorrentの配布ハッシュテーブルはこんな感じに欲しがっているコンテンツを誰が送信できるか教えてくれるget_nodes(hash)
という一つの処理を行うことによって利用することができます。
get_nodes('5fbfea8de70ddc686dafdd24b690893f98eb9475') =
[192.34.86.36:30000, ...]
さて、標準のBitTorrentで”trackless torrents”を行う際には、コンテンツとしてほしい_ファイル_を要求し、
そして手に入れることができればめでたしめでたしということなんですが、
Linuxカーネルのサイズのリポジトリでは400万コミットあり、たった一つのコミット5fbdea8de..
を受け取るだけでは
役に立ちません。更にコミットごとに400万個のリクエストを発行する必要もあります。
さもなくば’git pull’する度に1コミットずつ手に入れることになってしまいます。そこで、
他の手段が必要になるというわけです。
8-12行目: Gitはこの問題を解決します。Gitはgitオブジェクトの交換のネゴシエーションのために”smart protocol format”を持っています。 これは次のように考えることができます。
リポジトリに1から20の20コミットがあると考えてください。
15番目のコミットはbbbb
で最新の20番目のコミットはaaa
です。
Gitプロトコルのネゴシエーションはこんな感じに見えるはずです。
1> have aaaa
2> want aaaa
2> have bbbb
git graphの仕組みにより、ここではノード1>がbbbb
を探すことができます。
5コミットを要求しているだけなので、それらのみの”packfile”を作成しているのに注目してください。
たった3段階の対話です。
以上が今回GitTorrentでしたことです。欲しいコミットを探してBitTorrentでノードとつなぎますが、 一旦接続されれば、BitTorrent Extensionと呼ばれるBitTorrentプロトコルの最上層にあるオーバレイに施されたSmart Protocolネゴシエーションを実施することができます。 それからリモートノードはパックファイルを作成しそのパックファイルのハッシュを伝えてくれます。 そしてパックファイルのダウンロードをそのノードや標準のBitTorrentを利用してシードしている他のノードからダウンロードします。 展開したあとGitコミットのグラフが終わるはずの地点で終わっているか調べることにより、packfileを認証することができます。 もしそこで終わってなかったら他のノードが嘘をついたことになるので、その代わりに誰かまた他のノードと対話を試みます。
これがさっきこの端末で起こったことの全てです。そのハッシュ値を持つ、つまり最新のすべてのオブジェクトを含んでいるpackfileを得ることが出来ました。 ダウンロードして展開し、そして今、ここにローカルのGitリポジトリがあるわけです。
このgit cloneによって通常のGitHubのやり方で行われているようにgitオブジェクトの実際の ダウンロードを行うためにすべきことをすべて行います。もしGitHubが明日ディスクと帯域幅の仕事をダルい仕事だと結論づけてしまっても、 ユーザーにGitTorrentバージョンを実行するように呼びかけることができます。 これはGitHub用のP2Pコンテンツデリバリネットワーク (訳注: CDN)を構築するようなもので、 現在CDNにほしいコミットがない場合はGitHubのサーバーにフォールバックします。
##本当に分散されたのか?
ある程度は分散できました。しかし最終的に狙っているもののハッシュを見つけるためGitHubに対話したのが正に最初にしたことであることに気づいた人もいるでしょう。
もし本当にGitHubを分散化しようとするなら、それよりより良い方法、
すなわちリポジトリの所有者にそのリポジトリの最新版のハッシュが何か教える方法が必要となります。
端的に言えば、私達は今ダウンロードできるgitオブジェクトのデータベースを持っているのですが、
どのオブジェクトが欲しいのか知る必要があるのです。GitHubのユーザー/リポジトリ
にある部分をエミュレートし、
ユーザーのリポジトリの正に最新版を受け取っていることを知る必要があるのです。
じゃあ、なんとか良くしてみましょう。ハンマーがあったら何でも釘に見えますよね。
私のハンマーは配布されたハッシュテーブルで、どのコミットをどのノードが持っているか追跡するために作りました。
つい最近、subtrackがそれぞれのノードにネットワーク全体で共有されるキー・値の保持の一部分を行わせることができるBitTorrent拡張があることに気づき、
コードを書き上げました。DHTにget()
とput()
という2つの動作を付け加えました。
put()
はキーごとに1000バイトのメッセージをネットワークに置くことができ、
そのメッセージは後に参照され、ネットワークから離れたあとも他のノードによって繰り返されます。
2種類のキーがあり、一つはイミュータブルキーで、ご想像通り、登録したいデータのハッシュをとるだけで、
データはキーとなるハッシュとともに保存することができます。
2つ目の種類の鍵はミュータブルキーで、この種類のキーではキーペアの公開鍵のハッシュを見つけられます。 キーペアの所有者は値をその鍵で署名付きのアップデートを公開することができます。アップデートは連続した数値が割り振られるので、 クライアントは既に記録されている番号より新しい番号のアップデートを確認することで、 いつでも一つのミュータブルキーに対し一つのアップデートを見ることができます。 そしてアップデートがハッシュテーブルキーに対応する公開鍵で署名されていることを確認することにより、 キーの所有者からアップデートが来たことを証明できます。もしそれらの条件を満たせばその新しい値で更新して再配信を開始します。 これには様々な利用方法がありますが、私の場合リポジトリがなんと呼ばれ最新版がなんであるかを保存する場所として用います。 つまりローカルなGitコミットを作成して、そのネットワークにプッシュしてから、個人用ミュータブルキーにアップデートをプッシュして新しいコミットがあることを反映させます。 新しい処理のコードによる説明をお見せしましょう。
// Immutable key put
hash(value) = put({
value: 'some data'
})
// Mutable key put
hash(key) = put({
value: 'some data',
key: key,
seq: n
})
// Get
value = get(hash)
もうGitTorrent上のGitHubリポジトリをクローンするように誰かに言おうと思っても、github.comのURLを渡すことはありません。 代わりに私の公開鍵のハッシュである長い16進数値を渡します。これは配布されたハッシュテーブルのミュータブルキーとして使われます。 そのデモをお見せします。
λ git clone gittorrent://81e24205d4bac8496d3e13282c90ead5045f09ea/recursers
Cloning into 'recursers'...
Mutable key 81e24205d4bac8496d3e13282c90ead5045f09ea returned:
name: Chris Ball
email: chris@printf.net
repositories:
recursers:
master: 5fbfea8de70ddc686dafdd24b690893f98eb9475
Okay, we want to get: 5fbfea8de70ddc686dafdd24b690893f98eb9475
Adding swarm peer: 192.34.86.36:30000
Downloading git pack with infohash: 9d98510a9fee5d3f603e08dcb565f0675bd4b6a2
Receiving objects: 100% (47/47), 11.47 KiB | 0 bytes/s, done.
Resolving deltas: 100% (10/10), done.
Checking connectivity... done.
このデモではまたGitリポジトリをBitTorrentを介してクローンしましたが、 配布されたハッシュテーブルをを代わりに求めることによって探しているコミットを見つけることができたのでGitHubと全く対話する必要がありませんでした。 正にGitダウンロードの真の分散化が達成されたのです!
最後の不満点は、16進数の長い文字列は便利なユーザー名にはなってくれないということです。 私達は確かに信用できるハッシュテーブルの頒布によって達成できることの限りに直面しています。 これはユーザー名が争奪されうる、つまり2人の異なる人が同じユーザー名の所有を主張するアップデートを提出しうるということです。 2人の論争を解決する方法はありません。ユーザー名を与え、誰がその所有者なのか理解するため、 「合意の共有」を行う方法が必要です。私が見つけたもっとも信頼できる方法は実はBitcoinのblockchainです。 合意の共有が暗号通貨を可能にするのです。
Bitcoin取引の種類の一つとして、OP_RETURNトランザクションというものがあり、 ある財布から他の財布にお金を移す代わりに、blockchainに永遠に記録される取引のコメントを残します。 最近まで取引ごとに40バイトのコメントに制限されていましたが、Bitcoin Core 0.11によって80バイトまで引き上げられました。 blockchain上のどんなBitcoin取引も現在は約0.08米ドルかかるはずなので、 blockchainを80バイトのデータで汚染する代わりにマイナーとネットワークにに8セント支払うのです。
もしblockchainにコメントを残せるのなら、「やあ、ユーザー名はChrisを使いたいんだ。 僕の公開鍵のハッシュは<x>だよ」なんていうコメントも残せます。もし複数の人が同じユーザー名を要求したら、 blockchainは完全な履歴を誰でも見ることができる登録専用のデータ構造なので、 今度は最初に要求したユーザーの公開鍵の使用に同意します。これがBitcoinの本当の美しさです。 この通貨関連と言ったものは率直に言って私には面白くないものですが、 強固な方法で合意の共有を解決する方法を見つけ出しました。 取引のコメントはこんな感じになるかもしれません。
@gittorrent!cjb!81e24205d4bac8496d3e13282c90ead5045f09ea
(@service!username!pubkey)
通貨関連は面白くないと言いましたが、これは面白そうです。 最初にある”gittorent”は別になくても全く問題ないかもしれません。 もしかしたらこれはBitcoinによる分散型ユーザーアカウントに興味がある全てのサイトにこの方法でユーザー名を登録することができるかもしれませんし、 それからそれらのサイトの全てのユーザー名を既に得ていることになるのです。 これは別のモジュールやソフトウェアプロジェクトで実装されるかもしれません。 ユーザーアカウントを取得するために分散型アプリにそれらを導入すれば、 PythonやNode、Goと言ったあらゆる言語で動かすことができるでしょう。 blockchainを監視してデータベースに書き込むアプリとデータベースを解釈する、 Webやネットワークサービスのフレームワークへのプラグインで構成されることになるかもしれません。
驚きなのはこのような仕組みは分散型コミュニティで現在存在しないということです。 このようなプロジェクトに取り組むことができ、またその最上位にGitTorrentを据えることができ嬉しく思います。 興味がある方がいらっしゃれば、ぜひ教えていただきたいと思います。
ところで、ユーザー名の登録は私がさっき言ったよりはちょっと複雑になります。 なぜならマイナーはメッセージを見て、blockchainに追加する前にあなたのユーザー名を、 あなたのものとしてではなく、_彼ら_のものとして登録できてしまうからです。 これはドメイン名登録と同じで、欲しいドメインが利用可能か調べるために検索ボックスに入力すると、 その瞬間にそのドメインを登録業者が彼ら自身のものとして登録し、 それからあなたに10万支払えというわけです。これはよくありません。
これを気にする方のために、Bitcoinは2段階の登録による回避策を持っています。 最初のメッセージではユーザー名のハッシュのみを提出し、ユーザー名を予約するように要求します。 マイナーはハッシュからユーザー名を知ることはできませんので、あなたを先回りすることはできません。 もし予約がブロックチェインに登録され、先に他に誰も予約をしていなかったら、 「よし、じゃあ予約トークンを使わせてもらおう。予約したユーザー名はこれだよ。」 といった2つ目のコメントを送信します。これであなたのものになりました。
(私がこの方法を発明したわけではありません。Jeremie Miller氏によるBlocknameというプロジェクトでは、 bitcoinのblockchainへのDNS登録のためのOP_RETIRNトランザクションを用いて、正にこの方法 を実装します。唯一の違いはBlocknameがドメイン名登録を行うという点で、私の場合ユーザー名から 公開鍵のハッシュに割り当てました。かなり似たものとしてBlockstoreがあるという指摘も受けました。)
要約すると、GitオブジェクトのグローバルなBitTorrent swarmを作成し、ユーザーアカウント登録に取り組みました。 そのため、ユーザーの実体験はこんな風になるでしょう。
これが
git clone gittorrent://github.com/cjb/foo
こうなって、
git clone gittorrent://81e24205d4bac8496d3e13282c90ead5045f09ea/foo
こうなります。
git clone gittorrent://cjb/foo
この時点でGitHubの主な機能である、Gitリポジトリを探し、ダウンロードする、分散型の代替を達成したことになります。
##最後に まだもっとすべきことがたくさんあります。例えば、コメントやIssue、 Pull RequestといったどれもGitHubにはとても重要な側面を欠いています。
私が気に入っているこの問題の解決策は、コードリポジトリ内に問題をファイルとして実際に登録するというものです。 これによりブランチをマージすることでコードの変更とIssueの変更、例えばIssueの解決といったことの両方をそのブランチにマージできるということです。 このアイデアの実装の一つとしてBugs Everywhereがあります。
分散型ネットワークの追記専用のメッセージストリームを同期するSecure Scuttlebutt上でのIssueやPull Requestの運用も考えられます。
ですが、私はここまでこれただけで十分幸せです。この設計についてみなさんの意見を聞いてみたいと思います。 GitTorrent自体の設計は(十分皮肉なことですが)GitHub上にあります。 どんな改善点でもPull Requestは大歓迎です。
あなた方のうち数人には感謝しなければなりません。まずは私がここで使っているBitTorrentライブラリを書いてくださったFeross Aboukhadijeh氏にです。 彼のP2Pとへの情熱と彼の「マッド・サイエンス」なプロジェクトに携わる人々のコミュニティに、 私はとてもワクワクしましたし、私の貢献も歓迎してもらえました。 これは私がこのプロジェクトに取り組むようになった理由の一つでもあります。
またニューヨーク市のRecurse Centerに出席する間、 仕事を休むことができるため、このプロジェクトに取り組むことができています。 これは”Hacker School”とかつて呼ばれていた場所で、最近その名前を変えました。 その第一の理由は人々がものを教わるという学校の言外の意味を取り除くことです。 3か月のプロジェクトを通してプログラミング能力を向上させるプログラマーにとっての隠れ家と言いったほうがより本来の姿に近いでしょう。 出席することを許してくださった彼らに本当に感謝しています。
彼らが名前を変えようと決めた2つ目の理由はアメリカの国境で「ハッカースクールに行くために来ました!」 と言って…つまらない時間を過ごす羽目になってしまう海外からの出席者が続出したからです。
最後に、なぜ私がこの種の仕事が面白く、また重要だと考えているかについていくつか言葉を述べて終わりたいと思います。 プロジェクトには特定の大きさ、幅広さがあります。GitHubやWikipediaをその例としましょう。 大きなデータセンターでディスクや帯域幅を保持するためにGitHubやWikipediaのように何千万ドルを稼ぐこと以外に、 有名になったあと世界規模でプロジェクトを存続させるための方法はありません。これにより、 運営のため1年に何千万ドル稼ぐためにビジネスプランを作ることができる規模のプロジェクトしか制作したり想像したりできなくなってしまいます。 分散とP2Pアルゴリズムによって、そのような規模の投資がなくてもお互いに助け合い、 共有することのできるユーザーさえいれば夢のあるソフトウェアを作ることを考えられるようになることを願っています。
この度は聞いてくださり本当にありがとうございました。
(GitHub上のGitTorrentを確認したりそれについてHacker Newsで議論できます。 また、Twitterでは私をフォローできます。)