IPFSを触ってみた

## IPFSとは

Peer to Peerベースの分散ファイルシステムです。

まだ深いところまでは理解できていないので、とりあえず、Getting Startedをやってみました。

## IPFSの導入方法

1.公式サイトよりファイルのダウンロード　
2.ダウンロードフォルダ内に存在するipfsファイルを自分のパソコンの'$PATH'内に移動
 
`$ sudo mv ipfs /usr/local/bin/ipfs`

3.localのipfs nodeを初期化

``` javascript
$ ipfs init
initializing IPFS node at /Users/hiromitsu/.ipfs
generating 2048-bit RSA keypair...done
peer identity: QmZ3wsy1JrpY5qimbQAMcJund5Hg4ZKrbnXuNkdbvPnGNK
to get started, enter:

	ipfs cat /ipfs/QmVLDAhCY3X9P2uRudKAryuQFPM5zqA3Yij1dY8FpGbL7T/readme
```
　
4.以下のコードを実行し、readmeの内容を確認

``` javascript
$ ipfs cat /ipfs/QmVLDAhCY3X9P2uRudKAryuQFPM5zqA3Yij1dY8FpGbL7T/readme
Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

 -------------------------------------------------------
| 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.   |
 -------------------------------------------------------

Check out some of the other files in this directory:

  ./about
  ./help
  ./quick-start     <-- usage examples
  ./readme          <-- this file
  ./security-notes
```
　
5. 早速quick-startで試してみる

