トランザクションコスト

トランザクションコスト

Ripple Consensus Ledger をスパム攻撃やDOS攻撃から守るため、各トランザクションは少量のXRPを破棄する必要があります。このトランザクションコストは、故意にまたは不用意にネットワークに過負荷をかけると非常に高価になるように、ネットワークの負荷とともに増加するように設計されています。

すべてのトランザクションは、トランザクションコストを支払うためにXRPをどれだけ破棄するかを指定する必要があります。

現在のトランザクションコスト

ネットワークが標準のトランザクションに必要とする現在の最小トランザクションコストは、0.00001 XRP(10 drops)です。それは時々、通常のよりも高い負荷がかかることが原因で増加します。

現在のトランザクションコストを rippled に照会することもできます。

特別なトランザクションコスト

一部のトランザクションには異なるトランザクションコストがかかります:

トランザクション 負荷増加前のコスト
リファレンス・トランザクション(ほとんどのトランザクション) 10 drops
キーリセット・トランザクション 0
マルチサイン・トランザクション 10 drops × (1 + 提供される署名の数)

トランザクションコストの受益者

トランザクションコストはいかなる当事者にも支払われません: XRPは完全に破棄されます。新しいXRPを生成することはできないため、XRPをさらに少なくし、XRPの希少価値を上げることによってXRPのすべての保有者に利益をもたらします。

負荷コストとオープンレジャーコスト

FeeEscalation の改正が有効になった場合、トランザクションコストには2つのしきい値があります:

  • トランザクションコストが rippled サーバーの負荷に基づくトランザクションコストのしきい値を満たしていない場合、サーバーはそのトランザクションを完全に無視します。(このロジックは本質的には改正の有無にかかわらず変更されません。)
  • トランザクションコストが rippled サーバーのオープンレジャーコストのしきい値を満たしていない場合、サーバーはそのトランザクションを後続のレジャーのためにキューに入れます。

これにより、トランザクションは大きく3つのカテゴリに分類されます:

  • 負荷に基づくトランザクションコストによって拒否されるほどのトランザクションコストを指定するトランザクション。
  • 現在のオープンレジャーに含めるのに十分な高いトランザクションコストを指定するトランザクション。
  • 後続のレジャー・バージョンのためにキューに入れられる中間のトランザクション。

ローカル負荷コスト

各 rippled サーバーは、現在の負荷に基づいてコストのしきい値を維持します。rippled サーバーの現在の負荷に基づくトランザクションコストよりも低い手数料の値を持つトランザクションを送信すると、そのサーバーはそのトランザクションを適用も中継もしません。(注: 管理者接続を介してトランザクションを送信する場合、そのサーバーはトランザクションが無負荷の最小トランザクションコストを満たしている限り、そのトランザクションを適用して中継します。)トランザクションは、手数料の値が過半数のサーバーの要件を満たしていない限り、コンセンサス・プロセスで生き残ることは非常に困難です。

オープンレジャーコスト

rippled サーバーには、オープンレジャーコストと呼ばれる、トランザクションコストを実施するための第2の仕組みがあります。トランザクションはXRPのオープンレジャーコスト要件を満たしている場合にのみ、オープンレジャーに含めることができます。オープンレジャーコストを満たさないトランザクションは、代わりに次のレジャーのためにキューに入れられることができます。

新しいレジャー・バージョンごとに、サーバーは、前のレジャーのトランザクション数に基づいて、オープンレジャーに含めるトランザクション数のソフトリミットを選択します。オープンレジャーコストは、オープンレジャーのトランザクション数がソフトリミットに等しくなるまでは、最小の無負荷トランザクションコストと等しくなります。その後は、レジャーに含まれている各トランザクションごとに、レジャーのコストが指数関数的に増加します。次のレジャーについては、現在のレジャーにソフトリミットよりも多くのトランザクションが含まれている場合、サーバーはソフトリミットを増加させ、コンセンサス・プロセスが5秒以上かかる場合はソフトリミットを減少させます。

オープンレジャーコストの要件は、絶対トランザクションコストではなく、トランザクションの通常コストに比例します。マルチサイン・トランザクションのような通常よりも高い要件を持つトランザクションタイプでは、最小トランザクションコスト要件のトランザクションよりも、オープンレジャーコスト要件を満たすためにより多く支払う必要があります。

