はじめに
LibraとはFacebookが開発している仮想通貨。Facebook、VISA、Uber、Spotifyなどが参加するリブラ財団を後ろ盾として持ち、法定通貨と連動するステーブルコインということで、他の仮想通貨とは一線を画している感があります。最近は、仮想通貨系の勉強会でもLibraの話題になると参加者が何割増しかになるみたいですし(笑)
2020年のリリースを予定しているとのことですが、米政府からも懸念を示されていたりして実際にどうなるのかはもう少し経たないとわかりません。一方で、純粋に技術的な観点でLibraを見た場合、幾つか興味深い点が有るようです。まずはその手始めとして「触ってみる」というのをやってみたいと思います。
Libraを試す
Libraを試したい場合、本家サイトの通りにやればほぼ問題なくできるでしょう。ただ、Rustで書かれたソースgit cloneしてRustのツールチェーンもインストールしてビルドして、となるとそこそこ時間がかかります。そしてまだ開発中なのでcloneしたタイミングに寄っては動かない場合もある。実際、私も不可解なエラーがでて動作せず、git pullして更新したら動くようになりました。
その他のやり方としてはDockerのimageをpullしてやるというのもある(DockerでFacebookのリブラ(Libra)のテストネットをとりあえず触る)みたいですが、サイズが3GB超なのでそれはそれで気合が要ります。
で、見つけたのがpylibraというPythonのモジュール。以前はlibra-pythonと呼称していたようですが名前が変わったみたいです。Libraのソースを使わずにクライアント機能を実装しているのですが、これを試してみます。
pylibraのインストール
pyenvとpyenv-virtualenvが入っている前提で進めます。ない場合はMacの場合だとhomebrewで brew install pyenv pyenv-virtualenv
とかでサクッと入れられます。で、専用の環境を作ってそこにpylibraを入れます。pythonを起動して、pylibraがimportできればOK。
なおここは私がハマったところですが、Pypiに上がっている最新版にはfaucetからの入金に不具合があり、github上の最新を取ってくる必要があります。
$ pyenv virtualenv 3.7.4 libra
$ pyenv local libra
$ pip install git+https://github.com/bandprotocol/pylibra.git@master
$ python
Python 3.7.4 (default, Jul 14 2019, 17:36:13)
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import pylibra
>>>
ウォレットの生成
まずはじめにウォレットの機能から。引数なしにLibraWallet()
を呼ぶと新しいウォレットが生成されます。
from pylibra import LibraWallet
wallet = LibraWallet()
Walletオブジェクトにはto_mnemonic()
というメソッドがあり、そのウォレットのニーモニックを取り出せます。そして、ウォレット生成時にそれを与えると前に生成したウォレットを再生成できます。
mnemonic = wallet.to_mnemonic()
print(mnemonic) # e.g. "student deliver dentist cat gorilla sleep proud naive gown fiber awkward weasel"
wallet2 = LibraWallet(mnemonic) # walletとwallet2は同一
ただし、このmnemonicは本家のLibra CLIの生成するものとは互換性がないらしく、その点は注意が必要です。
アカウントの生成
次にアカウントの生成です。Walletオブジェクトのget_account()
を呼ぶとアカウントが取得できます。引数はcounter(nonce)で同じ値を与えれば同じアカウントを取得できます。Accountオブジェクトにはaddress
、private_key
、public_key
が属性として設定されます。
account_0 = wallet.get_account(0)
print(account_0.address) # c1b66e314403c2de08c07c3311acbf259140c563fed5dbf180dd436ff98a7de7
print(account_0.private_key) # 642b4a979778b6347266b59203dfd07549f8112364da95d146d707adbd105e20
print(account_0.public_key) # c59ba4172b0f0bc0382a7cbfd125696ecfe7812779242e6c37962f41dad997c2
クライアントの生成
ここまでがローカルで処理されるウォレットとアカウントの生成でしたが、いよいよブロックチェーンのネットワークに接続した処理になります。そのためにはまずクライアントを生成します。Libraのノードとはprotocol buffer のメッセージをやり取りすることでお話できますが、そのためのクライアントです。
from pylibra import LibraClient
client = LibraClient()
LibraClient
の引数にhost:port
を与えると特定のノードとお話できますが、ここではテストネットのノードに繋ぎに行っています。
残高追加
出来たばかりのアカウントの残高は当然ながら0です。そこにテストネットの公式faucet から送金してもらって残高を増やします。そのためにmint_with_faucet
というメソッドを使います。2つ目の引数は送金してもらう金額ですが、単位は mini-libra ($=10^{-6}$ LBR)なので、10000を指定すると0.01LBRとなります。
client.mint_with_faucet(account_0, 10000)
そしてClientオブジェクトのget_account_state()
メソッドをアカウントを引数に呼び出すと、そのアカウントの状態を取得できます。
account_0_state = client.get_account_state(account_0)
print(account_0_state.balance) # 10000
print(account_0_state.sequence_number)
print(account_0_state.received_events_count)
print(account_0_state.sent_events_count)
送金
せっかくLibraを入手できたのでこれを他のアカウントに送金してみましょう。新たにもう一つアカウントを作ってそこに向けた送金依頼を出します。まずはaccount_1
を作りそこに今度は3000入れておきましょう。
account_1 = wallet.get_account(1)
client.mint_with_faucet(account_1, 3000)
account_1_state = client.get_account_state(account_1)
print(account_1_state.balance) # 3000
で、1000をaccount_1
移動させるトランザクションを作り、send_transaction
する。
from pylibra.transaction import TransferTransaction
tx = TransferTransaction(account_1, 1000)
client.send_transaction(account_0, tx)
よしよし。で、結果を見てみる。
account_0_state = client.get_account_state(account_0)
print(account_0_state.balance) # 10000
account_1_state = client.get_account_state(account_1)
print(account_1_state.balance) # 3000
あれ、変わってない?
そうなんです。どうやら現時点で送金の機能は壊れているみたいです。Githubのissuesを見るとそんなレポートが複数あり、Libraテストネットの進化に追いついていっていない模様。まあでも、ここまで試せたのでとりあえず良しとしましょう。
まとめ
LibraをインストールせずにPythonのクライアントライブラリを使って試すというのをやってみました。まだまだ機能が足りていませんが、Libraが落ち着いてくればお手軽にLibraをいじれる方法の一つになりそうなので引き続きWatchしていきたいと思います。