OP_GROUP
に加えてBitcoin Cashの中期開発計画に含まれているのが、Bitcoinのトランザクションの署名検証の際に使われるECDSAと同じアルゴリズムを使って、任意のデータの署名を検証するOP_DATASIGVERIFY
という新しいopcode。
https://github.com/BitcoinUnlimited/BUIP/blob/master/078.mediawiki
通常BitcoinのスクリプトではOP_CHECKSIG
を使って署名の検証をするけど、この時検証に使われるデータはあくまでトランザクションのデータ。この署名検証においてトランザクションに限らず任意のデータに対して署名検証できるようにするスクリプトがOP_DATASIGVERIFY
というわけだ。
任意のデータについて署名検証できると何が嬉しいの?という話だが、外部の情報をトランザクションに持ち込むオラクルを想定しているようだ。
相変わらずBUIP単体ではプロトコルの内容が分からないので、Andrew Stoneのブログ記事を読もう↓
Bitcoinというのはプログラマブルなお金なので、シンプルなプログラマブルマネーということで考えると以下のようなifを使った条件が考えられる。
if (condition) then pay A else pay B
この時重要になるのが、条件を評価するところ、特に外部データをインプットして条件評価をする部分だ。
基本的にBitcoinもEthereumもスクリプトはサンドボックス環境で動作するようになっているため、スクリプトを評価する際にスクリプトが外部API叩いて値を取得するといったことはできない。まぁAPIを叩いたところでそれが正しいデータという保証は無いし、中間者攻撃のようなリスクも考えられる。
そのため外部データをブロックチェーンに取り込む場合、オラクルと呼ばれる信頼できるエンティティが登場する。オラクルは現実世界のデータをBitcoinのスクリプトで利用可能な形式に変換して提供する存在だ。もちろんオラクルが嘘を付けば破綻するのでオラクルへの信頼が必要になる。極力このオラクルへの信頼を取り除いていく仕組みやインセンティブ設計がいろいろと研究されており、Discreet Log Contractsなんかもそういった点が設計されている↓
techmedia-think.hatenablog.com
ちなみにこのBUIP自体ではオラクルへの信頼の問題を解消する方法については特に触れてはいない。
Andrew Stoneのブログでは株価などのデータを提供するオラクルサービスを仮定し、単純なif文を使ってバイナリオプションがサンプルのユースケースとして挙げて、OP_DATASIGVERIFY
の使い方を説明している。
オラクルのデータ提供方法
OP_RETURNの利用
データを提供するオラクルは、OP_RETURN
を使ってデータをブロックチェーンに記録できるが、他のスクリプトがそのデータを参照する方法は無い。そこで新しいopcodedata = OP_GET_DATA(address)
を追加する。このopcodeはaddress
によって署名されたブロックチェーンの履歴を調べ、そのOP_RETURN
のデータをスタックにプッシュする。そのアドレスで署名されているトランザクションが無い場合、opcodeは失敗して終了する。そのUTXOは現在使用不可能となる。まだオラクルが嘘をつくという問題はあるが、オラクルだけがそのアドレスのお金を使える(そのアドレスで署名できる)ため、それが提供元(オラクルよる)データであるという真正性は確認できる。
この方法の問題点は、オラクルがたくさんのトランザクションで情報をブロックチェーンに記録しても、それを使用するユーザーがおらず未使用に終わる可能性がある点だ。
OP_DATASIGVERIFYの利用
より現実的なオプションは、オラクルがバイナリオプションを使用するスクリプトの一部として使用できる署名付きにステートメントを個別に公開する方法だ。しかし、これはスクリプトがそのステートメントの真正性を検証しなければならないことを意味する。Bitcoinは簡単に署名を検証できるが、CHECKSIG
opcodeはトランザクションデータへの署名のみを検証し、任意のデータの署名は検証できない。そこで
data = OP_DATASIGVERIFY(signature, data, pubkeyhash)
というopcodeを追加する必要がある。
このopcodeはトランザクションではなくスタック上のデータに対してOP_CHECKSIGVERIFY
を行う。具体的には↓
- スタックからトップ3アイテム(公開鍵ハッシュ、署名、任意のデータ)をポップする。
- 署名が任意のデータに対する有効な署名か検証する。
- 署名の公開鍵のハッシュが公開鍵ハッシュと一致するか検証する。
この検証のいずれかで失敗するとトランザクションの検証は失敗する。検証が終わるとデータはスタックにプッシュバックされ残りのスクリプトで使われる。
オラクルが署名したデータが、1日の株価の中央値だったとする(証券コードと日付も含めて、データを一意にする)。このメタデータの検証をブロックチェーン上で行う場合、データを証券名、日付、金額の3つのパートに分け独立して評価されるよう、文字列を操作するopcodeを再度有効化する必要がある。
バイナリオプションのスクリプト構成例
とりあえずデータの一意性(証券名とか日付とか)を無視してバイナリオプションスクリプトを作成すると、バイナリオプションに勝ったユーザーが資金を入手する際のscriptSigは次のようなスタックを構成する。
オラクルの署名 オラクルのデータ 勝者の公開鍵 (標準のP2PKHの場合) 勝者のトランザクションの署名 (標準のP2PKHの場合)
参照されるscriptPubkeyは以下のような構成になる。
# オラクルの公開鍵をスタックにプッシュ OP_PUSHDATA(オラクルの公開鍵ハッシュ) # 上記のスクリプトのデータと署名を検証 OP_DATASIGVERIFY # 検証が成功したら、オラクルのデータはスタック上に残り、バイナリオプションのストライクプライスをスタックにプッシュ OP_PUSHDATA(バイナリオプションのストライクプライス) # プッシュしたストライクプライスとオラクルのデータを比較 OP_LESSTHAN # データの比較結果によって、参加者のいずれかへの支払いを許可する OP_IF # 通常のP2PKHトランザクションの始まり OP_DUP # 勝者の公開鍵をコピーする OP_HASH160 # 公開鍵をアドレスに変換 OP_DATA(参加者Aのアドレス) OP_ELSE OP_DUP OP_HASH160 OP_DATA(参加者Bのアドレス) OP_ENDIF # 通常のP2PKHトランザクション終わり OP_EQUALVERIFY # アドレスをハッシュされた公開鍵と比較 OP_CHECKSIGVERIFY # トランザクションと署名が一致するか検証
↑は単純な条件分岐だけど、MASTなんかと組み合わせるとより複雑な条件構成を持ち秘匿性のあるスクリプトにもできそう。