†IPFSを実行しながら学んでいく1†

2022.07.05

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

††学んだ内容をメモメモ††

IPFS(InterPlanetary File System)とはP2Pネットワーク上で動作するハイパーメディアプロトコルとその実装 と定義されています。

ファイル、Webサイト、アプリケーション、データを保存およびアクセスするための分散システムともとれます。

https://dev.classmethod.jp/articles/aaaaaaa//Users/mori.ryosuke/items/aaaa.txt,C:\Users\mori.ryosuke\My Documents\aaaa.txt のような現在も使われているURLやファイルパスはロケーション指向と言われ、場所を指定しています。

IPFSは場所ではなく、ファイルの内容またはコンテンツによってファイルのアドレスを指定します(コンテンツ指向)。

例) /ipfs/QmXoypizjW3WknFiJnKLwHCnL72vedxjQkDDP1mXWo6uco/wiki/Aardvark.html

/ipfs/ 後の文字列はコンテンツ識別子(CID)と呼ばれていて、IPFSが複数の場所からコンテンツを取得する方法となります。 暗号化されたハッシュで、元のコンテンツに固有のものです。

IPFSは、コンテンツが一つの場所で管理されていない(複数の場所から同じものを取得できる)ので、

  • 回復力が高い
    • コンテンツが存在する場所(サーバ等)がダウンしても、他の場所から同じものを取得できる
  • 検閲を困難にする
    • IPFS上のファイルはさまざまな場所から取得される可能性があるので、どこかのサーバがアクセスを遮断されても、他のどこかの別のサーバから同一の情報が取得可能になり、検閲が難しい
  • スピードアップ
    • より近いサーバから取得することになるので、一つのサーバーに負荷が集中することを防ぎ、ファイルをより速く取得することができる

といったメリットが挙げられます。

では、実際にIPFSがどんな感じで使えるのか、IPFSのコマンドラインツールを使って試していきます。

インストール

Goで記述されたリファレンス実装であるgo-ipfsをインストールします。

各OSごとのインスtーる方法は以下に。 - Windows - Mac - Linux

使用しているローカルPCはM1 Macなので

$ curl -O https://dist.ipfs.io/go-ipfs/v0.13.0/go-ipfs_v0.13.0_darwin-amd64.tar.gz
$ tar -xvzf go-ipfs_v0.13.0_darwin-amd64.tar.gz
$ cd go-ipfs && bash install.sh

でインストールします。

$ ipfs --version
ipfs version 0.13.0

インストールされたかを確認します。

初期化

IPFSはすべての設定と内部データをリポジトリと呼ばれるディレクトリに保存します。

ipfs init

で初期化できます。

実行結果

generating ED25519 keypair...done
peer identity: 12D3KooWHQjFYK75BGHkbsxAFPs8gGJUSwt8c5JEFt3QMCseBBsF
initializing IPFS node at /Users/mori.ryosuke/.ipfs
to get started, enter:

    ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme

実行ユーザーのホームディレクトリの直下に.ipfsというフォルダがつくられます(=IPFSのリポジトリ)。

コンテンツ内容を取得

init実行後、最後に出力されたコマンドを実行します。

ipfs catはIPFSネットワーク上に保存されているファイルの内容を取得するコマンドです

$ ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/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-note

コンテンツ追加

何かファイルを作成し、それをIPFSのレポジトリに追加してみます。

$ echo "hoge" > hoge.txt
$ cat hoge.txt
hoge

追加には、ipfs add コマンドを使用します。

$ ipfs add hoge.txt
added QmTY2kZZgvgjsivUo4hKjAmqcDHehGyDjueUzeK9At33Xb hoge.txt

ipfs addは、指定したファイルの内容をIPFSオブジェクト」してIPFSのリポジトリに登録します。

QmTY2kZZgvgjsivUo4hKjAmqcDHehGyDjueUzeK9At33Xb がそのコンテンツを示すコンテンツID(CID)です。

ipfs catを実行すると、中身が確認できました。

$ ipfs cat QmTY2kZZgvgjsivUo4hKjAmqcDHehGyDjueUzeK9At33Xb
hoge

<<参考>>

指定したファイルのデータからMerkleDAGを作るのがipfs addコマンド。

特定のファイルの「ハッシュ」は、実際にはDAGのルート(最上位)ノードのハッシュ。

ファイル名だけ変えたらどうなる?

hogehoge.txtという¥ファイルを作成します。内容はhoge.txtと同じにします。

このファイルをaddすると

$ echo "hoge" > hogehoge.txt
$ cat hogehoge.txt
hoge
$ ipfs add hogehoge.txt
added QmTY2kZZgvgjsivUo4hKjAmqcDHehGyDjueUzeK9At33Xb hogehoge.txt

IPFSはコンテンツの内容をもとにCIDが作られるので、hoge.txtと同じCIDがふられることになりました。

$ ipfs cat QmTY2kZZgvgjsivUo4hKjAmqcDHehGyDjueUzeK9At33Xb
hoge

hoge.txtやhogehoge.txtという場所を指定せずに中身を取得するということが体験できました。

ブロック?オブジェクト?

IPFSでは、ブロックはキー(ハッシュ)で識別される1つのデータ単位で、どのような種類のデータでもよく、必ずしも何らかの形式が関連付けられている必要はない。

オブジェクトはMerkle DAG protobufのデータ形式に従ったブロック

と定義されています。

Merkle DAG: ハッシュ木 とも呼ばれる

オブジェクトをコマンドで色々試す

