Rusty RussellのBitcoinにおけるCovenantsの記事を見てて、Covenants via Signaturesという手法について言及されてたので、このCovenants手法を調べてみた。APOを使ってCTV Covenantsをエミュレートするというアプローチ。
SIGHASH_ANYPREVOUT
BIP-118として定義されてるのが新しいSIGHASHフラグであるSIGHASH_ANYPREVOUT(APO)。BIPにはなってるけど、導入にはソフトフォークが必要で、まだデプロイはされてない。
SIGHASHフラグは、署名時にその署名がトランザクションのどのパーツにコミットするか指定するのに使われるフラグ(SIGHASH=署名対象のトランザクションデータのハッシュ)。よく使われるSIGHASHフラグは、SIGHASH_ALLで、トランザクションの全データ(インプットの署名以外)に対してコミットする(つまり署名後Txを変更すると署名が無効になるタイプ)。
SIGHASH_ANYPREVOUTを指定すると、SIGHASHがそのインプットが参照するUTXOのOutPoint(TXID+アウトプットインデックス)にコミットしなくなるので、UTXOのリバインドが可能になる。トランザクションのインプットの参照先を別のUTXOに切り替えてもトランザクションとしては有効になる。もちろんどんなUTXOでもリバインドできるのではなく、基本的にUTXOのscriptPubkeyと量が一致したものに限る。
これが利用可能になるとEltooスタイル(LN-Symmetry)のライトニングチャネルが可能になる。
APOでCTVをエミュレート
署名検証opcodeであるOP_CHECKSIG
は(OP_CHECKSIGVERIFY
も同様)が行うのは、
- スタック上から署名、公開鍵をPOPし、
- トランザクションをハッシュし、
- 2のデータと1の公開鍵に対して1の署名が正しいか検証する
という操作。そのため、scriptPubkeyを以下のように構成した場合、OP_CHECKTEMPLATEVERIFY(CTV)の機能をエミュレートできる。
<Txテンプレートに対する署名> <トランザクションテンプレートに対する公開鍵> OP_CHECKSIG
↑はつまり、予め期待するトランザクションテンプレートを作成し、それに対して有効な署名と公開鍵を指定することで、あるトランザクションテンプレートでのみ使用可能なUTXOを作成している。
ここで、事前に署名を作成する必要があるため、TXIDの循環参照問題が発生する(このUTXOを作るためには、このUTXOのTXIDが必要となる問題)。これを回避するのにAPOが必要になる。
CTVよりちょっとコスト高
CTVは、トランザクションのハッシュが予め指定された値と一致するか検証するopcodeで、scriptPubkeyではそのハッシュ値32バイトを指定する形になるが、APOでエミュレートすると64バイトの署名と32バイトの公開鍵をscriptPubkeyで指定することになり、64バイト分コスト高になる。
APOに必要な修正
APOでCTVをエミュレートするためには、BIP-118で定義されているAPOの仕様の内、ANYONECANPAYの振る舞いをオプションにする必要があり、そのPRが↓っぽい。