EVM・Bitcoinオペコードと手数料
オペコードとは機械語の1個の命令のことで、数学では+や=などの演算子にあたります。プログラミングをする場合、PythonやJavaなど高水準言語と呼ばれる人間にとって理解しやすい言語を使います。そのプログラムを変換(コンパイル)してコンピュータが処理しやすいように低水準言語へ置き換えるのですが、その時にオペコード(実際はバイトコード)へ変換されます。ビットコインやイーサリアムも同じような仕組みですが、今回はこのオペコードと手数料の関係について両者の比較をしたいと思います。
ビットコインとオペコード
ビットコインのプログラミング言語はビットコインスクリプトと呼び、これは低水準言語にあたります。ビットコインには一応Miniscriptという高水準言語ちっくなものが存在しますが、あまり活用されている事例は聞かないです。ビットコインスクリプトの例を以下に書いてみます。
OP_IF
OP_2 ${alice.publicKey} ${bob.publicKey} OP_2 OP_CHECKMULTISIG
OP_ELSE
3
OP_CHECKSEQUENCEVERIFY
OP_DROP
${alice.publicKey}
OP_CHECKSIG
OP_ENDIF
上記のスクリプトは、「アリスとボブの署名か、または3ブロック経過していればアリスの署名を使うとビットコインを引き出せる」というプログラムで、巷ではこれをスマートコントラクトと呼んでいます。このスクリプトをバイトコードへ変換したものが以下になります。
63522103d410a00494e5831cc4fbadc78028428647a8072748cf3ed29980ac02c58faa85210376d82d42e52d88710fd8cd05091246bec5a8111008f64fef8c5f7e312fb839ba52ae6753b2752103d410a00494e5831cc4fbadc78028428647a8072748cf3ed29980ac02c58faa85ac68
意味不明ですよね。機械が理解できればよいのでこんな感じになります。データサイズは112byteです。このデータをハッシュしてビットコインアドレスにしたものが以下になります。
2N7MMSjziUcgU6HwseBH8S9WzQhebg7Xkyq
上記のアドレスには少額のビットコインが入っています。ではどうやって取り出すのかと言うと、スマートコントラクトを正しく実行できれば取り出すことができます。そのためにはアリスとボブの署名か、または3ブロック経過していればアリスの署名のみでコントラクトを実行することができます。
ここでビットコイン手数料の話に移ります。ビットコインの手数料は以下のように求めます。
手数料=データサイズ×手数料率
手数料率は日々刻々と変化していて、送金したいユーザー数が多いと高く、少ないと低くなります。例えば、手数料率が 1satoshi/byte で、データサイズが 200byte だと、 200satoshi が手数料となります。上記のアドレスからビットコインを取り出すためのデータサイズは 345byte で、実データは以下になります。
0200000001d6af62a70fb91db1164bf0367a346827f5c73a1a444cacdb00a2943d9d9de13301000000fd0401004730440220547876f85d1a7612592ee8fede8d622ca187c65088a73cd64ac231cb62b678ee02204af365cb9afa3c1b6a5c631b907d5c2ea527d8c2db510b89e2b34fd21aeff7590147304402201ac0e595e87e4d756433d6debaf8b453d6b07a376760f0432e46fdbad57d1194022037759f00d0cba12830e22306d6bffd6ab572581c4d4bd1edf2027852bfd2687501514c7063522103d410a00494e5831cc4fbadc78028428647a8072748cf3ed29980ac02c58faa85210376d82d42e52d88710fd8cd05091246bec5a8111008f64fef8c5f7e312fb839ba52ae6753b2752103d410a00494e5831cc4fbadc78028428647a8072748cf3ed29980ac02c58faa85ac68ffffffff01804a5d050000000017a914808545d373518a98de1eec0a1fc5cae2d589ac778700000000
このデータはヘッダ、インプット、アウトプットなどの情報が含まれていますが、スマートコントラクト部分だけみると 112byte になります。これは最初にみたバイトコードのデータサイズですね。実際のデータサイズは 345byte なので、手数料率を 1sat/byte とすると 0.00000345BTC (345satoshi) が手数料となります。
上記の例で見たようにビットコインのスクリプトには OP_IF や OP_CHECKSIG などがありますが、どの演算子も1byteで、それにかかる費用も一律となっています。
では次にイーサリアムのスマートコントラクトをみてみましょう。
イーサリアムとオペコード
イーサリアムにはSolidityという高水準言語があり、このプログラミング言語でスマートコントラクトをつくり、バイトコードへ変換します。Solidityで書いた簡単なプログラムは以下となります。
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.8.0;
contract Storage {
uint256 number;
function store(uint256 num) public {
number = num;
}
function retrieve() public view returns (uint256){
return number;
}
}
上記のスクリプトをバイトコードへ変換したものが以下になります。データサイズは 230byte です。このサイトを使うとバイトコードからオペコードへ変換してくれます。
6080604052348015600f57600080fd5b506004361060325760003560e01c80632e64cec11460375780636057361d146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506087565b005b60008054905090565b806000819055505056fea2646970667358221220c9881e39a8354c748f8a6a5ac025e69ecd01234d361f842269e058dbde9e36db64736f6c63430007040033
このデータをブロックチェーンへデプロイしてコントラクトアドレスとなったのが以下になります。このアドレスに対して、トランザクションを送りつけることで、上記のStorageコントラクトを実行できます。
0x50f76052cde9d0e0B5951Cbb4FDCCb5C6dcd44D6
次に、トランザクションを送信するためにかかる手数料についてですが、イーサリアムの手数料は以下のように求めます。
手数料=ガス費用×ガス価格
ガス価格はビットコインの手数料率と同様に変動的です。ガス費用はどうやって求めるかというと、イーサリアムの各オペコードにはそれぞれガス費用が対応しており、「実行するオペコード×ガス費用の総額」がガス費用となります(対応表はここから参照可能)。例えば、2つの値を加算するADDの実行には3ガス必要で、値を保存するSSTOREの実行には20,000ガスが必要になります。
上記のStorageコントラクトのstore関数では、number変数へ値を保存するので、SSTOREが実行されます。なので最低でも20,000ガスが必要です。実際にstore関数を呼び出すトランザクションを実行する場合は以下のようなオペコード群が実行されるのでもう少し費用は高くなります。
[166] JUMPDEST
[167] DUP1
[169] PUSH1 0x00
[170] DUP2
[171] SWAP1
[172] SSTORE
[173] POP
[174] POP
[175] JUMP
以下は実際にstore関数を実行して値88を保存したトランザクションでデータサイズは 137byte 、ガスは26706となりました。このサイトから以下のデータを貼り付けてデコードすると詳細が分かります。
0xf88707843b9aca008268529450f76052cde9d0e0b5951cbb4fdccb5c6dcd44d680a46057361d000000000000000000000000000000000000000000000000000000000000005841a0816037cfe5869f440525de1049decb998a69930741f7f401c0813d7982a56b8aa03c09ebf814db5d235d2bc5b1506fd005cdb2499adf191ae3eb6537ed17364725
実際にstore関数に引数88を渡すインプットデータは36byteでした。また、ガス費用とガス価格は、26706と1Gweiだったので、トランザクション手数料は0.000026706 ETHとなります。
イーサリアムではオペコードごとにガス費用が対応しており、マシンの計算量をもとに、計算量が多いオペコードには高く、計算量が少ないオペコードには低く設定されています。ビットコインの場合はオペコードに関係なく一律同じ手数料でしたが、イーサリアムは細かく設定がされています。
手数料について、ビットコインではブロックチェーンへ書き込むトランザクションのデータサイズに、イーサリアムはEVMで実行されるコントラクトのオペコード計算量に依存していることが分かります。
イーサリアムの方がビットコインよりも取引データは少なくて済む気がするのですが、なぜイーサリアムは同期が遅いなどと言われているんでしょうか。イベントログとかが関係しているのかな?
まとめ
最後に、今回見てきた各スマコンの手数料を比較表として纏めます。
各手数料は、ビットコインはブロックチェーンへの書き込むTxサイズに依存し、イーサリアムは実行するコントラクトの計算量(ガス費用)に依存します。
以上、各ブロックチェーンのオペコードと手数料についてでした。