Rustを使ったグローバルステートへの読み書き

下記の例では、Casperネットワーク上のグローバルステートにプログラミング言語のRustを用いて読み書きする方法についての概要をお伝えしています。

基本的に、Casperエコシステムでは、ストレージに3つの意味を持たせています。それらは、runtime::put_key と storage::write(alongside storage::new_uref as explained below) 、 storage::dictionary_put です。この格納された値は、runtime::get_key と storage::read、storage::dictionary_get を使用して読みとれます。各メソッドが特有の方法でデータを格納していることとその違いへの理解は大切です。

関数についての説明

runtime::put_key / runtime::get_key

put_keyget_key 両方の関数は、Hash Typesの理解シリアライゼーション規格に書かれてあるように、CasperのKeyタイプを参照しています。この鍵は、KeyタイプとしてURefに格納されています。

storage::write / storage::read

storage::write は、事前に(storage::new_uref によって)生成されたURefに、指定された値を書き込みます。put_keyとは異なり、この値は上記にリストされたKeyタイプの1つではないが、潜在的にCLTypesのいづれかになります。storage::readは、これらの値を関連したURefから取得する方法を提供しています。

storage:dictionary_put / storage::dictionary_get

Casperネットワーク上の殆どのデータストレージにとって、辞書はNamedKeysより効率よく、ガスコストも低くなります。各辞書の項目は独立して存在しており、参照目的のために単一の辞書シードURefを共有します。

辞書に関する他情報は、辞書への理解をご確認ください。

コードのサンプル

put_key と storage::writeのサンプル

このコードサンプルは、新しいコントラクトを作成し、runtime::put_key関数を使用してグローバルステートにコントラクトハッシュを格納します。

格納された値が初期化されると、storage::write関数が既存の値をtrueに上書きします。その時、URefは現在のコンテキストにMY_STORED_VALUE_UREFという名前のNamedKey として格納されます。

    // Store contract hash under a Named key CONTRACT_HASH
    runtime::put_key(CONTRACT_HASH, contract_hash.into());

    // Store !MY_STORED_VALUE (false) as init value/type into a new URef
    let my_value_uref = storage::new_uref(!MY_STORED_VALUE);

    // Store MY_STORED_VALUE (true) under the URef value
    storage::write(my_value_uref, MY_STORED_VALUE);

    // Store the Uref under a Named key MY_STORED_VALUE_UREF
    let my_value_key: Key = my_value_uref.into();
    runtime::put_key(MY_STORED_VALUE_UREF, my_value_key);
}

get_key と storage::readのサンプル

このサンプルは、storage::readを用いて事前に格納されたMY_STORED_VALUE_UREFに対してランタイム引数ARG_MY_STORED_VALUEを比較する前に、get_key関数を用いて取得したCONTRACT_HASHにて上記のコードサンプルを補完します。

    let my_stored_value_uref: URef = runtime::get_key(MY_STORED_VALUE_UREF)
        .unwrap_or_revert()
        .into_uref()
        .map(|uref| URef::new(uref.addr(), AccessRights::default()))
        .unwrap_or_revert()
        .into_read();

    let my_actual_stored_value: bool = storage::read(my_stored_value_uref).unwrap().unwrap();

    // Compare my stored value with runtime arg
    let my_expected_stored_value: bool = runtime::get_named_arg(ARG_MY_STORED_VALUE);
    if my_actual_stored_value != my_expected_stored_value {
        // We revert if my stored value is not what is expected from caller argument
        runtime::revert(UserError::StoredValueError);
    }

    runtime::print(&my_actual_stored_value.to_string());
}

dictionary_put と dictionary_getのサンプル

ストレージの辞書の使用例は、辞書への理解の辞書へのエントリーの書込みにてご確認いただけます。

名前付き鍵の追加の関数

以下の関数は、名前付き鍵を使う際にも興味深そうです。

  • list_named_keys – 現在のコンテキストの名前付き鍵を返します
  • has_key – 鍵が現在のコンテキストの名前付き鍵に存在している場合は、trueを返します
  • remove_key – 現在のコンテキストから指定のNamedKeyを削除します