Cosmos sdkベースのBlockchainにおけるsmart contract実行プラットフォーム CosmWasmについて調べた

# What is CosmWasm
- Cosmos sdkで作られるApplication Specific Blockchainでwasm smart contractを構築するためのライブラリ
- もともとはベルリンのHackatom2019で Gaiansチームがプロトタイピングしたもの
- CosmWasmはCosmos sdkにプラグインできるモジュールとして書かれている
- gaiadをフォークしてCosmWasmを実行できるwasmdというsample chainも提供されているので、contractの開発から開始することも可能

**NOTE:** contract実行に関する最新の情報は以下のページを参考にすべし！
https://www.cosmwasm.com/docs/getting-started/first-demo

## Ecosystem
- CosmWasmには多くのlibraryやtoolがあったため、まずはecosystem全体を把握する
![CosmWasm](https://user-images.githubusercontent.com/21156794/81129936-f52a5700-8f80-11ea-9ac7-a2c8c8b1cb42.png)

- cosmwasm
  - cosmosに対応したwasm smart contractを構築するためのライブラリ
  - https://github.com/CosmWasm/cosmwasm
    - cosmwasm-std
      - smart contractの構築に必要なbindingと全てのimportを提供するcrate
      - https://github.com/CosmWasm/cosmwasm/tree/master/packages/std
	- cosmwasm-vm
      - wasmerを利用して特定のcontractを実行するためのcrate
      - https://github.com/CosmWasm/cosmwasm/tree/master/packages/vm
	- cosmwasm-storage
      - Storageパターンのためのhelperを提供するcrate
      - https://github.com/CosmWasm/cosmwasm/tree/master/packages/storage
- wasmd
  - cosmos-sdkベースのwasm contractを実行できるブロックチェーン
  - https://github.com/CosmWasm/wasmd
    - go-cosmwasm
      - wasmerを使って実行するcosmwasm contractへのgo binding
  	  - https://github.com/CosmWasm/go-cosmwasm
- cosmwasm-opt
  - docker imageとRustコードを受け取り、決定論的にwasmファイルを生成するためのスクリプト
- cosmwasm-examples
  - cosmwasm-templateで構築されたsample cosmwasm contract
  - https://github.com/CosmWasm/cosmwasm-examples
- cosmwasm-template
  - cosmwasmシステムと互換性のあるcustom contractを構築するために取得するスターターパック
  - https://github.com/CosmWasm/cosmwasm-template
- serde-json-wasm
  - serde-json-core からフォークされたカスタムjsonライブラリ
  - https://github.com/CosmWasm/serde-json-wasm
- cw-storage
  - cosmwasm-storageと同様Storageパターンのためのhelperを提供するlibrary。core libraryにはないので、自由にフォークして、自身のcontractのために必要に応じて拡張可能。
  - https://github.com/CosmWasm/cw-storage
  
 
# Getting Started
- 公式ドキュメントの以下のページ通りに進めるとWebAssembly Smart Contractが実行できるApplication Specific Blockchainが実行できる。  
https://www.cosmwasm.com/docs/getting-started/using-the-sdk

- 以下のページでcosmwasm-examplesのdemoコントラクトが実行できる
  https://www.cosmwasm.com/docs/getting-started/first-demo

# Smart Contract
- cosmwasm, cw_storage libraryを使用してSmart Contractを実装する。
- Messageベースでchainとデータのやり取りを行うためCosmos sdkモジュールの開発と同じようにsmart contractが開発できる。

## Model
### state.rs
- contractの初期状態を定義する
- sampleではsingletonのStorageを使用
- config: write function
- config_read: read function

```rust:state.rs
pub struct State {
    pub count: i32,
    pub owner: CanonicalAddr,
}

pub fn config<S: Storage>(storage: &mut S) -> Singleton<S, State> {
    singleton(storage, CONFIG_KEY)
}

pub fn config_read<S: Storage>(storage: &S) -> ReadonlySingleton<S, State> {
    singleton_read(storage, CONFIG_KEY)
}
```

### msg.rs
- smart contractが実行するtx, queryのためのMessageを定義する
- 使用したい構造体があれば、定義する

```rust:msg.rs
pub struct InitMsg {
    pub count: i32,
}

pub enum HandleMsg {
    Increment {},
    Reset { count: i32 },
}

pub enum QueryMsg {
    GetCount {},
}

pub struct CountResponse {
    pub count: i32,
}
```

### contract.rs
#### init function
- contractを初期化する

```rust:contract.rs
pub fn init<S: Storage, A: Api>(
    deps: &mut Extern<S, A>,
    env: Env,
    msg: InitMsg,
) -> Result<Response> {
    // 初期状態を作成
    let state = State {
        count: msg.count,
        owner: env.message.signer,
    };

    // 設定を保存する
    config(&mut deps.storage).save(&state)?;

    Ok(Response::default())
}
```
#### handle function
- txをhandleする
- Messageのtypeに応じて、実行する関数を分岐する


```rust
pub fn handle<S: Storage, A: Api>(
    deps: &mut Extern<S, A>,
    env: Env,
    msg: HandleMsg,
) -> Result<Response> {
    match msg {
        HandleMsg::Increment {} => try_increment(deps, env),
        HandleMsg::Reset { count } => try_reset(deps, env, count),
    }
}
```

#### query function
- queryを実行する
- tx同様、Messageのtypeに応じて実行する関数を分岐する

```rust
pub fn query<S: Storage, A: Api>(deps: &Extern<S, A>, msg: QueryMsg) -> Result<Vec<u8>> {
    match msg {
        QueryMsg::GetCount {} => query_count(deps),
    }
}
```

## NFT-MVP
- 公式ドキュメント、サンプルコードを参考にしてNFT用のsmart contractの実装を行った  
https://github.com/shiki-tak/nft-mvp

```rust:handle
        HandleMsg::Transfer { recipient, token_id } => transfer(deps, env, &recipient, token_id),
        HandleMsg::TransferFrom { sender, recipient, token_id } => transfer_from(deps, env, &sender, &recipient, token_id),
        HandleMsg::Approve { recipient, token_id } => approve(deps, env, &recipient, token_id),
        HandleMsg::ApproveForAll { owner, recipient } => approve_for_all(deps, env, &owner, &recipient),
        HandleMsg::Mint {} => mint(deps, env),
```

```rust:query
        QueryMsg::Balance { address } => balance(deps, &address),
        QueryMsg::Owner { token_id } => owner(deps, token_id),
        QueryMsg::Allowance { token_id } => allowance(deps, token_id),
```

# Conclusion
- CosmWasmはCosmos sdkベースのblockchainでwasm smart contractを実行するためのecosystem
- ドキュメント通りに進めるとsmart contractの実行まで正常に動作することが確認できた
- Cosmos sdkモジュール開発と同じようにMessageベースでsmart contractを記述していくので、Cosmos sdkの開発経験があれば、比較的簡単に開発できるはず
- 逆に言えば、Cosmos sdkモジュールの開発経験がない人にはコストが高い？
- 他のwasm smart contractが実行できるblockchain(substrateのink!やhypermint)はどのような仕組みになっているのか調べてみる必要がある

# Reference
- https://www.cosmwasm.com/