Tokens
はじめに
Casperネットワークは、 Highwayと呼ばれているプルーフ・オブ・ステークのコンセンサスアルゴリズムに基づく分散型計算プラットフォームです。ユーザーは計算に対する支払いを行う必要があり、バリデーターは担保する為のステーク(資産保有量)を所有している必要がある為、このシステムを機能させるには価値の単位が必要です。ブロックチェーン界隈では、この価値の単位を、トークンといいます。
本章では、トークンの定義の仕方、更にはCasperプラットフォームにおけるトークンの使用方法について説明します。
トークンの生成と配布
ブロックチェーンシステムでは、計算処理に対してや、ネットワーク上でのトランザクションデータ処理に対するバリデーターへの報酬の支払いといった、目的に応じたトークンが供給可能である必要があります。Mainnet(メインネット)立ち上げ時の初期供給量は、100億CSPRでした。現在の供給量は、こちらで確認できます。初期供給量に加えて、システムには低いインフレ率が設定され、その結果はシニョリッジ(通貨発行益)という形でバリデータに支払われます。
シニョリッジ(通貨発行益)を計算する基準として使用されるトークン数は100億となります。
トークンの可分性
通常、「トークン」はいくつかの部分に分割できます。私たちのトークンを構成するこうした分割不可能な単位をmotes(モーツ)と呼びます。各CSPRは109のモーツに分割できます。丸め誤差の発生を回避する為、トークンの残高を常にモーツで表すことが重要です。対照的に、Etherは1018のパーツ(Wei/ウェイと呼ぶ)に分割できます。
Mintとパース(財布)
mintは、特定の種類の新たなモーツを作り出すコントラクトです。EthereumにおけるERC20トークンと同様に、様々なトークンを対象とする巨大なエコシステムを見越して、多種のモーツ(各々が独自のMintを持つ)を対象にしています。CasperLabsは、特定のMintコントラクトをデプロイし、このコントラクトはCSPRユーティリティトークン(計算への支払いやネットワークへの担保に使用)を管理します。Mintは、モーツの種類毎の全残高も保持します。各残高は、URefに関連付けられており、Mintがその残高に対するアクション(例えば、送金モーツなど)を実行するように指示する一種のキーとして機能します。非公式には、こうした残高をパース(財布)と呼び、概念的に言うと、これはモーツの入れ物にあたります。URefは、Mint外にてパースを参照する方法を示しています。
URefsの許可モデルのAccessRightsは、パースに関連付けられたURefを使用する際に、実行可能なアクションを決定します。
全てのURefは偽造不可能であるので、パースとデータを交換する唯一の方法は、適切なAccessRightsを伴うURefを有効な方法で現在のコンテキストに与えることです。(詳細については、URefの権限を参照のこと。)
基本的なグローバルステートのオプションは、以下の表に従ってより標準的な通貨操作にマップされます。
| グローバルステートアクション | 通貨アクション |
| Add(追加) | 預入 (~への送金) |
| Write(書き込み) | 引き出し (~からの送金) |
| Read(読み取り) | 残高照会 |
Casperシステム上のトークンの実装・使用法を説明するにあたり、本章を通じてこれらの定義を使用していきます。
Mint(鋳造)コントラクトインターフェイス
有効なMintコントラクトについては、下記の方法で公開されます。(様々な形態のMint実装が存在しており、各々が異なる「通貨」に対応しています。)
- transfer(source: URef, target: URef, amount: Motes) -> TransferResult
- source(送信者)には、少なくともWriteアクセス権が必要であり、target(受信者)には、少なくともAddアクセス権が必要です。
- TransferResultは成功を返すか、無効なsourceもしくはtargetである場合、または送信者のお財布にある残高が不十分である場合にエラーとなる可能性があります。
- mint(amount: Motes) -> MintResult
- MintResultについては、作成されたURef(全てのアクセス権を保持)を与え、それにより、指定されたamountに等しい残高を得るか、または、許可されていない新たなmotesをMintしたことに起因するエラーを与えるかのいずれかを行います。
- CasperのMintは、システムアカウントだけがmintを呼び出すことができ、有効な暗号化署名を生成する秘密鍵はありません。つまり、ソフトウェア自体のみがシステムアカウントのコンテキストにおいてコントラクトを実行できます。
- create()-> URef
- mint(0)の簡易関数であり、常に空のパース(財布)を作成可能な為、エラーになることはありません。
- balance(purse: URef) -> Option<Motes>
- purseには、少なくともReadアクセス権が必要です。
- BalanceResultについては、purseが保持しているmotes数を返すか、URefが有効でない場合に何も返さないかのいずれかです。
パース(財布)のURefを使用する
Write権限を持つパース(お財布)のURefを任意のコントラクトに対して渡すのは危険です。悪意のあるコントラクトは、そのアクセスを利用して、想定より多くのトークンを取得したり、アクセスされるはずのない他のコントラクトと紐づいたURefを共有する可能性があります。従って、コントラクトにWrite権限を持つパースを必要とする場合には、他でもなく単一のトランザクションのみに使用される「payment_purse(支払い用のお財布)」を常に使用することを推奨します。これにより、URefが危殆化した場合でも、ユーザーが予定した付与額以上の資金は保持しないという状況を確実に維持できるのです。
let main_purse = contract_api::main_purse();
let payment_purse = contract_api::create_purse();
match contract_api::transfer_purse_to_purse(main_purse, payment_purse, payment_amount) {
TransferResult::Success => contract_api::call_contract(contract_to_pay, payment_purse),
_ => contract_api::revert(1),
}こうした不便さを回避するのに、オンチェーンでの支払いを実施予定であるアプリケーション開発者が、ReadとAddアクセス権を備えた独自のパースURefのバージョンを公開するというのは、望ましい実施例の一つとなるでしょう。こうした方策を取れば、クライアントと開発者どちらもパースに対してWriteアクセスを公開することなく、クライアントは自分のパースを用いて送金を通した支払いを行うことができるのです。
パース(財布)とアカウント
Casperシステム上の全てのアカウントには、CasperシステムのMintと紐付いた「財布(パース)」があり、これを「メインパース」と呼びます。ただし、セキュリティー上の理由から、メインパースのURefは、そのアカウントを使って実行されるコード(つまり、ペイメントコードまたはセッションコード)でのみ使用可能です。従って、URefを受け取るMintのtransfer(転送)は、アカウントのメインパース間での転送方法として最も使い勝手が良い方法とは言えません。こうした理由から、Casperは、transfer_to_account関数を提供します。この関数は、アカウントのIDを導くのに使用する公開鍵ーを取得します。この関数は、source(送信者)として現時点でのアカウントのメインパースを使用し、提供された鍵にあるアカウントのメインパースをtarget(受信者)として使用します。