• Tezos node の sandboxed mode で気楽にTezosの基本操作を試してみる
  • はじめてのプロトコル更新
  • はじめてのコントラクト: 送金
  • Bakingとその手数料と保証金

これはTezosの技術を理解をしたい人のための記事です。 Tezosを自分でビルドできること、基本的なUnixの操作ができることを仮定しています。 Tezosを暗号通貨としてカジュアルに使いたい方はGUIウォレットなど、 もっと使いやすいものを使ってくださいね。

Sandboxed modeへのお誘い

Tezosで遊ぶ時は外界と通信しないsandboxed modeが便利です。

テストネットであるalphanet(本番のmainnetとほぼ同じコード),zeronet(開発版コードのネット)に繋げて試すのももちろん良いのですが、その場合、テスト環境とはいえP2Pネットワークに参加し、ブロックチェーンの同期を行わなければいけないので、少なくない量のネット通信を時間をかけて行わなければいけません。その点、sandboxed modeは気軽に試せます。

Tezosをビルドする

まずTezosをビルドしてください。ブランチはなんでもいいですが、alphanetzeronetが良いです。

  • alphanet: 本番とほぼ同じコード
  • zeronet: 開発版コード

以下の例ではalphanetブランチを使っています。

Sandboxed mode ノードを立ち上げる

参考: http://tezos.gitlab.io/alphanet/introduction/various.html?highlight=sandboxed#use-sandboxed-mode

ScreenCastの詳しい内容は下に解説します。以下同様。

まずノードを立ち上げます

$ src/bin_node/tezos-sandboxed-node.sh 1 --connections 1
Generating a new identity... (level: 0.00)
...

詳しくはスクリプトの中を見てほしいのですが、このノードのRPCポートは18731で動きます。

クライアント側の環境準備

新しいターミナルを立ち上げて、ノードと簡単な通信をしてみます:

$ ./tezos-client -P 18731 rpc get /chains/main/blocks/head/metadata
{ "protocol": "PrihK96nBAFSxVL1GLJTVhu9YnzkMFiBeuJRPA8NwuZVZCE1L6i",
  "next_protocol": "Ps6mwMrF2ER2s51cp9yYpjDcuzQjsc2yAz8bQsRgdaRxw4Fk95H",
  "test_chain_status": { "status": "not_running" }, "max_operations_ttl": 0,
  "max_operation_data_length": 0, "max_block_header_length": 105,
  "max_operation_list_length": [] }

繋がったノードがsandboxで、Genesisプロトコルで動いているのがわかります。 そしてもちろんあなたはTezos開発者なので警告は無視して良いのです。

さて、いちいち-P 18731と打ち込むのが面倒臭いので、ちょっと便利な設定変更を行います:

$ eval `src/bin_client/tezos-init-sandboxed-client.sh 1`

このコマンドでPATHが書き換えられていることに注意してください:

$ set | grep tezos
...
PATH=..:/tmp/tezos-tmp-client.某/bin:..

この一時ディレクトリにはsandboxed nodeと話をするためのTezos関連コマンドが用意されています。 これらは全部シェルスクリプトなので、中身を見ると何をやっているかわかります。

これらのコマンドではなく、ソースディレクトリ中のtezos-clientをそのまま使ってしまうと通常のローカルで動いているnodeと話をしてしまうので注意が必要です:

$ ls /tmp/tezos-tmp-client.某/bin
tezos-accuser-003-PsddFKi3*  tezos-baker-003-PsddFKi3*
tezos-endorser-003-PsddFKi3* tezos-admin-client*
tezos-client*                tezos-signer*

このように、Sandboxed modeは一時ディレクトリを使ってノードを特別なオプションで起動することで実現しています。クライアント側はPATHを変更することでこのノードと対話するオプションを提供しています。Sandboxed modeでノードの奥底で何が起こっているのか理解するにはこれを知っておく必要があります。

それから、一回一回警告が出るのが面倒なので消してしまいましょう:

$ export TEZOS_CLIENT_UNSAFE_DISABLE_DISCLAIMER=Y

同時にいくつかTezosのアカウント(アドレス)が作成されました。これらのアカウントにはたくさんꜩが入っているのでお金持ちになった気分になれます。もちろんテスト用ネットなので、換金はできません。 気分になれるだけです。

