SCamlによるTezosプログラミング#3 ウォレット基本操作

Tezos ブロックチェーン のためのスマートコントラクト記述言語 SCaml、チュートリアルの第3回目です。

今回はTezosブロックチェーンにアクセスするコマンドラインウォレット tezos-client の実習です。

このブログではSCamlを使ったTezosスマートコントラクトプログラミングについて少しずつ日本語で連載をしていきたいと思います。

(この内容は 2020-03-21 にやった SCaml ハンズオンの資料を手直ししたものです。)

やっと実習

はいやっとです。でも SCaml には…まだ触れません。あれ〜。

まずは Tezos ブロックチェーンにアクセスするための基本プログラムであるコマンドラインウォレット、 tezos-client の使い方を理解しないといけません。

Tezos ネット

Tezos には使用目的によって複数の異なるネットワークがあります:

mainnet
換金性のあるトークンが扱われている本番環境です。このネットワークに書き込みを行いたい場合は mainnet トークンを所持している必要があります。持っていない場合は仮想通貨交換所で購入などしなければいけません。
現在(2020-04)の mainnet で動作している Tezos のプロトコルのバージョンは 006 Carthage (カルタゴ)といいます。
テストネット
失敗しても金銭的損害を受けずに安心してテストできるネットワークとして、テストネットがあります。テストネットのトークンは無料で入手できます。(でもお金には変えられません。残念。)
現在の Mainnet と同じ 006 Carthage プロトコルが動いているテストネットを carthagenet といいます。 このチュートリアルではこの carthagenet を使います。
(他にも不安定版を動かしている zeronet などもあります。)

このテストネットの名前は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 http://carthagenet.tezos.cryptium.ch:8732: Failed
Checking https://carthagenet.smartpy.io: OK
Using -A carthagenet.smartpy.io -P 443 -S
Preparing /Users/jun/.tezos-handson-client for Tezos hands on...
Warning: /Users/jun/.tezos-handson-client/config does not exist.
Please set it by ./tezos-client -A HOSTNAME -P PORT config update
Updated the config of ./tezos-client:
{ "base_dir": "/root/.tezos-client", "node_addr": "carthagenet.smartpy.io",
  "node_port": 443, "tls": true, "web_port": 8080, "confirmations": 0 }
Ok

ここで問題が出る場合は、第1回の記事を確認してください。(もしかするとスクリプトがアップデートされているかもしれません)

上の例では carthagenet.smartpy.io:443 にあるパブリックRPCノードと通信する設定になっています。 $HOME/.tezos-handson-client に設定を書き込むので、気になる人は実習後消してください。

tezos-client

Tezosノード、つまり Tezos の分散データベースにアクセスする基本プログラムが tezos-client です。

これは仮想通貨的には「ウォレット」と呼ばれます。tezos-clientは普通のウォレットのようなカッコイイGUIなどはありませんので、コマンドライン・ウォレットと言われます。見た目は貧弱ですが、全ての機能にコマンドラインからアクセスできるようになっている Tezos 公式のウォレットです。

Carthagenet のアカウントを作る

Tezos ネットで作業をするためにはアカウントと暗号通貨トークンが必要です。Mainnet ではお金を出してトークンを買わなければいけませんが、テストネットではタダで手に入ります(ヤッター)。

Faucet(蛇口) https://faucet.tzalpha.net/ でテストネットのアカウントを作成し、設定 JSON ファイル tz1abcdef....json を保存してください。

./tezos-client activate account «アカウント名» with «JSONファイル名» でJSON ファイルの情報からアカウントを有効化できます。たとえば:

$ ./tezos-client activate account myself with tz1abcdef....json

ダウンロードした JSON ファイルは `tezos-client` スクリプトと同じ場所に置いて上のコマンドを実行してください。

うまくいくと次のような画面になる:

$ ./tezos-client activate account myself with ./tz1....json 
Waiting for the node to be bootstrapped before injection...
Current head: BL5g8Riuo93k (timestamp: 2020-04-13T13:21:07-00:00, validation: 2020-04-13T13:21:25-00:00)
Node is bootstrapped, ready for injecting operations.
Operation successfully injected in the node.
Operation hash is 'onkBzyHkhsK1cxkkBfpTQAvapbKEhjNCobHdebPfnw69BSUaUAy'
Waiting for the operation to be included...

ここで止まりますが慌てないで。しばらく待っていると:

Operation found in block: BL9QBVytfEd9Biff1tYWDayRgdcTBeEsgf2KNwBVkSqgcr4QwVn (pass: 2, offset: 0)
This sequence of operations was run:
  Genesis account activation:
    Account: tz1...
    Balance updates:
      tz1... ... +ꜩ21365.347582

The operation has only been included 0 blocks ago.
We recommend to wait more.
Use command
  tezos-client wait for onkBzyHkhsK1cxkkBfpTQAvapbKEhjNCobHdebPfnw69BSUaUAy to be included --confirmations 30 --branch BL5g8Riuo93k8KCjdbQpAhy4hiQWzTbPq36PZ6vGTaJBA2VeQ8J
