用語集 / 開発者向けリファレンス
OP_DUP
- OP_DUPとは?
- OP_DUPはスタックの最上位の項目をコピーして2回使えるようにする命令であり、そのため標準的なpay-to-public-key-hashのスクリプトは公開鍵のハッシュを計算することと、その公開鍵に対して検証することの両方を行えます。
1バイト、0x76、そして役割は1つです。ビットコインのスクリプトには変数がなくスタックしかないため、ある命令が消費した項目は次の命令が実行される前になくなっており、それを再利用する唯一の方法が複製です。25バイトのスクリプトのうち、実際に働く4つのオペコードの最初のものであり、このスクリプトは1で始まるほぼすべてのビットコインアドレスを守っていました。
仕組み
複製が必要なのは、検証が同じ公開鍵を2つの両立しない目的で必要とするからです。アウトプットはハッシュにしかコミットしていないため、正しい鍵であることを示すには鍵をハッシュ化して比較する必要があります。その後の署名検証には鍵そのものが必要ですが、比較の時点でそれが消費されてしまいます。
レガシーの支払いを順に追ってみます。支払う側のデータは、署名の上に公開鍵が載った形でスタックに積まれます。OP_DUPが鍵の2つ目のコピーを作ります。OP_HASH160がそのコピーを20バイトのダイジェストに置き換えます。アウトプットがコミットした20バイトを積み、OP_EQUALVERIFYが両方を消費し、不一致があればスクリプト全体を中断します。そしてOP_CHECKSIGが元の鍵と署名に対峙する形で残り、まさに必要なものがそろいます。5つの手順、分岐なし、ループなし、そして毎回一定のコストです。
このオペコードは、高価な処理をすることなく2つの上限に算入されます。Taproot以前のスクリプトが含められる201個の実行命令の1つであり、作られるコピーはスタック全体で1,000個という項目数の上限に算入されます。どちらも単一鍵の支払いでは問題にならず、ループのない条件の連鎖の中で複製を行うスクリプトではどちらも問題になります。
どこで見られるか
1で始まるアドレスを使うトランザクションを見ると、アウトプットスクリプトはOP_DUPで始まります。ブロックエクスプローラーでは、アセンブリの最初のトークンとして表示されます。
より興味深いのは、姿を現さずに実行される場所です。ネイティブSegWitの単一鍵アウトプットにはロジックが一切なく、バージョンバイトと20バイトのハッシュだけですが、BIP-141はそのハッシュから古典的なテンプレートを組み立ててそのまま実行するようノードに指示します。そのためこのオペコードはネットワーク上のすべてのP2WPKHの支払いで今も実行され、ブロックの中にはどこにも現れません。かつてその1バイトに要した4重量単位を支払うことなく、同じ動作が得られます。
スクリプトハッシュのアウトプットとTaprootのキーパス支払いは、これを完全に省きます。P2SHのアウトプットはハッシュを直接比較し、Taprootの鍵による支払いはスクリプトを介さずにアウトプット鍵に対して署名を検証します。これはSegWitとTaprootが実際に何をしたのかを最小限に示す例です。新しい機能というよりも、同じ検証を、チェーンがより少ないバイトを運ぶだけで得られるように並べ替えたということです。