先日BIP-442としてマージされたOP_PAIRCOMMITという新しいopcodeの提案について↓
https://github.com/bitcoin/bips/blob/master/bip-0442.md
Bitcoinでは、ハッシュロックやタイムロックなど単一の項目にコミットする手法はあるものの、複数の項目にまとめてコミットするような機能はない。そこでOP_PAIRCOMMITは、スタック上の2要素を安全にコミットする専用のオペコードとして提案された。
OP_PAIRCOMMITの仕様
OP_PAIRCOMMIT opcodeは、TapscriptのOP_SUCCESS205(0xcd)opcodeを置き換える形で導入される。
この新しいopcodeのスタック操作は以下のとおり:
- スタック内の要素が2つ未満の場合、スクリプトの実行は失敗する。
- スタック内の要素を
とした場合(右が最上位)
- タグ付きハッシュ関数で
を計算し、
- スタックから
をポップし、
- pcをスタックにプッシュする
簡単に言うと、スタックの上位2つの要素を連結して(その際各要素の先頭に長さのプレフィックスを付与)、そのハッシュを計算し、計算結果のハッシュ値をスタックにプッシュするというもの。
OP_CATとの違い
ぱっとみOP_CATと同様の挙動をするけど、違いはデータの長さをプレフィックスとして付与している点。
OP_CATの場合、連結するデータの境目が識別できない。たとえば、
<0x01> <0x0203> <0x0102> <0x03>
という2つの各データは異なるものの、OP_CATを実行すると同じ<0x010203>というデータになる。スクリプトが意図した分割と異なる分割で同じハッシュを作ることができる。バイトシフト攻撃と呼ばれるこの攻撃をOP_PAIRCOMMITの場合は、上記のようにデータ長をプレフィックスとすることで構造的に防止する。
また、OP_CATの場合、スタック上でトランザクションデータを再構成できるため、スクリプトが自分自身のscriptPubKeyを検証・複製することが可能になり、再帰的コベナントが構築できてしまう。OP_PAIRCOMMITは結果が必ず32バイトのハッシュになるため、元データへの復元が不可能で、この問題を構造的に回避している。逆に言うと、OP_PAIRCOMMITではスタック上でトランザクションデータを構築するようなことはできない。
マークルツリーコミットメント
OP_PAIRCOMMITを使うと、スクリプト内で事前に決めた構造のデータセットに対するコミットメントを作ることができる。
たとえば、a、b、c、dという4つの要素があるツリーに対するコミットメントは、Root = PC(a, PC(b, PC(c, d)))
PC
/ \
a PC
/ \
b PC
/ \
c d
と計算でき、このようなツリーのメンバーシップ証明などをスクリプトで行うことができる。(ただ、仕様的にはTaptreeとは互換性はない)
LNHANCEでの利用
OP_PAIRCOMMITはもともと単体で提案された訳ではなく、ライトニングネットワーク向けのソフトフォーク提案をまとめた
LNHANCE提案(LN + HANCE(enhance))の一部。LNHANCEは、以下の4つのopcodeで構成される。
| opcode | BIP | 役割 |
|---|---|---|
| CHECKTEMPLATEVERIFY | BIP-119 | トランザクション構造へのコミットメント |
| CHECKSIGFROMSTACK | BIP-348(ブログ) | スタック上の任意のデータへの署名検証 |
| INTERNALKEY | BIP-349(ブログ) | Taprootの内部鍵をスタックに積む |
| PAIRCOMMIT | BIP-442(本記事) | 2つの要素のペアコミットメント |
この主な目的は、LN Symmetry(旧称eltoo)を導入すること。LN Symmetryでは、古い状態のTxがブロードキャストされても、その状態を後続の状態のTxで上書きすることができる。もともとこれは、トランザクションインプットの再バインドを可能にするanyprevout(APO)を利用して、事前署名済みのTxのインプットの参照先を入れ替える(再バインド可能なため)ことで実現する。
その部分をLNHANCEでは
<ctv_hash> OP_CHECKTEMPLATEVERIFY <公開鍵> OP_CHECKSIGFROMSTACK
で実現しようというアプローチ。OP_PAIRCOMMITは内部で、
- ある状態nのトランザクションがどういうトランザクション(
state-n-hash)で、 - nが最終状態になった場合の決済情報(誰にいくら払うか)(
recovery-data)
という2つのデータを束ねることで、「state-n-hashに合意するならrecovery-dataも必ずウィットネスに含めなければならない」という強制が生まれる。片方だけ提出するとPCの計算結果が変わりCSFSの検証が失敗するため。これによりコンテスト時にsettlement-txを再構築するために必要なデータ可用性が保証される。
現時点ではAPOもLNHANCEどちらもドラフトなので、どちらが採用されるかまた全く別の提案になるかはまだ不明。