アドレスリストを確認します:

$ tezos-client list known addresses
activator: tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV (unencrypted sk known)
bootstrap5: tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv (unencrypted sk known)
bootstrap4: tz1b7tUupMgCNw2cCLpKTkSD1NZzB5TkP2sv (unencrypted sk known)
bootstrap3: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU (unencrypted sk known)
bootstrap2: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN (unencrypted sk known)
bootstrap1: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx (unencrypted sk known)

なるほど、いくつかアドレスがありますね。キー情報も取れます:

$ tezos-client show address bootstrap1
Hash: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx      # パブリックキーのハッシュ
Public Key: edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav

じゃあこのアドレスにどれくらいお金があるんだろう。

プロトコルとAlphaへの昇格

実はこの段階ではアドレスにどれだけꜩがあるか調べる事ができません!! tezos-client manしてみてください。そういったコマンドないですよね。

これは現在、次のブロックに使われるプロトコルはGenesisブロックに紐付いている Genesisプロトコルというものだからです。Genesisプロトコルはほとんど何もできません。 (tezos-client manはこのGenesisプロトコルにプロトコルが何ができるか聞いて表示します。)

現在のブロックのプロトコル情報を表示してみます:

$ tezos-client rpc get /chains/main/blocks/head/metadata
{ "protocol": "PrihK96nBAFSxVL1GLJTVhu9YnzkMFiBeuJRPA8NwuZVZCE1L6i",
  "next_protocol": "Ps6mwMrF2ER2s51cp9yYpjDcuzQjsc2yAz8bQsRgdaRxw4Fk95H",
  "test_chain_status": { "status": "not_running" }, "max_operations_ttl": 0,
  "max_operation_data_length": 0, "max_block_header_length": 105,
  "max_operation_list_length": [] }

"next_protocol": "Ps6mwMrF2ER2s51cp9yYpjDcuzQjsc2yAz8bQsRgdaRxw4Fk95H" とあるように次に付け加えられるブロックはGenesisプロトコルを使いますよと言っています。

Genesisブロックに紐付いているGenesisプロトコルの機能は本当に基本的なものしかなく、 その役割は実際に暗号通貨を使えるプロトコルへの橋渡しです。 Tezosの最大の特徴としてプロトコル(合意形成)が動的に更新できることにありますが、 アカウントの残高を調べるなど、面白いことをするには早速そのプロトコル更新を行う必要があります。 Genesisからより機能が追加されたAlphaプロトコルに昇格してみましょう:

$ tezos-activate-alpha
Injected BL6j1cTcwFqA

なにやらInjectedと出てきました。これは新しいプロトコルへの昇格されたことを記した新しいブロックBLadAXKFP1WAがブロックチェーンに付け加えられたことを示しています。 (alias tezos-activate-alphaで実際に何をやっているか確認できます。)

プロトコル情報はどうなったでしょうか:

$ tezos-client rpc get /chains/main/blocks/head/metadata
{ "protocol": "Ps6mwMrF2ER2s51cp9yYpjDcuzQjsc2yAz8bQsRgdaRxw4Fk95H",
  "next_protocol": "PsddFKi32cMJ2qPjf43Qv5GDWLDPZb3T3bF6fLKiF5HtvHNU7aP",
  "test_chain_status": { "status": "not_running" }, "max_operations_ttl": 1,
  "max_operation_data_length": 16384, "max_block_header_length": 238,
  "max_operation_list_length":
    [ { "max_size": 32768, "max_op": 32 }, { "max_size": 32768 },
      { "max_size": 135168, "max_op": 132 }, { "max_size": 524288 } ] }

現在のブロックまでのプロトコルはGenesisだが、次からはAlphaというプロトコルになる、とあります。 ノードの次ブロックのプロトコルが変わったので、やれることも増えます:

$ tezos-client man
...
  get balance for <src>
...
  transfer <qty> from <src> to <dst> [--fee <amount>] [-D --dry-run]
...

Alphaプロトコルでは残高を調べる事ができます:

$ tezos-client get balance for activator
0.000001 ꜩ
$ tezos-client get balance for bootstrap1
4000000 ꜩ
$ tezos-client get balance for bootstrap2
4000000 ꜩ
$ tezos-client get balance for bootstrap3
4000000 ꜩ

