Edited at

IOTA:【入門】トランザクション大解剖!ウォレットは裏で何をやっているか。


はじめに

 来たるIoT時代。そこでは、大量のノードからの大量のリクエストがネット上を駆け巡っていることだろう。その中にはお金をやり取りする決済のリクエストもかなりの数が行き来しているはずである。しかし、現存のブロックチェーンでそれらを捌ききることはできるだろうか?未だ世間的に少数の利用者しか使っていないビットコインでも、ご覧の通り決済が滞り、それゆえスケーラビリティが大きな課題として今後も直面し続ける可能性がある以上、もし、分散型システムでそれを実現したいとしたら、ブロックチェーンとはちがったアプローチを模索しなければならない。また、手数料も問題である。IoTが行き届いた社会とは、小さなデバイスの小さな仕事がネットワーク上で無数に実行される社会であるため、おそらくその決済も少額なものがほとんどであると考えられる。


IOTA

 しかし、ブロックチェーンではシステムの存続作業(=採掘)をするマイナーたちに報酬をあたえることが不可欠であるため、手数料は必ず利用者から徴収しなければならず、1円単位の少額決済には向かない。そこで考案されたのがタングル(Tangle)という新しい分散型台帳であり、Tangle上で価値を持つ仮想通貨がIOTAである。

 IOTAは上記ブロックチェーンの課題を解決できるよう設計された。具体的には



  1. スケーラビリティの克服(参加者が何人いても大丈夫)

  2. 手数料はゼロ


 では、これを実現したTangleとは一体何なのであろう?

tangle.png

 端的にBlockchain(ビットコイン等)とIOTAのTangleの違いを図に表すとこうなる。Blockchainではブロックのサイズにスケーラビリティを依存するが、Tangleでは理論上、サイズの柔軟性がBlockchainに比べて高い。

 先日、コミュニティの中でIOTAのホワイトペーパー勉強会が開催されたようだ。その際使われたこちらのスライドは深いところまで掘り下げられており、とても分かりやすい。また、リンク集も貼っておく。


IOTA日本語ファンサイト 実質IOTA日本公式サイト。というのもIOTA公式の情報を日本語訳して掲載しているからである。初心者向けの情報も多く掲載されている。

ホワイトペーパー英語日本語 Tangleについての概要は序盤までで、それ以降は安全性、想定される攻撃とその耐性について高度な数学で説明している。後半は初心者向きではない。

Redditの初心者向けスレッド(英語) 僕はここから始まった。

IOTA Guide(英語) ホワイトペーパーが理学部なら、これは工学部。



シードと三進数

 IOTAは将来的に3進数チップで動作するプロトコルを目指しているため現段階から3進数で全て設計されている。ちなみに3進数を採用した理由としては2進数より計算コストが安いかららしい。

 シード(Seed)は決して外に漏らしてはいけない。マイナンバーやクレジット番号と同じである。長さ81トライト以下の文字列で。トライト(Tryte)は3進数の単位で、大文字のアルファベットのA-Zと数字の9を使って値を表す。

十進数
2進数(バイト)
3進数(トライト)

0
0000 0000 (00)
000 (9)

1
0000 0001 (01)
00+ (A)

2
0000 0010 (02)
0+- (B)

3
0000 0011 (03)
0+0 (C)

4
0000 0100 (04)
0++ (D)

10
0000 1010 (0A)
+0+ (J)

-10
1111 0110 (F6)
-0- (Q)

上記は簡単な3進数*の表だ。3進数のtrit(トリットと読む。2進数でいうbit、ビット)は、0+-の3種類で表されて、3トリット=1トライトの情報(3の3乗=27通り)を大文字アルファベットA-Zの26通りと数字の9(26+1=27通り)で表す。変換表はこちら。シードは今のところ81トライト以下で設定されるので、HELLOでもTESTでも99999999でも、AFNE9AOU....WHI9DLWでも大丈夫である。もちろん、ランダムな81トライトの文字列がセキュリティ上安全である。

ちなみに推奨されるシード自動生成コマンドとして、


コマンド

$ cat /dev/urandom |LC_ALL=C tr -dc 'A-Z9' | fold -w 81 | head -n 1


がある。オンラインのジェネレーターなどは絶対使ってはいけない。オフラインと謳っているのも基本危険と認識すべきである。また、上記コマンドで生成したとしても数桁は自分で入れ替えるなどすると尚良い。

試しに下記のシードを生成した。(本当は他人に見せてはダメだが便宜上のサンプルとして)

9ABCDEFGKLAEUNVMSL9AKRUG9ACBWGQ9NVBAEUOWKHG9AEBVWAIWUEROIKXMZHWYQGW9WYERTBVNIAAEX

