Loom Blockchain環境構築 + TruffleによるSmart Contractデプロイ + ブロックチェーンデータをExpress.jsからRest APIでフロントで取得して表示してみる

# 開発環境
Mac : 10.13.6（OS X High Sierra）
Node : v10.6.0
npm : 6.3.0

# 実装背景

Ethereumブロックチェーンは、スマートコントラクトに任意のプログラムを執行するスクリプトを作ることである一定以上の条件を満たしたロジックを自動化できるブロックチェーンです。

現在ではCryptoKittiesのようなゲームから、サプライチェーンを管理するアプリケーションといった幅広いアプリケーションが作成されています。

しかし、イーサリアムは現在、単位時間あたりの処理能力の点で問題に直面しており、Ethereumブロックチェーンのメインチェーンだけでは合意形成時のセキュリティ保護の観点から1秒間で15回のトランザクションを承認するルールがあるため承認スピードにおいて上限が存在します 。

解決策としては、承認時間が長い問題を解決するためにトランザクションを承認した結果をメインチェーンに戻すといったサイドチェーンを構築する考えが提唱されています。

Loom Blockchainでは、イーサリアムのスケーラビリティ問題を解決するサイドチェーンの一つとなります。

# Loom Blockchain 環境構築

今回、私はGameWith × Loom Hackathonに参加し、そこで、開発して来たことを中心に備忘録として記事に書いて行こうと思います。

