Tezos ブロックチェーン のためのスマートコントラクト記述言語 SCaml、チュートリアルの第3回目です。
今回はTezosブロックチェーンにアクセスするコマンドラインウォレット tezos-client
の実習です。
- コンセプトの紹介(英語)
- リリースのお知らせ(英語)
- プロジェクトページ
- レポジトリ
- 第0回: コンセプトの説明
- 第1回: 準備
- 第2回: 概観
- 第3回: ウォレット操作
- 第4回: スマートコントラクトのデータ型
- 第5回: はじめての SCaml コントラクト
- 第6回: もう少し複雑なコントラクト。パラメータとストレージ
- 第7回: 投票コントラクトを書いてみる
このブログではSCamlを使ったTezosスマートコントラクトプログラミングについて少しずつ日本語で連載をしていきたいと思います。
(この内容は 2020-03-21 にやった SCaml ハンズオンの資料を手直ししたものです。)
やっと実習
はいやっとです。でも SCaml には…まだ触れません。あれ〜。
まずは Tezos ブロックチェーンにアクセスするための基本プログラムであるコマンドラインウォレット、 tezos-client
の使い方を理解しないといけません。
Tezos ネット
Tezos には使用目的によって複数の異なるネットワークがあります:
- mainnet
- 換金性のあるトークンが扱われている本番環境です。このネットワークに書き込みを行いたい場合は mainnet トークンを所持している必要があります。持っていない場合は仮想通貨交換所で購入などしなければいけません。
- 現在(2022-05)の mainnet で動作している Tezos のプロトコルのバージョンは 012 Ithaca (イタカ)といいます。
- テストネット
- 失敗しても金銭的損害を受けずに安心してテストできるネットワークとして、テストネットがあります。テストネットのトークンは無料で入手できます。(でもお金には変えられません。残念。)
- 現在の Mainnet と同じ 012 Ithaca プロトコルが動いているテストネットを ithacanet といいます。 このチュートリアルではこの ithacanet を使います。
このテストネットの名前はTezos プロトコルのアップデートに伴って変わります。
Tezos ノード
本来の Tezos 開発では手元でノード(ブロックチェーンサーバのインスタンス)を動かして、それとお話しするのですが、時間がかかるのでこのチュートリアルではしません。RPCポートを公開している node を使わせてもらいます。この設定は check
スクリプトで自動的に行われているはずです。念のため、もう一度 check
を走らせてみてください:
$ cd docker-tezos-hands-on (Git clone したディレクトリで作業)
$ ./check
(以下は出力例です)
Checking network connectivity inside Docker... Ok
Finding an accessible public Tezos RPC server...
Checking https://ithacanet.smartpy.io: Ok
Using --endpoint https://ithacanet.smartpy.io
Updated the config of ./tezos-client:
{ "base_dir": "/root/.tezos-client",
"endpoint": "https://ithacanet.smartpy.io", "web_port": 8080,
"confirmations": 0 }
Ok
ここで問題が出る場合は、第1回の記事を確認してください。(もしかするとスクリプトがアップデートされているかもしれません)
上の例では https://ithacanet.smartpy.io にあるパブリックRPCノードと通信する設定になっています。この設定は $HOME/.tezos-handson-client
に書き込まれます。気になる人は実習後消してください。
tezos-client
Tezosノード、つまり Tezos の分散データベースにアクセスする基本プログラムが tezos-client
です。
これは仮想通貨的には「ウォレット」と呼ばれます。tezos-client
は普通のウォレットのようなカッコイイGUIなどはありませんので、コマンドライン・ウォレットと言われます。見た目は貧弱ですが、全ての機能にコマンドラインからアクセスできるようになっている Tezos 公式のウォレットです。
Ithacanet のアカウントを作る
Tezos ネットで作業をするためにはアカウントと暗号通貨トークンが必要です。Mainnet ではお金を出してトークンを買わなければいけませんが、テストネットではタダで手に入ります(ヤッター)。
Faucet(蛇口) https://teztnets.xyz/ithacanet-faucet でテストネットのアカウントを取得し、設定 JSON ファイル ithacanet.json
を保存してください。
./tezos-client activate account «アカウント名» with «JSONファイル名»
でJSON ファイルの情報からアカウントを有効化できます。たとえば:
$ ./tezos-client activate account myself with ithacanet.json
ダウンロードした JSON ファイルは `tezos-client` スクリプトと同じ場所に置いて上のコマンドを実行してください。
うまくいくと次のような画面になる:
$ ./tezos-client activate account myself with ithacanet.json
Waiting for the node to be bootstrapped...
Current head: BMaE7CSn8Dqs (timestamp: 2022-05-19T07:32:45.000-00:00, validation: 2022-05-19T07:32:58.922-00:00)
Node is bootstrapped.
Operation successfully injected in the node.
Operation hash is 'onh8b2Qp1axyLTeu9CoJmHaSivgCFJu4x6XfWQVFGKnKNa4HkJ2'
Waiting for the operation to be included...
ここで止まりますが慌てないで。しばらく待っていると:
Operation found in block: BLT5MPJzySFVegM2SkzRSJJNcSpMxmmF5As2XJFmGnWdsPGGEgY (pass: 2, offset: 0)
This sequence of operations was run:
Genesis account activation:
Account: tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez
Balance updates:
commitment(btz1RY54ZjohSe73o8boe94L2GfXLXTeiNdaC) ... -ꜩ8029.299319
tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez ................ +ꜩ8029.299319
The operation has only been included 0 blocks ago.
We recommend to wait more.
Use command
tezos-client wait for onh8b2Qp1axyLTeu9CoJmHaSivgCFJu4x6XfWQVFGKnKNa4HkJ2 to be included --confirmations 1 --branch BLtjJjoYxEzgmo3FpKmfhaqQZMd44FWfMUSDnuKiqGf5dExsxE4
and/or an external block explorer.
Account myself (tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez) activated with ꜩ8029.299319.
$
何が起こったの?
接続先ノードがネットワーク上で最新の状態になっているか確認:
Waiting for the node to be bootstrapped...
Current head: BMaE7CSn8Dqs (timestamp: 2022-05-19T07:32:45.000-00:00, validation: 2022-05-19T07:32:58.922-00:00)
Node is bootstrapped.
アカウント有効化の命令(operation)をノードに送付。Operation識別子であるハッシュを得る:
Operation successfully injected in the node.
Operation hash is 'onh8b2Qp1axyLTeu9CoJmHaSivgCFJu4x6XfWQVFGKnKNa4HkJ2'
Waiting for the operation to be included...
この operation は Tezos ブロックチェーンの P2P ネットワークに広がっていきます:
Operation \(O_1, O_2\) がユーザによりネットワークに放流され、P2Pにより伝搬されていく。
ネットワーク上にはブロック生成者V(Tezos では Baker といいます)がいて、operation を取り上げてブロックを作り、それを P2P ネットワークに放流します:
\(V\) は \(O_1, O_2\) を使ってブロック B を作り、ネットワークに提出する。
ブロック B は P2P によりネットワークに広がっていく。
このブロックがあなたが使ったノードに到達します:
Operation found in block: BLT5MPJzySFVegM2SkzRSJJNcSpMxmmF5As2XJFmGnWdsPGGEgY (pass: 2, offset: 0)
ここから先はレシート(receipt)といい、実際にデータベースにどんな変化があったのかを表示します。プロだと端から端まで読まないとダメなんだけど、まあ今回は要点だけ:
This sequence of operations was run:
Genesis account activation:
Account: tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez
Balance updates:
commitment(btz1RY54ZjohSe73o8boe94L2GfXLXTeiNdaC) ... -ꜩ8029.299319
tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez ................ +ꜩ8029.299319
...
この faucetアカウントには ꜩ8029 が割り当てられていて、activation によりこの金額が入ったアカウント tz1Uuf..
が利用できるようになりました。
Tezos ブロックチェーンは現在 BFT コンセンサスである Tendermint アルゴリズムを採用しています。このアルゴリズムでは、作られた直後のブロックは他のブロックに取って変わられる可能性がわずかながらあります。ブロックが完全に確定されるにはさらにもう一ブロック待つ必要があります。待つのであれば tezos-client wait for ...
コマンドを使うようにとの情報が出ています:
The operation has only been included 0 blocks ago.
We recommend to wait more.
Use command
tezos-client wait for onh8b2Qp1axyLTeu9CoJmHaSivgCFJu4x6XfWQVFGKnKNa4HkJ2 to be included --confirmations 1 --branch BLtjJjoYxEzgmo3FpKmfhaqQZMd44FWfMUSDnuKiqGf5dExsxE4
and/or an external block explorer.
今回は価値のないテストトークンなので、気にせず先に進みましょう。最終的に "myself"
という名前でアカウントがウォレットに登録されます:
Account myself (tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez) activated with ꜩ8029.299319.
Tezos ブロックチェーンで起こること
これはアカウントアクティベーションでしたが、基本的にどんなTezos DB書き込み操作も同じことが起こります:
- 行いたい操作を operation にして放流
- Baker が流れてきた operation を取り上げ、ブロックを作成、放流
- ブロックが元のノードに伝わってきて operation が DBに書き込まれたことが確認できる
- 合意形成によってブロックが覆される可能性はあるが、可能性はどんどん少なくなる
アカウントを確認
アカウントを確認しましょう。ウォレットが知っているコントラクト(アカウント)を表示します:
$ ./tezos-client list known contracts
myself: tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez
myself
は別名です。ウォレット内でしか通用しません。もしあなたが myself
以外の別名を使ったのならそれが出てくるはず。
残高は?
$ ./tezos-client get balance for myself
8029.299319 ꜩ
ブロックエクスプローラを使う
GUIを使ってアカウントやブロックチェーンの状態を調べることもできます。いくつかありますが、今回は TzStat を使ってみましょう。URL に ithacanet
を忘れずに。忘れるとメインネットの情報になるよ:
一番上のエントリにアカウント名を入れて残高を確認してください。下の Other タブから関連した operation を眺めることもできます。今はアカウント有効化の operation があるはず。
新しいアカウントを作る
Faucet から得たのはトークンが予約されていた(擬似)ICOアカウントです。残高0の新しいアカウントを作ることもできます:
$ ./tezos-client gen keys myself2
$ ./tezos-client list known contracts
myself2: tz1h1CEBP7nYP8Rdt8Ahkni8qmCb3SrF5mGY
myself: tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez
$ ./tezos-client get balance for myself2
0 ꜩ
ブロックエクスプローラでこの新しいアカウント tz1..
を確認すると… 出ません。このアカウントはウォレット内で作られただけで、まだブロックチェーンには存在していないんです。このアカウントに対して送金を行うと初めてブロックチェーン上に出現します。
送金してみる
はじめに作ったアカウント myself
から新しいアカウント myself2
に送金をしてみましょう:
$ ./tezos-client transfer 1 from myself to myself2
Waiting for the node to be bootstrapped...
Current head: BKskcVZUySiA (timestamp: 2022-05-19T07:47:40.000-00:00, validation: 2022-05-19T07:47:47.244-00:00)
Node is bootstrapped.
Fatal error:
The operation will burn ꜩ0.06425 which is higher than the configured burn cap (ꜩ0).
Use `--burn-cap 0.06425` to emit this operation.
エラーが出ました。これは新しいアカウント myself2
をブロックチェーンに登録するためにはディスク領域が必要で、その費用、storage burnを支払う必要があります。Burn したいときは、その上限を --burn-cap
で明示する必要があります。
--burn-cap
は 0.06425 あれば良いらしいですが、上限値なので、テストネットだし、適当な大きい値(たとえば100)で構いません:
$ ./tezos-client transfer 1 from myself to myself2 --burn-cap 100
Waiting for the node to be bootstrapped...
Current head: BLuRDaj4tN82 (timestamp: 2022-05-19T07:48:55.000-00:00, validation: 2022-05-19T07:48:56.374-00:00)
Node is bootstrapped.
Estimated storage: no bytes added
Estimated gas: 1420.040 units (will add 100 for safety)
Estimated storage: 257 bytes added (will add 20 for safety)
Operation successfully injected in the node.
Operation hash is 'opR8qFcmiNsL1bYEstHYaKnZJAq9CKS38QdxiTq7FDxD859843V'
Waiting for the operation to be included...
Operation found in block: BLzjioteCmCY7Rxh7csbbp32AroijqqkJhH54qjY7h9oTtXGxVx (pass: 3, offset: 0)
This sequence of operations was run:
Manager signed operations:
From: tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez
Fee to the baker: ꜩ0.00036
Expected counter: 10593029
Gas limit: 1000
Storage limit: 0 bytes
Balance updates:
tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez ... -ꜩ0.00036
payload fees(the block proposer) ....... +ꜩ0.00036
Revelation of manager public key:
Contract: tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez
Key: edpkvUCk1egM2Mn9aiR6TTMu9Yo3YBTusBKsrvw2scjAVFZS6NK3tV
This revelation was successfully applied
Consumed gas: 1000
Manager signed operations:
From: tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez
Fee to the baker: ꜩ0.000311
Expected counter: 10593030
Gas limit: 1521
Storage limit: 277 bytes
Balance updates:
tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez ... -ꜩ0.000311
payload fees(the block proposer) ....... +ꜩ0.000311
Transaction:
Amount: ꜩ1
From: tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez
To: tz1h1CEBP7nYP8Rdt8Ahkni8qmCb3SrF5mGY
This transaction was successfully applied
Consumed gas: 1420.040
Balance updates:
tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez ... -ꜩ1
tz1h1CEBP7nYP8Rdt8Ahkni8qmCb3SrF5mGY ... +ꜩ1
tz1Uuf4NLeeEWcX7p7cDCJhPztyoqrdTTuez ... -ꜩ0.06425
storage fees ........................... +ꜩ0.06425
The operation has only been included 0 blocks ago.
We recommend to wait more.
Use command
tezos-client wait for opR8qFcmiNsL1bYEstHYaKnZJAq9CKS38QdxiTq7FDxD859843V to be included --confirmations 1 --branch BLA3chcnErYg5BPcD6JPkN6WjfED6ekm2Hi2BLwgiuJv3tp1hGH
and/or an external block explorer.
クッソ長いレシートを貰いました。細かい説明を省いてまとめるとブロック生成者(the block proposer)に報酬を支払っています:
- アカウント公開operationの報酬: the block proposer へ ꜩ0.00036
- 送金operationの報酬: the block proposer へ ꜩ0.000311
- 新アカウント保存領域費用: ꜩ0.06425 (これは燃やされる)
- 元アカウントから新アカウントへの送金: myself2 へ ꜩ1
新アカウント保存領域にかかる storage 費用はネットワーク全体にかかる費用なので、特定bakerへの報酬ではなく、「燃やされて」しまいます。
テレビで金を燃やすと言えば日本では赤瀬川原平だが、あれは偽札だった。フランスではセルジュ・ゲンズブール が生放送で本物の500フラン札を燃やした。
さてこれで新アカウントがブロックエクスプローラでも見れるはずです。元アカウントと新アカウントに関する operation も見てみるとちゃんと上の operation も見えるはず。
なお Faucetアカウントの有効化に fee や burn は必要ありません。Faucet アカウントはICOに参加した人のためのアカウント。すでに有効化などの費用は払っているとみなされます。
コマンドが長い…
./tezos-client
ではコマンドの打ち間違いで損することを避けるためにわざとコマンドを冗長に英語っぽくしてあります。長くて覚えられないのは当然です。私もよく忘れます。忘れた時は、
$ ./tezos-client man
で全コマンドリストが、各コマンドについてだけ知りたければ、例えば、
$ ./tezos-client transfer --help
...
Block contextual commands (see option -block):
transfer <qty> from <src> to <dst> [--fee <amount>] [-D --dry-run]
[--verbose-signing] [--simulation] [--force] [-G --gas-limit <amount>]
[-S --storage-limit <amount>] [-C --counter <counter>] [--arg <data>]
[-q --no-print-source] [--minimal-fees <amount>]
[--minimal-nanotez-per-byte <amount>]
[--minimal-nanotez-per-gas-unit <amount>] [--force-low-fee]
[--fee-cap <amount>] [--burn-cap <amount>] [--entrypoint <name>]
Transfer tokens / call a smart contract.
<qty>: amount taken from source in ꜩ
<src>: name of the source contract
<dst>: name/literal of the destination contract
--fee <amount>: fee in ꜩ to pay to the baker
-D --dry-run: don't inject the operation, just display it
--verbose-signing: display extra information before signing the operation
--simulation: Simulate the execution of the command, without needing any signatures.
--force: Inject the operation even if the simulation results in a failure.
-G --gas-limit <amount>: Set the gas limit of the transaction instead of letting the client decide based on a simulation
-S --storage-limit <amount>: Set the storage limit of the transaction instead of letting the client decide based on a simulation
-C --counter <counter>: Set the counter to be used by the transaction
--arg <data>: argument passed to the contract's script, if needed
-q --no-print-source: don't print the source code
--minimal-fees <amount>: exclude operations with fees lower than this threshold (in tez)
--minimal-nanotez-per-byte <amount>: exclude operations with fees per byte lower than this threshold (in nanotez)
--minimal-nanotez-per-gas-unit <amount>: exclude operations with fees per gas lower than this threshold (in nanotez)
--force-low-fee: Don't check that the fee is lower than the estimated default value
--fee-cap <amount>: Set the fee cap
--burn-cap <amount>: Set the burn cap
--entrypoint <name>: entrypoint of the smart contract
とすればヘルプが表示されます。
演習
myself2 から myself へ ꜩ0.5 送ってみてください