セッションコードの書き方

このセクションでは、セッションコードの書き方についてお伝えします。セッションコードの定義についてやセッションコードとコントラクトコードの違いについては、コントラクトとセッションコードの比較をご確認ください。セッションコードは、Wasmにコンパイルされるどのプログラミング言語でも書けます。ただ、この項目のサンプルにはRustを使用しています。

ディレクトリ構造の作成

セッションコードを書く場合、ここで説明しているコントラクトを書く際に使用したプロジェクト構造と同様のものを使用します。

Example 1: セッションコードの書き方

下記ステップは、アカウント(https://github.com/casper-ecosystem/two-party-multi-sig/)設定用のサンプルセッションコードの参考リポジトリを用いてセッションコードを書くプロセスを描いています。サンプルコードがアカウントにアソシエイトキーを追加し、アクション閾値を更新します。Casper ネットワーク上のアカウントがアソシエイトアカウントとデプロイのマルチシグスキーマをセットアップ可能であることは記憶に留めておいてください。手順に沿っていく為には、まずはリポジトリをクローンします。

git clone https://github.com/casper-ecosystem/two-party-multi-sig/

💡NOTE

セッションコードの実行前に、セッションコードの動作について把握しているかご確認ください。意味を分かっていない場合、問題を引き起こしかねません。

Cargo.tomlの依存関係

Cargo.tomlファイルは、依存関係とセッションコードが必要とするバージョンを持っています。最低限の条件として、casper-contract と casper-typesクレートの最新版をインポートしなくてはなりません。下記の依存関係とバージョンは、あくまで参考までとなりますので自分の必要性に応じて調整してください。

  • casper-contract = "1.4.4" – 実行エンジン(EE)のSDKを提供。クレートのバージョンは、ここに公開されています。
  • casper-types = "1.5.0" – Casperネットワーク用のCasperクレートが共有している型。EEがセッションコードを理解しインタープリットするために必要なものです。クレートの最新バージョンは、ここに公開されています。

main.rsファイルのアップデート

サンプルのセッションコードを持つ、contract/src/main.rsファイルを開いてください。以下が、ファイルの頭にくるディレクティブたちです。

  • #![no_std] – 標準ライブラリをインポートしないよう指定します。
  • #![no_main] – main関数は、call関数のように1つのエントリーポイントのみを持つセッションコードのため、必要ではないことを表示します。

次に、インポートしたクレートと他の必要となるライブラリをレビューします。

#![no_std]
#![no_main]

use casper_contract::contract_api::{account, runtime};
use casper_contract::unwrap_or_revert::UnwrapOrRevert;
use casper_types::account::{AccountHash, ActionType, Weight};

ライブラリをインポート後、定数(constant)が確認できます。

const ASSOCIATED_ACCOUNT: &str = "deployment-account";

次に、このサンプルセッションコードの唯一のエントリーポイントである call関数について見ていきます。#[no_mangle]フラグは、関数名がWasmバイナリにて文字列として保有されていることを確認します。セッションコードの場合、このフラグがcall文字列の保有と実行エンジンのエントリーポイントのマークを行います。call関数の詳細については、クローンされたプロジェクトを開いて確認いただけます。

#[no_mangle]
pub extern "C" fn call() {
    // Open the repository for details
}

コンパイルされると、call関数は他のライブラリにて使用されこともあります。例えば、Cライブラリが結果のWasmに紐づいていたりします。

Example 2: セッションコードによるコントラクトの呼び出し

他のセッションコードのサンプルとして、counterレポジトリ内のcounter-call/src/main.rsファイルがあります。このサンプルでは、スマートコントラクト内に格納されたロジックを呼び出すセッションコードの共通の使い方についてお見せしています。手順に従って進めたい場合は、レポジトリをクローンしてください。

git clone https://github.com/casper-ecosystem/counter/

どのようにプロジェクトがセットアップされ、counter/counter-call/Cargo.tomlファイル内の依存関係がレビューされるのか、を観察します。そして、セッションコードを持つ counter/counter-call/src/main.rs ファイルを開きます。ファイルの頭にあるディレクティブが、必要な依存関係と宣言された定数です。

call関数は、コントラクトの counter_inc と counter_get のエントリーポイントとやり取りします。これが、セッションのcallエントリーポイントがカウンターコントラクト内に格納されたロジックをトリガーにする方法です。

    // Call the counter to get the current value.
    let current_counter_value: u32 =
        runtime::call_contract(contract_hash, COUNTER_GET, RuntimeArgs::new());

    // Call the counter to increment the value.
    let _: () = runtime::call_contract(contract_hash, COUNTER_INC, RuntimeArgs::new());

Example 3: セッションコードを用いた転送(transfer)

この例では、セッションコードを用いて、システム関数であるtransfer_from_purse_to_purseを使用した転送(transfer)を実行します。セッションコード全体については、GitHub上にてご確認いただけますが、ここで、call関数をお見せします。

#[no_mangle]
pub extern "C" fn call() {
    let target_purse: URef = runtime::get_named_arg(ARG_TARGET_PURSE);
    let amount: U512 = runtime::get_named_arg(ARG_AMOUNT);

    let source_purse = account::get_main_purse();

    system::transfer_from_purse_to_purse(source_purse, target_purse, amount, None)
        .unwrap_or_revert();
}

他のシステム関数は、transfer_to_public_key です。全体の参考セッションコード、GitHub上にあります。

#[no_mangle]
pub extern "C" fn call() {
    let account_hash: PublicKey = runtime::get_named_arg(ARG_TARGET);
    let transfer_amount: U512 = runtime::get_named_arg(ARG_AMOUNT);
    system::transfer_to_public_key(account_hash, transfer_amount, None).unwrap_or_revert();
}

他の有効な transfer 関数は以下です。

セッションコードのコンパイル

セッションコードをCasper Networkにデプロイする前に、Wasmにコンパイルする必要があります。Cargo.tomlファイルとsrcフォルダーがホストのディレクトリ内にて次のコマンドを実行してください。

cargo build --release --target wasm32-unknown-unknown

上記サンプルでは、提供されたMakefilesが必要な場合があります。

make build-contract

セッションコードの実行

稼働中のCasperネットワークにセッションコードをデプロイする前に、ここに記載の通りテストを実施できます。NCTLを使用してローカルネットワーク上で試運転を行うことも可能です。

デプロイを介して、セッションコードをCasperネットワーク上で実行します。デプロイ全て、全般的にカテゴライズされており、実行もしくはコミット時にネットワークのグローバルステートへ変更を書き込むタスク毎のいくつかのユニットとなっています。

Casper command-line クライアントとそのput-deployコマンドがセッションコードの実行方法を提供してくれます

casper-client put-deploy \
    --node-address <HOST:PORT> \
    --chain-name casper-test \
    --secret-key <PATH> \
    --payment-amount <PAYMENT-AMOUNT> \
    --session-path <SESSION-PATH> \
    --session-arg <"NAME:TYPE='VALUE'" OR "NAME:TYPE=null">
  • node-address – ネットワーク上のピアのIPアドレス。MainnetとTestnetのJSON-RPCサーバーのデフォルトポートは、7777です。
  • secret-key – デプロイを支払うアカウントの秘密鍵を含むファイル名
  • chain-name – デプロイを送信したいネットワークのチェーン名(chain-name)。Mainnetでは、casperを使います。Testnetの場合は、casper-testを使用します。
  • payment-amount – デプロイの対価への支払い(motes単位)。支払いの合計は、デプロイとネットワークのchainspecを基に変わります。
  • session-path – コンパイルしたコントラクトを指す、コントラクトWasmへのパス
  • session-arg – Wasmコードに渡される名前と型付けされた引数

–help を使って、サポートされている引数の最新のリストを確認できます。

casper-client put-deploy --help

Video Walkthrough

このビデオでは、アカウント設定用のサンプルセッションコード についての簡単な説明をお見せします。

What’s Next?

・Casperのテストフレームワークを用いたセッションコードのテストについて