OP_CAT😺とCovenants📜の備忘録
先月末に物議を醸しだしたOP_CTVを調べていくなかで、他のOPコードや暗号トリックを使ってCovenantsを実現する方法が面白かったので、以下の記事をベースに纏めてみました(以下の記事を理解した前提で記事を書いてます)。
https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-i.html
前提
Covenantsの仕組みを理解するためには、ビットコインのトランザクションのデータ構造とスクリプトシステムを理解する必要があります。
1. トランザクションのデータ構造
トランザクションのデータ構造は以下のようになっています。inputsフィールドはさらにprev txidやscriptSigに、outpusフィールドはvalueやscriptPubkeyに細分化されています。
2. スクリプトシステム
スクリプトシステムは、OPコード(命令語・機械語)を1つ1つ実行し、データをスタック領域へプッシュしたりする実行環境のことです。以下の図例は標準的なビットコインのスクリプトを実行しているもので、scriptPubkeyとscriptSigを結合し、OPコードを実行、データをスタックへプッシュしていく流れを表しています。
ビットコインを送金する場合、上記のデータ構造に沿ってデータを組み立て、それに対して署名をしscriptSigに署名をセットします。このデータをブロードキャストし、受け取ったノードが、この署名を検証する時、prev txidとprev txout-indexを参照して消費しようとしている前のトランザクションのscriptPubkeyを取得します。イメージとしては以下の図のようになります(参照元)。そして上記のスクリプトシステムに従ってスクリプトを実行していきます。
Covenantsの実現方法
さて今回見ていくCovenantsを実現するための方法は、以下の3つです。
1. CAT
+ CHECKSIGFROMSTACK
+ CHECKSIG
→TXにアクセス、Covenantsは可能
2. CHECKSIGFROMSTACK
+ CHECKSIG
→TXハッシュにアクセス、Covenantsは不可能
3. CAT
+ BIP340 + CHECKSIG
→TXにアクセス、Covenantsは可能
冒頭で触れたOP_CTVはCovenantsを実現するためのOPコードですが、以下で紹介するOPコード CAT
と CHECKSIGFROMSTACK
はより低級な命令語で汎用性のあるものです。 CAT
は二つのアイテムを結合する命令語、 CHECKSIGFROMSTACK
は任意のメッセージの署名検証をする命令語となります。
1. CAT + CHECKSIGFROMSTACK + CHECKSIG
まず、1について。このOPコードの CAT
と CHECKSIGFROMSTACK
はビットコインには含まれていないもので、サイドチェーンのElementsに含まれているものです。このOPコードを使うことで、トランザクションデータへのアクセスが可能となるため、Covenantsを構成できます。具体的には以下のscriptPubkeyとscriptSigを実行します。
scriptPubkey: OVER SHA256 <pubKey> 2 PICK 1 CAT OVER CHECKSIGVERIFY CHECKSIGFROMSTACKVERIFY
scriptSig: <sigTransactionData> <signature>
その実行結果としてスタックにTXデータが残ります。実際の実行過程と結果はこちらの記事を参照してみてください。
スタックにTXデータが残ると何が良いのかというと、scriptPubkeyに様々な制約を課すことができます。例えば、上記のscriptPubkeyに送金先アドレスと送金金額、そのアドレスと金額チェックを入れておくことで送金先を制御することができます。
2. CHECKSIGFROMSTACK + CHECKSIG
次に、2について。ここでも CHECKSIGFROMSTACK
はビットコインには含まれていないですが、もし含まれていると仮定しスクリプトを実行するとスタックにTXハッシュが残り、TXハッシュへのアクセスが可能となります。具体的には以下のscriptPubkeyとscriptSigを実行します。
scriptPubkey: DUP <fixed signature> SWAP CHECKSIGVERIFY
scriptSig: <P>
その実行結果としてスタックにTXハッシュが残ります。しかし、TXハッシュに対して制約を課そうとすると、scriptPubkeyに自身のTXハッシュを含める必要があります。これは自己参照となるため、このようなscriptPubkeyの構築は不可能となります。ここが少しピンと来ない箇所かもしれません。もう少し具体的に見てみましょう。
TXハッシュ(以下TXID)は、上記でみたデータ構造のデータを纏めてハッシュしたものですが、以下の図ではTxNewのTXID:0f898c54に該当します。データ構造を見るとprev txidがあるのが分かります。prev txidはTxPrevのデータを纏めてハッシュしたもので、TXID:30f3701fに該当します。このTXID:0f898c54をscriptPubkeyの一部にセットすることでCovenantsとして制約を課す訳ですが、このscriptPubkeyはTxPrevのものだということに注意してください。TxPrevのscriptPubkeyの一部にセットするTXID:0f898c54は、自身のTXID:30f3701fをハッシュしたものになり、これが循環参照をしていることになります。
3. CAT + BIP340 + CHECKSIG
最後に、3について。これも現状のビットコインに含まれていない CAT
を使用しますが、2との違いは CHECKSIGFROMSTACK
を用いず、BIP340のSchnorr署名をうまく活用して、 CHECKSIGFROMSTACK
をエミュレートしようというもの。このトリックを使うことで、スタックにTXデータが残り、TXデータへのアクセスが可能となります。よって、 CAT
とBIP340をつかうことでCovenantsを実現することができます。今回参考にしているAndrew Poelstra氏の記事ではTXハッシュへのアクセスとなっていますが、TXデータへアクセスする場合のスクリプトは以下のようになると思います。
scriptPubkey: DUP SHA256 <G> DUP ROT CAT CHECKSIG
scriptSig: <TxData>
ポイントは<TxData>をSHA256すると署名sと同値になることです。また、PとRをGと置き換えることで、xとkは1と等しくなり、よって、s = 1 + eとなります(e = H(P|R|m) である)。詳細はこちらか日本語での解説記事を参照してみてください。
まとめ
CAT
+ CHECKSIGFROMSTACK
を使うことでTXデータにアクセスでき、Covenantsを構成することができます。一方、CHECKSIGFROMSTACK
のみを使うことでTXハッシュへのアクセスは可能ですが、TXハッシュを使ったCovenantsを構成しようとすると循環参照問題が生じて、Covenantsを構成することができないことが分かりました。また、CAT
とBIP340のシュノア署名トリックを使うとCovenantsを構成することが可能です。
OP_CTVでは、prev txidを除くその他のデータをハッシュし検証することで、循環参照問題を回避しCovenantsを可能にしています。また、今回上記で紹介したもの以外にも、OP_TXHASHやOP_TXなどを使ったCovenantsについてBitcoin-devメーリングリストで提案・議論されているので、これらを調べるのも面白いと思います。
参考
https://en.bitcoin.it/wiki/Script
https://en.bitcoin.it/wiki/Transaction
https://en.bitcoin.it/wiki/OP_CHECKSIG
https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-i.html
https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-ii.html
https://techmedia-think.hatenablog.com/entry/2016/12/02/000113
https://techmedia-think.hatenablog.com/entry/2021/07/20/213922
https://btctranscripts.com/tabconf/2021/2021-11-05-jeremy-rubin-andrew-poelstra-covenants