Libra開発言語 MOVEのLibraCoinモジュール

# はじめに
前回はModuleのローカルへのデプロイ方法を説明しました。
[Libra開発言語 Moveをローカルで使ってみる](https://qiita.com/YosukeAramaki/items/394c1f3cdf2e49ee3674)

今回はLibraにデフォルトでデプロイされているModuleを説明していきます。

# Module / Resource とは？
前回から出ている **Module/Resource** の説明を簡単にします。
Libraはアカウントベースデータモデルを採用しており、account addressにMove modulesとresourcesを紐ずけてデータの管理を行います。

**Module**はcodeを保存してあるもので、**Resource**はデータを管理しているものです。
そして1つのaddressに1つのModule, resourceを持つことができます。（＊プログラム次第で2つ以上持つことも可能です）

![スクリーンショット 2020-01-19 15.53.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342028/60fcb2c9-06aa-9136-9be6-811848ebfc4b.png)
 
White paperでは上記のようにModuleとRecourseの管理が図示されていました。
`0x56...`が`Currency`というModuleを公開しておりその中に`T`というResourceが含まれています。そして他のアカウントが'Currency Module'にある`T`をアカウントアドレスに紐ずけて保持できたり、'Currency Module'で定義されている関数を使用できたりします。

# LibraCoin Module
では早速`LibraCoin Module`の中身を見ていきます。

Libra Coinの発行や残高などはこの`LibraCoin Module`で管理されています。
例えば、Libra Coinの残高管理の場合は、`LibraCoin Module`の`resource T`をアドレスに紐付けて所有されることで管理されています。

下記が``LibraCoin`の全体です。

```rs
//LibraCoin.mvir
module LibraCoin {
    resource T {
        value: u64,
    }

    resource MintCapability {
        _dummy: bool 
    }

    resource MarketCap {
        total_value: u128,
    }
    
    public mint_with_default_capability(amount: u64): Self.T acquires MintCapability, MarketCap {
        return Self.mint(move(amount), borrow_global<MintCapability>(get_txn_sender()));
    }
 
    public mint(value: u64, capability: &Self.MintCapability): Self.T acquires MarketCap {
        let market_cap_ref: &mut Self.MarketCap;
        let market_cap_total_value: u128;

        _ = move(capability);

        market_cap_ref = borrow_global_mut<MarketCap>(0xA550C18);
        market_cap_total_value = *&copy(market_cap_ref).total_value;
        *(&mut move(market_cap_ref).total_value) = move(market_cap_total_value) + to_u128(copy(value));

        return T{value: move(value)};
    }

    public initialize() {
        assert(get_txn_sender() == 0xA550C18, 1);

        move_to_sender<MintCapability>(MintCapability{ _dummy: true });
        move_to_sender<MarketCap>(MarketCap { total_value: 0u128 });

        return;
    }

    public market_cap(): u128 acquires MarketCap {
        return *&(borrow_global<MarketCap>(0xA550C18)).total_value;
    }

    public zero(): Self.T {
        return T{value: 0};
    }

    public value(coin_ref: &Self.T): u64 {
        return *&move(coin_ref).value;
    }

    public split(coin: Self.T, amount: u64): Self.T * Self.T {
        let other: Self.T;
        other = Self.withdraw(&mut coin, move(amount));
        return move(coin), move(other);
    }

    public withdraw(coin_ref: &mut Self.T, amount: u64): Self.T {
        let value: u64;

        value = *(&mut copy(coin_ref).value);
        assert(copy(value) >= copy(amount), 10);

        *(&mut move(coin_ref).value) = move(value) - copy(amount);
        return T{value: move(amount)};
    }

    public join(coin1: Self.T, coin2: Self.T): Self.T  {
        Self.deposit(&mut coin1, move(coin2));
        return move(coin1);
    }

   
    public deposit(coin_ref: &mut Self.T, check: Self.T) {
        let value: u64;
        let check_value: u64;

        value = *(&mut copy(coin_ref).value);
        T { value: check_value } = move(check);
        *(&mut move(coin_ref).value)= move(value) + move(check_value);
        return;
    }

    public destroy_zero(coin: Self.T) {
        let value: u64;
        T { value } = move(coin);
        assert(move(value) == 0, 11);
        return;
    }

}

```

よく使いそうなところを見ていきます。
自分もRustに触れるのは初めてなのでどこまで正確に説明できるかわかりませんが頑張ります。

## resource T
```rs
resource T {
    value: u64,
}
```

上記でも述べたようにこの`resource T`をaddressに紐付けてLibra coinの残高管理を行なっています。
例えば、`0x123`のaddressが`100 Libra coin`持っているとしたら、`0x123.LibraCoin.T = 100`となります。

## resource MintCapability
```rs
resource MintCapability {
    _dummy: bool 
}
```

Libra associationのみに`LibraCoin.mint`の関数を使用権限を与えるために使われるものらしいです。mintの際に見てみます。

## resource MarketCap
```rs
resource MarketCap {
    total_value: u128,
}
```

`MarketCap`はおそらくLibra coinの総発行量を示しています。

## mint 

```rs
public mint(value: u64, capability: &Self.MintCapability): Self.T acquires MarketCap {
    let market_cap_ref: &mut Self.MarketCap;
    let market_cap_total_value: u128;

    _ = move(capability);

    assert(copy(value) <= 1000000000 * 1000000, 11); 
    market_cap_ref = borrow_global_mut<MarketCap>(0xA550C18);
    market_cap_total_value = *&copy(market_cap_ref).total_value;
    *(&mut move(market_cap_ref).total_value) = move(market_cap_total_value) + to_u128(copy(value));

    return T{value: move(value)};
}
```

・`acquires`と関数の引数の後につける理由はbytecode verifierに伝える際に必要になるそうです。下記のリンクで詳しく説明してあったのでわかるたいたら教えていただきたいです、、、
[How could I understand the keyword “acquires”?](https://community.libra.org/t/how-could-i-understand-the-keyword-acquires/1832)

・`market_cap_ref = borrow_global_mut<MarketCap>(0xA550C18);`では`0xA550C18`に紐付いてる`resource MarketCap`を参照しています。`0xA550C18`はLibLibのアドレスだと思われます。

・`market_cap_total_value = *&copy(market_cap_ref).total_value;`でLibraCoinのそう発行料を取得しています。
`market_cap_ref`はこれ以降も使うので`copy()`で指定しており、`*&`で間接参照しているみたいです。

・`*(&mut move(market_cap_ref).total_value) = move(market_cap_total_value) + to_u128(copy(value));`で今回のmintした量を総発行料に追加しています。
`to_u128`でu64だった引数をu126に変換できるみたいですね。`value`は最後に使うのでcopyで、`market_cap_ref`と`market_cap_total_value`はこれ以降使わないのでmoveで所有権を以降してます。

・`return T{value: move(value)};`でmintしたLibra coinを渡しています。


・mintの関数では`&`や`*`が出ていましたがC言語で使われるものらしいので下記の記事を参考にしてみてください。mintの関数だと`&market_cap.total_value`は`&u64`で`*&market_cap.total_value`は`u64`になります。
[【C言語ポインタ】&(アンパサンド)や*(アスタリスク)の使い分け](https://qiita.com/pen2000/items/fc5b06795dce3e0f679c)

## withdraw

```rs
public withdraw(coin_ref: &mut Self.T, amount: u64): Self.T {
    let value: u64;

    value = *(&mut copy(coin_ref).value);
    assert(copy(value) >= copy(amount), 10);

    *(&mut move(coin_ref).value) = move(value) - copy(amount);
    return T{value: move(amount)};
}
```
`withdraw`は所有しているLibra coinを分割するための関数です。下記のサイトの2つのアドレスに同時に送金されるときに使われるみたいです。Moveにはrustと同じように所有権が存在しているので送金するときもその所有権の概念が、同時に送金する際に絡むのかなと思いました。
[Getting Started With Move](https://developers.libra.org/docs/move-overview)

・`value = *(&mut copy(coin_ref).value);`で自分のLibra coin残高を取得して、次の文で分割する数より多いか確かめています。

・`*(&mut move(coin_ref).value) = move(value) - copy(amount);`で合計残高から`amount`を引いています。
`move(coin_ref).value`は書き換えられているため`mut`をつけてると思われます。


```rs
public deposit(coin_ref: &mut Self.T, check: Self.T) {
    let value: u64;
    let check_value: u64;

    value = *(&mut copy(coin_ref).value);
    T { value: check_value } = move(check);
    *(&mut move(coin_ref).value)= move(value) + move(check_value);
    return;
}
```

`deposit`は2つのコインを合わせる関数です。これは、Libra coinを受け取るときに使われる関数だと思います。「自分のcoin」と「受け取るcoin」を合わせる形でLibra coinを受け取るとき仕組みになっています。ややこしいですが、これもrustの特徴によるものでしょう。

・`T { value: check_value } = move(check);`で`check_value`がcheckと同じ数のLibra coinになります。`check`は引数で｀Self.T`と指定されてるので`resource`の形で渡されます。

・`*(&mut move(coin_ref).value)= move(value) + move(check_value);`で関数を呼び出す前の残高である`value`と送金された`check_value`を合わせて新しい残高に更新しています。


# 終わりに

MoveのデフォルトモジュールであるLibraCoinの仕組みをみました。MoveはRustを参考にした言語で、所有権の概念や言語特有の縛りなどがあり初学者には少々難しく感じました。

次回は`LibraAccount`モジュールの中身をみていこうと思います。