参照: Fee Escalation explanation in rippled repository.

キューに入れられたトランザクション

rippled がサーバーのローカル負荷コストは満たしているが、オープンレジャーコストを満たしていないトランザクションを受信した場合、そのサーバーはトランザクションが後のトランザクションに「含まれる可能性が高い」かどうかを推定します。可能性が高いと推定した場合、そのサーバーはトランザクションをトランザクションキューに追加し、トランザクションをネットワークの他のメンバーに中継します。そうでない場合、サーバーはそのトランザクションを破棄します。サーバーは、トランザクションが検証されたレジャーに含まれている場合にのみトランザクションコストが適用されるため、トランザクションコストを支払わないトランザクションに起因するネットワーク負荷が最小限に抑えられるように試みます。

現在のオープンレジャーがクローズし、サーバーが新しいオープンレジャーを開始すると、サーバーは新しいオープンレジャーに含めるために、キューからトランザクションを取り込みはじめます。トランザクションキューは、それらのトランザクションのリファレンスコストに比例して、最も高いトランザクションコストを最初に支払うトランザクションでソートされます。同じトランザクションコストを支払うトランザクションは、サーバーが受信した順序でキューに入れられます。

Note: rippled がトランザクションをキューに入れたとき、暫定的なトランザクション・レスポンス・コードは terQUEUED になります。これは、トランザクションが将来成功する可能性があることを意味します。すべての暫定的なレスポンス・コードと同様に、トランザクションの結果は、トランザクションが検証されたレジャーに含まれるか、恒久的に無効となるまで最終的なものではありません。

キューイングの制限

rippled サーバーは、さまざまな経験則を使用して、どのトランザクションが「レジャーに含まれる可能性が高い」か推定します。現在の実装では、次のルールを使用して、キューに入れるトランザクションを決定します:

  • トランザクションは、適切に形成され、有効な署名で承認されなければなりません。
  • AccountTxnID フィールドがあるトランザクションをキューに入れることはできません。
  • 1つの送信アドレスは、同時にキューに入れられたトランザクションを最大で10個持つことができます。トランザクションがキューに入れられるように、送信者は、各トランザクションが送信できるXRPの合計と Fee フィールドの両方を含む、送信者のキューに入れられたすべてのトランザクションのXRPコストを支払うのに十分なXRPを持たなければなりません。New in: rippled 0.32.0
  • トランザクションが、どのように送信アドレスがアカウントを承認するかに影響を与える場合、その背後で同じアドレスからの他のトランザクションはキューに入れられません。New in: rippled 0.32.0
  • トランザクションに LastLedgerSequence フィールドが含まれている場合、そのフィールドの値は少なくとも 現在のレジャーインデックス + 2 でなければなりません。

手数料アベレージング

New in: rippled 0.33.0

送信アドレスに1つ以上のトランザクションがキューイングされている場合、その送信者は、すべてのトランザクションコストを支払うために十分なトランザクションコストで新しいトランザクションを送信することによって、既存のキューに入れられたトランザクションをオープンレジャーに「プッシュ」できます。具体的には、新しいトランザクションは、レジャーに追加された各トランザクションのオープンレジャーコストをカバーするために、新しいトランザクションを含む同じ送信アドレスからキューに登録されたトランザクションの合計トランザクションコストを増やす必要があります。合計には、新しいトランザクションごとの増加したオープンレジャーコストが含まれていなければなりません。トランザクションは依然として他のキューイングの制限に従わなければならず、送信アドレスは、すべてのキューに入れられたトランザクションのトランザクションコストを支払うのに十分なXRPを保有している必要があります。

この機能は、特定の状況を回避するのに役立ちます。キューに入れられた低コストの1つ以上のトランザクションを送信した場合、次のいずれかを行わない限り、同じアドレスから新しいトランザクションを送信することはできません:

上記のいずれも発生しない場合、トランザクションは理論的に無期限にキューに留まることができますが、他の送信者はより高いトランザクションコストでトランザクションを送信することで「カット・イン・ライン(キューに割り込む)」ことができます。署名されたトランザクションは不変なので、キューに入れられたトランザクションのトランザクションコストを増加させて優先度を上げることはできません。以前に送信されたトランザクションを無効にしたくない場合は、手数料アベレージングが回避方法を提供します。補正のために新しいトランザクションのトランザクションコストを増やせば、キューに入れられたトランザクションがすぐにレジャーに含まれるようにすることができます。