Loomブロックチェーンを構築する際など参考になるページはこちらの会社の公式ページになります。[Loom Developerページ](https://loomx.io/developers/)

では環境構築に入ります。

以下のコマンドをloom環境を構築したいディレクトリ中で、叩くとLoomブロックチェーンが起動します。

```terminal:terminal
 # loomファイルの取得
 $ wget https://private.delegatecall.com/loom/osx/build-330/loom 
 # loomファイルの権限の変更
 $ chmod +x loom 
 # loom blockchian環境の初期化
 $ ./loom init 
 # loom blockchain起動
 $ ./loom run 
```

# アプリケーション環境構築

次に、Loomブロックチェーンを用いたアプリケーションのサンプルがgitに上がっていますので、git cloneを行いアプリケーションの環境をlocalに作成します。

```terminal:terminal

 # localにサンプルをclone
 $ git clone https://github.com/loomnetwork/truffle-dappchain-example

 # truffleをインストールしていない人はこちらを実行
 $ npm install -g truffle

 # ディレクトリ移動
 $ cd truffle-dappchain-example

 # packageをインストール
 $ npm install

 # contractをデプロイする 
 # contractはcontracts directoryにあります。
 $ npm run deploy 

 # reactの環境を動かす
 $ npm run serve 
```

この時点でlocalhost:8080にアクセスすることで以下のような UIのアプリケーションが動きます。

![Screen Shot 2018-08-12 at 23.07.24.png](https://qiita-image-store.s3.amazonaws.com/0/199917/a62bc9be-73ae-3aba-071b-f500466d9b82.png)


React.jsのindex.jsを書き換えたり、Contractを書き換えることでloomブロックチェーン環境を用いたブロックチェーンアプリケーションを作ることができます。(サンプルソースでは、contract.jsにトランザクション処理をまとめて書いているようです。勉強になります。)

# サーバー側で作成したユーザーアドレスを取得 + REST APIにする

次に、現在の仕様では、ブロックチェーンの情報取得をする際、string型の配列を取得することができないため、ユーザーが自分に関係のある文字列をindexを指定して一つ一つ取りに行く必要があります。

一回一回ユーザーがブロックチェーンに情報を取りに行くことは、ブロックチェーンがDDos攻撃を受けてしまうようなことが起き、レスポンスの遅れなどといった問題が生じる可能性があります。

現状これを解決するためのアーキテクチャーとして今回は、Expressサーバーを立て、情報をキャッシュして置くことで、REST Apiで簡単に早くデータ取得することを可能としました。(今回はキャッシュまでしていません。)

今回はLoomブロックチェーンから情報を取るためにloom-jsというライブラリを用いており、プライベートキーを生成してパブリックキー、アドレスを生成し、web3ライブラリを用いてLoomブロックチェーンにアクセスしています。

![Screen Shot 2018-08-12 at 15.13.37.png](https://qiita-image-store.s3.amazonaws.com/0/199917/8ccf8a7c-16a6-7e84-d510-8899bd0d6f38.png)

Directoryを作成して次のコマンドを実行します。

```:express
 $ mkdir expressServer
 $ cd expressServer
 $ npm init 
 $ npm install express loom-js web3 --save
 $ touch app.js
```

app.jsに次のコードを記述します。

```javascript:app.js

const express = require("express");
const app = express();
const Web3 = require('web3')
const Loom = require('loom-js')

const server = app.listen(8080, function () {
  console.log("Node.js is listening to PORT:" + server.address().port);
});

const privateKey = Loom.CryptoUtils.generatePrivateKey()
const publicKey = Loom.CryptoUtils.publicKeyFromPrivateKey(privateKey)

const client = new Loom.Client(
  'default',
  'ws://127.0.0.1:46657/websocket',
  'ws://127.0.0.1:9999/queryws',
)

const from = Loom.LocalAddress.fromPublicKey(publicKey).toString()

const web3 = new Web3(new Loom.LoomProvider(client, privateKey))

app.get("/get", async (req, res, next) => {
  	res.header("Access-Control-Allow-Origin", "*");
  	res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  	res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
    const account = await web3.eth.getAccounts();
    res.json(account);
  	next();

});

```


こちらのコードは、Loom Blockchainに接続するためのweb3インスタンスを作成しており、こちらのweb3インスタンスを用いて作成されたユーザーアドレスデータを取得しています。

# Expressサーバーで取得した情報をRest ApiでReact側に表示

今回はgithubに上がっておりあらかじめcloneしておき[truffle-dappchain-example](https://github.com/loomnetwork/truffle-dappchain-example)を用いてExpress.jsから情報をとってきたいと思います。

index.jsを次のように書き換えます。

```react:index.js

import React from 'react'
import ReactDOM from 'react-dom'
import Contract from './contract'
import axios from 'axios'

const Index = class Index extends React.Component {

  constructor(props) {
    super(props)
    this.contract = new Contract()
    this.state = {}
  }


  async componentWillMount() {

    // ここでExpress.jsからデータを取得してstateにデータを格納する
    axios.get(`http://localhost:8080/get`)
      .then(res => {
        const address = res.data;
        this.setState({
          address
        });
      })
  }

  render() {
    return (
      <div className="container" style={{ marginTop: 10 }}>
        <div>
          {this.state.address}
        </div>
      </div>
    )
  }
}

ReactDOM.render(<Index />, document.getElementById('root'))

```

これにて準備完了です。各ファイルがあるディレクトリで異なるターミナルウィンドウ上で次の三つのコマンドを実行します。


```terminal:各ディレクトリ
./loom run 
node app.js　// 8080ポート
npm run serve // 8081ポート
```

サンプルのアプリケーションがすでに8080番ポートが埋まっている際は、次の番号の8081番ポートでアプリケーションを開くように指定しているようです。
(8081番ポートが埋まっていたら8082番ポートが開くことも確認済みです)。


今回は、8080番ポートでExpress.jsサーバーを立てているためlocalhost:8081のURLでアプリケーションを開いてみましょう。


するとreactで表示される画面上にExpress.js側で作成したLoomブロックチェーンに接続したユーザーアドレスデータを取得できていることが確認できます。

同様にして、Loomブロックチェーンにデプロイしたコントラクト情報をExpress.jsでキャッシュしてフロントから情報を取得することはできると思います。（制限時間内ではここまでの実装が限界でした💦）

以上です。最後まで読んでいただきありがとうございました (^^)

# 参考

[Loom developer page](https://loomx.io/developers/docs/en/loom-js-quickstart.html)