アルゴリズムとかオーダーとか

仕事で勉強したことなどをまとめてます

μRaidenの概要

RaidenNetworkもテストネットに公開されていたので、RaidenNetworkの勉強のためにまずは簡単な実装であるμRaidenについて調査してみました。
今回はμRaidenについての理解を整理する意味でも記事としてまとめてみます。

お断り

μRaidenに関しては、技術的情報をまとめた公式のドキュメントがなかったので、この記事の内容はgithubに上がっているソース等から理解が理解したもの基づいて書いております。そのため公式の物ではありませんし、間違いが多分に含まれているかもしれません。
もし間違い等ありましたらぜひご指摘ください。

μRaidenとは?

μRaidenはRaiden Networkの一部ではありません。しかし、それは同じ状態チャネルのアイデアを使用して構築され、有料コンテンツのマイクロペイメントの具体的な適用に焦点を当てて、あまり一般的ではない方法で実装しています。(implements it in a less general fashion:訳は自信なし。)

RaidenNetworkとμRaidenの主な違いは次のとおりです。

  • μRaidenは多対1の一方向状態チャネルプロトコルですが、RaidenNetworkは多対多の双方向ソリューションであり、チャネルネットワークのより複雑な設計を意味します。これにより、Raiden Networkはすでにネットワークに参加している人と新しいチャネルを開くための料金を支払うことなく効率的に送信できます。
  • μRaidenオフチェーン取引は、送信者と受信者の間でのみ交換されるため、何も費用はかかりません。Raiden Networkは、あるユーザから別のユーザへ(送信者と受信者を接続するために使用されるチャネルネットワーク経路に沿って)より複雑なインセンティブベースのトランザクション情報のオフライントランザクション情報を持っています。
GitHub - raiden-network/microraiden

Bitcoinと対比すると、BItcoinでのLightning NetworkがEthereumでのRaiden Networkであり、Bitcoinでのmicro payment channelがEthreumでのμRaidenになります。
また、μRaidenはERC20及びERC223準拠のtokenを高速・少額決済するためのものです。etherのやり取りはできません。

μRaidenのライフサイクル

μRaidenのChannel openからChannel closeまでの流れです。

  1. Deploy RaidenMicroTransferChannels - RaidenMicroTransferChannels contract をデプロイ(必要であれば)
  2. Open Channel - 支払いチャンネルのオープン
  3. off-chain transactions - オフチェーン取引
  4. Topup Channel - デポジット金額の増量 (必要であれば)
  5. receiver withdraw - 中間支払い (必要であれば)
  6. Channel Close - 支払いチャンネルのクローズ
    1. cooperative close - 両者合意の上でのクローズ
    2. uncooperative close - 合意のないクローズ(送信者のみ実行可能)

それぞれの処理の概要

1.Deploy RaidenMicroTransferChannels

μRaidenで支払いチャンネルを開くとき、取引したいTokenが対象となっているRaidenMicroTransferChannels Contractがすでにデプロイしているかチェックします。RaidenMicroTransferChannelsで扱えるTokenは1種類のみなので、取引したいTokenを対象としているRaidenMicroTransferChannelsが存在しない場合は、デプロイする必要があります。

2. Open Channel

Contract.createChannel(receiver_address, deposit)

http://microraiden.readthedocs.io/en/latest/contract/index.html#opening-a-transfer-channel

取引を開始するために決済チャンネルを開きます。μRaidenは一方向状態チャンネルなので、チャンネルをopenした側がsenderです。
チャンネルをopenするときにはreceiverのaddressとデポジットするtoken量を指定します。
チャンネルをopenした直後はdepositしたtokenは全てsenderの物です。

3. off-chain transactions

Smart Contract — microraiden 0.1.0 documentation
オフチェーンで取引情報をやり取りします。
取引情報は次の形式のJSONフォーマットです。

[
      {
        type: 'string',
        name: 'message_id',
        value: 'Sender balance proof signature', // この文字列は固定値
      },
      {
        type: 'address',
        name: 'receiver',
        value: ${channel.receiver.address},
      },
      {
        type: 'uint32',
        name: 'block_created',
        value: ${channel.block},
      },
      {
        type: 'uint192',
        name: 'balance',
        value: ${proof.balance},
      },
      {
        type: 'address',
        name: 'contract',
        value: ${contract.address}
      }
]

このJSONデータをEIP712に基づいて署名したものが取引データになります。
μRaidenは一方向状態チャンネルなので、この情報を支払いが必要になる度にsenderがreceiverへoff-chainで送ります。
この取引情報はwithdrawやcooperativeCloseを呼び出すときに使用します。