先ほどから実行してきたipfs addは、コンテンツやディレクトリをIPFSオブジェクトとして追加するものです。

IPFSはコンテンツのサイズが256KBを超える場合は分割して保存するというのが仕様になっています(UnixFSデータ形式に従う)。

UnixFSデータ形式

実際に試してみます。郵便局の郵便番号データを用います。

$ ipfs add KEN_ALL.CSV
added Qme1M1uCBJZaCVojeLNbzHkLchoQLBmJMYAJEsSfeBWNCa KEN_ALL.CSV

$ ipfs cat Qme1M1uCBJZaCVojeLNbzHkLchoQLBmJMYAJEsSfeBWNCa
~~~~

KEN_ALL.CSVは12MBほどのサイズなので仕様に従って分割されるはずです。

分割されたサブブロックを確認するには、<code>ipfs ls</code>コマンドを使用します。

$ ipfs ls Qme1M1uCBJZaCVojeLNbzHkLchoQLBmJMYAJEsSfeBWNCa
QmZHj97h6y666Jq3URg5bdfSHsn4tzCnRuF4a7QbtWBdmx 262144
Qma6FoFH6YuCoqQXTCyQJNhPayvH62RbMDYo1A2YWAyB3S 262144
Qmcn1R3T8xZSxkdUdzTg8zZsAmbMRLGC4STKoAHuMhTchm 262144
QmRsP9HHWsUDr8FpewWpRyxVd55Aq42bsNEmcTCVdbnyjy 262144
QmTRZHHfExWuWPatzp9Qav4eu6yEoHcW3YVsG9tVuqavoL 262144
QmPxzn6z8GWWwva7v5rtsNrNAhu2LzT47xNBSuEc17XWSD 262144
QmU4aN9f24NrUUrrNLRi6qiSg9PTXFsE6QZPbHY7xGmi6k 262144
QmWgyZwmyaNvLezgQZNAB9o94apk7eapyxwBiRCZGMCFFr 262144
~~~ 省略 ~~~
QmYFzF22PinsQZsjwHU6ooiQ9vTf4sjvAbEHRfFiJAT1hP 16279

ファイルのすべての直接のサブブロックと、それらのサイズおよびディスク上の子が表示されます

各サブブロックのハッシュをcatして、分割されたコンテンツの中身を見ることができます。

$ ipfs cat QmYFzF22PinsQZsjwHU6ooiQ9vTf4sjvAbEHRfFiJAT1hP

ipfs addは、コンテンツやディレクトリをIPFSオブジェクトとして追加するもの とありますが、オブジェクトの実態を確認するコマンドもあります。

ipfs object getで、KEN_ALL.CSVのルートハッシュで試してみたところ

$ ipfs object get Qme1M1uCBJZaCVojeLNbzHkLchoQLBmJMYAJEsSfeBWNCa
{
  "Links": [
    {
      "Name": "",
      "Hash": "QmZHj97h6y666Jq3URg5bdfSHsn4tzCnRuF4a7QbtWBdmx",
      "Size": 262158
    },
...
...
  ],
  "Data": "\b\u0002\u0018 <<省略>>"
}

オブジェクトは上記のようなデータ構造となっていました

  • Links
    • 分割されたIPFSオブジェクトへのリンク(IPFSリンク)の配列
  • Data
    • オブジェクトの中身(unicode)

です。

Linksの一つのハッシュに対してipfs object getを実行すると、Linksは空の配列になりました(これ以上分割されていないから)。

ブロックをコマンドで色々試す

オブジェクトはMerkle DAG protobufのデータ形式に従ったブロック なので、先ほど実行したipfs object getの代わりにブロックを扱うコマンド(ipfs block get)もつかえるのでは?

$ ipfs block get QmRAX8dJYRPmdugaskCQaB6wd94wZaR1DxPp15S689pNdq

��マグントクノシマチョウ","トクワセ","鹿児島県","大島郡徳之島町","徳和瀬",0,0,0,0,0,0
46530,"89174","8917424","カゴシマケン","オオシマグントクノシマチョウ","トドロキ","鹿児島県","大島郡徳之島町","轟木",0,0,0,0,0,0
46530,"89174","8917426","カゴシマケン","オオシマグントクノシマチョウ","ボマ","鹿児島県","大島郡徳之島町","母間",0,0,0,0,0,0
46530,"89171","8917103","カゴシマケン","オオシマグントクノシマチョウ","ミナミハラ","鹿児島県","大島郡徳之島町","南原",0,0,0,0,0,0

~~~~ 省略 ~~~~

実行してみると、生データを読み取ることができました。今回だとCSV形式のテキストファイルですね。

ipfs block statでは、特定のブロックの正確なサイズ(子なし)がわかります。

$ ipfs block stat QmRAX8dJYRPmdugaskCQaB6wd94wZaR1DxPp15S689pNdq
Key: QmRAX8dJYRPmdugaskCQaB6wd94wZaR1DxPp15S689pNdq
Size: 135529

$ ipfs block stat QmUYvfWLpAUBNRxPvGDFeup4Gfvn4ZYbUZTV2JynVhLoMm
Key: QmUYvfWLpAUBNRxPvGDFeup4Gfvn4ZYbUZTV2JynVhLoMm
Size: 262158

今日はここまで。

途中経過

IPFSの学びのため、IPFSのコマンドラインツールを用いて色々と実行していきました。

今回はIPFSへのコンテンツ追加が中心でした。

https://docs.ipfs.io/ をベースにして引き続き試していく予定です。

参考