暗号通貨のトランザクション手数料について資料を読む。
前回
トランザクション手数料
ほとんどのトランザクションはトランザクション手数料を含んでいて、この手数料はBitcoinマイナーに与えられます。
支払いをする人が手数料を支払う。それを目当てにマイニングし、その取引を承認する。支払う人は承認してもらい、取引が成立する。そんなエコシステム。
取引を承認することをマイニングと呼ぶ。マイニングする人をマイナーと呼ぶ。取引を第三者が承認することで、公平な取引が成立する。だから暗号通貨には必ずマイナーが必要。
取引の承認であるマイニングは、コンピュータのリソースを消費する。ネット通信、ディスク容量、CPU計算リソース、電気代。それらを消費する代わりに手数料としてコインを受け取る。
この節では、どのようにしてトランザクション手数料がトランザクションに含められるかを説明します。ほとんどのウォレットはトランザクション手数料を自動的に計算しトランザクションに含めます。しかし、もしトランザクションをプログラムを通して構築する、またはコマンドラインを使って構築する場合は、手動でこれらの手数料をトランザクションに含めなければいけません。
前回の話から察するに、自分のアドレスが所有しているトランザクションをかき集めて、支払額+手数料以上になるようなトランザクションデータをvin
の配列として渡すのだろう。
トランザクション手数料はトランザクションを次のブロックに含める(マイニングする)ことのインセンティブとして働き、また少額でも手数料をトランザクションに入れなければいけないため"スパム"トランザクションやBitcoinシステムを悪用することに対する逆のインセンティブとして働きます。トランザクション手数料はトランザクションを記録しているブロックをマイニングしたマイナーによって集められます。
手数料があるから、いたずら目的でトランザクションデータを作成する動機もなくなる、ということかな? でも手数料は支払う人が出すのだから、どのみちコストなく取引データを作成することはできないのでは? 支払先を自分にすることでスパムになるってことかな?
コインを所有していて、かつ支払先を自分にすれば、誰でもスパムトランザクションを無限に作れてしまう。でも手数料をかければ所持金は減るため、無限スパムが成立しなくなるってことかな?
そもそも自分に送金できるかどうかも知らないけど。
トランザクション手数料はトランザクションのデータサイズ(KB)に基づいて計算され、いくらの支払いをしたかによって手数料は決まりません。トランザクション手数料はBitcoinネットワーク内での市場原理に基づいて決められます。マイナーごとにどのトランザクションを優先的に選ぶかの判断条件は違っており、この判断条件には手数料の大きさも含まれます。
だから手数料も支払う人自身に決定させようとするわけか。ふつう手数料といったらサービス提供側によって決められているイメージだけど、暗号通貨の場合はP2Pでありサービス提供者の一部として自分がいるわけで。しかも取引成立の是非や速度にかかわるため、自分で決めざるを得ない。
手数料の金額についてはデータサイズが係数になって算出されるらしい。なら、vin
やvout
などのデータが少ないほうが手数料も安いということかな? もしかしてmpurseでsendAssetするときメモにテキストを入れたらその分だけ手数料に上乗せされるのだろうか。
手数料が含まれていないトランザクションも状況によってはマイナーに選ばれるかもしれません。しかし、トランザクション手数料はマイナーによって処理される優先順位に影響し、十分な手数料をもっているトランザクションがマイニングされている次のブロックに含まれる可能性が高くなり、一方十分な手数料を持っていないか、手数料がないトランザクションはブロックに取り込まれることが遅れてしまいます。数ブロック後に取り込まれる、そもそも処理されないということになるかもしれません。
悩ましい。決済されないのは困る。
トランザクション手数料は必須ではなく、ときどき手数料がないトランザクションもマイナーに処理されますが、トランザクション手数料を含めることは処理の優先順位をあげることに繋がるのです。
手数料は必須ではないけど、マイナーがマイニングすることで決済が成立するので、マイニングする動機である手数料は事実上必須。少なくとも手数料が高い取引ほど優先してマイニングしようとすることは間違いない。電気代などがかかっているのにタダでやる人は少ないはず。だから動機づけとして手数料をつけるのが事実上必須である。という話だろう。
で? いくらにすればいいの? と聞きたくなる。
時間とともに、トランザクション手数料の計算方法やトランザクションの優先順位付け方法が発展してきました。最初、トランザクション手数料は固定されており、Bitcoinネットワーク全体で一定でした。次第に手数料制限は緩和され、Bitcoinネットワークのキャパシティやトランザクション量に基づく市場の力関係にトランザクション手数料が影響されるようになってきました。
歴史があるんだね。
現在の最小トランザクション手数料はトランザクションのデータサイズ1KBあたり0.0001bitcoin、0.1ミリbitcoinに固定されており、最近1ミリbitcoinに減らされました。多くのトランザクションは1KBより小さいですが、いくつかのインプットまたはアウトプットを持っているとより大きな手数料になります。Bitocinプロトコルの将来の改定で、ウォレットが最近のトランザクションの手数料平均値に基づき統計的に最適な手数料を決定できるようになると予想されています。
ビットコインだのイーサリアムだの、まったく触ったこともないのだが、そういった大手コインはトランザクション手数料が超高いらしい。しばしば「ガス代」と呼ばれるようだ。そしてガス代高すぎ問題というのがあるらしい。
トランザクションへの手数料の追加
トランザクションのデータ構造には手数料に対するフィールドはありません。
それがあれば簡単だったのに。
代わりに、手数料はインプットの総和とアウトプットの総和との差として暗に含められる形になっています。全てのインプットの総和から全てのアウトプットの総和を引いて残った余分な額がマイナーによって集められる手数料です。トランザクション手数料はインプットとアウトプットの差として暗に含められています。
Fees = Sum(Inputs) – Sum(Outputs)
Fees = vin - vout
手数料 = 総入力 – 総出力
らいうさんのコメントにもあった部分。
これは、幾分トランザクションを理解する上で混乱してしまうところですが重要なポイントです。というのは、もし自身でトランザクションを構築するとしたときに、うっかり大きな額の手数料を含めないようにしないといけないためです。つまり、全てのインプットを把握しておかなければいけません。そして、必要であればおつりを送るアウトプットを作成しなければいけません。さもなければ、マイナーにとても大きなチップをあげることになってしまうのです!
これはうっかりやらかすと大変そう。結構めんどうくさそうだな。
例えば、20bitcoinのUTXOを消費して1bitcoinの支払いをしようとするなら、19bitcoinのおつりがアウトプットに含まれていなければいけません。そうしないと、19bitcoinの"残り物"はトランザクション手数料としてカウントされてしまい、あなたのトランザクションを含むブロックをマイニングしたマイナーによって19bitcoinが集められてしまうのです。
おつり用のvout
を作らないと想定外の大出費になってしまうから注意しろよと。
そう思うなら、なぜ自動でやってくれないの? ブロックチェーンによる取引って結構面倒くさいんだね。
例
再度Aliceのコーヒー代支払いの例を使って実用上どのように動作するかを見ていきましょう。Aliceは0.015bitcoinをコーヒー代として支払おうとしています。分かりやすくするために彼女は0.001bitcoinをトランザクション手数料として含めようとしているとしてみましょう。これはトランザクションの総コストが0.016bitcoinになることを意味しています。
名目 | 金額 |
---|---|
コーヒー代 | 0.015 |
手数料 | 0.001 |
合計 | 0.016 |
よって、彼女のウォレットは0.016bitcoinかまたはそれより多い額になるようにUTXOを集め、必要ならおつりを作らなければいけません。
項目 | 値 |
---|---|
vin |
0.016 以上 |
vout[0] 支払い |
0.015 |
vout[1] おつり |
vin - vout[0] + 手数料 |
彼女のウォレットが0.2bitcoinのUTXOが使用可能だとしてみると、このUTXOを消費することになります。アウトプットとしては、Bobのカフェ店への支払いとして0.015bitcoinのアウトプットを作り、そして2つ目のアウトプットとして自分自身のウォレットに返ってくる0.184bitcoinのおつりのアウトプットを作ります。0.001bitcoinが残っていますが、これが暗にトランザクションに含められているトランザクション手数料になります。
名目 | 金額 | 所有者 |
---|---|---|
vin[0] |
0.2 |
自分 |
vout[0] |
0.015 |
支払先 |
vout[1] |
vin - vout[0] + 手数料 = 0.2 - 0.015 + 0.001 = 0.184 |
自分 |
手数料 | (0.2-(0.015+0.184)=0.2-(0.199)=0.001 |
マイナー |
実際に手数料を計算するときはデータ量1KBあたりに係数をかけて算出する。それを元にUXTOのvout[1]
を計算するはず。とりあえずUXTO内データでは、このように計算できる。
少額が多数ある場合
フィリピンの子供チャリティーディレクターのEugeniaは子供のために学校の教科書を購入するための支援金集めが完了し、全世界の人々からいただいた数千個の小さな寄付を受け取りました。総額にして50bitcoinです。このため、彼女のウォレットは小さな支払い(UTXO)でいっぱいになってしまいました。彼女は数百冊の学校の教科書を地元の出版社から購入したいと考えていて、支払いをbitcoinでするつもりでいます。
受取アドレス | 支払アドレス | 金額 |
---|---|---|
Eugeniaのアドレス | Aのアドレス | 0.00001 |
Eugeniaのアドレス | Bのアドレス | 0.00005 |
Eugeniaのアドレス | Cのアドレス | 0.00030 |
Eugeniaのアドレス | ... | ... |
こんなイメージかな。
Eugeniaのウォレットは1個の大きなトランザクションを作ろうとしたため、多くの小さな額のUTXOで占められているUTXOセットからUTXOを集めてこなければいけません。結果として作られるトランザクションにはインプットとして数百個の小さな額のUTXOと出版社に支払われるたった1個のアウトプットで構成されることになります。多くのインプットを伴ったトランザクションのデータサイズは1KBよりも大きく、おそらく2、3KBです。結果的に、最小手数料0.0001bitcoinよりも高いトランザクション手数料が必要になります。
やはりvin
やvout
が増えるほどデータ量が増え、手数料に上乗せされるらしい。
Eugeniaのウォレットはトランザクションのデータサイズと1KBあたりの手数料を掛け合わせて適切な手数料を計算することになります。多くのウォレットは大きなトランザクションに対して手数料を多めに払っています。これは、トランザクションを迅速に処理してもらうためです。高い手数料を払うのはEugeniaが多くのお金を使っているからではなく、トランザクションがより複雑でよりデータサイズが大きいからです。トランザクション手数料の額はトランザクションのbitcoin額とは無関係なのです。
vin
, vout
などのデータ量が増えれば、手数料も増える。そしてvin
は小さい金額単位だとデータ量の増加につながりやすい。大口のUXTOならデータ量が少なくなる確率が高い。
まとめてみよう。
支払うためのトランザクションを作成する方法
自分がだれかに支払うときのトランザクション作成方法についてまとめる。
- vinを作る
- voutを作る
vinを作る
- 自分のアドレスが所持するトランザクションデータUXTOを取得する
- 「支払い額+手数料」を上回ること
- トランザクションデータは
txid
で指定すること
気になるのは以下。
- データ一件で足りなければ複数用意すること
- データ件数が多いと手数料が増える
残高が大きいUXTOデータのほうが手数料が安く済む場合が多い。
voutを作る
- 支払い用のデータを作る(宛先は支払う相手)
- おつり用のデータを作る(宛先は自分)
注意点はおつり用データを作っておかないとvin
から支払額を引いた残り全額トランザクション手数料としてマイナーに支払われてしまうこと。
トランザクション手数料について
- 手数料はコインを支払う人が出す
- 手数料はデータ量に係数をかけて算出する
vin
からvout
を引いた額がすべて手数料になる- 手数料はその取引を承認したマイナーに支払われる
mpurseでモナコイン取引をするときは1Byteあたり101 watanabes
支払うのがデフォルト設定。その単位が謎だが、とにかくデータ量とかけあわせた結果、0.00022725 MONA
になるらしい。vin
のデータ量が増えたら手数料も増える。それは自分のもっているUXTOと支払額次第。
手数料があるせいで最小値である0.00000001 MONA
で送金しづらい。手数料より少ない額を送るのもどうかと思ってしまう。
手数料は少ないほうがいい。が、そうするとマイニングの動機がなくなって取引が成立しなくなる。そのバランスは支払う人が手数料を変動させることで決定する。だからmpurseでも送金する人が自分で手数料をある程度の範囲で決めることができる。
「なんで手数料を自分で決めれるの?」と思っていたが、そういうことらしい。