4. Topup Channel

Contract.topUp(receiver_address, open_block_number, added_deposit)

http://microraiden.readthedocs.io/en/latest/contract/index.html#topping-up-a-channel

senderはtopupを呼び出して、deposit金額を増額できます。topupにはreceiverのアドレス、チャンネルを開いたblockNumber、増量する額を指定する必要があります。

5. receiver withdraw

Contract.withdraw(_open_block_number, _balance, _balance_msg_sig)

receiverはoff-chainでやり取りした取引情報があれば、withdrawを使っていつでも中間支払いを受け取ることができます。
中間支払いの額はContractが記憶しているため、追加で中間支払いを受け取るためには以前受け取ったよりも大きな額が記入された取引情報が必要になります。(このため、1つの取引情報を使って何度もwithdrawを呼び出しても重複して中間支払いを受け取ることはできません。)
# channel closeのときにも支払い処理があるので、withdrawについては僕が勝手に中間支払いのための機能だと予想してます。ドキュメントが見当たらなかったので本来の意図とはズレてるかもしれません。。。

6. Channel Close

支払いチャンネルをクローズします。支払いチャンネルのクローズ処理は2つの方法が用意されています。

6-1. cooperative close

Contract.cooperativeClose(receiver_address, open_block_number, balance, balance_msg_sig, closing_sig)

http://microraiden.readthedocs.io/en/latest/contract/index.html#closing-a-channel

cooperativeCloseはsender、receiver等、senderが署名した最終的な支払い情報と、receiverが署名したクローズ情報があれば誰でも呼出せます。
通常は、senderが最終的な取引情報を署名してreceiverに送り、receiverは取引情報に問題がなければクローズ情報に署名し、channelをクローズします。
クローズ情報は以下のJSONフォーマットのデータにreceiverがEIP712に基づいて署名をして作成します。

[
      {
        type: 'string',
        name: 'message_id',
        value: 'Receiver closing signature', // 固定値
      },
      {
        type: 'address',
        name: 'sender',
        value: ${sender.address}
      },
      {
        type: 'uint32',
        name: 'block_created',
        value: ${channel.block}
      },
      {
        type: 'uint192',
        name: 'balance',
        value: ${channel.proof.balance}
      },
      {
        type: 'address',
        name: 'contract',
        value: ${contract.address}
      }
]
6-2. uncooperative close

Contract.uncooperativeClose(receiver_address, open_block_number, balance)
Contract.settle(receiver_address, open_block_number)

http://microraiden.readthedocs.io/en/latest/contract/index.html#closing-a-channel

receiverからの応答がない場合等のために、sender側から一方的にchannelを閉じることもできます。uncooperativeCloseを呼び出すと、あらかじめ設定されたblock数(デフォルトは500。RaidenMicroTransferChannels deploy時に指定可能)が経過したのちに、channelがクローズされます。そのあとにsettleを呼び出すことで残ったデポジットtokenをsenderが受け取ることができます。
ChannelCloseリクエストが送られて実際にチャンネルが閉じられるまでの間に、cooperativeCloseやwithdrawを呼び出すことができます。

receiverはsenderの裏切りで、意図せずにチャンネルが閉じられようとしている場合に、それまでにoff-chainで送られてきた取引情報を元に必要な分のtokenを引き出すことができます。

μRaidenでの署名検証の利用方法

μRaidenでは以前の記事で紹介した署名検証の方法を用いて、データの改ざんを防いでいます。
μRaidenではContractの内部で、署名検証に使うhashデータを生成しているため、例えば、実際の署名と違う支払い金額を渡しwithdrawを呼び出しても検証に失敗し、中間支払いを受け取ることはできません。

まとめ

まだ実際に動かしてない(pythonに疎いので苦戦中)のですが、基本的にはRaidenMicroTransferChannelsに書いてあることが全てなので大きく外していることはないとは思います。
また、μRaidenでは一方向の支払いチャンネルのみを定義していますが、少し拡張すれば双方向の支払いチャンネル(not Raiden Network)も実装できるんじゃないかなぁ?って感じました。
EIP712についてはまだgethやparityなど主要なnode実装では取り入れられていないので、μRaidenでは自前で署名処理を実装しています。
off-chain技術は高速決済だけでなく、いろいろなシーンで利用可能なので早くEIP712を実装したnodeが増えていって欲しいなぁ。

追記(2018/01/25)

μRaidenのドキュメントページができてました。
Welcome to microraiden’s documentation! — microraiden 0.1.0 documentation
それに伴って、githubからいくつか消えてるドキュメントがあったのでリンクを貼り直しておきました。