Develop with pleasure!

福岡でCloudとかBlockchainとか。

Grinでコントラクトを作る際の基本要素

MimblewimbleとGrinのトランザクション構成が把握できたので↓

techmedia-think.hatenablog.com

今回は↓を参考にGrinでどんなコントラクトを作る際に使える基本要素についてまとめる。

https://github.com/mimblewimble/grin/blob/master/doc/contracts.md

Mimblewimbleでは基本的にコインはPedersen Commitmentで管理されるため、Bitcoinのようなスクリプトは存在しないが、トランザクションにタイムロックの仕組みは用意されている。それに↑の記事で説明したように、署名は送信者と受信者それぞれのSchnorr署名を集約して構築することから、Schnorrもコントラクトを構成する上で利用可能だ。

タイムロック

トランザクションをある一定の時間(ブロック高)までブロックに入れられないようロックする機能で、Bitcoinではさまざまなコントラクトを実現する上で欠かせない機能の1つである。

Grinでは以下の2種類のロックをサポートしている。

絶対時間によるタイムロック

クロスチェーンのアトミックスワップや、Lightning Networkのマルチホップ決済で使われるHTLCs(Hashed Time-Locked Contract)で必要となる要素の1つが絶対時間によるタイムロック。

Grinではトランザクショントランザクションカーネルに、手数料と一緒にlock_heightというフィールドがセットできるようになっており、このフィールドには任意のブロック高を指定することができる。そして、指定されたlock_heightまでトランザクションをブロックに入れることはできないようになっている。

通常Grinのトランザクションに署名をする際、署名対象のメッセージはM = fee | lock_heightと手数料とこのlock_heightで構成される。Grinでは送信者と受信者が協力して署名を構成するため、このlock_heightは当然両者が合意した値になり、署名のメッセージに含まれているので第三者が変更することもできない。

Bitcoinにも同様のnLockTimeというフィールドがトランザクションのプロパティにあるが基本的にはそれと同じ機能になる。

相対時間によるタイムロック

Lightning Networkで不正を働いたユーザーに対するペナルティを設ける際などに使われているのが、あるトランザクションがブロックに入ってからタイマーがスタートする相対時間によるタイムロック。

Grinではトランザクションカーネルlock_heightを相対的に解釈するよう拡張する。Tx1Tx2があるとして、Tx1がブロックに格納されてからlock_heightで指定したブロック経過した後、Tx2がブロックに入れられるよう制御する。

このような相対的なタイムロックを持つトランザクションTx2を作成する際は、絶対的なタイムロックと以下が異なる。

  • lock_timeは絶対的なブロック高ではなく相対的なブロック高を指定する。
  • トランザクションに署名する際のメッセージは、手数料とlock_heightに加えて、タイムロックの起点となるトランザクションカーネルコミットメントから構成される。
    M = fee | lock_height | Tx1のカーネルコミットメント

マルチシグ

コインを使用するのにアリスとボブの両者の署名が必要なマルチシグをGrinでどう作るか。基本的にGrinはスクリプト言語が無いので、Scriptlessで実現する必要がある。そもそもGrinではトランザクションに署名する際に、送信者と受信者がそれぞれ作成した署名を集約するSchnorrの集約署名を利用してるので、マルチシグも基本的にSchnorrの集約署名で実現する。

通常のSchnorr署名であれば、アリスとボブがマルチシグにコインをロックする場合は、アリスの公開鍵をPA = xaG、ボブの公開鍵をPB = xbGとするとP = PA + PBとなる公開鍵にコインをロックし、そのコインを使用する際はお互い署名用のランダムnonce RA = kaG、RB = kbGを選択し、R = RA + RB、sa = ka + H(P, R, M)xa, sb = kb + H(P, R, M)xbを計算し、集約した署名(R, sa + sb = ka + kb + H(P, R, m)(xa + xb))を作れば良い。

Grinの場合も基本的に仕組みは同じで、マルチシグは両者がそれぞれ知る秘密の情報が無いと署名を作成することができないコミットメント宛にコインを送る。つまり1つのコミットメントに対してそのブランディングファクターはアリスとボブがそれぞれ知るブランディングファクターを足し合わせたものになる。

具体的には以下の手順でコインをロックする。

  • ボブがブラインディングファクターrbを選択し、rb*Gをアリスに送る。
  • アリスも同様にブラインディングファクターraを選択し、コミットメントC = ra*G + rb*G + v*Hを計算する。このコミットメントをボブに送る。
  • ボブはrbCを使ってvに対する範囲証明を作成し、それをアリスに送る。
  • アリスは自身の範囲証明を生成し、ボブの範囲証明に集約する。最終的なマルチシグのアウトプットを {O_{AB}}とする。

あとはトランザクションを作成し、そのアウトプットに {O_{AB}}を含めれば良い。また {O_{AB}}のコミットメントを使用する時は、インプットのブランディングファクターの集約署名を作成する際に、アリスとボブが協力してそれぞれのブランディングファクターを加味したSchnorr署名を作成し集約すればいい。

マルチパーティ+タイムロック付きトランザクション

ペイメントチャネルを構成する際によく使われるのが、マルチシグ宛にコインをロックしてペイメントチャネルをオープンするけど、オープンする前にタイムロック付きの払い戻しトランザクションを作成しておくというパターン。

Grinでも上述したマルチシグとトランザクションカーネルのタイムロック機能を利用すると、以下の手順で同様の事ができる。

  1. 上記のようにアリスはボブとの2-of-2のマルチシグトランザクションを作成し、それをボブに共有する。ただしこの段階ではアリスはトランザクションカーネルにセットする署名は作っていない。
  2. ボブは↑のタイムロックを使って、24時間(1440ブロック)経過したらアリスにマルチシグのコインを返金する払い戻しトランザクションを作成し、ボブの署名を付与しアリスに送る。
  3. アリスは払い戻しトランザクションのボブの署名の有効性を検証し、問題なければボブと一緒に2-of-2のマルチシグトランザクションを完成させ(トランザクションカーネルに署名をセットし)ブロードキャストする。

これで、アリスとボブは2-of-2のマルチシグにロックされた資金を元に単方向のオフチェーン決済が可能になる。もしボブから応答がなくなったとしても、タイムロック期間が経過したらアリスは自分の資金を取り戻すことができる(ただ上記だけではまだペイメントチャネルを双方向にしたり、チャネルの有効期間を無期限にするといったことはできない)。また、他のチェーンのコインとgrinを交換する際のAtomic Swapなんかにも利用できる。

と、マルチシグの仕組みとタイムロックの機能についてははっきりしたので、次は上記の基本要素を使って複雑なコントラクトをどう実装するか見ていきたい。キーはタイムロック部分をBitcoinでいうOP_CLTVOP_CSVみたいにどうコントロールするのかという部分。