#はじめに
EthereumでDAppを開発する時、データのストレージが問題になってくると思います。
Ethereumのステートを変更する時に発生するガスコストはコントラクト実行に必要な計算量によって決まるため、スマートコントラクトのstorage領域にデータを格納するとガスコストが高額になってしまいます。
何か方法はないか調べてみるとIPFSとSwarmという分散ファイルシステムがあることが分かったので、今回はIPFSについて調べたことを残しておきます。
#IPFSとは
IPFS(Inter Planetary File System)とはp2pネットワーク上で動作する分散型のファイルシステムで、HTTPを補完または置き換えるプロトコルです。
HTTPとの最大の違いは、HTTPが「ロケーション指向型」であるのに対し、IPFSは「コンテンツ指向型」である点です。
ロケーション指向型とは、例えば https://hogehoge.com/fuga/aaa.txt というファイルにアクセスする時、ファイルの場所(hogehoge.com/fuga)にアクセスしてファイルを取得・閲覧する仕組みを指します。
これに対しコンテンツ指向型は、ファイルの場所(サーバーやディレクトリ)は問題ではなく、ファイルのコンテンツをp2pネットワークに登録し、必要な時はコンテンツ自体にアクセスする仕組みです。
ロケーション指向型が中央集権的な仕組みであるのに対し、コンテンツ指向型はコンテンツの置かれている場所ではなく、あくまでコンテンツ自体を分散管理するので非中央集権的な仕組みとなっています。
もっと詳しく知りたい方は、参考サイト・参考文献に記載しているサイトや書籍に詳しく記述されていますので、そちらもご覧になってみてください。
#IPFSをインストールする
それでは早速IPFSをインストールしてみようと思います。
###Dockerコンテナを準備する
まずはDockerの環境を構築します。
今回は一からインストールしたいので、ubuntuOSだけのDocker imageを作成します。
それではDockerfileを作成します。
FROM ubuntu:latest
RUN apt-get update && apt-get install -y\
wget
WORKDIR /work
ipfsのパッケージをインストールしたいのでwgetだけ予めインストールしておきます。
Dockerfileが出来たらdocker buildし、docker runでコンテナを作成します。
ここから下はコンテナ環境での作業です。
###IPFSをインストールする
まずはipfsのダウンロードサイトからインストールパッケージをインストールしてきます。
root@42db220e8bdf:/work# wget https://dist.ipfs.io/go-ipfs/v0.10.0/go-ipfs_v0.10.0_linux-amd64.tar.gz
--2021-10-03 04:07:28-- https://dist.ipfs.io/go-ipfs/v0.10.0/go-ipfs_v0.10.0_linux-amd64.tar.gz
Resolving dist.ipfs.io (dist.ipfs.io)... 209.94.78.1, 2602:fea2:3::1
Connecting to dist.ipfs.io (dist.ipfs.io)|209.94.78.1|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 26156481 (25M) [application/gzip]
Saving to: 'go-ipfs_v0.10.0_linux-amd64.tar.gz'
go-ipfs_v0.10.0_linux-amd64.tar.gz 100%[================================================================>] 24.94M 1.41MB/s in 33s
2021-10-03 04:08:02 (773 KB/s) - 'go-ipfs_v0.10.0_linux-amd64.tar.gz' saved [26156481/26156481]
ワーキングディレクトリにtargzファイルがインストールされました。
このtargzファイルを解凍します。
root@42db220e8bdf:/work# tar xvzf go-ipfs_v0.10.0_linux-amd64.tar.gz
go-ipfs/LICENSE
go-ipfs/LICENSE-APACHE
go-ipfs/LICENSE-MIT
go-ipfs/README.md
go-ipfs/install.sh
go-ipfs/ipfs
解凍するとgo-ipfsフォルダが作成されました。
カレントディレクトリを確認してみます
root@42db220e8bdf:/work# ls
Dockerfile go-ipfs go-ipfs_v0.10.0_linux-amd64.tar.gz
もうtargzファイルは要らないと思うので削除します。
go-ipfsフォルダにinstall.shがあるので実行します。
root@42db220e8bdf:/work# go-ipfs/install.sh
Moved go-ipfs/ipfs to /usr/local/bin
ipfsプロトコルのファイルがusr/local/binへ移動したようです。(pathの設定も自動で行われたはず)
これでipfsコマンドが使えるようになります。
それでは正常にインストール出来たか確認してみます。
ipfsのバージョンを確認し、帰ってきたらインストールは成功しています。
root@42db220e8bdf:/work# ipfs version
ipfs version 0.10.0
問題ないようです。
#IPFSを使ってみる
###ipfsをinitする
まずはipfs initコマンドでイニシャライズします。
root@42db220e8bdf:/work# ipfs init
generating ED25519 keypair...done
peer identity: 12D3KooWJEKSJGzb9J4BB66XGE5XfeU6LtRErKMXJoirYCMBs9jg
initializing IPFS node at /root/.ipfs
to get started, enter:
ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme
peer identityがこのノードのidとなります。
###readmeとusageをチェック
イニシャライズが終わるとreadmeのコマンドが表示されるので、これを実行してみます。
ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme
root@42db220e8bdf:/work# 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-notes
同様にusageも確認してみます。
root@42db220e8bdf:/work# ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/quick-start
# 0.1 - Quick Start
This is a set of short examples with minimal explanation. It is meant as
a "quick start".
Add a file to ipfs:
echo "hello world" >hello
(must be online)
ipfs swarm peers
ipfs id
ipfs cat <hash-of-remote-object>
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
なんか色々出来るようです。
シンプルだけど分かりやすそうですね。
###コンテンツをリポジトリに登録してみる
それではusageに従って色々試してみます。
まずは"Hello World"という文字列を格納したhelloファイルを作成します。
root@42db220e8bdf:/work# echo "Hello World" > hello
root@42db220e8bdf:/work# ls
Dockerfile go-ipfs hello
ipfs addコマンドでこのhelloファイルのコンテンツをリポジトリにaddしてみます。
root@42db220e8bdf:/work# ipfs add hello
added QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u hello
12 B / 12 B [=====================================================================================================================] 100.00%
helloファイル内のコンテンツがリポジトリにipfsオブジェクトとして登録されました。
"QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u"はオブジェクトのアドレスです。
ipfs catコマンドでオブジェクトのアドレスを指定するとコンテンツを表示することが出来ます。
root@42db220e8bdf:/work# ipfs cat QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u
Hello World
helloファイルのコンテンツ(Hello World)が格納されています。
このオブジェクトの構成を見てみます。
ipfs object getコマンドを使うとオブジェクトの構成が見れるようです。
root@42db220e8bdf:/work# ipfs object get QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u
{"Links":[],"Data":"\u0008\u0002\u0012\u000cHello World\n\u0018\u000c"}
ユニコード文字が入っていますが、Dataの中にHello Worldが入っています。
それでは新たにhello2ファイルを作成して、そこのhelloファイルと同じ"Hello World"文字列を格納してみます。
root@42db220e8bdf:/work# echo "Hello World" > hello2
root@42db220e8bdf:/work# ls
Dockerfile go-ipfs hello hello2
このhello2をipfs addしてみます。
root@42db220e8bdf:/work# ipfs add hello2
added QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u hello2
12 B / 12 B [=====================================================================================================================] 100.00%
hello2のオブジェクトアドレスとhelloのオブジェクトアドレスが一緒ですね。
これは"Hello World"というコンテンツが同一なので同じオブジェクトになっているからです。
このようにIPFSはファイルの場所ではなくコンテンツをオブジェクト化し登録・参照出来る仕組みとなっています。
#おわりに
少し長くなってきたので今回はIPFSの環境構築と動作確認までの確認にしようと思います。
次回はディレクトリの作成やIFPSネットワークへの接続の方を試してみようと思います。
ご覧いただきありがとうございました。
#参考サイト、文献
-
IPFS入門
IPFSについて詳しく紹介されています。
すごく参考になったサイトです。 -
「マスタリング イーサリアム」オライリー
Andreas M.Antonopoulos, Gavin Wood 著
EthereumやDAppについて詳しい書籍です。