Ethereum Swarm

# はじめに

最近EthereumとFabricの沼にはまっています、こんにちわ。
突然ですがEthereum Swarmをご存知ですか？
Docker Swarmのことではないですよ。

紹介ページにはこんな風なことが書かれてます。

```
Swarm is a distributed storage platform and content distribution service, a native base layer service of the ethereum web 3 stack.
The primary objective of Swarm is to provide a sufficiently decentralized and redundant store of Ethereum’s public record, in particular to store and distribute dapp code and data as well as block chain data. 
From an economic point of view, it allows participants to efficiently pool their storage and bandwidth resources in order to provide the aforementioned services to all participants.
From the end user’s perspective, Swarm is not that different from WWW, except that uploads are not to a specific server. 
The objective is to offer a peer-to-peer storage and serving solution that is DDOS-resistant, zero-downtime, fault-tolerant and censorship-resistant as well as self-sustaining due to a built-in incentive system which uses peer-to-peer accounting and allows trading resources for payment.
Swarm is designed to deeply integrate with the devp2p multiprotocol network layer of Ethereum as well as with the Ethereum blockchain for domain name resolution, service payments and content availability insurance (the latter is to be implemented in POC 0.4 by Q2 2017).
```
引用元：http://swarm-guide.readthedocs.io/en/latest/introduction.html

ちょっと意味が分からないので要約すると、
Ethereumの仕組みを使って、不特定多数の参加者にファイルを分散配布します。
参照する際にはファイルを持っている人が誰か分からなくても、誰かが持っているのでその誰かからファイルを送って貰うことができるのです。
エンドユーザから見ると、普通のHTMLサイトにアクセスするのと同様にファイルにアクセスすることができます。  


# どんなことができるかって？  
・たとえば、非中央集権のファイル共有サービス
特定のファイルサーバがなくてもファイルのアップロードができます。

・ブロックチェーンを介したファイルやりとり
非中央集権アプリを作成したら、取引データの中にファイルを格納したくなることありますよね。(添付する見積書とか決済文章とか)
そんなときにSwarmを使ってファイルをアップロードすると、改ざんできないファイルができあがります。

超絶簡単に言うと「ファイルの所在がマジで分からないのに、なぜかファイルにアクセスできる。」です。
クラウドの場合はクラウド事業者のサーバにファイルがあることになりますけど、Swarmの場合は参加者の誰が持っているのか本当にわからないのです。
(超頑張れば特定できなくはないので悪いことはしないように…。)

IPFSと仕組みは似ているのですが、どちらも理論がクレイジーすぎて説明できないので研究目的の方はこの辺参考にしてください。
https://github.com/ethersphere/swarm/wiki/swarm#rd




# インストール方法  
Ubuntu16.04とgo-ethereumで試します。  

- go言語のインストール

```
curl -O https://storage.googleapis.com/golang/go1.7.3.linux-amd64.tar.gz
tar -C /usr/local -xzf go1.7.3.linux-amd64.tar.gz
```
- go-ethereumをソースからコンパイル

```
$ mkdir -p $GOPATH/src/github.com/ethereum
$ cd $GOPATH/src/github.com/ethereum
$ git clone https://github.com/ethereum/go-ethereum
$ cd go-ethereum
$ git checkout master
$ go get github.com/ethereum/go-ethereum

$ go install -v ./cmd/geth
$ go install -v ./cmd/swarm
```

- こんな結果が返ってきたら成功です。

```
$GOPATH/bin/swarm version

Swarm
Version: 0.2
Network Id: 0
Go Version: go1.7.4
OS: linux
GOPATH=/home/user/go
GOROOT=/usr/local/go
```

# 起動方法

- まずはgethでアカウントを作成し、アドレスを取得します。

```
$ geth account new
Your new account is locked with a password. Please give a password. Do not forget this password.
Passphrase:
Repeat passphrase:
Address: {d2ffd81ed4c7c7b7249eac2edac1c4fe9812087a}
```

- gethを起動します  
fullnodeでやると同期に時間がかかってしょうがないので、ライトクライアントモードを使用しましょう。  

```
$ geth --syncmode light
```

- 取得したアドレスを使用してswarmを起動します。  
起動するとlocalhost:8500にアクセスすると使えるようになります。  
ファイルのアップロード/ダウンロードを行うときはこのアドレスを使用します。  

```
$ BZZKEY=d2ffd81ed4c7c7b7249eac2edac1c4fe9812087a
$ swarm --bzzaccount $BZZKEY
```

- 準備はここまでです。

# 使い方

- アプロードするために、なんか適当なファイルを用意します。

```
$ cat test.txt
aaaa
bbbb
```

- アップロードします  
そうするとアドレスが返ってくるので、これがファイルのありかを示すものになりますので忘れないようにしてください。  

```
$ swarm up test.txt
63b573d26aeb334060b28ce10dba10d3cf602c00bc2b667211855b78c4d5de59
```