bootstrapXはなかなかお金持ちのようです。

Alphaプロトコルは現在実際にTezosのmainnet(本番環境)で使われているプロトコルと 細かいパラメータを除いてほとんど同じプロトコルです。このAlphaと、テストネットワーク環境である alphanetとは別の概念なので混乱しないようにしてください。(正直、ひどい名前づけだと思います)

送金してみる

bootstrap1からbootstrap2に100ꜩ移してみましょう:

$ tezos-client transfer 100 from bootstrap1 to bootstrap2
...
Operation successfully injected in the node.
Operation hash: ooz1xpwuEcZH7Mg7arjXhfNesL6ArDWbYKegXusvXyjTHHBQyzx
Waiting for the operation to be included...
# コマンドが終了しない

あれ、終了しません。このコマンドはꜩを移す操作(operation)をノードに登録しただけで、 実際にブロックチェーンに登録されるところまでは行いません。 コマンドは、この登録された操作がチェーンに登録されるまで待機しています。 誰かがこの操作を新しいブロックの中に取り込んで、チェーンに付け加えなければいけません。

Bakerでブロックをチェーンに付け加える

Tezosで操作の正しさを確かめてブロックを作成しチェーンに付け加える行為をbakingといいます。 このbakingをしなければ操作が登録されることはありません。Sandboxed node では tezos-client bakeコマンドを使う事で登録された操作をbakeすることができます。

まずtezos-client transferをバックグラウンドにします:

# ターミナルで C-z をタイプ(bashの場合)
[1]+  Stopped                 tezos-client transfer 100 from bootstrap1 to bootstrap2

それから、bakeします。ここでbootstrap3を使っていることに注意してください:

$ tezos-client bake for bootstrap3
Injected block BLbEfs1cGRoU

新しいブロックBLbEfs1cGRoUが作成され、ブロックチェーンに追加されました。 tezos-client transfer ...のプロセスに制御を戻すと、プロセスはこの更新を発見して、終了します:

$ fg
Operation found in block: BLbEfs1cGRoUKpoGe5tBnWKLHKB8rD46n3gs1kJnuRNub68HDMC (pass: 3, offset: 0)
This sequence of operations was run:
  Manager signed operations:
    From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx
    Fee to the baker: ꜩ0.05
    Expected counter: 1
    Gas limit: 200
    Storage limit: 0 bytes
    Balance updates:
      tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ........... -ꜩ0.05
      fees(tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU,0) ... +ꜩ0.05
    Transaction:
      Amount: ꜩ100
      From: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx
      To: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN
      This transaction was successfully applied
      Consumed gas: 100
      Balance updates:
        tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx ... -ꜩ100
        tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN ... +ꜩ100

...

何やら長いメッセージが表示されましたが、これはレシート(receipt)と言われ、ブロックチェーンへの登録が済んだという結果です。

  • tezos-client transfer の結果が新しいブロック BLbEfs1cGRoU に見つかりました
  • アカウントbootstrap1(tz1KqTpEZ7..)からbakerであるbootstrap3(tz1faswCTD..)に手数料(fee)としてꜩ0.05が支払われます
  • bootstrap1(tz1KqTpEZ7..)からbootstrap2(tz1gjaF81..)にꜩ100が転送されました

本当にそうなっているか、tezos-client get balance で確かめてみましょう:

$ tezos-client get balance for bootstrap1
3999899.95 ꜩ
$ tezos-client get balance for bootstrap2
4000100 ꜩ
$ tezos-client get balance for bootstrap3
3999488 ꜩ

Feeとdeposit

bootstrap1からはꜩ100.05が引き出されました。これは転送したꜩ100と bakerへのデフォルトの手数料ꜩ0.05の和なので正しいですね。

bootstrap2にはꜩ100が振り込まれました。これも正しいです。

ではbootstrap3はどうでしょうか。baking手数料の0.05ꜩが足されて 4000000.05 ꜩになっているかと思いきや、3999488 ꜩに減っています!

Tezosでは(より正確にはAlphaプロトコルでは)、bakerはbakingの際に保証金として ꜩ512を一旦システムに預けなければいけないルールになっています。 もしbakerが不正をし、それがブロックチェーン上で認定された場合は、この保証金は 没収されてしまいます(不正を指摘した人に保証金が回されます)。

