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

Getting Started

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
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を定義する
  • 使用したい構造体があれば、定義する
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を初期化する
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に応じて、実行する関数を分岐する
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に応じて実行する関数を分岐する
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

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),
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