``` javascript
$ ipfs cat /ipfs/QmVLDAhCY3X9P2uRudKAryuQFPM5zqA3Yij1dY8FpGbL7T/quick-start
0.1 - Quick Start

This is a set of short examples with minimal explanation. It is meant as
a "quick start". Soon, we'll write a longer tour :-)


Add a file to ipfs:

  // hello worldをhelloファイルに書き込み
  $ echo "hello world" >hello
  
  // ipfsにファイルをあげる
  $ ipfs add hello
  added QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o hello


View it:

  // あげたファイルの表示
  $ ipfs cat QmT78zSuBmuS4z925WZfrqQ1qHaJ56DQaTfyMUF7F8ff5o
  hello world


Try a directory:

  $ mkdir foo
  $ mkdir foo/bar
  $ echo "baz" > foo/baz
  $ echo "baz" > foo/bar/baz
  // fooディレクトリに存在するディレクトリ、ファイルを全てipfsにあげる
  $ ipfs add -r foo
  added QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR foo/bar/baz
  added QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR foo/baz
  added QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN foo/bar
  added QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm foo

View things:

  // foo直下にあるディレクトリ、ファイルのリストを表示
  $ ipfs ls QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
  QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN 61 bar/
  QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR 12 baz
  
  // foo/bar直下にあるディレクトリ、ファイルのリストを表示
  $ ipfs ls QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm/bar
  QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR 12 baz
  
  // foo/bazに記述された内容を表示
  $ipfs cat QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm/baz
　baz

  // foo/bar/bazに記述された内容を表示
  $ ipfs cat QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm/bar/baz
  baz
  
  // foo/barディレクトリの内容を表示（ディレクトリであるため、表示されない）
  $ ipfs cat QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm/bar
  Error: this dag node is a directory

  // foo/baz内の内容をリスト表示（ファイルであるため、表示されない）
  $ ipfs ls QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm/baz


References:

  // foo直下の子nodeのhashを表示
  $ ipfs refs QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
  QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN
  QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR

  // foo直下より下の階層のnodeのhashまで表示
  ipfs refs -r QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
  QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN
  QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR
  QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR

  // helpを表示
  ipfs refs --help


Get:

  // ipfs上にあるファイルをfoo2ファイルに出力
  $ ipfs get QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm -o foo2
  Saving file(s) to foo2
  4.00 KB / 167 B [=================================================] 2452.69% 0s

  // 2つのファイルを比較
  $ diff foo foo2
  Common subdirectories: foo/bar and foo2/bar

Objects:

  // オブジェクト形式でfooファイル直下のファイル内容を表示
  $ ipfs object get QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
  {"Links":[{"Name":"bar","Hash":"QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN","Size":61},　　　　
  {"Name":"baz","Hash":"QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR","Size":12}],"Data":"\u0008\
  u0001"}
  
  ipfs object --help


Pin + GC:

  // ローカルストレージにピン留めする
  $ ipfs pin add QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
  pinned QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm recursively
  
  // GC(gabage collection)を実施
  $ ipfs repo gc
  removed QmQHQ8eqpdaKCBhwZsDS7cZV49YnMpuByggPCPwRpKoRkL が何行も表示される
  
  $ ipfs ls QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
  QmeBpzHngbHes9hoPjfDCmpNHGztkmZFRX4Yp9ftKcXZDN 61 bar/
  QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR 12 baz
  
  // local strageへのpinを外す
  $ ipfs pin rm QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
  unpinned QmdcYvbv8FSBfbq1VVSfbjLokVaBYRLKHShpnXu3crd3Gm
  
  //  pinを外したファイルもGCが実行される
  $ ipfs repo gc


Daemon:

  // daemonの実行
  $ ipfs daemon  (in another terminal)
  
  // 自分のipfs nodeの情報を表示
  $ ipfs id
  {  
	"ID": "QmZ3wsy1JrpY5qimbQAMcJund5Hg4ZKrbnXuNkdbvPnGNK",
	"PublicKey":   
	"CAASpgIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCuWALiivn3zBi6LjlwOd65VgAkJOHOzVrcaZaH4JuoVNSZoU
	Aa6SPV6hipxjguvPR/noZq7FbtCEJ1ri3SqHm6hQS9UP7lOjs0Li1twWxSV84CTpoAdfQ/XxXz2hR6/26h72So+fuXq7pklyG09
	laxtqywn7pDZvUbkrwFhigHXCp5heWk4HFZjZXMN5k80qLFigPUi0ei9g4Sn5i2FgUSJYsy8BAoKmb6SoX4onmV5RQEaziY4IrF
	Q7ZTSl5WPpFbCMb0BbJ8PWREYKzZJs79OmId+5fMRzedLcUq27JttZXsqG71YPcCDaDW+0KpWbRqAiLiqgWK4EJx8f5HhzBbAgM
	BAAE=",
	"Addresses": [
		"/ip4/127.0.0.1/tcp/4001/ipfs/QmZ3wsy1JrpY5qimbQAMcJund5Hg4ZKrbnXuNkdbvPnGNK",
		"/ip4/192.168.1.4/tcp/4001/ipfs/QmZ3wsy1JrpY5qimbQAMcJund5Hg4ZKrbnXuNkdbvPnGNK",
		"/ip6/::1/tcp/4001/ipfs/QmZ3wsy1JrpY5qimbQAMcJund5Hg4ZKrbnXuNkdbvPnGNK",
		"/ip4/118.241.156.122/tcp/1025/ipfs/QmZ3wsy1JrpY5qimbQAMcJund5Hg4ZKrbnXuNkdbvPnGNK"
	],
	"AgentVersion": "go-ipfs/0.4.6/",
	"ProtocolVersion": "ipfs/0.1.0"
  }

Network:

  (must be online)
  // 誰とつながっているか
  $ ipfs swarm peers
  /ip4/96.60.11.62/tcp/27528/ipfs/QmZGzJ6ejcAqdhsmHbH3EFvCV3PhCUGwfHkrvCHER1pXdR
  
  ipfs id
  ipfs cat QmSMSC9SmN1wmfPsiCHxm5uuprL1ciRxkpaUqXRDkGCSDU


Mount:

  (warning: fuse is finicky!)
  ipfs mount
  cd /ipfs/<the-hash-here>
  ls


Tool:

  ipfs version
  ipfs update
  ipfs commands
  ipfs config --help
  open http://localhost:5001/webui


Browse:

  webui:

    http://localhost:5001/webui

  video:

    http://localhost:8080/ipfs/QmVc6zuAneKJzicnJpfrqCH9gSy6bz54JhcypfJYhGUFQu/play#/ipfs/QmTKZgRNwDNZwHtJSjCp6r5FYefzpULfy37JvMt9DwvXse

  images:

    http://localhost:8080/ipfs/QmZpc3HvfjEXvLWGQPWbHk3AjD5j8NEN4gmFN8Jmrd5g83/cs

  markdown renderer app:

    http://localhost:8080/ipfs/QmX7M9CiYXjVeFnkfVGf3y5ixTZ2ACeSGyL1vBJY1HvQPp/mdown
```