login.png

 シードを決めたら、ウォレットログイン画面のSeedにそれを入力してログインボタンを押す。

 そうするとアカウントに入ることができる。注意してほしいのは、Googleなどのアカウントと違ってIDとパスワードがあるわけではない。つまり、IOTAのウォレットアカウントに入る際はシードだけが必要なので、81トライトのシード単体がIDとパスワードを兼ねている(=アカウントそのもの)と考えられる。そのため、繰り返しになるがシードの管理は徹底して行うことを強調する。

 早速、このアカウントにIOTAを送金して決済の準備をしたいが、IOTAのアドレスと受取はどのようになっているのだろうか?

*正確には0+-で表される3進数のことを平衡三進法というが詳細は省略。


アドレス

 さて、IOTAのアドレスはシードから複雑な数理計算(ハッシュ関数)を経て生成される。(アドレスからシードの逆生成はできない。)

address0.png

 ここでまず注目してほしいのはPrivate Keyの生成である。(JavaScriptのソースはこちら)IOTAでは1つのアドレスの永久利用をセキュリティの観点から推奨していない。(2017/7/28追記:その理由はIOTAの署名のアルゴリズムにある。それについてはこちらで詳しく検証した。)アドレスは生成のたびにindexという内部の変数を1つずつ足していき、毎回異なるものが自動的に生成される様になっている。また、lengthではセキュリティレベルを設定できる。1〜3のレベルがあり、数字が大きい方がセキュリティが強固なものになる。ちなみにウォレットのレベルは2


アドレスの運命

 よくIOTAの英語情報を探っていると、address is deterministic(アドレスは決定論的である。)という文言を目にすると思う。この文の意味をくだいて説明するならば、アドレス生成の引数(seedindexlength)が同一な場合、生成されるアドレスもまた同一になるということだ。これについては別の記事で例え話を使って図解したのでよければ一読してほしい。

 また、seedindexlengthによってどのようなアドレスが生成されるかを図にすると以下のようになる。

addresses.png

 これを見ると、index=0、つまり今の(=初期)状態でのアドレスはBCEQI...となっており、ウォレットで見れる(下図)ものと一致している。

address0.png

次にアドレスを生成したときには、index=1のアドレスが生成される。

 また、Private Keyからアドレス生成にもシード->Private Keyとは異なる複雑な演算処理が行われているが、それについては以前の記事で解説したのでそちらを参照。


Transaction大解剖

 Transaction(トランザクション)は仮想通貨のシステムではたいてい最少単位のオブジェクトである。宇宙で言う原子。そのためこのTransactionの構造を解剖してみることは今後の理解の速度をアップするはすだ。