リファレンストランザクションコスト

「リファレンス・トランザクション」は、ロード・スケーリング(負荷増加)する前の必要トランザクションコストの点で、最も安価な(無料ではない)トランザクションです。ほとんどのトランザクションは、リファレンス・トランザクションと同じコストです。マルチサイン・トランザクションなどの一部のトランザクションでは、代わりにこのコストの倍数が必要です。オープンレジャーコストが上昇するとき、その要件はそのトランザクションの基本コストに比例します。

手数料レベル

手数料レベルは、最小コストと実際のトランザクションコストの比例差を表します。オープンレジャーコストは、絶対コストではなく手数料レベルで測られます。比較のために次の表を参照してください:

トランザクション 最小コスト(drop) 最小コスト(手数料レベル) 往復コスト(drop) 往復コスト(手数料レベル)
リファレンス・トランザクション(ほとんどのトランザクション) 10 256 20 512
マルチサイン・トランザクション with 4 signatures 50 256 100 512
キーリセット・トランザクション 0 (事実上無限) N/A (事実上無限)

トランザクションコストの問い合わせ

Rippled API には、ローカルの負荷に基づくトランザクションコストを問い合わせする2つの方法があります。server_info コマンド(人間用)と server_state コマンド(マシン用)です。

FeeEscalation の改正が有効な場合、, fee コマンドを利用してオープンレジャーコストを確認することができます。

server_info

server_info コマンドは、validated_ledger.base_fee_xrp として、前のレジャー時点での無負荷の最小XRPコストを10進数のXRPの形式でレポートします。トランザクションを中継するのに必要な実際のコストは、base_fee_xrp の値に、同じレスポンスにあるサーバーの現在の負荷レベルを表す load_factor パラメータを掛けることによって見積もられます。言い換えると:

現在のトランザクションコスト(XRP) = base_fee_xrp × load_factor

server_state

server_state コマンドは、rippled の内部的な負荷計算の直接的な表現を返します。この場合、実効負荷率は、load_base に対する現在の load_factor の比率です。validated_ledger.base_fee パラメータは、XRPから起算した drop で最小トランザクションコストをレポートします。この設計により、サーバー負荷のためのいくらかの微調整の余地はあるものの、rippled は整数演算のみを使用してトランザクションコストを計算することができます。トランザクションコストの実際の計算は次の通りです:

現在のトランザクションコスト(Drop) = (base_fee × load_factor) ÷ load_base

トランザクションコストの指定

署名されたすべてのトランザクションには、Fee フィールドにトランザクションコストが含まれていなければなりません。署名されたトランザクションのすべてのフィールドと同様に、このフィールドは署名を無効にしないと変更できません。

原則として、Ripple Consensus Ledger は、署名されたとおりにトランザクションを実行します。(少なくとも分散コンセンサス・ネットワーク全体で調整して何か他のことをするのは難しいでしょう。)この結果、指定された金額がネットワークのどの部分の現在の最小トランザクションコストをはるかに上回っていても、すべてのトランザクションは Fee フィールドで指定された正確な量のXRPを破棄します。トランザクションコストは、さもなければアカウントの必要準備金のために設定されるであろうXRPを破壊する可能性さえあります。

トランザクションに署名する前に、現在の負荷に基づくトランザクションコストを調べることをお勧めします。ロード・スケーリング(負荷増加)のためにトランザクションコストが高い場合は、それが減少するのを待つことをお勧めします。直ぐにトランザクションを送信するつもりがない場合は、トランザクションコストの将来の負荷に基づく変動を考慮して、わずかに高いトランザクションコストをアカウントに指定することをお勧めします。

トランザクションコストの自動指定