#### オンラインにしよう
別のターミナルを立ち上げて、デーモンを実行する

```
$ ipfs daemon
Initializing daemon...
Adjusting current ulimit to 1024...
Successfully raised file descriptor limit to 1024.
Swarm listening on /ip4/118.241.156.122/tcp/4001
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/192.168.11.22/tcp/4001
Swarm listening on /ip6/::1/tcp/4001
API server listening on /ip4/127.0.0.1/tcp/5001
Error: serveHTTPGateway: manet.Listen(/ip4/127.0.0.1/tcp/8080) failed: listen tcp4 127.0.0.1:8080: bind: address already in use
```
8080ポートが既に使われているみたい。
/Users/hiromitsu/.ipfs/config内の以下のコードの8080を別のポートに変更（[参考](https://github.com/AkashaProject/Alpha/issues/58)）

``` javascript
{
  "API": {
    "HTTPHeaders": null
  },
  "Addresses": {
    "API": "/ip4/127.0.0.1/tcp/5001",
    "Gateway": "/ip4/127.0.0.1/tcp/8080",
    "Swarm": [
      "/ip4/0.0.0.0/tcp/4001",
      "/ip6/::/tcp/4001"
    ]
  },
...
```

再度実行

``` javascript
$ ipfs daemon
Initializing daemon...
Adjusting current ulimit to 1024...
Successfully raised file descriptor limit to 1024.
Swarm listening on /ip4/118.241.156.122/tcp/4001
Swarm listening on /ip4/127.0.0.1/tcp/4001
Swarm listening on /ip4/192.168.11.22/tcp/4001
Swarm listening on /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/8000
Daemon is ready
```
今度は実行できた。これでポートが繋がった。
続いて、自分とつながっているピアーアドレスを確認する。

```
$ ipfs swarm peers
<transport address>/ipfs/<hash-of-public-key>の形式で表示
/ip4/104.131.20.170/tcp/4001/ipfs/QmQG8e6xjqbwK7BCURayW7X6YahbCognPuAeqsVpnnVifS
```
実際にIPFSからデータを取得する。

``` javascript
$ ipfs cat /ipfs/QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ/cat.jpg >cat.jpg
$ open cat.jpg
```
猫の画像が表示された。

次に、ネットワークに自分のオブジェクトを流してみる

``` javascript
$ hash=`echo "I <3 IPFS -$(whoami)" | ipfs add -q`
$ curl "https://ipfs.io/ipfs/$hash"
I <3 IPFS -hiromitsu
```
パブリックゲートウェイでは表示された
別の方法（ローカルゲートウェイ）でもネットワークに流した情報が取得できるか確認する

```
$ curl "http://127.0.0.1:8000/ipfs/$hash"
I <3 IPFS -hiromitsu
```

**デフォルトでは、自分のゲートウェイはパブリックではなく、ローカルで動いているようです**

ブラウザ上で今の自分のIPFSへの接続状況が観れるみたい
http://localhost:5001/webui
![68d965c0-3ecd-43d2-a17d-60736fd5821c.png](https://qiita-image-store.s3.amazonaws.com/0/124592/015dae55-87fb-45bb-5fb0-09b5ac49cfba.png)

以上、ざっと触ってみましたが、簡単にIPFS上にファイルをアップでき、内容の取得も迷わず実行することができます。
まだまだ発展途上だと思いますが、これからどんどん応用されていくと思います。

詳しい内容はもう少し勉強してから記事にしたいと思います。