IPFS
最終更新日:2018-10-25
IPFSとは、WEBをより速く、より安全に、より開かれたものにするためのP2Pハイパーメディアプロトコルです!
https://www.youtube.com/watch?v=8CMxDNuuAiQ
概要
go-ipfs v0.4.17を前提に解説する。
IPFS (InterPlanetary File System) はP2Pで分散されたファイルシステムのためのプロトコルであり、その仕様を定義するプロジェクトである。また、仕様はまだまだ策定中 (wip) となっている。
IPFSは全てのコンピュータデバイスを同じファイルシステムで繋ごうという分散ファイルシステムとなっている。これはある側面では元々のWEBの目標に似ているが、あるGitリポジトリ内のオブジェクトを交換するようなBitTorrentのsingle swarmと考えた方がより近い。言い換えれば、IPFSはコンテンツに対してハイパーリンクのアドレスが定義される(同じハッシュ値を持つコンテンツなら同じアドレスになる)ような高スループットのブロックストレージモデルとなっている。 IPFSはマークルDAG (リンクがハッシュの有向非巡回グラフ) を形成する。マークルDAGはバージョン管理可能なファイルシステムやブロックチェーン、パーマネントWEBを構築できるようなデータ構造となっている。
GitのマークルDAGのイメージ
https://gyazo.com/c2db18606a43c642697045766acb1d76
IPFSはブロック交換を奨励するような分散ハッシュテーブル (Kademlia) と、自己証明する名前空間を組み合わせている。 また、SPoF (単一障害点) が無く、ノードはお互いを信頼する必要がないtrustlessなシステムになっている。
サマリー
IPFSはプロトコルである
コンテンツごとにアドレスが決まるようなファイルシステムを定義する
コンテンツ配信を調整する
Kademlia + BitTorrent + Gitを組み合わせる
IPFSはファイルシステムである
ディレクトリとファイルがある
マウント可能なファイルシステム(FUSE経由)となっている
IPFSはウェブである
ウェブのように、文書を表示するために使用することができる
HTTP経由でhttps://ipfs.io/<path>からファイルにアクセス可能
ブラウザまたは拡張機能で直接ipfs://URLやdweb:/ipfs/URIスキームの使い方を学ぶことができる
ハッシュ値でアドレス指定されたコンテンツの真正性 (Authenticity) を保証する
IPFSはモジュール化されている
任意のネットワークプロトコル上の接続層
ルーティング層
DHT (kademlia / coral) によるルーティング層を利用
パスベースのネーミングサービスを利用
BitTorrentにインスパイアされたブロック交換を利用
IPFSは暗号化される
暗号学的ハッシュ関数によるコンテンツアドレスの決定
ブロックレベルで重複を除外
ファイルの整合性 (integrity) とバージョン管理
ファイルシステムレベルの暗号化と署名のサポート
IPFSはp2pである
ワールドワイドでp2pファイル転送
完全に分散したアーキテクチャ
中央の障害がない
IPFSはCDNである
ローカル環境でファイルシステムにファイルを追加すれば、そのまま世界中でそのファイルが利用できるようになる
キャッシュフレンドリー(名前がコンテンツのハッシュ値になる)
ビットトレントベースの帯域分散
IPFSにはネームサービスがある
SFS (Self-Certified Filesystems) にインスパイアされたIPNS
PKI (Kademliaのpublic key infrastructure) に基づくグローバルな名前空間
信頼されたチェーンを構築する役割を果たす
他のNSとの互換性
DNS, .onion, .bitなどをIPNSにマップできる
実装について
実装はGo実装がリファレンスとして提案されている。また様々な言語によるHTTP APIが非公式のコミュニティで開発されている。
使い方
まずgo-ipfsのコメントから引用
code:warning
-------------------------------------------------------
| Warning: |
| This is alpha software. Use at your own discretion! |
| Much is missing or lacking polish. There are bugs. |
| Not yet secure. Read the security notes for more. |
-------------------------------------------------------
code:security-notes
IPFS Alpha Security Notes
We try hard to ensure our system is safe and robust, but all software
has bugs, especially new software. This distribution is meant to be an
alpha preview, don't use it for anything mission critical.
Please note the following:
- This is alpha software and has not been audited. It is our goal
to conduct a proper security audit once we close in on a 1.0 release.
- ipfs is a networked program, and may have serious undiscovered
vulnerabilities. It is written in Go, and we do not execute any
user provided data. But please point any problems out to us in a
github issue, or email security@ipfs.io privately.
- security@ipfs.io GPG key:
- 4B9665FB 92636D17 7C7A86D3 50AAE8A9 59B13AF3
- ipfs uses encryption for all communication, but it's NOT PROVEN SECURE
YET! It may be totally broken. For now, the code is included to make
sure we benchmark our operations with encryption in mind. In the future,
there will be an "unsafe" mode for high performance intranet apps.
If this is a blocking feature for you, please contact us.
これらを踏まえた上で、MacOS前提でIPFSの使い方を解説していく。
なお、IPFS実装としてgo-ipfsを利用するが、go-ipfsはIPFSのリファレンス実装となっており、他にもJavaScript実装が開発中、PythonやCによる実装は始まったばかりという感じ。
インストール
code:bash
tar xzf go-ipfs_v0.4.17_darwin-amd64.tar.gz
cd go-ipfs
./install.sh
ipfs version
アップデートも上記手順で出来る。go-ipfsをデーモンとして起動している場合は停止してから行う。
IPFSリポジトリの初期化
code:bash
ipfs init
リポジトリにコンテンツ追加
code:bash
echo "hello world" > test1.txt
ipfs add test1.txt
すると、
added QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o test1.txtt
という出力が得られる。
code:bash
ipfs cat QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o
とすると中身を見ることができる。
同じコンテンツなら同じアドレスになる
すでに概要で説明したが、改めて実験してみる。
code:bash
echo "hello world" > test2.txt
ipfs add test2.txt
すると、
added QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o test1.txt
という出力が得られる。これはtest1.txtと同じハッシュ値であり、コンテンツとして同一であることを示している。
従来のWEBではtest1.txtやtest2.txtのファイルがある場所(アドレス)を指定して取得していたが、IPFSではコンテンツ自体の識別子(アドレス)を示すハッシュ値を指定する。これがコンテンツ指向の思想となっている。
大きなファイルはチャンクに分割されて保存される
コンテンツのサイズが256kBを超える場合は256kB以下のチャンクに分割して管理される。こうすることでBitTorrentのように一つのノードに集中させず複数のノードに分散することでコンテンツ取得を高速化できる。
code:bash
ipfs add Lenna_\(test_image\).png
するとQmY6uB34eTv4dptqt6RX22yNmSGYgqm44T7q6dNiRfhFYXというアドレスが得られる。これをlsしてみる。
code:bash
ipfs ls QmY6uB34eTv4dptqt6RX22yNmSGYgqm44T7q6dNiRfhFYX
すると
QmW38fM6fKFpLqn19Y9k22EzGDbTdV9ZMJUr77QuPpGEsp 262158
QmQ7RY8ihrvQuihep5K8fyefQjLNZLVNacFV88iJCVqneD 211701
が得られる。2つのオブジェクトが参照されている。IPFSからLennaの画像を取得し、元の画像と比較してみる。
code:bash
ipfs cat QmY6uB34eTv4dptqt6RX22yNmSGYgqm44T7q6dNiRfhFYX > Lenna_ipfs.png
cmp Lenna_\(test_image\).png Lenna_ipfs.png
何も出力されず、差分がないことがわかる。
ディレクトリ
ディレクトリを作成してアクセスすることもできる。ディレクトリはコンテンツをさすリンクオブジェクトとなっており、これらを辿ることでコンテンツにアクセスできるよう実現されている。
code:bash
mkdir testdir
mv test*.txt testdir/
mv Lenna_ipfs.png testdir/
テスト用ディレクトリtestdirを作成し、先ほど使ったファイルを移動した。次にipfs addでディレクトリ自体を追加してみる。-rオプションを使うと再帰的に追加できる。
code:bash
ipfs add -r testdir
added QmY6uB34eTv4dptqt6RX22yNmSGYgqm44T7q6dNiRfhFYX testdir/Lenna_ipfs.png
added QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o testdir/test1.txt
added QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o testdir/test2.txt
added QmQXCPxeFCbXEoCb6fk2eEfkg4VmF9ybrgFPwQnu3sYi2p testdir
というような結果が得られる。同じコンテンツのアドレスは同じハッシュ値になるので、さっきやった時と同じアドレスが得られる。testdirのアドレスをlsしてみると
code:bash
ipfs ls QmQXCPxeFCbXEoCb6fk2eEfkg4VmF9ybrgFPwQnu3sYi2p
QmY6uB34eTv4dptqt6RX22yNmSGYgqm44T7q6dNiRfhFYX 473963 Lenna_ipfs.png
QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o 20 test1.txt
QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o 20 test2.txt
という結果が得られ、test1.txtなどの名前付きのリンクが含まれる。つまり
code:bash
ipfs cat QmQXCPxeFCbXEoCb6fk2eEfkg4VmF9ybrgFPwQnu3sYi2p/test1.txt
というようにディレクトリからリンクを辿ってアクセスすることができる。もちろんコンテンツのハッシュを直接指定してアクセスしても良い。
IPFSの初期化
code:bash
rm -rf ~/.ipfs
ipfs init
ネットワークに接続
これから行う操作は実際にP2Pノードへの接続を行う。したがって、公開したくない秘密のコンテンツはローカルのIPFSリポジトリから削除しておかなければならない。
早速接続する。
code:bash
ipfs daemon
Initializing daemon...
Swarm listening on /ip4/10.11.1.38/tcp/4001
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip6/::1/tcp/4001
Swarm listening on /p2p-circuit/ipfs/Qmbka2Ztvn6DU8Rk8Qm4hJcv2UKkSACnS6WamiabmcjFTS
Swarm announcing /ip4/10.11.1.38/tcp/4001
Swarm announcing /ip4/127.0.0.1/tcp/4001
Swarm announcing /ip6/::1/tcp/4001
API server listening on /ip4/127.0.0.1/tcp/5001
Gateway (readonly) server listening on /ip4/127.0.0.1/tcp/8080
Daemon is ready
と表示されれば完了。
code:bash
ipfs swarm peers | less
/ip4/100.6.105.61/tcp/4001/ipfs/Qmb8unXAJNurpDkXKbJ33pTV8Yukdm6AXj2ReWVLFvFAvt
/ip4/100.7.25.238/tcp/28594/ipfs/QmVABSMP8nHWpsJxfWzQgKpQctB6bVADxF6zA3Xdz5h7h7
/ip4/103.108.140.230/tcp/4001/ipfs/QmS1TSn6s9q9BrYgTEj1sFpmkZ6aNoG5EF3f9syF41FPxd
/ip4/103.205.97.78/tcp/4125/ipfs/QmVzTqbbcy7Sx3wkCVo2wqUzW7m4tDek1XNKcnAXRzEjCd
/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ
/ip4/104.208.137.78/tcp/4001/ipfs/QmTScdhgReTSo6RUy9DQnXuv9mLej4w2p7bD9MNDwd1TSC
(略)
といった結果が得られ、多くのピアと接続されていることがわかる。
code:bash
ipfs swarm peers | wc -l
としたところ、376のピアと接続していることがわかった。
自身が登録したコンテンツの共有状態を見てみる。
code:bash
ipfs dht findprovs QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o
このコマンドにより、指定アドレスに対応するコンテンツを保持しているピアの一覧が得られる。hello worldはみんながチュートリアルで登録するためか、たくさんのピアが得られた。一方でLennaの画像は自分しか登録してないみたいでピアが一つしか得られなかった。
登録・公開されたコンテンツはパブリックゲートウェイのピアを介して閲覧可能になる。
勉強会メモ
nrryuya.icon > Swarmとの違いがきになる(Swarm機運高まっているので)
yudetamago.icon > 来週話します!(間に合えば
yamarkz.icon > 来週devconでは
yudetamago.icon > vたしv
shuntak.icon > 単にswarmというといろんなswarmがあり、以下のswarmはそれぞれ別物なのでご注意ください
BitTorrentのswarm
IPFSのサブシステムのlibp2pのswarm
Dockerのswarm
Ethereumのプロジェクトのswarm
nrryuya.icon > ネームサービス、ビザンチン将軍どうするのだ
nrryuya.icon > torrent系は、トレントファイルにインデックスが書いてあり、どのピアが持っているかとかをナントカノードが教えてくれるが、IPFSは純粋にゴシップだけでいく