皆さんはビットコイン送金の際、支払う手数料をどうやって推定していますか?ご自身のビットコインノードやウォレットから送金手数料を決めていたり、mempool.spaceのようなブロックチェーンエクスプローラーを利用している方が多いのではないでしょうか。もちろん、特に考えずにウォレットに任せているという方も多いでしょう。

実は昨日からオンチェーン手数料の推定が実情と異なる、という指摘が多発しています。mempool.spaceなどでは30sats/vbyteでトランザクションが次のブロックに含まれると書いてあるのに、実際は100sats/vbyte以上の手数料を支払わないと次のブロックには入らないという出来事が置きているのです。どういうことでしょうか?

その理由はブロックに含められるデータ量の制限が「トランザクションサイズ(バイト数)」以外にもあることにあります。今日はこの理由を解説します。

・StampsとSRC-20というトークンプロトコルの特徴

・ブロックに含められるトランザクションの「データ量」以外の制限とは

・手数料推定に使える対処法はあるのか?

StampsとSRC-20というトークンプロトコルの特徴

Ordinals Inscriptionsが誕生してまもなく、似たコンセプトとしてStampsプロトコルが誕生しました。

2014年に登場したCounterpartyの技術を流用していることがポイントで、Base64文字列化した画像をCounterpartyプロトコルを使って多数のUTXOに分割してオンチェーンに記録します。この際、P2SHのマルチシグを装ってデータを保管します。OP_ReturnやWitness Data(署名データ)とは異なり、確実に不要と言い切れないため、ビットコインノードはこれらのUTXOをプルーニングすることができません。その点において、Ordinals Inscriptionsよりさらに悪質とする人もいます。(ただし、その分手数料も余分にかかります)

例えばこのトランザクションは大量のマルチシグUTXOを生んでいますが、これらは組み合わせるとこちらのNFTの画像に復元できる文字列を記録しています。(実際のマルチシグではありません)

Stampsプロトコルのトランザクションは、このように1つのP2PKHアドレスと大量のP2SHマルチシグアドレスに対する送金としてエンコードされる。
それぞれのマルチシグアドレスにある公開鍵ハッシュ(に見せかけた画像データ)をつなぎ合わせると、このようにNFT画像など元データを復元できる。

このように、StampsプロトコルはもともとはOrdinals Inscriptionsと同様に画像データをNFTとして扱うことを念頭に置いていましたが、SRC-20という(Ordinals Inscriptionsに対するBRC-20のような)トークンプロトコルの登場によって主にそちらに利用されるようになっています。これは画像データではなく、JSONエンコードしたStampsトランザクションと呼ばれるデータを記録し、Stampsユーザー間で共通のルールのもと実行されたと認識するものです。(BRC-20と非常に似ています)

stampchain.ioというエクスプローラーで直近のトランザクションを見ると、ほぼ全てがJSON形式のSRC-20トランザクションだとわかります。

BRC-20と比べたときの違いはインデクサーにCounterpartyを利用しているため、Counterparty関連の既存のソフトウェアツールが利用できること、トークンに紐づく画像情報はオフチェーンで保管されることなどが挙げられます。元のStampsプロトコルはNFTにしたい画像をいくつものUTXOに分けてオンチェーンに保管するものであったことを考えると不思議な発展ですね。

そしてOrdinals Inscriptionsだと1つのUTXOで済んだものが何十、何百ものUTXOを生むためビットコインノードにとっては負担が大きいです。

ブロックに含められるトランザクションの「データ量」以外の制限とは

ビットコインのブロックには総サイズの制限(1MvB、あるいは4MWU)があるのは皆さんご存知かと思います。そして冒頭で言ったように、今回はそれとは異なる「ある制限」によって多くのトランザクションが安い手数料ではブロックに含めてもらえない、逆に言えば特定の条件を満たすトランザクションは安い手数料でブロックに含めてもらえる状況が発生しました。どうしてSRC-20トランザクションはBRC-20トランザクションでは発生しなかったこのような現象を巻き起こしたのでしょうか?

先ほど述べた通り、多数のUTXOの保管はビットコインノードにとって負担となります。しかし、今回引っかかるトランザクションが発生した「ある制限」とは、1ブロックに含められるSigOpsの総数の制限、つまり「ビットコインノードが実行するかもしれない署名検証に係る計算量」の負担を制限するものです。