and/or an external block explorer.
Account myself (tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4) activated with ꜩ21365.347582.
$ 

何が起こったの?

接続先ノードがネットワーク上で最新の状態になっているか確認:

Waiting for the node to be bootstrapped before injection...
Current head: BL5g8Riuo93k (timestamp: 2020-04-13T13:21:07-00:00, validation: 2020-04-13T13:21:25-00:00)
Node is bootstrapped, ready for injecting operations.

アカウント有効化の命令(operation)をノードに送付。Operation識別子であるハッシュを得る:

Node is bootstrapped, ready for injecting operations.
Operation successfully injected in the node.
Operation hash is 'onkBzyHkhsK1cxkkBfpTQAvapbKEhjNCobHdebPfnw69BSUaUAy'
Waiting for the operation to be included...

この operation は Tezos ブロックチェーンの P2P ネットワークに広がっていきます:

https://gitlab.com/dailambda/images/-/raw/master/consensus3.svg

Operation \(O_1, O_2\) がユーザによりネットワークに放流され、P2Pにより伝搬されていく。

ネットワーク上にはブロック生成者V(Tezos では Baker といいます)がいて、operation を取り上げてブロックを作り、それを P2P ネットワークに放流します:

https://gitlab.com/dailambda/images/-/raw/master/consensus4.svg

\(V\) は \(O_1, O_2\) を使ってブロック B を作り、ネットワークに提出する。

https://gitlab.com/dailambda/images/-/raw/master/consensus5.svg

ブロック B は P2P によりネットワークに広がっていく。

このブロックがあなたが使ったノードに到達します:

Operation found in block: BL9QBVytfEd9Biff1tYWDayRgdcTBeEsgf2KNwBVkSqgcr4QwVn (pass: 2, offset: 0)

ここから先はレシート(receipt)といい、実際にデータベースにどんな変化があったのかを表示します。プロだと端から端まで読まないとダメなんだけど、まあ今回は要点だけ:

This sequence of operations was run:
  Genesis account activation:
    Account: tz1...
    Balance updates:
      tz1... ... +ꜩ21365.347582

テストアカウントに入っているトークン量はランダムです。たくさんあると意味もなく嬉しい。

Tezos ブロックチェーンは現在 Nakamoto コンセンサスの変種を採用しているので、このブロックが後から他のブロックに取って代わられる可能性があります。この可能性はブロックが積み上がっていくと指数関数的に減少していきます(probablistic finality)。30ブロックも待てば覆される可能性はほとんど0になります:

The operation has only been included 0 blocks ago.
We recommend to wait more.
Use command
  tezos-client wait for onkBzyHkhsK1cxkkBfpTQAvapbKEhjNCobHdebPfnw69BSUaUAy to be included --confirmations 30 --branch BL5g8Riuo93k8KCjdbQpAhy4hiQWzTbPq36PZ6vGTaJBA2VeQ8J
and/or an external block explorer.

今回は価値のないテストトークンなので、気にせず先に進みましょう。最終的に "myself" という名前でアカウントがウォレットに登録されます:

Account myself (tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4) activated with ꜩ21365.347582.

Tezos ブロックチェーンで起こること

これはアカウントアクティベーションでしたが、基本的にどんなTezos DB書き込み操作も同じことが起こります:

  • 行いたい操作を operation にして放流
  • Baker が流れてきた operation を取り上げ、ブロックを作成、放流
  • ブロックが元のノードに伝わってきて operation が DBに書き込まれたことが確認できる
  • 合意形成によってブロックが覆される可能性はあるが、可能性はどんどん少なくなる

アカウントを確認

アカウントを確認しましょう。ウォレットが知っているコントラクト(アカウント)を表示します:

$ ./tezos-client list known contracts
myself: ttz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4

myself は別名です。ウォレット内でしか通用しません。もしあなたが myself 以外の別名を使ったのならそれが出てくるはず。

残高は?

$ ./tezos-client get balance for myself
21365.347582 ꜩ

ほんとなら450万円か〜

ブロックエクスプローラを使う

GUIを使ってアカウントやブロックチェーンの状態を調べることもできます。いくつかありますが、今回は TzStat を使ってみましょう。URL に carthagenet を忘れずに。忘れるとメインネットの情報になるよ:

https://gitlab.com/dailambda/images/-/raw/master/tzstats.png

一番上のエントリにアカウント名を入れて残高を確認してください。下の Other タブから関連した operation を眺めることもできます。今はアカウント有効化の operation があるはず。

新しいアカウントを作る

Faucet から得たのはすでにトークンの入っていた(擬似)ICOアカウントです。残高0の新しいアカウントを作ることもできます:

$ ./tezos-client gen keys myself2
$ ./tezos-client list known contracts
myself2: tz1dJhKH66ZD1mj4M4L51aAm9VXBLU3CqyYn
myself: tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4
$ ./tezos-client get balance for myself2
0 ꜩ

ブロックエクスプローラで確認すると… 出ません。このアカウントはウォレット内で作られただけで、まだブロックチェーンには存在していないんです。このアカウントに対して送金を行うとブロックチェーン上に出現します。

