BCHハードフォーク(5/15)の内容と、関連するOP_CAT、OP_RETURNの技術的説明

f:id:usatie:20180428174230j:plain株式会社Yenom(旧・株式会社mikan)のうさみ(@usatie)です。

現在は、iOS開発を中心に担当してます。iOS開発チームは沖縄での開発合宿を経て、絶賛「RxSwift + MVVM + テスト」化を進めています。

今回は、簡単に5/15のビットコインキャッシュのハードフォークの内容を紹介した後に、今回のハードフォークで関係のあるOP_RETURNとOP_CATというOP_CODEについての説明を書いてみたいと思います。

5/15のビットコインキャッシュのハードフォークの内容

アップデート(ハードフォーク)の内容を簡単にまとめると以下の4つです。

1. OP_RETURNのサイズが220 byteまで拡大
2. Block Sizeを32MBに拡大
3. 6個のOP_CODEを復活
4. 3個のOP_CODEの追加

1. OP_RETURNのサイズが220 byteまで拡大

後ほど、解説するOP_RETURNに含められるデータのサイズが220 byteまで拡大します。 (今までは80 byte)

2. Block Sizeを32MBに拡大

これまで8MBだったBlock Sizeが32MBに拡大します。

3. 6個のOP_CODEを復活

3つのビット演算子(OP_AND, OP_OR, OP_XOR)、2つの算術演算子(OP_DIV, OP_MOD)、そしてOP_CATの合計6個のOP_CODEが復活します。 OP_CATについては、なぜ使えなくなっていたのか後ほど解説します。

OP_AND:論理積 (A & B)
OP_OR:論理和 (A | B)
OP_XOR:排他的論理和 (A ^ B)
OP_DIV:割り算(A / B)
OP_MOD:割り算の余り(A % B)
OP_CAT:文字列の結合(A + B)

4. 3個のOP_CODEを追加

OP_SPLIT(OP_SUBSTRと交換), OP_NUM2BIN, OP_BIN2NUM

さて、それではここからは肝心のOP_CATとOP_RETURNの説明にいきたいと思います。

OP_CATを有効化できる理由

OP_CATは文字列の結合のため

OP_CATは、二つの文字列を結合するためのOP_CODEです。

OP_CATを使ってメモリを溢れさせてクラッシュさせる

当初はビットコインに存在したものの、2010年に使えなくなってしまっていました。

なぜ、このような単純なOP_CODEが使えなくなっていたのかというと、OP_DUPとOP_CATを組み合わせることでメモリを溢れさせてクラッシュさせる攻撃ができてしまうためです。

"ABC" OP_DUP OP_CAT OP_DUP OP_CAT OP_DUP OP_CAT ...

上記のようにOP_DUPとOP_CATを組み合わせることで出力のサイズは10回ごとに約1000倍(1KBは1MB、1MBは1GB、1GBは1TB)になってしまいます。 普通に入力できる文字列データの大きさは32byteですが、30回繰り返せば32GB、50回繰り返せば32PBにもなってしまいます。

どんなに大きなメモリを積んだコンピューターを使っていても、簡単にメモリを使い果たしてクラッシュしてしまうことがわかります。

このようなアタックを防ぐために、OP_CATは2010年8月15日のバージョン0.3.10で無効化されてしまいました。

OP_CATからの出力値のサイズに上限を設定

今回の有効化されるにあたっては、以下のようにOP_CATからの出力値のサイズに上限を設け、閾値以上の大きさ以上の値が出力される場合はすぐにfailすることでこの問題を解決しています。

case OP_CAT: {
    // (x1 x2 -- out)
    if (stack.size() < 2) {
        return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
    }
    valtype &vch1 = stacktop(-2);
    valtype &vch2 = stacktop(-1);
    if (vch1.size() + vch2.size() > MAX_SCRIPT_ELEMENT_SIZE) {
        return set_error(serror, SCRIPT_ERR_PUSH_SIZE);
    }
    vch1.insert(vch1.end(), vch2.begin(), vch2.end());
    popstack(stack);
} break;

ちなみに、現在この閾値であるMAX_SCRIPT_ELEMENT_SIZEは520byteに設定されています。

OP_CATが使えるようになると軽量に超巨大なマルチシグのトランザクションを作れるようになったりします。楽しみ。

OP_RETURNの技術的説明

OP_RETURNを使えばオンチェーンに任意のデータを記録できる

OP_RETURNは簡単に任意のデータをブロックチェーンに記録するためのOP_CODEです。

もう少し詳しくいうと、トランザクションアウトプットを無効化するためのOP_CODEであり、無効化したトランザクションに追加で少しだけデータを追加することができます。Burnのためにも使われるようなOP_CODEです。このOP_RETURNで追加できるデータのサイズには限界があり、これまではその限界が80byteでしたが220byteに変更になります。

OP_RETURNを使ってメモをオンチェーンに記録

例えば、以下のスクリプトは何を意味するでしょうか?

OP_RETURN 621 43616e2774207761697420666f7220656e61626c696e67206e6577204f505f434f444573210a536f206578636974656420746f20747279207468656d2e

これは、「Can't wait for enabling new OP_CODEs! So excited to try them.」というコメントをOP_RETURNの後ろに追加しているものです。 そして、今そのトランザクションアウトプットを追加したトランザクションをオンチェーンに記録してみました。 以下がそのトランザクションになります。 explorer.bitcoin.com

メモをオンチェーンに記録するときの手数料

OP_RETURNを使うと、簡単にブロックチェーン上に情報を記録できるというのが面白いです。色々と活用方法がありそうですね。先ほどのトランザクションもサイズはわずか267byteなので、手数料は267satoshi(=約0.2〜3円)で記録できました。 わずか0.2〜0.3円で永遠にブロックチェーンにデータを刻めるというのはなかなか面白いです。 誰かへの手紙でも、結婚の証明や、永続的に記録しておきたいものがある人は、これを使えば簡単にオンチェーンに記録ができますね。

おわりに

今回はハードフォークを前に、それに関係するOP_CODEについて少し調べてみました。 とても面白かったので、次回はこれらを使ってもう少し面白いことができないか試してみたいと思います。

参考

https://github.com/shadders/uahf-spec/blob/100a677a41305907951a021715ac06be7e749c6b/reenable-op-codes.md https://bitcointalk.org/index.php?topic=938880.0 https://en.bitcoin.it/wiki/OP_RETURN https://bitcoin.org/en/release/v0.9.0#opreturn-and-data-in-the-block-chain https://github.com/Bitcoin-ABC/bitcoin-abc/commit/73dd62acd7651f0f156b6be6ab8d9de508dae822 https://github.com/Bitcoin-ABC/bitcoin-abc/commit/cbf4410912f6512e481f15270329683d4d4378d4