- 世界中のswarmユーザに共有されるのに時間がかかるのでご飯でも食べながら待ちましょう。

- ファイルが先ほどのアドレスで参照できることを確認します。

```
$ curl -s http://localhost:8500/bzz:/63b573d26aeb334060b28ce10dba10d3cf602c00bc2b667211855b78c4d5de59/
aaaa
bbbb
```

- おめでとうございます。無事にファイルが世界中にばらまかれました。
- 本当に世界中にばらまかれたか確かめましょう。  
http://swarm-gateways.net というアドレスでswarmのapiを実行できるURLが用意されています。  
このURLからファイルが見えれば成功です。  

```
$ curl -s http://swarm-gateways.net/bzz:/63b573d26aeb334060b28ce10dba10d3cf602c00bc2b667211855b78c4d5de59/
aaaa
bbbb
```

- はい、見れましたね。おめでとうございます、成功です。

- ファイルディレクトリもアップロードできるみたいですが、容量大きくなっても大丈夫なのかは試してないです。
ロジックを見るとファイル細かく分割して、次のファイルのハッシュを持っているように見えたので、理論上はどこまででも行けそうですけど
実際問題何MB?GB?までいけるんですかね？

# ディレクトリごとアップロード

```
$ mkdir test
$ cd test
$ echo aaa > aaa.txt
$ echo bbb > bbb.txt
$ cd ..
$ swarm --recursive up test/
```

# FUSE
FUSEをインストールすると、Swarmをファイルシステムとして利用できるようになります。
今のところLinux,MacOS,FreeBSDのみサポートされていて、windowsは対象外となっています。

- FUSEのインストール

```
sudo apt-get install fuse
sudo modprobe fuse
sudo chown vagrant:vagrant /etc/fuse.conf
sudo chown vagrant:vagrant /dev/fuse
```
- マウントポイントの作成

```
$ sudo mkdir /mnt/swarm
$ sudo chown vagrant:vagrant /mnt/swarm/
```

- swarmのipcに接続

```
$ geth attach .ethereum/bzzd.ipc
```

- マウントポイントにアタッチ
ここで指定するハッシュはディレクトリをアップロードした時のものを指定してください。

```
swarmfs.mount(<事前にアップロードしたファイルのハッシュ>,<マウントポイント>)
swarmfs.mount("b411f71fd72846939c339058c25b538f3a37432a635e89b3f93a4dd545deaed3","/mnt/swarm")
```

- マウントされた。やったー。

```
$ ls /mnt/swarm/
aaa.txt  bbb.txt
```

- ここにファイルを配置すると、swarm upしたときと同じことになります。  
ただしmanifesのハッシュtが変わるので、参照するときは新しいハッシュを使いましょう。  
新しいハッシュはログに出力されています。

```
INFO [08-11|06:37:58] syncer[782493eb]: syncing all history complete
INFO [08-11|06:41:52] Removed file:                            fname=.ccc.txt.swx New Manifest hash=b411f71fd72846939c339058c25b538f3a37432a635e89b3f93a4dd545deaed3
INFO [08-11|06:41:52] Removed file:                            fname=.ccc.txt.swp New Manifest hash=b411f71fd72846939c339058c25b538f3a37432a635e89b3f93a4dd545deaed3
INFO [08-11|06:41:52] Added new file:                          fname=.ccc.txt.swp New Manifest hash=44e045d4c87a0676dcb271e0588667371439477a72e19b3230fc6d833a586b64
INFO [08-11|06:41:54] Appended file:                           fname=.ccc.txt.swp New Manifest hash=ba5735a5e487dc0d213ff377ce65e7c20143154aee38eb10dde3471915476527
INFO [08-11|06:41:56] Added new file:                          fname=ccc.txt      New Manifest hash=10ad9d37be18d0141d9a9b3be75df11edaccb58a6af765f6f9390be8ec3986c1
INFO [08-11|06:42:00] Appended file:                           fname=.ccc.txt.swp New Manifest hash=fcf9a4a064d38873a3c9a2cbc0d92a52647ca9d9037f495c685570612dd9d043
INFO [08-11|06:42:04] Removed file:                            fname=.ccc.txt.swp New Manifest hash=9b56bb46dcd12c6c8c504534c7e7fa593f98d5f0f99313a4430a4e15696a2826
INFO [08-11|06:42:09] Appended file:                           fname=ccc.txt      New Manifest hash=16d8241f9017e3c3fdbf8062b38a827c2b83822fe6ade71d941f1678a655651a
```

[ccc.txtアップロード前]

```
$ swarm ls b411f71fd72846939c339058c25b538f3a37432a635e89b3f93a4dd545deaed3
HASH                                                              CONTENT TYPE               PATH
55a4d8567248c73aea803764e9d8ec770366112a22fb50571b5dba4e45c4f8de  text/plain; charset=utf-8  aaa.txt
ec4d1bae3ea590a9c24eacbe2130032a2ba6102d32c33a7bf94b415319a2c9e1  text/plain; charset=utf-8  bbb.txt
```