よくScriptに関する記事でオペコード(OP_ナントカと表現される、Scriptの関数)について触れますが、それぞれが検証時にビットコインノードが実行する計算となります。特に署名検証は計算負荷が大きいものです。したがって、膨大な数の署名検証を実行させることで多数のビットコインノードを機能不全に陥らせる攻撃を防ぐのがブロック内のSigOps数の制限です。

実際には署名検証オペコードに応じてカウントが異なります。例えば出力のScriptPubkeyに含まれるOP_CHECKSIGは4のところ、計算量が大きくなりやすいOP_CHECKMULTISIGは80としてカウントします。そして、1ブロックに含められるSigOpsの点数は80,000までと制限されているので、例えばOP_CHECKMULTISIGだとおよそ1000個までしか含められません。

ちなみに「ScriptPubkeyに含まれる」というのは今ではあまり一般的ではないトランザクション形式ですが、StampsはCounterpartyを踏襲しているのでこれに該当します。P2SH、P2WSH、P2TRなどでは生成時ではなく使用時にRedeem Scriptでカウントされますし、それぞれカウント面で優遇があります。

StampsプロトコルはまさにOP_CHECKMULTISIGを使うため、多数のSRC-20トランザクションが発生するとブロックサイズではなくSigOps数が制限となってブロックにこれ以上のトランザクションを入れることができなくなってしまいます。

したがって、昨夜Stampsトランザクションが手数料を競い合っていたのは「1MvBのブロックサイズ」より厳しい「80,000 SigOps」という上限であり、余ったブロックサイズはSigOpsを含まないトランザクションで分けることになります。(またはSigOps単価がStampsトランザクションを超えるものが選択されます)

通常のトランザクションへの影響

通常のトランザクションにもSigOps数が関わるとなってくると厄介です。例えばP2SHマルチシグ(3から始まるアドレス)からの出金時にはSigOps数がm-of-nのn×4として評価されますし、P2WSHマルチシグ(bc1qから始まる)だとm-of-nのnまたは20として評価されるなど、計算方法が少し厄介です。Pieter Wuille氏がStack Exchangeへの回答でまとめてくれています。

競争相手のStampsトランザクションの数や大きさにもよりますし、マイナーがどれくらい上手にトランザクションを選別しているかにもよるので最適な手数料の計算は厄介ですが、P2TR(bc1pで始まる)以外のアドレスからの送金だと必ずSigOpsがカウントされることになります。

そう、P2TRにおけるtaproot scriptのSigOpsにはブロック全体に関する上限はありません(トランザクション単位ではあり)。つまり、P2TRアドレス→P2TRアドレスの送金などはブロック制限の面ではSigOps数が0としてカウントされるため、「余ったスペース」の手数料競争に参加するだけでよく、Stampsトランザクションなどが100sats/vbyteの手数料を払う中30sats/vbyteほどでも次のブロックに含まれていました。

実際にはP2TRの普及はそれほど進んでいないため、Runesなどのトランザクションが含まれがちだったようですが…。

手数料推定に使える対処法はあるのか?

先ほど述べた通り、手数料推定は困難を極めます。メモリプールをみて次のブロックの内容を推定するにしても、「簡単な」アルゴリズムだとブロックサイズだけをみて手数料推定をされる(この場合30sats/vbyte近傍を提案され、しばらく承認されにくい状態が続いたと推測される)ことが多いかもしれません。

実際にBitcoin Coreの提案するブロックもSigOps数が手動する手数料相場において最適ではないと指摘されています。例えばSigOpsが0のトランザクションが存在しない環境において最適なブロックと比べて手数料を60%も取り損なう場合があるようです。(つまり、SigOpsとWUの2変数での最適化が弱い)

多くのマイナーやウォレットはBitcoin Coreが提案するブロック(や、それを元に改変したもの)を鵜呑みにしている可能性があるので、最適な推定ができていると考えないほうが良さそうです。メモリプールの状況も刻々と変化します。

SigOps・トランザクションサイズの両方を考慮したギリギリの手数料を設定してブロック生成側のロジックに拾ってもらえることを祈るよりは、将来的にP2TRの普及によってSigOps変数に左右されない送金ができるようになるほうがまだ希望が持てそうです。