オンラインでトランザクションに署名するときは、Fee フィールドを省略することができます。この場合、rippled または RippleAPI は現在の要件についてピアツーピア・ネットワークの状態をチェックし、トランザクションに署名する前に Fee の値を追加します。ただし、このようにトランザクションコストを自動的に記入することには、いくつかの欠点と制限があります:

  • トランザクションの署名と配信の間にネットワークのトランザクションコストが上昇した場合、トランザクションが承認されないことがあります。
    • 最悪の場合、LastLedgerSequence パラメータが含まれていなければ、同じ Sequence 番号を使用する新しいトランザクションでそのトランザクションをキャンセルするまで、トランザクションは断定的に承認または拒否もされていない状態でスタックする可能性があります。ベストプラクティスについては、reliable transaction submission を参照してください。
  • あなたは、事前に Fee フィールドにどのような値を署名しているか正確には知りません。
    • rippled を使用している場合、sign コマンドの fee_mult_max と fee_div_max パラメータを使用して、署名したいロード・スケーリング(負荷増加)の上限を設定することもできます。
  • オフラインのマシンから現在のトランザクションコストを参照することはできません。
  • マルチサインする際にトランザクションコストを自動的に指定することはできません。

トランザクションコストと失敗したトランザクション

トランザクションコストの目的は、Rippleのピアツーピア・ネットワークを過剰な負荷から保護することであるため、トランザクションが成功するかどうかにかかわらず、ネットワークに配信されるすべてのトランザクションに適用する必要があります。ただし、共有グローバル・レジャーに影響を与えるには、トランザクションを検証されたレジャーに含める必要があります。従って、rippled サーバーは、失敗したトランザクションを tec ステータスコードとともにレジャーに含めるようにします(”tec” は “Transaction Engine – Claimed fee only” を意味します)。

トランザクションコストは、トランザクションが実際に検証されたレジャーに含まれるとき、送信者のXRP残高から差し引かれるだけです。これはトランザクションが成功したとみなされるか、または tec コードで失敗するかに関係なく当てはまります。

トランザクションの失敗が最終的な場合、rippled サーバーはそれをネットワークには中継しません。そのトランザクションは検証されたレジャーに含まれないため、誰のXRP残高に影響を与えることもできません。

不足XRP

rippled サーバーが最初にトランザクションを評価するとき、送信アカウントのXRP残高がXRPトランザクションコストを支払うのに十分でない場合、エラーコード terINSUF_FEE_B でトランザクションが拒否されます。これは ter(Retry)コードなので、rippled サーバーは、トランザクションの結果が最終的になるまで、ネットワークに中継せずにトランザクションを再試行します。

トランザクションが既にネットワークに配信されていても、トランザクションコストを支払うのに十分なXRPがアカウントにない場合、代わりに結果コード tecINSUFF_FEE が発生します。この場合、アカウントは 0 XRP になるまで、支払うことができるすべてのXRPを支払います。これは、rippled が処理中のレジャーに基づいてトランザクションをネットワークに中継するかどうかを決定するために起こりますが、コンセンサス・レジャーを形成するときは、トランザクションが破棄または再発注される可能性があります。

キーリセット・トランザクション

特殊なケースとして、アカウントの lsfPasswordSpent フラグが無効である限り、アカウントはトランザクションコストが 0 の SetRegularKey トランザクションを送信できます。このトランザクションは、アカウントのマスターキー・ペアで署名する必要があります。このトランザクションを送信すると、lsfPasswordSpent フラグが有効になります。

この機能は、レギュラーキーに障害が起きた場合に、障害が起きたアカウントに利用可能なXRPがあるかどうかを心配することなく、アカウントを回復できるように設計されています。これにより、さらに多くのXRPを送る前に、アカウントのコントロールを取り戻すことができます。

lsfPasswordSpent フラグは無効で始まります。マスターキー・ペアで署名された SetRegularKey トランザクションを送信すると有効になります。アカウントがXRPの支払いを受け取ると、再び無効になります。

FeeEscalation 改正が有効になった場合、rippled は、キーリセット・トランザクションの名目上のトランザクションコストがゼロであっても、他のトランザクションよりもキーリセット・トランザクションを優先します。

トランザクションコストの変更

Ripple Consensus Ledger には、XRPの価値の長期的な変動に対して最小トランザクションコストを変更する仕組みがあります。すべての変更は、コンセンサス・プロセスによって承認されなければなりません。詳細については、Fee Voting を参照してください。


注意:

本ドキュメントは、リップル社が公式サイトで公開している『Transaction Cost』を私が個人的に翻訳したものです。注意して頂きたいのは、当方は現役のエンジニアではありませんし、Rippleについての技術的な探求心があるわけでもありません。誤訳などの間違いがあるかもしれないため、公式サイトの英語で書かれた原文もあわせて読むことをお勧めします。