Libra開発言語 Moveをローカルで使ってみる

# はじめに
Libraの開発言語であるMoveをローカルで動かしてみます。
公式ドキュメント「[Run Move Programs Locally](https://developers.libra.org/docs/run-move-locally)」を元に、補足説明をしながら進めていきます。

# Moveの現状
2020年1月現在、MoveはTest-netでは使えずローカル環境でしかで試すことしかできません。
ただLibraの開発は盛んでもうそろそろできるようになりそうです。

# 1. Libraをローカルで立ち上げる

Libraのディレクトリをcloneしローカルで立ち上げます。

```
$ git clone https://github.com/libra/libra.git
$ cd libra
$ cargo run -p libra-swarm -- -s
```

`libra-swarm` はローカルでLibraを立ち上げるためのコマンドで、`-- -s`をつけることで自動的に
・1つのValidator nodeの立ち上げ
・Genesis transaction, mint key, and bootstrap configuration の作成
・ローカルのLibraに繋がった、Libra CLIインスタンスの作成
を行ってくれます。


下記のように`libra%` と出てきたら立ち上げ成功です。立ち上げまでかなり時間がかかることがあるので気長に待ちましょう。

```
usage: <command> <args>

Use the following commands:

account | a
Account operations
query | q
Query operations
transfer | transferb | t | tb
<sender_account_address>|<sender_account_ref_id> <receiver_account_address>|<receiver_account_ref_id> <number_of_coins> [gas_unit_price_in_micro_libras (default=0)] [max_gas_amount_in_micro_libras (default 100000)] Suffix 'b' is for blocking.
Transfer coins (in libra) from account to another.
dev
Local Move development
help | h
Prints this help
quit | q!
Exit this client


Please, input commands:

libra%
```

# 2. アカウントの作成

Libraアカウントを作成しLibra Coinをmintします。

```
libra% account create
>> Creating/retrieving next account from wallet
Created/retrieved account #0 address ffbff21715437c87f78c3c069c61b2239f7255c2d073eab280e7a5df4f0ecfcb

libra% account mintb 0 100
>> Minting coins
waiting for 000000000000000000000000000000000000000000000000000000000a550c18 with sequence number 2.............................transaction is stored!
Finished minting!

libra% query balance 0
Balance is: 100.000000
```

Libra Coinの送金などに関してはこちらをご覧ください。
[My First Transaction](https://developers.libra.org/docs/my-first-transaction)

# 3. Move moduleのCompile

`my_module.mvir`を作成し、MyModuleを作ります。Moduleはアカウントに紐付き生成されます。

```my_module.mvir
module MyModule {
  import 0x0.LibraCoin;

  public id(c: LibraCoin.T): LibraCoin.T {
    return move(c);
  }
}
```

`MyModule`ではデフォルトのモジュールである`LibraCoin`をインポートし、`LibraCoin`にある`T`というリソースを、`id`という関数で呼び出せるようにしているだけものです。

>デフォルトのモジュール、モジュール、リソースに関しては別記事で説明しようと考えてます。

Fileを作成したら、下記のコマンドでコンパイルします。

```
libra% dev compile 0 /Users/{{your user name}}/Desktop/Move/my_module.mvir module
```

ここではDesktopにMoveディレクトリを作成しその中に保存しました。任意の場所に保存しても大丈夫です。


Compileが成功したら、下記のように表示されmoduleのbytecode file が自動的に作成されます。

```
Successfully compiled a program at /var/folders/zk/5v9mctxx3p1fdc_4j1dqq7780000gp/T/acb821e01a491d6f6bf188c5065d2c70.mv
```

# 4. Moduleを公開する
Compileで作成された bytecode file を使って Module をローカルのLibraに公開します。
公開する際は関数の実行者の元で公開されます。コンパイルした際に`Successfully compiled a program at`以降に表示される場所に、bytecode file は保存されています。コピペしてそのまま使いましょう。


```
ibra% dev publish 0 /var/folders/zk/5v9mctxx3p1fdc_4j1dqq7780000gp/T/acb821e01a491d6f6bf188c5065d2c70.mv
waiting for ffbff21715437c87f78c3c069c61b2239f7255c2d073eab280e7a5df4f0ecfcb with sequence number 1............................transaction is stored!
no events emitted
Successfully published module
```

これで公開できました。

# 5. 使ってみる

では実際に公開したModuleを使ってみます。

## 5-1. scriptの作成
まずModuleを使うためのScriptを作成します。今回は`custom_script.mvir`の名前で作成しました。

```custom_script.mvir
import 0x0.LibraAccount;
import 0x0.LibraCoin;
import {{sender}}.MyModule;

main(amount: u64, receiver: address) {
  let coin: LibraCoin.T;
  let receiver: address;
  coin = LibraAccount.withdraw_from_sender(move(amount));
  LibraAccount.deposit(move(receiver), MyModule.id(move(coin)));
  return;
}
```

`import {{sender}}.MyModule;`で公開した`MyModule`を参照してます。
`{{sender}}`とすると自動的に関数の実行者のアドレスが割り振られますが、他の方が作成した Module を参照する場合は`{{sender}}`の代わりに作成した方のアドレスを書けば利用することができます。
`coin = LibraAccount.withdraw_from_sender(move(amount));`で関数の実行者から`amount`分のLibraが引き落とされ、
`  LibraAccount.deposit(move(receiver), MyModule.id(move(coin)));`で`Receicer`にLibra Coinが送金される仕組みです。
また、`MyModule.id`で`my_module.mvir`で公開した`id`関数を呼び出しています。

## 5-2. Scriptのコンパイル

下記のコマンドでsctiptをコンパイルします。

```
$ dev compile 0 /Users/{user name}/Desktop/Move/custom_script.mvir script
```

このように表示されたら成功です。

```
Successfully compiled a program at /var/folders/zk/5v9mctxx3p1fdc_4j1dqq7780000gp/T/b51adcbc76e7d0fa8b8bc79f2706ee72.mv
```
## 5-3. Scriptの実行

実行する前にローカルにLibraアカウントを追加しておきます。

```
libra% account create
>> Creating/retrieving next account from wallet
Created/retrieved account #1 address da773d29e572a58111193a5a71e8c97557ea53d7ffae905e3fa680771cf3191c
```

この作成されたアカウントにLibra Coinを送金してみます。
Scriptを実行する関数は下記です。scriptのbytecode fileはcompileの際に作成されたものを利用します。

```
libra% dev execute /var/folders/zk/5v9mctxx3p1fdc_4j1dqq7780000gp/T/b51adcbc76e7d0fa8b8bc79f2706ee72.mv 100 da773d29e572a58111193a5a71e8c97557ea53d7ffae905e3fa680771cf3191c
```

これで`100 microlibracoin`が`da773d29e572a58111193a5a71e8c97557ea53d7ffae905e3fa680771cf3191c`へ送られていると思います。

# 終わりに
Libraの仕組みがなんとなく見えてきたような気がします。

次回はデフォルトのモジュールの中身をみていきたいと思います。