送金してみる

はじめに作ったアカウント myself から新しいアカウント myself2 に送金をしてみましょう:

$ ./tezos-client transfer 1 from myself to myself2 
Waiting for the node to be bootstrapped before injection...
Current head: BLDjdsc5n5pQ (timestamp: 2020-04-14T04:17:55-00:00, validation: 2020-04-14T04:18:01-00:00)
Node is bootstrapped, ready for injecting operations.
Fatal error:
  The operation will burn ꜩ0.257 which is higher than the configured burn cap (ꜩ0).
   Use `--burn-cap 0.257` to emit this operation.

エラーが出ました。これは新しいアカウント myself2 をブロックチェーンに登録するのに追加の費用を支払う必要があって、その上限を --burn-cap で明示する必要があるからです。

--burn-cap は 0.257 あれば良いらしいですが、上限値なので、テストネットだし、適当な大きい値で構いません:

$ ./tezos-client transfer 1 from myself to myself2 --burn-cap 100
Waiting for the node to be bootstrapped before injection...
Current head: BLDjdsc5n5pQ (timestamp: 2020-04-14T04:17:55-00:00, validation: 2020-04-14T04:18:16-00:00)
Node is bootstrapped, ready for injecting operations.
Estimated gas: 10207 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 'onsDCDFhrWcBQYn8kZGHg8T41NrpTaUjemGKb1egk1AWNhT5jiV'
Waiting for the operation to be included...
Operation found in block: BMczqyLuaaykTveYrdvxc7YZ7q2ry74GS1sF7mWhK2uHvSTDvkw (pass: 3, offset: 1)
This sequence of operations was run:
  Manager signed operations:
    From: tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4
    Fee to the baker: ꜩ0.001259
    Expected counter: 671135
    Gas limit: 10000
    Storage limit: 0 bytes
    Balance updates:
      tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4 ............. -ꜩ0.001259
      fees(tz1PirboZKFVqkfE45hVLpkpXaZtLk3mqC17,167) ... +ꜩ0.001259
    Revelation of manager public key:
      Contract: tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4
      Key: edpkumupUn6iV98bttm128xZQbWUVmGvcS6UHv7y97sG6ez8htAgjW
      This revelation was successfully applied
      Consumed gas: 10000
  Manager signed operations:
    From: tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4
    Fee to the baker: ꜩ0.001188
    Expected counter: 671136
    Gas limit: 10307
    Storage limit: 277 bytes
    Balance updates:
      tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4 ............. -ꜩ0.001188
      fees(tz1PirboZKFVqkfE45hVLpkpXaZtLk3mqC17,167) ... +ꜩ0.001188
    Transaction:
      Amount: ꜩ1
      From: tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4
      To: tz1dJhKH66ZD1mj4M4L51aAm9VXBLU3CqyYn
      This transaction was successfully applied
      Consumed gas: 10207
      Balance updates:
        tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4 ... -ꜩ1
        tz1dJhKH66ZD1mj4M4L51aAm9VXBLU3CqyYn ... +ꜩ1
        tz1a9GVLbdYxbJdJ3dTbP8H4g3A9s7JkoNK4 ... -ꜩ0.257

クッソ長いレシートを貰いました。細かい説明を省いてまとめるとブロック生成者(tz1PirboZKFVqkfE45hVLpkpXaZtLk3mqC17)に報酬を支払っています:

  • アカウント公開operationの報酬: ꜩ0.001259
  • 送金operationの報酬: ꜩ0.001188
  • 新アカウント保存領域費用: ꜩ0.257 (これは燃やされる)
  • 元アカウントから新アカウントへの送金: ꜩ1

新アカウント保存領域にかかる費用はネットワーク全体にかかる費用なので、特定bakerへの報酬ではなく、「燃やされて」しまいます。

https://i.pinimg.com/originals/97/62/ca/9762ca8d6c96a4ea940127e0c631091e.jpg

テレビで金を燃やすと言えば日本では赤瀬川原平だが、あれは偽札だった。フランスではセルジュ・ゲンズブール が生放送で本物の500フラン札を燃やした。

さてこれで新アカウントがブロックエクスプローラでも見れるはずです。元アカウントと新アカウントに関する operation も見てみるとちゃんと上の operation も見えるはず。

なお Faucetアカウントの有効化に fee や burn は必要ありません。Faucet アカウントはICOに参加した人のためのアカウント。すでに有効化などの費用は払っているとみなされます。

コマンドが長い…

./tezos-client ではコマンドの打ち間違いで損することを避けるためにわざとコマンドを冗長に英語っぽくしてあります。長くて覚えられないのは当然です。私もよく忘れます。忘れた時は、

$ ./tezos-client --help

で全コマンドリストが、各コマンドについてだけ知りたければ、例えば、

$ ./tezos-client transfer --help
...
Block contextual commands (see option -block):
  transfer <qty> from <src> to <dst> [--fee <amount>] [-D --dry-run]
      [--verbose-signing] [-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
...

とすればヘルプが表示されます。