
ビットコインが「勝手な送金」を許さなくなる?注目技術「OP_CAT」と「OP_CSFS」の恐るべき正体
ビットコインの送金先や取引条件を、あらかじめ決めた“型”に縛りつける「コベナンツ」。その実現に向けて注目されているのが、OP_CHECKSIGFROMSTACKとOP_CATだ。単独では不完全な2つの命令が手を組んだとき、ビットコイン・スクリプトは取引の中身を自ら検査する能力を手に入れる。

ビットコインは通常、秘密鍵を持つ人であれば、受け取ったコインを好きな相手へ送ることができる。
しかし「このコインは指定された相手にしか送れない」「一定の条件を満たした取引でなければ動かせない」といったルールを、あらかじめ設定できるようにする技術がある。それが「コベナンツ」だ。
コベナンツが実現すれば、ビットコインの盗難対策や資産管理、複雑な契約の自動化など、これまで難しかった仕組みを構築できる可能性がある。
その実現方法として注目されているのが、「OP_CHECKSIGFROMSTACK(OP_CSFS)」と「OP_CAT」という2つのオペコードだ。
ただし、この2つはそれぞれ単独で完全なコベナンツを実現するものではない。ほかのオペコードやスクリプト要素と組み合わせることで、コベナンツを組み立てるための「部品」として機能する。
OP_CHECKSIGFROMSTACKとOP_CAT――2つの命令が手を組むと何が起きるのか
「OP_CHECKSIGFROMSTACK」、略して「OP_CSFS」は、スタック上に置かれた任意のメッセージについて、署名が正しいかどうかをビットコイン・スクリプトで検証できるようにするオペコード案だ。
現在使われているOP_CHECKSIGは、有効なSIGHASHモードに従い、実際に支出されるトランザクションに対する署名を検証する。
これに対しOP_CSFSは、トランザクションそのものに限らず、別のデータについても署名を確認できる。
ここに大きな違いがある。
たとえば、現実世界で起きた出来事を外部の第三者がオフチェーン上のメッセージとして署名する「オラクル型スクリプト」への応用が考えられる。
信頼されたオラクルが、選挙結果や価格、試合結果などを表すメッセージにシュノア署名を付ける。OP_CSFSを使ったスクリプトは、その署名が正しい場合に限って支払いを実行できるというわけだ。

だが、OP_CSFSだけではコベナンツにならない。
外部データが本物であることは確認できても、そのデータと、実際に支出されるトランザクションの構造を結びつけることができないからだ。
そこで登場するのが「OP_CAT」である。
OP_CATは、スクリプトのスタック上にある2つの値を連結し、別々のデータではなく、ひとつのバイト列として扱えるようにするオペコード案だ。
OP_CSFSと組み合わせれば、トランザクションの特定フィールドをつなぎ合わせ、決められた形式のメッセージを作ることができる。
そのうえで、提示された署名が、そのメッセージに対して作成されたものかどうかを検証する。
要するに、OP_CATがトランザクション情報を「ひとつの検査対象」に組み立て、OP_CSFSがその内容に付けられた署名を確認するのである。
送金者に「取引の中身を全部出せ」と迫る
OP_CSFSとOP_CATを組み合わせると、トランザクションの内部情報をスクリプト自身が検査する「イントロスペクション」が可能になる。
その仕組みはこうだ。
まず、支出を行う人物に対し、トランザクションの詳細をウィットネス・スタック上へ提出させる。
次に、同じ署名についてOP_CSFSとOP_CHECKSIGの両方が成功すれば、ウィットネス・スタック上に提出された情報が、実際のトランザクション情報と一致していることを証明できる。
提出されたデータを、さらにスクリプト内で分析することも可能になる。
そして、そのトランザクションが事前に定められたテンプレートと一致しているかを確認すれば、OP_CTVに近いコベナンツを強制できる。
つまり、「このビットコインは、あらかじめ決められた形式の取引でしか動かしてはならない」というルールを、スクリプトで押しつけられるのだ。


OP_CATと「シュノア署名の裏技」
実はOP_CATを使えば、OP_CSFSがなくても、タップルート環境でコベナンツに似た仕組みを実現できる可能性がある。
利用するのは、シュノア署名と、BIP 341で規定されたタップルートのSIGHASHルールだ。BIP 341は、シュノア署名を採用するSegWit v1の支出ルールを定めている。
この方法では、本来は秘密鍵の所有者を認証するために使われるOP_CHECKSIGを、トランザクションの中身を調べる道具として転用する。
シュノア署名は、一般に〈R、s〉という2つの値で構成される。
通常は、まず秘密のノンス「k」を選び、そこから楕円曲線上の点「R=kG」を導き出す。
そして、メッセージのハッシュと秘密鍵を使い、署名値「s」を計算する。
検証者は、公開鍵Pと署名対象のメッセージに対し、〈R、s〉が正しい署名になっているかを確認する。
ノンスkにはランダム性があるため、秘密鍵を知らない人間がsを予測したり、同じ署名を再現したりすることはできない。
ところが、イントロスペクションに使われる“裏技”では、このランダム性を消してしまう。
署名時にRをランダムに選ぶのではなく、あらかじめ決められたRと、固定された公開鍵Pをスクリプトに埋め込むのである。
シュノア署名の検証式は決定論的に処理される。
そのため、RとPを特殊な値に固定すれば、署名スカラーsが、特定のトランザクション情報のハッシュと一致しなければならないように仕向けられる。

OP_CHECKSIGをだますことはできない
支出者は、Rとsをウィットネス・スタック上に提出する。
OP_CATは、それらをOP_CHECKSIGが受け取れる〈R、s〉形式の署名データへ連結する。
スクリプトは、その署名を、あらかじめ埋め込まれた公開鍵Pに対して検証する。
ここでRとPの両方を基準点Gに固定しておく。
するとOP_CHECKSIGが署名を受理するためには、sが、プロトコルによって計算された実際のトランザクションデータのSHA-256ハッシュと一致しなければならなくなる。
支出者が、でたらめなsを作ってOP_CHECKSIGを突破することはできない。
sが本物のトランザクション情報を反映していない限り、検証には失敗するからだ。
ただし、支出者はSHA-256ハッシュの末尾が特定の1バイトになるまで、トランザクションのデータを少しずつ変えて試行する必要がある。
平均すると約256回の試行が必要になるが、追加コストは無視できるほど小さいとされる。
こうしてOP_CHECKSIGは、もはや「秘密鍵を持っている人物を確認する命令」ではなくなる。
代わりに、「そのトランザクションが決められたテンプレートと一致しているか」を強制する命令として働くのだ。
表現力は、おおむねOP_CTVに匹敵する。
使えるのはタップルートだけ
もっとも、この方法はどこでも使えるわけではない。
シュノア署名とタップルートのSIGHASHアルゴリズムに依存しているため、対象となるのはSegWit v1のアウトプットだけだ。
BIP 143のダイジェスト方式とECDSA署名を使用するSegWit v0のアウトプットには適用できない。BIP 143は、バージョン0のウィットネス・プログラム向けに、トランザクション署名検証用のダイジェスト方式を定義している。

