Develop with pleasure!

福岡でCloudとかBlockchainとか。

OP_CATの再導入の提案BIP-347

TapscriptでOP_CAT opcodeを利用可能にしようという提案のBIPがBIP-347として登録された↓

https://github.com/bitcoin/bips/blob/master/bip-0347.mediawiki

OP_CATとは

OP_CAT opcodeは、スタックから上位2つの要素をポップし、それらを連結した値をスタックにプッシュするというシンプルなopcode。

無効化

元々Bitcoinに実装されていたopcodeだけど、2010年に他のいくつかのopcodeと共に無効化されている。無効化された理由とされているのが、スクリプト実行時に巨大なデータを生成することでメモリを大量消費する可能性があるというもの。

例えば、1バイトのデータをプッシュし、その後にOP_DUPOP_CATのセットが続くスクリプトの場合。OP_DUPスタックの上位の要素を複製するopcodeなので、

  1. スタック上のデータがOP_DUPにより複製され、
  2. OP_CATにより、スタック上の2つの要素を連結し、その結果をスタックにプッシュする
  3. OP_DUPOP_CATの数分、1〜2を繰り返す。

そうするとスタック上の要素のサイズは、OP_DUPOP_CATの数に対して指数関数的に増加する。ただ、元々のOP_CATの実装には↓

 case OP_CAT:
 {
     // (x1 x2 -- out)
     if (stack.size() < 2)
         return false;
     valtype& vch1 = stacktop(-2);
     valtype& vch2 = stacktop(-1);
     vch1.insert(vch1.end(), vch2.begin(), vch2.end());
     stack.pop_back();
     if (stacktop(-1).size() > 5000)
         return false;
 }
 break;

最後のチェックがあるので、スタック要素のサイズは最大でも5,000バイトに制限される。

しかし、約5,000バイトの要素を作る場合、1バイトのデータとOP_DUPOP_CATの組み合わせで約24バイトのスクリプトでできるので、別のスタック要素として5,000バイトの要素を多数生成することで、メモリ使用量を増やすことはできる。

Tapscriptでの有効化

BIP-347ではTapscriptのopcodeとしてOP_CATを導入しようとしている。Tapscriptでは将来の拡張用に確保されているOP_SUCCESS系のopcode*1があるが、この1つをOP_CATに割り当てて、ソフトフォークでアクティベートするというもの(ソフトフォークの方法や時期は現状明記されていない)。

割り当てられるopcodeは、OP_SUCCESS126(hex値だと0x7e)で、元々OP_CATに割り当てられていたopcodeを利用する。

また、Taprootではスタック要素の最大サイズは520バイトに制限されており、OP_CATで連結したスタック要素の最大サイズも520バイトに制限される。

OP_DUPOP_CATの組み合わせを利用した場合でも、520バイトの制限と、スタック要素の最大数1,000の制限から、1,000個のスタック要素を520バイトで埋めても消費するのは520KBほど。

*1:このopcodeが評価されるとその瞬間にスクリプトが成功するopcode