[ccc.txtアップロード後]

```
$ swarm ls 16d8241f9017e3c3fdbf8062b38a827c2b83822fe6ade71d941f1678a655651a
HASH                                                              CONTENT TYPE               PATH
55a4d8567248c73aea803764e9d8ec770366112a22fb50571b5dba4e45c4f8de  text/plain; charset=utf-8  aaa.txt
ec4d1bae3ea590a9c24eacbe2130032a2ba6102d32c33a7bf94b415319a2c9e1  text/plain; charset=utf-8  bbb.txt
e7b8382739f0b459a1af2d7f0c8e4f764e2b710592597ca45a3ec3c080ac6f87  text/plain; charset=utf-8  ccc.txt
```

# 削除してみる

```
$ cd /mnt/swarm
$ rm aaa.txt
$ ls
bbb.txt  ccc.txt

```

```
INFO [08-11|07:00:20] syncronisation request sent with address: 00000000-00000000, index: 0-0, session started at: 0, last seen at: 0, latest key: 00000000
INFO [08-11|07:06:08] Removed file:                            fname=aaa.txt      New Manifest hash=8c148663734caa76ef7e88e06cafb5d32e41aa453a7d57d988591a8fc73afb9d
```

[今までのmanifest]

```
$ swarm ls b411f71fd72846939c339058c25b538f3a37432a635e89b3f93a4dd545deaed3
HASH                                                              CONTENT TYPE               PATH
55a4d8567248c73aea803764e9d8ec770366112a22fb50571b5dba4e45c4f8de  text/plain; charset=utf-8  aaa.txt
ec4d1bae3ea590a9c24eacbe2130032a2ba6102d32c33a7bf94b415319a2c9e1  text/plain; charset=utf-8  bbb.txt

$ swarm ls 16d8241f9017e3c3fdbf8062b38a827c2b83822fe6ade71d941f1678a655651a
HASH                                                              CONTENT TYPE               PATH
55a4d8567248c73aea803764e9d8ec770366112a22fb50571b5dba4e45c4f8de  text/plain; charset=utf-8  aaa.txt
ec4d1bae3ea590a9c24eacbe2130032a2ba6102d32c33a7bf94b415319a2c9e1  text/plain; charset=utf-8  bbb.txt
e7b8382739f0b459a1af2d7f0c8e4f764e2b710592597ca45a3ec3c080ac6f87  text/plain; charset=utf-8  ccc.txt

```

[削除後のmanifest]

```
$ swarm ls 8c148663734caa76ef7e88e06cafb5d32e41aa453a7d57d988591a8fc73afb9d
HASH                                                              CONTENT TYPE               PATH
ec4d1bae3ea590a9c24eacbe2130032a2ba6102d32c33a7bf94b415319a2c9e1  text/plain; charset=utf-8  bbb.txt
e7b8382739f0b459a1af2d7f0c8e4f764e2b710592597ca45a3ec3c080ac6f87  text/plain; charset=utf-8  ccc.txt
```

新しいmanifestからは消えましたけど、古い方は消えてないですね。
アップロードしたファイルはこの世から消せない可能性あるのでご注意を。


# 小ネタ

ファイル名が分からないとアクセスできないので、ファイル名一覧を書いたテキストを一緒にアップロードすると便利です。

```
$ curl -XGET http://swarm-gateways.net/bzz:/8cf62f0a78b19b6557425c4aed1821c765d83775977e4e367f1581837d7b8868/itemlist.txt
bbb.txt
ccc.txt
itemlist.txt

$ curl -XGET http://swarm-gateways.net/bzz:/8cf62f0a78b19b6557425c4aed1821c765d83775977e4e367f1581837d7b8868/bbb.txt
bbb
```


# 注意
ファイルを削除する方法が分からないので、アップロードするときには注意してください。ご存知の方いたら教えてください。
下手すると削除できない可能性があります。
試験するときはプライベートなテストネットを使用することと、機密情報はアップロードしないように注意してください。
違法なファイルはアップロードしちゃだめですよ。
くれぐれも悪用するんじゃないぞ


# もっと簡単にインストールする方法

```
go-ethereumのバイナリを取ってくる方が楽でした。
Geth & Toolsをwgetで取得すると、すぐにswarmが使えます。
wget https://gethstore.blob.core.windows.net/builds/geth-alltools-linux-amd64-1.7.3-4bb3c89d.tar.gz
tar zxvf geth-alltools-linux-amd64-1.7.3-4bb3c89d.tar.gz
```

# 用語
- Manifests  
data structure describing collections allow for url based access to content
- chunks  
pieces of data (max 4K), the basic unit of storage and retrieval in the swarm
- hash  
cryptographic hash of data that serves as its unique identifier and address

# 参考

Swarm Introduction
http://swarm-guide.readthedocs.io/en/latest/introduction.html