イーサリアムでスマートコントラクトを動かしてみる


![2021-10-02_12h30_44.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/80055eac-20b9-76d6-90f4-fcff203fbc05.jpeg)

仮想通貨は数あれどイーサリアムに代表されるブロックチェーンが実装してるスマートコントラクトという仕組みは面白いですね。ビットコインは通貨だけどイーサリアムのようなスマートコントラクトは非中央集権のスーパーコンピュータを構築するのを目的に作られているようです。

Amazon, Google, Microsoft のクラウドサービスと競合するのかな？

イーサリアムをローカルで動かしてスマートコントラクトでプログラムを動かしてみようと思います。おおまかな流れはこんな感じ。

* イーサリアムをインストール＆起動してマイニング
* スマートコントラクトをイーサにデプロイ
* スマートコントラクトを実行

スマートコントラクトとはなんだ？と思われる人がいると思いますがSolidityという言語で書かれたただのプログラムコードです。この記事の最初に書かれているコードがスマートコントラクトです。

![2021-10-02_12h30_44.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/80055eac-20b9-76d6-90f4-fcff203fbc05.jpeg)

もう一度載せておきます。

これをイーサのネットワークにデプロイするとメンバ関数を呼び出すことができます。仮想通貨の顔したただのクラウドサーバです（ただしAWSみたいな特定の運営者はいない）


# イーサリアムをインストール＆起動してマイニング

