今日はビットコインの使い道を制限することで安全性を高めるCovenantsという技術と、それを実現する方法としてScaling BitcoinでもプレゼンされたOP_SECURETHEBAGという新たなオペコードについて書きます。

Covenants関連では、8月8日の記事「開発者メーリスより:Covenants抜きでBitcoin Vaultsを実現する」も寄稿しましたので、ぜひご覧ください。

開発者メーリスより:Covenants抜きでBitcoin Vaultsを実現する
送金完了までに一定の待ち時間を設け、その間に不正送金を無効化できるBitcoin Vaultsの仕組みを解説。2016年の原案から、Covenantsなしで実現する2019年の新提案まで、ビットコインのセキュリティ強化アイデアを紹介します。

Covenants

上で紹介した記事にも書いてあるように、Covenantsとは、出力(=コイン)に課される使用条件のことで、単純に秘密鍵を持っていれば送金できるのではなく、それ以外に指定する条件を満たしていなければ使用できなくなるというものです。

これを使えば、例えば一定期間経ってからしか使用できないようにしたり、秘密鍵以外に指定したリカバリー用の特別な秘密鍵を使えるようにできます。上の記事で紹介しているBitcoin Vaultsを利用すれば、ハッキングに遭うなどしたときに普通なら送金されてしまうと不可逆なビットコインで送金を一定期間、事実上キャンセル可能にできます。

また、ビットコイン上でビットコイン以外の資産を表現するカラードコインという概念がありますが、Covenantsを使って実現する方法もあります。簡単に言えば、カラードコインは他のビットコインやカラードコインと「混ざってはいけないもの」なので、Covenantsを使って「混ざることができないようにする」アプローチです。

OP_SECURETHEBAG

OP_SECURETHEBAGは現在提案されている新たなオペコード(スクリプトの関数)で、Covenantsに関する提案の一つです。Covenantsに対応するにはトランザクションの作成と検証に使う新しいオペコードを導入する必要があります。(オペコードはビットコインのスクリプト言語の関数のようなものです。)

先程説明した以外にも、これを使えば送金手数料が高いときにトランザクションを「予約」するという面白いユースケースが提案されています。これは、「最終的な宛先に、手数料が低いときに支払う」ことしかできないトランザクションを作成し、手数料が安いときにそこから展開することで、着金時間は遅くなるが承認数は最初のトランザクションから数えることができる、というアイデアです。(二重支払いするには、最初のトランザクションをも巻き戻す必要がある) スケーリング系のカンファレンスでの発表にもってこいな内容ですね。

オペコードのイロハ (おまけ)

私のコラムは技術寄りの内容が多いので、オペコードに関する話やビットコインスクリプトに関する話がよく出てきます。そこで簡単にオペコードが何かイメージしてもらおうと思います。

まず、ビットコインのスクリプト言語はかなり古典的な形となっていて、「スタック指向」という形をとっています。スタックとは書類などの山のことで、新しいものは一番上に追加し、取り出すときも一番上から取り出すというデータ構造のことです。ScriptはJavaやC、Pythonとは違い、すべての関数と定数を順番に書いていくものです(※)。

Forthというスタック指向言語のWikipediaページから例を借りると、

25 10 * 50 + .

は順に
「25をスタックに置く」
「10をスタックに置く」
「スタックの上から2つを取り除き、掛け合わせて(=250)スタックに置く」
「50をスタックに置く」
「スタックの上から2つを取り除き、足し合わせて(=300)スタックに置く」
「スタックの一番上の値(=300)を出力する」
といったものです。(Wikipediaの図がわかりやすいです。)

このとき、数字は定数で、「*」「+」「.」は定数を操作する関数なのですが、ビットコインにおいてオペコードが関数なのです。したがって、簡単なビットコインスクリプトはこのような見た目です:

<sig> <pubKey> OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG

これは順に
「署名をスタックに置く」
「公開鍵をスタックに置く」
「スタックの一番上の値(=公開鍵)を複製してスタックに置く」
「スタックの一番上の値を取り除き、ハッシュして(=公開鍵のハッシュ)スタックに置く」
「公開鍵のハッシュ(つまりアドレス)をスタックに置く」
「スタックの上から2つの値を比較し、等しければ両方取り除き続行する(等しくなければエラーを出し失敗)」
「スタックの上から2つの値(=署名、公開鍵)を取り除き、それでトランザクションの署名を検証、正しければ『正』を意味する1を出力して検証終了」

この一連の流れがビットコインで最も古典的なP2PKH(=Pay to Public Key Hash, 公開鍵のハッシュで認証)という種類のトランザクションの検証です。

(※)…一方、イーサリアムで使われるSolidityはJavaなどの有名なプログラミング言語と似た形をとっています。また、ビットコインのソフト自体もこういう「普通の」言語で書かれているので、スクリプト限定の話です。

まとめ

OP_SECURETHEBAGは上記の例のオペコードよりは複雑で、まだ比較的早い段階でまだ決定事項は少ないのですが、概念だけを表現すると

OP_SECURETHEBAG <BagHash>
※BagHashはロックタイム、出力などに関する制限をまとめたもののハッシュ

という使い方になるようです。

今回はCovenants, OP_SECURETHEBAG, そしてオペコードに関するとても初歩的なことに触れました。将来的にエンドユーザーがこれらを意識することはないと思いますが、ビットコインのスクリプトが現在どのような形なのか知っておくと技術的な話題が少し理解しやすくなるのではないでしょうか。