Runtime Return Valueの活用
Casper Networkと繋がっているユーザーは、セッションコードとコントラクトコードの違いを気に留めておいてください。セッションコードは、アカウントを初期化するコンテキスト内にて全体を実行し、コントラクトコードの場合は、そのステートのコンテキスト内にて実行されます。コントラクトによって実行されたいかなるアクションも、外部からの呼び出しを介して(通常は、セッションコード経由)初期化されることになります。
開発者は、Caller(呼び出し元)と即時Callerの違いについて、把握しておいてください。即時Callerは、セッションもしくはエントリーポイントに直接アクセスしているコントラクトコードを表示します。Callerは、最初に全体のプロセスを開始するセッションコードを生成する元です。コントラクトコードが他のコントラクトコードを呼び出すケースはたくさんあります。この場合、即時Callerは、他のコントラクトコードのインスタンスである場合もあります。このイベントでも、即時Callerとして動作するいくつかのスタックしたコントラクトコードレイヤーがあるので、全体のCallerがセッションコードの生成を行います。
コントラクトコードは、runtime::ret() 経由で、即時Callerが他のコントラクトコードかセッションコードの値を即時Callerに返すこともできます。返された値は、セッションかコントラクトコードのコンテキスト内で使われたり、後で使用する為に保存されたり、必要でなければ破棄されます。戻り値の必要性は、相対的に開発者がそのインスタンスで何を必要としているか次第です。
セッションコードは、Callerとみなされるアカウントの代わりにアクションをとってくれます。よって、何も値を返すことはできません。
Contract Code
例えば、寄付の記録を受け取り、保存するコントラクトを作成する場合、 runtime::ret() を用い、下記のとおりCallerに渡される想定の結果を定義します。
#[no_mangle]
pub extern "C" fn donate() {
let donating_account_key: Key = runtime::get_named_arg(DONATING_ACCOUNT_KEY);
if let Key::Account(donating_account_hash) = donating_account_key {
update_ledger_record(donating_account_hash.to_string())
} else {
runtime::revert(FundRaisingError::InvalidKeyVariant)
}
let donation_purse = *runtime::get_key(FUNDRAISING_PURSE)
.unwrap_or_revert_with(FundRaisingError::MissingFundRaisingPurseURef)
.as_uref()
.unwrap_or_revert();
let value = CLValue::from_t(donation_purse.into_add()).unwrap_or_revert();
runtime::ret(value)
}この例での戻り値は、資金づくりのお財布に対応している「追加」権限のみを持ったURefです。この情報を使うことで、呼び出しコードは寄付エントリーポイントを呼び出した後、お財布に資金を転送できるようになります。
runtime::ret を追加しないと、お財布がCallerに戻らないでしょう。
Session Code
下記が、指定エントリーポイントを呼び出しているセッションコードの一例となります。即時Callerはセッションコードを必要とせず、コントラクトコードの他のインスタンスであり得るということを覚えておいてください。
#[no_mangle]
pub extern "C" fn call() {
let fundraiser_contract_hash: ContractHash = runtime::get_named_arg(FUNDRAISER_CONTRACT_HASH);
let donating_account_key: Key = runtime::get_named_arg(DONATING_ACCOUNT_KEY);
let donation_amount: U512 = runtime::get_named_arg(DONATION_AMOUNT);
let donating_purse_uref: URef = runtime::call_contract(
fundraiser_contract_hash,
ENTRY_POINT_DONATE,
runtime_args! {
DONATING_ACCOUNT_KEY => donating_account_key
},
);
system::transfer_from_purse_to_purse(
account::get_main_purse(),
donating_purse_uref,
donation_amount,
None
)
.unwrap_or_revert()
}このセッションコードは、呼び出し先のコントラクトを特定する contract_hash と、この寄付のケースで呼び出されるエントリーポイントの名前を供給する runtime::call_contract を用いて、コントラクトのエントリーポイントを呼び出します。この場合ではCallerのアカウントキーである、donating_account_key を供給します。コントラクトは、この場合、donating_purse_uref の値を返します。 エントリーポイントを呼び出すには、戻り値のCLType(英文)が分かっていることと、コード内でそれを識別する必要があります。
グローバルステートのアカウントのクエリにて、戻り値のタイプを指定できます。アカウントではなくコントラクトをクエリするには、フォーマット可された文字列表記のコントラクトハッシュをキーパラメーターに置き換えます。この例でのコードは、返された値を取得し、呼び出しているアカウントのメインのお財布から作られた寄付用のお財布へ donation_amount を転送します。返された値をコードが保存する必要もなければ、使う必要さえありません。返された値を使うかどうかは、開発者にとっての必要性次第です。