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_DUP
とOP_CAT
のセットが続くスクリプトの場合。OP_DUP
スタックの上位の要素を複製するopcodeなので、
- スタック上のデータが
OP_DUP
により複製され、 OP_CAT
により、スタック上の2つの要素を連結し、その結果をスタックにプッシュするOP_DUP
とOP_CAT
の数分、1〜2を繰り返す。
そうするとスタック上の要素のサイズは、OP_DUP
とOP_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_DUP
とOP_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_DUP
とOP_CAT
の組み合わせを利用した場合でも、520バイトの制限と、スタック要素の最大数1,000の制限から、1,000個のスタック要素を520バイトで埋めても消費するのは520KBほど。