Substrateでブロックチェーンとアプリケーションを作る　Runtimeの設定から〜ゲームPlayまで

こんにちは、[Staked](https://staked.co.jp/)の渡辺創太です。

前回[こちら](https://qiita.com/SotaWatanabe/items/8de30f3728b07c9aa7d9)の記事で、Substrateのインストールからアカウントの作成までを行いました。この記事はその続きです。Gavin Woodの [Web3 Summitでのプレゼン](https://www.youtube.com/watch?v=0IoUZdDi5Is)を参考にしています。

<h1>Runtimeモジュールを作成する</h1>
RuntimeとはSubstrateにおけるブロック処理ロジックなどを決める機能です。State Transaction Functiuonとも言われるときもあり、WebAssemblyバイナリーでオンチェーンに記載さてています。詳しくは[Scraobox](https://scrapbox.io/StakedTechnologies/Substrate_%E2%91%A0Basic)に記載しています。

前回、`substrate-node-template`をインストールしましたが、`./runtime/src/demo.rs`のフォルダに記載していきます。

<img width="1014" alt="Screen Shot 2019-02-13 at 11.09.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/327904/81fa13ad-d231-d699-34bc-5e12fb1e5380.png">

作成した`demo.rs`にいくつかのライブラリーをインストールします。

```rust
use parity_codec::Encode;
use support::{StorageValue, dispatch::Result, decl_module, decl_storage};
use runtime_primitives::traits::Hash;
use {balances, system::{self, ensure_signed}};

pub trait Trait: balance::Trait {}
```

Web3 Summitのプレゼンでは、簡単な賭けゲームを作成していました。ゲームに勝てば、Potに溜まっていた金額を得ることができ、負ければPotに没収されるという簡単な仕組みです。

ライブラリーをインストールしたので、次に、モジュールを宣言する必要があります。(module declaration）

```rust
decl_module! {
    pub struct Module<T: Trait> for enum Call where origin: T::Origin {
        fn play(origin) -> Result{
            //ゲームをプレイするロジック
        }

        fn set_payment(_origin, value: T::Balance) -> Result{
            //ゲームのpaymentの仕様
        }
    }
}
```

```rust

decl_storage! {
  trait Store for Module<T: Trait> as Demo {
    Payment get(payment): Option<T::Balance>;
    Pot get(pot): T::Balance;
  }
}
```
strageモジュールはオンチェーンに載せる情報を定義するために使用します。

次に、モジュール内のロジックを書いていきます。

<h3>ゲームをプレイするロジック</h3>

```rust
fn play(origin) -> Result {

  let sender = ensure_signed(origin)?;
  //decl_strage!で宣言しているからpaymentが使える
  let payment = Self::payment().ok_or("Must have payment amount set")?;
　//senderの残高を減少させる
  <balances::Module<T>>::decrease_free_balance(&sender, payment)?;
  
  //ハッシュ関数を通してハッシュ値の最初のbyteが128以下であれば勝ち。potにあった金額がSenderに払われる
  if (<system::Module<T>>::random_seed(), &sender)
  .using_encoded(<T as system::Trait>::Hashing::hash)
  .using_encoded(|e| e[0] < 128)
  {
    <balances::Module<T>>::increase_free_balance_creating(&sender, <Pot<T>>::take());
  }
　
  //結果どうあれ、senderが賭けに参加した金額がデポジットされる
  <Pot<T>>::mutate(|pot| *pot += payment);

  Ok(())
}
```
<h3>ゲーム内のPaymentのロジック</h3>

```rust

fn set_payment(_origin, value: T::Balance) -> Result {
　//イニシャルpaymentがセットされていない場合の処理
  if Self::payment().is_none() {

    <Payment<T>>::put(value);
    <Pot<T>>::put(value);
  }
  
  Ok(())
}
```

<h1>変更をアップデートする</h1>
上記でModuleを設定しました。変更を実行するために`./runtime/src/lib.rs`を編集します。

`mod demo；`の追記。

<img width="1066" alt="Screen Shot 2019-02-14 at 13.48.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/327904/ca8e025a-163d-28f0-fe51-d910450e62e5.png">

`impl demo::Trait for Runtime {}`の追記

<img width="1137" alt="Screen Shot 2019-02-14 at 14.20.39.png" src="https://qiita-image-store.s3.amazonaws.com/0/327904/45d5b702-e25a-ee13-f8f9-706396a36bf3.png">


`Demo: demo::{Module, Call, Storage},`の追記

<img width="1092" alt="Screen Shot 2019-02-14 at 13.55.29.png" src="https://qiita-image-store.s3.amazonaws.com/0/327904/bf2ead39-0a65-b0f9-c4f2-0ef6a6564115.png">

上記で新しいRuntimeモジュールを作成したので、次にブロックチェーンのアップデートをします。

Substrate-node-templateのディレクトリでビルド
`substrate-node-template $ ./build.sh`

<img width="923" alt="Screen Shot 2019-02-14 at 14.21.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/327904/3c95cf52-f989-63ed-c204-432ff75c776d.png">

ビルド後、substrate-uiの`npm run dev`で接続したlocalhost8000にて一番下にRuntime Upgradeができるので、Select Runtimeを押し、

`./runtime/wasm/target/wasm32-unknown-unknown/release/node_runtime.compact.wasm`

を選択する。これでRuntimeのアップデートができました。Developer Consoleでみると動いていることがわかります。

![Screen Shot 2019-02-14 at 14.58.08.png](https://qiita-image-store.s3.amazonaws.com/0/327904/2fc356c0-b5db-8426-83ce-38385c93dc43.png)


<h1>UIを整える</h1>
UIを整えるにはsubstrate-uiレポジトリーを編集する必要があります。
`./substrate-ui/src/app.jsx`を編集します。

新しく以下のセクションを追加します。

```javascript
<Divider hidden />
<Segment style={{margin: '1em'}} padded>
  <Header as='h2'>
    <Icon name='game' />
    <Header.Content>
      Play the game
      <Header.Subheader>Play the game here!</Header.Subheader>
    </Header.Content>
  </Header>
  <div style={{paddingBottom: '1em'}}>
    <div style={{fontSize: 'small'}}>player</div>
    <SignerBond bond={this.player}/>
    <If condition={this.player.ready()} then={<span>
      <Label>Balance
        <Label.Detail>
          <Pretty value={runtime.balances.balance(this.player)}/>
        </Label.Detail>
      </Label>
    </span>}/>
  </div>
  <TransactButton
    content="Play"
    icon='game'
    tx={{
      sender: this.player,
      call: calls.demo.play()
    }}
  />
  <Label>Pot Balance
    <Label.Detail>
      <Pretty value={runtime.demo.pot}/>
    </Label.Detail>
  </Label>
</Segment>

```
同時に、exportの部分に`this.player = new Bond;`を追記します。

```
................
this.seedAccount.use()
this.runtime = new Bond;
//これ
this.player = new Bond;
}
```

これでUIを構築することができ、ゲームをPlayすることができます。

![Screen Shot 2019-02-14 at 15.21.10.png](https://qiita-image-store.s3.amazonaws.com/0/327904/00f19dcf-9527-8eb9-0bfa-53ec75ee3370.png)


Source: https://www.youtube.com/watch?v=0IoUZdDi5Is&t=22s