IOTA:【技術解説】送金Bundleの全容。

**English [here](https://iotafan.jp/en/developer/outline_of_bundles_20171227/). Special thanks to *Take san* for translating it!**

　過去の記事、*[IOTA:【技術解説】トランザクション大解剖！ウォレットは裏で何をやっているか。](https://qiita.com/ABmushi/items/e271ff05884a7d47658d)*で説明しきれなかったマニアックだが痒いところに手がとどく内容にした。というのも、今後IOTAの注目技術、MAMやマルチ署名を理解していく際に前提知識となるのがこのBundleの基礎だからである。
　なお、記事内のソースコードはJavaを使用した。理由としてはJavaが筆者のお気に入りであることと、変数の型が見える方が理解しやすいからである。もちろん、IOTAでは様々な環境で開発することができるので気になる方は [IOTA公式Github](https://github.com/iotaledger)をチラ見しておこう。

#IOTA（アイオータ）とは
まだIOTAがあまり認知されていないため、IOTAの基本をおさえるのに役立つリンク集。
>[**IOTA日本語ファンサイト**](https://iotafan.jp/)　実質IOTA日本公式サイト。というのもIOTA公式の情報を日本語訳して掲載しているからである。初心者向けの情報も多く掲載されている。
**ホワイトペーパー**[英語](https://www.dropbox.com/s/i4l3g88wh6gpi5d/IOTA_Whitepaper%20v1.1.pdf?dl=0) [日本語](https://www.dropbox.com/s/1w5vtu7s4idquc9/IOTA_Whitepaper%20v1.1%20in%20Japanese.pdf?dl=0)　Tangleについての概要は序盤までで、それ以降は安全性、想定される攻撃とその耐性について高度な数学で説明している。後半は初心者向きではない。
[**Redditの初心者向けスレッド（英語）**](https://www.reddit.com/r/Iota/comments/61rc0c/for_newcomers_all_information_links_you_probably/)　僕はここから始まった。
[**IOTA Guide（英語）**](https://domschiener.gitbooks.io/iota-guide/content/)　ホワイトペーパーが理学部なら、これは工学部。

　IOTAのコミュニティは[Slack](http://slack.iota.org/)ベースに育ってきた。日本語のチャンネル**#japanese**もあるので気軽に参加・質問してみよう。

# トランザクションの構造
　過去の[記事](https://qiita.com/ABmushi/items/e271ff05884a7d47658d#transaction%E5%A4%A7%E8%A7%A3%E5%89%96)も見ると分かりやすいかもしれない。下のソースは[Transaction.java](https://github.com/iotaledger/iota.lib.java/blob/master/jota/src/main/java/jota/model/Transaction.java)から抜粋した。主に重要なものにコメントをふっておいた。

```java:Transaction.java
public class Transaction {

    private static final transient Logger log = LoggerFactory.getLogger(Transaction.class);

    private transient ICurl customCurl;

    private String hash;                //  トランザクションのハッシュ（アイデンティティ）
    private String signatureFragments;  //  署名等に使われる2187トライトの長さを持つフィールド
    private String address;             //  アドレスを指定する
    private long value;                 //  金額を指定する
    private String obsoleteTag;
    private long timestamp;             //  必須になった
    private long currentIndex;          //  このTxはBundle内で何番目？（0からスタート）
    private long lastIndex;             //  Bundleの最後のTxのindexは何？
    private String bundle;              //  このトランザクションはどのBundleに所属するかを指定
    private String trunkTransaction;    //  承認するTxその１
    private String branchTransaction;   //  承認するTxその２
    private String nonce;               //  PoWのとき探す
    private Boolean persistence;        //  承認されたらTrue。未承認だとfalse
    private long attachmentTimestamp;
    private String tag;                 //  任意の27トライトのタグ
    private long attachmentTimestampLowerBound;
    private long attachmentTimestampUpperBound;
```

　送金には**受取アドレス（宛先）**と**送金元アドレス（送り主）**という最低二つが必要である。しかし、ご覧の通り一つのTransactionオブジェクトにはアドレスが一つしかない。そこで、IOTAではBundleという概念を導入した。BundleにはTransactionオブジェクトを複数含むことで受取アドレスと送金元アドレス、また署名などの様々な必要事項を別々のTransactionオブジェクトで役割分担して管理する。

# 送金のAPI
　送金をするAPIは見るだけなら簡単である。
## Transferクラス
　送金情報を保持する。

```java:Transfer.java
public class Transfer {

    private String timestamp;      // タイムスタンプ
    private String address;        // 受け取りアドレス（宛先）
    private String hash;
    private Boolean persistence;   // true:承認済み、false:未承認
    private long value;            // 送金額
    private String message;        // 任意のトライト
    private String tag;            // タグ（27トライト）

    // Transferオブジェクト生成
    // 宛先アドレス、送金額、任意のメッセージトライト、タグ
    public Transfer(String address, long value, String message, String tag) {
        this.address = address;
        this.value = value;
        this.message = message;
        this.tag = tag;
    }
...
```
## sendTransfer関数
　送金に使われるのは`sendTransfer`という関数だ。引数にTransferオブジェクトのリストを取ることで複数の送金を一度に行う。

```java:IotaApi.java
/**
 * Wrapper function that basically does prepareTransfers, as well as attachToTangle and finally, it broadcasts and stores the transactions locally.
 *
 * @param seed               Tryte-encoded seed
 * @param security           The security level of private key / seed.
 * @param depth              The depth.
 * @param minWeightMagnitude The minimum weight magnitude.
 * @param transfers          Array of transfer objects.
 * @param inputs             Optional: List of inputs used for funding the transfer.
 * @param remainderAddress   Optional: If defined, this remainderAddress will be used for sending the remainder value (of the inputs) to.
 * @param validateInputs     Whether or not to validate the balances of the provided inputs.
 * @param validateAddresses  Whether or not to validate if the destination address is already used and if a key reuse is detect.
 * @return Array of valid Transaction objects.
 * @throws ArgumentException is thrown when the specified input is not valid.
 */
public SendTransferResponse sendTransfer(
        String seed,
        int security, int depth, int minWeightMagnitude,
        final List<Transfer> transfers,
        List<Input> inputs,
        String remainderAddress,
        boolean validateInputs, boolean validateAddresses) throws ArgumentException {
....
}
```
## 送金
**「AさんがBさんにメッセージを載せて100通貨送金する」**という例をざっくり見てみると。

```java
// メッセージは任意のサイズのトライト
String message = "MESSAGE..."

// タグは27トライト
String tag = "SAMPLE9TAG99999999999"

// アドレスは81トライト。Bさんのアドレス。
String address = "B9ADDRESS..."

// Transferオブジェクトの生成（Bさんのアドレスに100通貨をmessage付きで送金）
Transfer transfer = new Transfer(address,100,message,tag);
List<Transfer> list = new List<>();
list.add(transfer);

// 送金
sendTransfer("Aさんのseedを指定",security,depth,minWeightMagnitude,list,null,null,true,true);
```
　公式ウォレットのソースコードの送金部分を単純化してみた。これで試してはいないのでなんとも言えないが送金は上記ようなの流れで行われる。
　この記事はこの`sendTransfer`関数の中身がどうなっているかに注目していきたい。正しい送金の仕方は公式のソースを見るのが一番正しいのでリンクを貼っておく。
>**Python** [iota.lib.py/examples/send_transfer.py](https://github.com/iotaledger/iota.lib.py/blob/master/examples/send_transfer.py)
**Android** [android-wallet-app/app/src/main/java/org/iota/wallet/ui/fragment/NewTransferFragment.java](https://github.com/iotaledger/android-wallet-app/blob/master/app/src/main/java/org/iota/wallet/ui/fragment/NewTransferFragment.java#L191)


# Bundleの構造
　まず、送金のためにIOTAではBundleというものを生成する。BundleとはIOTAの最小単位である`Transaction`をまとめたものである。送金額や署名等の１つの送金に必要な情報をまとめている。
　Bundleには大きく分けて３つの部分がある。
>①出力部 - 'output'（どこへいくら送金するかを指定）
②入力部 - 'input'（どこからその金額を持ってくるかを指定）
③差額出力部 - 'remainder'（お釣りをどこへ送金するかを指定）

　アドレス`DEFBQV...`に`13i`送金する例。（`security=2`）
![bundle_basic.png](https://qiita-image-store.s3.amazonaws.com/0/187795/e21f2b87-f38f-00ff-5e9a-8f81b7ba885d.png)


##出力部 - output
　指定された宛先アドレスに送金することを**出力**という。その出力を請け負うのがBundleの前半である出力部という部分である。出力部には以下の役割がある。
>①送金額の指定
②送金先の指定
③任意のメッセージ（message）の保管

　先ほどの**「AさんがBさんにメッセージを載せて100通貨送金する」**という例だと以下のようになる。
*`sigF`というのは上記Transaction内の`signatureFragments`を意味する。
*分かりやすさのために`address`にはBさんが代入されているが、これはBさんのアドレスという風に見て欲しい。
* Tx.0、Tx.1 の0や1は上記Transaction内の`currentIndex`を示す。

![bundle_output.png](https://qiita-image-store.s3.amazonaws.com/0/187795/17d5fdfc-6409-5aff-00d4-d18f7b7ae4e0.png)


　図を見てわかる通り、送金額は**Tx.0**の`value`に宛先は`address`に指定する。そして、`message`部分はサイズ2187トライトのチャンクごとに分けられ、前から順番にTx.0、Tx.1、...の`sigF`に保管される。もし、`message`が2187トライトより短ければ出力部はTx.0のみ、つまり１つの`Transaction`で足りる。また、もし`message`が長ければその分`Transaction`が増えて出力部自体も長くなる。`message`が2187の倍数ぴったりになることはほぼないので、大抵`sigF`の端数を'9'で埋める。
　また、`message`はそれぞれ`sigF`にトライトで表されているものの、もちろんトライトから文字に変換することができるので、文章の中身はTangle上で筒抜けである。そこでこの`sigF`を暗号化することでTangle上にプライベート空間を提供する**MAM(Masked Authenticated Message)**という活用法も提案され研究・開発中である（次項）。

###MAMとの関連性
　MAMとはIOTAでも最も期待されている機能の一つであり、Tangle上にプライバシーを保ちつつデータを保存できる機能である。要するに、今のままではTangle上でむき出しになっている誰でも閲覧できるこの`sigF`の中身を暗号化する。手数料が無料のIOTAではゼロ円送金ができるため、そのトランザクションの`sigF`をプライベートなデータ領域として積極的に利用出来る。
　解説記事を公開するのが今年最後の夢だ。


##入力部 - input
　Tangle上の残高のあるアドレスから送金額を集めてくることを**入力**と呼ぶ。出力部で指定した出力を実行するにはそれに十分な額をどこかで保有していないといけない。また、アドレスから支払われたことを署名することによって、二重支払いを防がないといけない。それらを請け負う入力部には以下の役割がある。
>①入力額の指定
②入力アドレスの指定
③入力アドレスの署名

　**「AさんがBさんにメッセージを載せて100通貨送金する」**という例で引き続き考えると、100通貨以上をどこから持ってくるかをここで指定する。ここで"以上"と言ったのは、余剰分は次の差額出力部で回収できるからだ。

![bundle_input.png](https://qiita-image-store.s3.amazonaws.com/0/187795/87c8a8aa-025b-04f6-cecb-aafd620c0b4d.png)

　今回の例だと入力は２つ（入力１と入力２）ある。なぜ、２つかというとそれぞれの`address`の保有額を合計（Aさん①+Aさん②=**-144**）してやっと送金額の**100**を賄えるからだ。余った**44**は次項、差額出力部で扱う。もし、Aさんのとあるアドレスに例えば100以上の残高があれば、その一つを入力とすれば足りるため、入力部の長さは結果的に短くなる。
　それよりも重要なのは、`sigF`である。１つの入力アドレスに対して署名が２つにわかれている。これは`sendTransfer`関数の`security`引数によって変わる。`security=1`なら「その１」だけしか生成されない。つまり、今回の図だとAさん①、Aさん②のために合計２つの署名で済む。もし、`security=3`ならそれぞれの入力アドレスに「その３」まで署名が必要で合計2*3=6個のTransactionが入力部に生成される。公式化すると以下のようになる。

$Transaction数 = security*input数$

　また、署名の方法については[過去の記事](https://qiita.com/ABmushi/items/422d1bf94be0c919583a#%E7%BD%B2%E5%90%8D%E3%81%AE%E6%96%B9%E6%B3%95)で言及したので参照していただけると幸いだ。

##差額出力部 - remainder
　出力額ぴったりの残高をもつ入力アドレスは大抵存在しないため、出力額以上の残高を複数の入力アドレスから集めることになる。そのためお釣りが発生する。IOTAでは一度署名されたアドレスを再度入力アドレスとして新しく署名するとPrivate Keyの漏洩に繋がる。言い換えると、一度署名されたアドレスで金額を受け取ってはいけない。もし、お釣りを元あった入力アドレスに戻すことはその原則に違反する。そこでお釣りは新しい別のアドレスに出力される。
差額出力部は以下の役割がある。
>①差額の指定
②出力アドレスの指定

　**「AさんがBさんにメッセージを載せて100通貨送金する」**という例では、最終的に**44**通貨の余りが出た。下の図を見てみよう。

![bundle_remainder.png](https://qiita-image-store.s3.amazonaws.com/0/187795/e21d3724-5ee1-2601-5dd8-bededcb08f86.png)

　とてもシンプルである。差額出力部は差額がある場合は1つだけのTXを生成する。お釣りの金額が新しいAさんのアドレス（Aさん③）に出力されるだけである。新しいアドレスとはなんぞやという方は、[過去の記事](https://qiita.com/ABmushi/items/e271ff05884a7d47658d#%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9)を読み返してほしい。
　ちなみにもしお釣りがゼロ（ぴったりの入力アドレスが見つかった）場合は差額出力部自体が生成されない。

##複数アドレスに送金する場合
　複数の別のアドレスに送金する場合は、**出力部をアドレスの数だけ増やす。**

![bundle_mult_out.png](https://qiita-image-store.s3.amazonaws.com/0/187795/8a5cfc41-0bd7-ab10-615b-be3617b3c33a.png)
　入力部、差額出力部の扱い方は簡単だ。入力部では今回の例だと（100+1000+634=1734）以上分の入力アドレスを探し、差額はお釣りをまた１つのTxに入れるだけで特に特別なことはしない。

#Bundleの全容
　さてIOTAのTransactionはただ生成するだけでなく、`trunkTransaction`と`branchTransaction`と呼ぶ二つのTransactionを承認するという仕事がある。
##承認するTipsの選択
　承認するTipsと呼ばれるTransactionは`getTransactionToApprove`という関数で簡単に取得することができる。あまりに簡単だが、その裏には高度な数学が潜んでおり、筆者のような素人の頭を悩ませる。とても手に負えないため、この説明は誰か数学のできる人にお願いしたい。

##Bundleの承認関係
　以前の記事でも触れたがもう一度あえて図を描き直した。
　![bundle_approve.png](https://qiita-image-store.s3.amazonaws.com/0/187795/ca96cfdd-ae0b-e9ec-c746-c9573f6adb4e.png)
　`getTransactionsToApprove`関数が返す`trunkTransaction`、`branchTransaction`をそれぞれ図内の`Milestone`と`other Tx`に当てはめる。
　[https://iotasear.ch/](https://iotasear.ch/)などのTangle Explorerで適当なトランザクションとBundleを見てみよう。この記事で紹介した通りになっているはずだ。（違っていたら報告して下さい）

#チートシート
　印刷できるサイズ。随時更新して美しいものに仕上げていきたい。
![bundle_cheat_sheet.png](https://qiita-image-store.s3.amazonaws.com/0/187795/ca1ef2da-03ef-1d53-54b5-bf9e331a08f1.png)


#参考文献
**IOTA Java ライブラリ JOTA** [iotaledger/iota.lib.java](https://github.com/iotaledger/iota.lib.java)

毎度のごとく、記事に対するフィードバックお待ちしています。