Bakerの保証金と手数料報酬はブロックチェーンが伸びて間違いがないだろうとなった時に bakerのアドレスに払い込まれます。 それは今回は確かめませんが、現時点でのbootstrap3の残高が説明できました。

秘密鍵

さて、bootstrap1からbootstrap2へとお金を移せました。 こうやって自由にお金が移せたら素敵ですね!! 私なら世界中のみなさんのアカウントから自分のアカウントにお金を移して引退します。

現実にはそういうことはできません。じゃあなんでできたのか、とういと、 tezos-clientコマンドは eval `src/bin_client/tezos-init-sandboxed-client.sh 1` コマンドで作ったbootstrapXというアカウントの秘密鍵を知っている、 つまり自分のアカウントだからです。

アカウントの秘密鍵を知らなければ、そのアカウントからお金を抜くことはできません。

それを念のため確かめてみます。bootstrap1アカウントの秘密鍵を忘れることにします:

# まず公開鍵をメモしておきます
$ tezos-client show address bootstrap1
Hash: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx
Public Key: edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav
# 公開鍵、秘密鍵ともに tezos-client の設定から消します
$ tezos-client forget address bootstrap1 --force
# 公開鍵だけをbootstrap1として登録
$ tezos-client add address bootstrap1 tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx

これでbootstrap1は公開鍵だけのアカウントになりました。

# bootstrap1については秘密鍵(sk)についての情報が表示されないことに注意
$ tezos-client list known addresses
bootstrap1: tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx
activator: tz1TGu6TN5GSez2ndXXeDX6LgUDvLzPLqgYV (unencrypted sk known)
bootstrap5: tz1ddb9NMYHZi5UzPdzTZMYQQZoMub195zgv (unencrypted sk known)
bootstrap4: tz1b7tUupMgCNw2cCLpKTkSD1NZzB5TkP2sv (unencrypted sk known)
bootstrap3: tz1faswCTDciRzE4oJ9jn2Vm2dvjeyA9fUzU (unencrypted sk known)
bootstrap2: tz1gjaF81ZRRvdzjobyfVNsAeSC6PScjfQwN (unencrypted sk known)

tezos-clientbootstrap1のことを一旦忘れましたが、ブロックチェーンは そこにある残高を知っています:

$ tezos-client get balance for bootstrap1
3999899.95 ꜩ

先ほどと同じようにtezos-client transferを使ってbootstrap1から bootstrap2にお金を移してみようとしても、bootstrap1の秘密鍵がないので、 tezos-client側で操作に署名する事ができず失敗します:

$ tezos-client transfer 100 from bootstrap1 to bootstrap2
Error:
  Unknown secret key for tz1KqTpEZ7Yob7QbPE4Hy4Wo8fHG8LhKxZSx

今度は逆にbootstrap2からbootstrap1にお金を移してみます。 bootstrap2の秘密鍵は知っているので成功します。 お金の移し先であるbootstrap1の秘密鍵を知っている必要はありません。 これは普通の銀行の送金と同じですよね:

$ tezos-client transfer 100 from bootstrap2 to bootstrap1
...
Estimated gas: 100 units (will add 100 for safety)
Estimated storage: no bytes added
Operation successfully injected in the node.
Operation hash: oos7YjL3FqTodgBkNMJSGHDoMEJXahedswt3wyHVwX9RPF3CRxg
Waiting for the operation to be included...

というわけで、自分の秘密鍵を他人に教えてはいけません! 日本の銀行だと、通帳と銀行印と身分証明書を相手に渡すことと同じ行為です。

今日はここまで

長くなったので今日はここで終わりです。次のことをざっとやってみました:

  • Tezosのノードをsandboxed modeで立ち上げる
  • Sandboxed modeノードのためのクライアント環境を整え、実験用のアカウントを作成する
  • Sandboxed modeは一時ディレクトリを利用し、PATHを変更することで実現されている
  • Genesisプロトコルと、そこからAlphaプロトコルへの昇格。プロトコルの確認。
  • ꜩの転送
  • Bakingの必要性
  • レシートの読み方
  • Feeとdeposit
  • 秘密鍵を知らないアカウントからお金は動かせない
  • 公開鍵を知っていればアカウントにお金を送る事ができる