Transactionの構造

 ビットコインではトランザクションの承認の際、複数のTransactionを一つのハッシュ値(Merkle root)にまとめて、それをブロックに添付してまとめて承認していたがIOTAにはブロックが存在しない。Tangleではトランザクションが生成されるとき、Tips(Tangle上の未承認の別のトランザクション)を2つ承認する必要がある。承認とはつまり採掘なので、IOTAではトランザクション生成者(ユーザー)がトランザクション生成のとき同時に採掘(PoW方式)も行っている。(これが手数料0のカラクリ)なので、Transactionの構造にその2つの承認したトランザクション(TrunkTransactionBranchTransaction後述)とnonceが含まれている。文章で説明してもなので以下がTransactionの構造である。(原本

フィールド
内容

hash
このトランザクションのハッシュ(81トライト)

signatureMessageFragment
2187トライトの署名に関連する部位。後述

address
もしこのトランザクションが出力なら受取人のアドレス。もし入力(UTXOからの受け取り)ならそのUTXOのアドレス。UTXOについて分からない方はこちらから。

value
移動するIOTAの額

timestamp
タイムスタンプ。IOTAでは必須ではない。

currentIndex
Bundle(後述)内のインデックス

lastIndex
Bundle内のトランザクションの数

bundle
このトランザクションを内包するbundleのハッシュ(81トライト)

trunkTransaction

1番目にこのトランザクションに承認されたトランザクションのハッシュ(81トライト)

branchTransaction

2番目にこのトランザクションに承認されたトランザクションのハッシュ(81トライト)

nonce
PoWで生成される値


Tangleにアタッチ(Attach to Tangle)

 ウォレットの機能その1であるタングルにアタッチだが、これが分かりにくい。あたかも受取に必要のように思わせておいて実は、このボタンを押さなくても送金を受け取ることができる。

 何をやっているかを一言で言えば、空の(0円送金の)トランザクションを指定アドレス宛へ発行することである。上項のアドレスでちらっと出てきたindex+1することを行い、新しいアドレスをSeedから生成(生成自体はハッシュ計算をオフラインで行えるためローカルでやっている)する。そして、この"タングルにアタッチ"ボタンを押すことで、その新しいアドレス宛の空トランザクションをTangle上に発行する(ここはオンラインの動作)。

 また、最近Discordの日本語チャンネルにおけるアタッチについての議論が非常に有意義に行われ、IOTA日本ファンサイト様にまとめていただいた。一見の価値あり。

 では、アタッチしてみよう。

attaching.png

しばらくの時間(1〜2分)待っていると...

attached.png

と表示される。空のトランザクションが生成されたことを確認しよう。IOTAのTangle ExplorerはIOTA Tangle Explorerを利用する。受取のアドレス(今回の場合ならBCEQI...)で検索するとアドレス詳細が出てくる。その下のRelated Transaction(関連するトランザクション)の詳細を見てみると、空のトランザクションが見れる(ここ)。

pending.png

執筆時点ではConfirmed=falseとなっていて未承認となっていた。ウォレットの記録の中にペンディング中と表示されているので"バンドル表示"から"再ブロードキャスト"してみたところ、何度やっても承認済みにならない。どうやら同じようなトラブルが多数報告されているようだが、「ウォレットを最新バージョンにする」「再ブロードキャストを繰り返す」「待つ」と言ったそんなの分かっている的な対処法しか見つからない。私の場合はただの空のトランザクションだからマシだが、大きな金額が動くトランザクションでは大きな問題だと思う。


予定にはなかったペンディング地獄。そちらについてまとめたのでこちらの記事を参照してほしい。


結局一日経っても承認されずに終わってしまったのでこの記事にこのアドレスを使うことはこれ以降では行わない。

(2017/7/28追記)

どうやら、この"タングルにアタッチ"によって生成される空のトランザクションは承認される必要はないとのことだ。そのため、今回のペンディング地獄は幻想だった。


余談

 Attach to Tangleの日本語訳をタングルにアタッチとしてしまったのには、筆者にも後悔が残る。というのもAttachという動詞をカタカナにすると初心者にはなんのことか分かりにくいからだ。

 一応、候補としては添付といった面白みのないものから、登録など飛躍したものまで考えたが、語学の専門家でもないので仕方なくカタカナにしてしまった次第だ。

 参考のため他の漢字文化圏の訳がどうなっているか調べてみると、韓国語では연결(連結)、中国語では附加添加というふうに決して統一はできていない様子だ。やはり他の文化圏の言葉を輸入するのは難しいということだろうか。

 結局、Attachという動詞がIOTAに採用されたのも、Tangleという小さなトランザクションの大群に新しくくっ付けるといったニュアンスから来たのかなと想像ができる程度だ。まあ想像の域を越えることはない細かい話は余談程度に留めておくのが最善であろう。


送金の仕組みとBundle

 気を取り直してウォレットの記録にあるバンドル(Bundle)とは何か説明したい。

例えば、AさんからBさんへの送金の際、IOTAは1つのトランザクションでそれを行わない。基本4つのトランザクションで1つの送金を行うことになっている。Bundleはその4つのトランザクションをまとめる単位と考えるとよい。(4つ以上、4つ以下の場合もある。詳しくはこちらから。)

 では、わざわざ4つのトランザクションで送金をする意味を理解するためにBundle内の4つのトランザクションの役割を見てみよう。上記のTransactionの構造と見比べながらだといい。

Bundle内のindex
Transactionのフィールド
役割

[0]
送金額はvalue>0で指定。送金相手はaddressで指定。

addressvalueを送る。

[1]
入力アドレス(どこから[0]のvalueの額を持ってくるか)をaddressで指定。また、その入力アドレスからいくら引くかの額をvalue<0に指定。そして、その入力アドレスの電子署名の半分をsignatureMessageFragmentに指定。(署名の生成方法はこちら)
入力したいUTXOのアドレス・額の指定。署名(1/2)の保持。

[2]
もう半分の電子署名をsignatureMessageFragmentに指定。入力アドレス([1]のaddressと同一だが)をaddressで指定。value=0
署名(2/2)の保持。

[3]
[1]のaddressから引き落とした額([1]のvalue)と送金額([0]のvalue)の差をvalue>0に指定。また、その額がどこの出力アドレス(UTXO)に送るかをaddressに指定。
入力-支払いのおつりを持たせる新UTXOのアドレス・額を指定。

AさんがBさんに24 iota送金する例で考える。送金前Aさんは777 iotaの残額がある。その777 iotaはZさんから以前受け取った額であるとする。下の図ではZさんからの受取時に生成されたUTXO(アドレス:AUTXO9...)に777 iotaが存在していることを示している。Aさんの残高はAさんの所有権のあるUTXO全ての残高の合計ということだ。

figure1-1.png

この状態から送金のためにBundleとその中にTransactionを生成する。

figure1-2b.png

Bundle承認後、送金が完了される。AさんはTransaction[3]が指定したアドレス(address=AUTXOA...)に新たなUTXOを作り、その残高は777-24=753 iotaとなる。また、BさんはTransaction[0]のアドレス(address=BADR......)に新たなUTXOを作り、その残高は24 iotaとなる。

figure1 (9).png

ビットコインとよく似ているが、ポイントとしては手数料が引かれないということであろう。


TrunkTransactionとBranchTransaction

 さて、上記Transactionの構造にtrunkTransaction(幹トランザクション)branchTransaction(枝トランザクション)という変数がある。先ほども述べたようにIOTAのPoWは新しいトランザクションが別の2つのトランザクションを承認する際になされる。そしてこの二つの変数はその承認された2つのトランザクションのハッシュを保持するためのものだ。基本的には2つのトランザクションの選定(Tips Selection)はランダムに行われるが、実は送金の際は特殊なルールがある。まず、下の図を見てほしい。

bundle3_eng.png

気づいてほしいのは、trunkTransactionの承認はindexが0から3の方向へまるでBundleを幹にする木を作るようになっている。このような特殊な承認をするのは、送金のためにBundle内に複数のトランザクションがある場合である。例えば、'タングルにアタッチ'の時生成される空のトランザクションは、Bundle内にそのトランザクション1つしかないためこのルールは適用されず、単純に1番目に承認されたものをtrunkTransaction、2番目をbranchTransactionとする。

チートシートを作成しました


Milestone(マイルストーン)

 Milestone(マイルストーン)というのは現在運用中のCoordinatorと呼ばれるノードが発行する特殊なTransactionのことで、主にTangle上のチェックポイントとして使われる。マイルストーンのTransactionはBundle内から上図のように参照される。また、マイルストーンは下図のような構造になっている。

milestone2_eng.png

 一つのマイルストーンは2つのTransaction(Milestone[0]とMilestone[1])で構成されている。マイルストーンの生成アナウンスはIOTA公式Slackの#botboxチャンネルで逐次確認できる。


ネットワークをスパム(Spam the network、スパミング)

 主にSpammer(スパマー)によって行われるスパミングについて説明したい。スパムと言えばネット上の迷惑行為だが、どうやらIOTAにおいてはスパムはちがう。そのため、IOTAにおいてのSpamはスパミングとあえて訳した。スパマーは非公式のものならここでそのコードを見ることができる。(バージョンによってはウォレットからもできるようだが。)スパマーの目的はズバリ、空のトランザクションを無意味に大量生成することである!そんなF5攻撃みたいなことをしてTangleの処理は滞らないか心配するかもしれないが、どうやら問題ないらしい。むしろ、スパムトランザクションの生成にも2つのトランザクション承認義務があるため、ネットワークはスパミングによって恩恵すら受けるということだ。また、そんなことしてたらたちまち膨れ上がっていくだろうストレージサイズも、一定期間で残額が0のアドレスを除去し、スナップショット(その時点のデータだけを保存)を残すことができるので、ビットコインのようにジェネシスブロックから全てのブロック(=ブロックチェーン)を保持する訳ではないそうだ。スナップショットをとるタイミングはフルノードごとにローカルで決めることができるらしい。


スナップショット

 IOTAのTangleのデータのダイエットが不定期に行われる。この際は全てのトランザクションが消去され、残高のあるアドレスを新たなGenesisアドレスとしてTangleを言うなれば"生まれ返らせる"操作をスナップショットと呼ぶ。

 こちらもIOTA日本ファンサイト様のDiscordまとめ記事は一読の価値ありだ。


IOTAの今後(2018年2月時点)

 仮想通貨が大暴落、米国株価や日経平均も急落。と経済的不安要素が高まりそうな2018年だが、皆様はどうお過ごしだろうか。ただ、IOTAや他の仮想通貨でもここで踏ん張って開発しきれたプロジェクトが今後の世の中のためになる技術となっていくに違いはない。仮想通貨は通貨ではなく、暗号とプロトコルで分散管理され、サービスに直結している株のようなものだと筆者は考えているので、サービス自体に価値がないと通貨の価値もなくなってしまうだろう。

 IOTAに関して言えば、まず今年上半期にTrinityウォレットのリリースを控える。

 そして、フラッシュ(IOTA版ライトニングネットワーク)の実用化(ハッカソンの結果も発表された)、データマーケットの整備、そしてIXI(C++版フルノード)運用開始、Coordinator引退が今年中にでも実現できれば及第点ではないかと個人的には思う。3進数プロセッサーJINNは慌てなくてもいいかなというのが私の勝手な意見だが...

 フルノードはアップデートごとに安定してきておりIOTA開発陣の努力を肌で感じられるので、これからもこの調子でコツコツ開発を続け、新たな価値を創造してくれることを期待している。