以前、Lightning Networkを構築する際のPayment Channelの仕組みについて書いた↓
techmedia-think.hatenablog.com
プリイメージを使ったコミットメントトランザクションの取消
このPayment Chanelを使ったオフチェーンの決済には、悪意あるユーザによって最新の残高ではなく自分の残高が多い古いコミットメントトランザクションをブロードキャストする不正が行われた際に、チャネルにデポジットされている全資金を取り戻す仕組みが存在する。
この仕組みはHTLCsで使われている仕組みと似ていて、新しいコミットメントトランザクションに両者が合意した際、古いコミットメントトランザクションに含まれているハッシュの元となったプリイメージを交換する。そのプリイメージがあれば、相手によって古いコミットメントトランザクションがブロードキャストされても、自分の署名とそのプリイメージで全資金を自分のものにできるというもの。
具体的には、アリスとボブがいてアリスは以下のようなコミットメントトランザクション作成してボブに送る(事前にボブからボブが生成したrevokehashを受け取っておく)。
# 入力 アリスとボブのマルチシグにデポジットされたコイン # 出力1(アリスの残高をアリスに送る出力) OP_DUP OP_HASH160 <アリスの公開鍵のハッシュ> OP_EQUALVERIFY OP_CHECKSIG # 出力2(ボブの残高で、24時間経てばボブの公開鍵でコインが入手可能、もしくはrevokehashのプリイメージが分かればアリスの公開鍵でコインが入手可能) OP_HASH160 <ボブが生成したrevokehash> OP_EQUAL OP_IF <アリスの公開鍵> OP_ELSE "24h" OP_CSV OP_DROP <ボブの公開鍵> OP_ENDIF OP_CHECKSIG
新しいコミットメントトランザクションを作成したら、アリスとボブがお互いに古くなったコミットメントトランザクションに使ったrevokehashのプリイメージを相手に公開する。もしボブが裏切って↑の古いコミットメントトランザクションに署名してブロードキャストしてもアリスはボブが明かしたプリイメージを使って、出力1と出力2のコイン全てを入手することができる。
プリイメージを使わずRevocation Keyを利用
ただ、最近のLNの実装ではこのプリイメージを使った仕組みは使われておらず、代わりにRevocation Keyが使われている。
OP_IF <revocation-pubkey> OP_ELSE "24h" OP_CSV OP_DROP <ボブの公開鍵> OP_ENDIF OP_CHECKSIG
見ての通り、ハッシュとそのプリイメージを使う形から、ある公開鍵<revocation-pubkey>による署名があればコインを取り戻せるようになっている。
この<revocation-pubkey>を導出する方法だが、まずLNのチャネルをオープンする際にそれぞれ自分のベースポイントを相手に伝える。ここでいうベースポイントは楕円曲線上のポイントなので言ってしまえば公開鍵。ただこのポイント自体はチャネルのセットアップに使うだけで決済に使う公開鍵ではない。
このベースポイントを使って<revocation-pubkey>を導出する。
コミットメントトランザクションを新しく生成する際、ボブがプリイメージを新しく生成しそのハッシュをアリスに伝える代わりに、ボブは新しく生成したハッシュに楕円曲線のGを乗算し新しいポイントを作成しそのポイントをアリスに伝える。アリスはそのポイントをアリスのベースポイントに加算し<revocation-pubkey>を生成する。ちなみに(正確には元のハッシュが異なるが)アリスがボブから受け取ったポイントをボブのベースポイントに加算したのがタイムロックされたブランチのボブの公開鍵になる。
新しいコミットメントトランザクションを作成する際は、このコミットメントトランザクションの<revocation-pubkey>を作るのに使ったポイントの元のハッシュを交換する。(Payment Channelは鏡像となるトランザクションをお互いに作るのでアリスはその逆を行う)
※ LNの仕様は現在標準化されていないので、この <revocation-pubkey>の計算方法はLNの実装によって異なる。lndとかはもう少し算出方法が複雑。
プリイメージを使うパターンでなくRevocation Keyを使うメリットとしては、redeem scriptのデータ量ががOP_HASH160 <revokehash> OP_EQUAL
の分だけ少なくてすむ。