イーサリアムはただの仕様なのでそれを実装しているアプリケーションはたくさんあります。今回はGethというものを使います。WSL(Windows Subsystem for Linux)のUbuntuにGethをインストールして立ち上げました。apt-getでできるので簡単です。[オフィシャルのドキュメントはこちら。](https://geth.ethereum.org/docs/install-and-build/installing-geth)

```bash
$ sudo add-apt-repository -y ppa:ethereum/ethereum
$ sudo apt-get update
$ sudo apt-get install -y ethereum
```

これで Geth という ethereum のノードを起動することができます。ブロックチェーンは世界中にあるノードがP2Pでやりとりして処理を行っていきます。ここにスマートコントラクトをデプロイ（マイニングでブロックに取り入れる）した後にメンバ関数を呼び出すことができます。

次にデータを格納するフォルダを作成して移動します。

```bash
$ mkdir geth
$ cd geth
```

ブロックチェーンはマイニング（採掘）するノード（PC）がブロックを生成することで動きます。マイニングするとコインをゲットできるので多くのノードが仮想通貨ネットワークに参加してくれます。そしてそのリソースを使ってプログラムを実行していくという仕組みになっています。今回はローカルでの環境ですがマイニングしてコインをゲットするアカウントをまず作ります（ややこしいですね。これがブロックチェーンを理解するのが難しいところだと思います）

```bash
$ geth account new --datadir data
```

```data``` はディレクトリです。ローカルで動かす ethereum のデータが全て格納されます。

![2021-10-02_14h20_21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/6ebf4633-be63-35d0-7de5-9d13bc3dd79a.jpeg)

パスワードの設定を２回求められるので適当なものを入力します。```password``` にしました。アカウントの識別子は ```0xaD52931b7C97A6bCe6bAbC66E7E0B713844FE47C``` になります。

次はローカルで ethereum を初期化します。[オフィシャルのドキュメントはこちらになります。](https://geth.ethereum.org/docs/interface/private-network)

最初のブロックを定義します。ブロックチェーンはデータをブロックに格納してそれを繋げていくという仕組みなのですが、一番最初のブロックを ```genesis.json``` で定義して Geth を初期化します。

```json:genesis.json
{
  "config": {
    "chainId": 88889999,
    "homesteadBlock": 0,
    "eip150Block": 0,
    "eip155Block": 0,
    "eip158Block": 0,
    "byzantiumBlock": 0,
    "constantinopleBlock": 0,
    "petersburgBlock": 0,
    "clique": {
      "period": 5,
      "epoch": 30000
    }
  },
  "difficulty": "1",
  "gasLimit": "8000000",
  "extradata": "0x0000000000000000000000000000000000000000000000000000000000000000aD52931b7C97A6bCe6bAbC66E7E0B713844FE47C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "alloc": {
    "aD52931b7C97A6bCe6bAbC66E7E0B713844FE47C": { "balance": "1000000000000000000" }
  }
}
```

```bash
geth init --datadir data genesis.json
```

```chainID``` を ```0``` にすると ethereum のメインネットワークに接続するノードとして動きます。今回はローカルで動かすので被らないような数値にします。

ブロックチェーンでの処理効率はコンセンサスアルゴリズムというP2Pネットワークで相手を信用するためのアルゴリズムで変わるのですが、ローカル環境では```clique``` というのを指定します。ビットコインは ```proof of work``` を使ってるのですが電気消費量が半端ないので問題になってます。

そして、先程作成したアカウント ```aD52931b7C97A6bCe6bAbC66E7E0B713844FE47C``` を ```extradata``` と ```alloc``` に指定します。そして、このアカウントには初期値として ```1 ether``` の仮想通貨を持たせます。。

```bash
$ geth --http --http.corsdomain="https://remix.ethereum.org" --http.api web3,eth,debug,personal,net --vmdebug --datadir data --allow-insecure-unlock --networkid 88889999 --unlock 0xaD52931b7C97A6bCe6bAbC66E7E0B713844FE47C --mine
```

起動します。

```--networkid 88889999``` と ```--unlock 0xaD52931b7C97A6bCe6bAbC66E7E0B713844FE47C``` を環境に合わせて変えてください。あと大切なのは ```--mine``` です。マイニングしないとシステムが動かないのがブロックチェーンです。

# スマートコントラクトをイーサにデプロイ

ここまでできれば後はボタンをポチポチするだけの簡単な作業になります。

まずはイーサのスマートコントラクトを書いたりデプロイできる [Remix](https://remix.ethereum.org/) をブラウザで起動します。
https://remix.ethereum.org

![2021-10-02_15h08_51.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/237fa32a-7827-ac54-a6d7-42150e2aeff0.jpeg)

サンプルプログラムを動かしていきます。①②の順で ```Storage.sol``` を開いて

![2021-10-02_15h09_24.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/be991685-8428-612c-3271-747848ceb857.jpeg)

③④でコンパイルして

![2021-10-02_15h10_11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/94e2b106-dc0f-176d-cad7-b943f5f86e68.jpeg)

⑤でデプロイ画面を開き、⑥で ```Web3 Provider``` に変更することでローカルに立ち上げたイーサにプログラムをデプロイできるようになります。

![2021-10-02_15h09_46.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/bc2e09ba-005f-00be-bb03-cd25df11d1b3.jpeg)

⑥で ```Web3 Provider``` を選択すると接続先を聞いてくるので　先程立ち上げたイーサの ```http://127.0.0.1:8545``` を指定します。デフォルトで入力されるのでOKを押すだけ大丈夫です。なお Geth を起動するためのパラメーターもここに書かれています。

# スマートコントラクトを実行

![2021-10-02_15h10_45.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/e9850b19-426b-22ca-9940-54c794336709.jpeg)

デプロイが成功してブロックにスマートコントラクトが取り込まれると ```Submitted contract creation``` というログが出ます。ブロックチェーンではマイニングしてブロックに取り込むことが重要になります。

![2021-10-02_15h11_57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/ab50878b-6176-517b-49fe-d39aec780ff9.jpeg)

無事プログラムがブロックに取り込まれるとメンバ関数を呼び出しできるようになります。⑦の ```store()``` 関数で変数 ```number``` に値をセットして⑧の ```retrieve()``` 関数で値を取り出せます。

デプロイしたときに指定した⑨のイーサのウォレットからガス代としてイーサがどんどん吸われていくのでそこだけ注意してください。

# しめ

ビットコインの実装は個人的にはとても邪悪だと思うのですが、そこから派生したスマートコントラクトはその設計思想から悪くないイメージを感じてます。電力効率的には既存のクラウドシステムよりあまり良くないのだけど上手く発展していってほしいなと感じる技術です。