🧐

XRP LedgerのSponsored Fees and Reserves

2024/12/26に公開

はじめに

この記事はXLS-68dとして提案されているSponsored Fees and Reservesを紹介するものです。

原文

この提案はまだ確定しているものではないため、今後変更される可能性があります。

Sponsored Fees and Reserves

概要

ブロックチェーン業界が成長するにつれて、多くのプロジェクトがブロックチェーン上でプロジェクトを行いたいと考え、ブロックチェーンの利用に関する複雑さを抽象化したいと考えています。これはユーザは自分でトランザクションを送信したり、トランザクション手数料を支払う必要がなく、プラットフォームにその複雑さを任せることを意味します。(もちろん、ユーザは自分の鍵を自身で管理します)

また、一部のプロジェクトではユーザをより簡単にオンボーディングしたいと考えており、ユーザが自身のアカウント準備金を支払う必要がなく、また準備金としてXRPを無料でアカウントに譲渡する必要もない方法を求めています(譲渡の方法では悪用された場合にかなり高額になる可能性があります)。

このようなユースケースに対応するため、この提案ではユーザが自身の鍵とアカウントの管理を維持しながら、別のアカウント(例:プラットフォーム)がトランザクション手数料や準備金を代わりに支払うプロセスを追加します。この提案はアカウントとオブジェクトの両方の準備金をサポートします。

他のチェーンでは、同様の機能は"sponsored transactions"、"meta-transactions"、または"relays"と呼ばれることがあります。

1. 概要

アカウントは、トランザクションにスポンサーの署名を含めることができ、これによりスポンサーがトランザクション手数料やトランザクションで作成されるアカウント/オブジェクトの準備金を負担することができます。

私たちは1つのレジャーオブジェクトの変更と1つの新しいトランザクションタイプの追加を提案します。

  • AccountRootレジャーオブジェクト
  • SponsorTransferトランザクションタイプ

また、すべてのレジャーオブジェクトとすべてのトランザクションの共通フィールドも変更されます。

さらに、account_objectsRPCメソッドの変更と、account_sponsoringという新しいRPCメソッドが追加されます。

この機能には暫定的にfeatureSponsorと名付けられたAmendmentが必要になります。

1.1. 用語

  • Sponsor: 別のアカウントに代わって準備金やトランザクション手数料を負担するアカウント。
  • Sponsee: スポンサーがトランザクション手数料や準備金を負担する対象のアカウント。
  • Owner: 特定のオブジェクト(またはアカウント自体)を所有するアカウント。多くの場合、Sponseeと同じ。
  • Sponsored account: スポンサーが準備金を負担するアカウント(現在1XRPに設定)。
  • Sponsored object: スポンサーが準備金を負担するアカウント以外のレジャーオブジェクト(現在0.2XRPに設定)。
  • Sponsor relationship: スポンサーとSponseeの関係。
  • Sponsorship type: スポンサーシップの種類 - トランザクション手数料のスポンサーシップか準備金のスポンサーシップか。

1.2. スポンサーシップのフロー

このシナリオでは、スポンサーのSpencerがSponseeのAliceのトランザクションの手数料や準備金を負担したいと考えています。

  • Aliceはトランザクションを作成し、自動入力(autofill)を行います(手数料やシーケンス番号を含むすべてのフィールドがトランザクションに含まれるようにします)。また、Spencerのアカウントとスポンサーシップタイプをトランザクションに追加します。
  • Spencerはトランザクションに署名し、その署名をAliceに提供します。
  • AliceはSpencerの公開鍵と署名を自身のトランザクションに追加します。
  • Aliceは通常通りトランザクションに署名して送信します。

1.3. スポンサーされたオブジェクトの準備金の回収

このシナリオでは、スポンサーのSpencerが、Aliceのオブジェクトのスポンサーシップによって負担されている準備金を回収したいと考えています。

SpencerはSponsorTransferトランザクションを送信することができ、これにより準備金の負担をAliceに戻すか、別のスポンサーに移すことができます。

1.4. スポンサーされたアカウントの準備金の回収

このシナリオでは、スポンサーのSpencerが、Aliceのアカウントのスポンサーシップから自身の準備金を回収したいと考えています。

これを行うには2つの方法があります。

  • Aliceがアカウントの使用を終了する場合、AccountDeleteトランザクションを送信することができ、これによりアカウントに残っているすべての資金がSpencerに返還されます。
  • Aliceがアカウントの使用を継続したい場合、または別のプロバイダーに切り替えたい場合、AliceまたはSpencerがSponsorTransferトランザクションを送信して、スポンサーシップを解除するか新しいプロバイダーに移転することができます。

2. レジャーオブジェクト: 共通フィールド

2.1. レジャー

現在すべてのレジャーオブジェクトが持つフィールドは以下の通りです。

フィールド名 必須? JSONの型 内部の型
LedgerIndex ✔️ 文字列 Hash256
LedgerEntryType ✔️ 文字列 UInt16
Flags ✔️ 数値 UInt16

以下のフィールドの追加を提案します。

フィールド名 必須? JSONの型 内部の型
SponsorAccount 文字列 AccountID

2.1.1. SponsorAccount

SponsorAccountは、このレジャーオブジェクトの準備金を負担するスポンサーです。

3. レジャーオブジェクト: AccountRoot

3.1. フィールド

参考として、こちらAccountRootレジャーオブジェクトで現在利用可能なフィールドです。

フィールド名 必須? JSONの型 内部の型 説明
Account ✔️ 文字列 AccountID このアカウントの識別アドレス
AccountTxnID 文字列 Hash256 このアカウントが最後に送信したトランザクションの識別ハッシュ
AMMID 文字列 Hash256 このアカウントがAMM疑似アカウントの場合、対応するAMMレジャーエントリーのID
Balance 文字列 Amount アカウントの現在のXRP残高
BurnedNFTokens 数値 UInt32 このアカウントが発行したNFTの合計焼却数
Domain 文字列 Blob このアカウントに関連付けられたドメイン
EmailHash 文字列 Hash128 メールアドレスのmd5ハッシュ
FirstNFTokenSequence 数値 UInt32 アカウントが最初のNFTを発行した時点のシーケンス番号
LedgerEntryType ✔️ 文字列 UInt16 0x0061の値で、文字列AccountRootにマッピングされ、これがAccountRootオブジェクトであることを示す
MessageKey 文字列 Blob このアカウントに暗号化されたメッセージを送信するために使用できる公開鍵
MintedNFTokens 数値 UInt32 このアカウントによって/のために発行されたNFTの総数
NFTokenMinter 文字列 AccountID このアカウントの代わりにNFTを発行できる別のアカウント
OwnerCount ✔️ 数値 UInt32 このアカウントがレジャー上で所有するオブジェクトの数(オブジェクト準備金に影響)
PreviousTxnID ✔️ 文字列 Hash256 このオブジェクトを最後に変更したトランザクションの識別ハッシュ
PreviousTxnLgrSeq ✔️ 数値 UInt32 このオブジェクトを最後に変更したトランザクションを含むレジャーのインデックス
RegularKey 文字列 AccountID マスターキーの代わりにこのアカウントのトランザクションに署名するために使用できるキーペアのアドレス
Sequence ✔️ 数値 UInt32 このアカウントの次の有効なトランザクションのシーケンス番号
TicketCount 数値 UInt32 このアカウントがLedger上で所有するTicketの数
TickSize 数値 UInt8 このアドレスが発行する通貨を含むOfferの為替レートに使用する有効桁数
TransferRate 数値 UInt32 このアカウントが発行した通貨を他のユーザ間で送信する際に課される転送手数料
WalletLocator 文字列 Hash256 ユーザが設定できる任意の256ビット値
WalletSize 数値 UInt32 未使用

以下の追加フィールドを提案します。

フィールド名 必須? JSONの型 内部の型
SponsorAccount 文字列 AccountID
SponsoredOwnerCount 数値 UInt32
SponsoringOwnerCount 数値 UInt32
SponsoringAccountCount 数値 UInt32

3.1.1. SponsorAccount

SponsorAccountフィールドは既にレジャーの共通フィールドで追加されていますが(セクション2.1.1参照)、AccountRootオブジェクトには追加のルールが関連付けられています。

このフィールドは、アカウントがスポンサーによってアカウント準備金が支払われて作成された場合に含まれます。このスポンサーされたアカウントが削除される場合、AccountDeleteトランザクションの送信先はSponsorAccountと一致する必要があり、これによりスポンサーは手数料を回収できます。

注: アカウントがスポンサーされていない場合、AccountDeleteDestinationフィールドは従来通り任意のアカウントに設定できます。

3.1.2. SponsoredOwnerCount

これは、アカウントが所有する、スポンサーによってスポンサーされているオブジェクトの数です。

3.1.3. SponsoringOwnerCount

これは、アカウントが準備金をスポンサーしているオブジェクトの数です。

3.1.4. SponsoringAccountCount

これは、アカウントが準備金をスポンサーしているアカウントの数です。

3.2. アカウントの準備金の計算

既存の準備金の計算は以下の通りです。

acctReserve + objReserve * acct.OwnerCount

この提案によるアカウントの準備金は以下のように計算されるべきです。

(acct.SponsorAccount \: ? \: 0 : acctReserve) + \\\\ objReserve * (acct.OwnerCount + acct.SponsoringOwnerCount - acct.SponsoredOwnerCount) + \\\\ acctReserve * acct.SponsoringAccountCount

4. トランザクション: 共通フィールド

4.1. Fields

参考として、こちらが現在すべてのトランザクションが持つフィールドです。

以下の変更を提案します。

フィールド名 必須? JSONの型 内部の型
Sponsor オブジェクト STObject

4.1.1. Sponsor

Sponsor内部オブジェクトには、トランザクションで発生するスポンサーシップに関するすべての情報が含まれます。

このオブジェクトに含まれるフィールドは以下の通りです。

フィールド名 必須? JSONの型 内部の型
Account ✔️ 文字列 AccountID
Flags ✔️ 数値 UInt16
SigningPubKey 文字列 STBlob
Signature 文字列 STBlob
Signers 配列 STArray
4.1.1.1. Account

Sponsor.Accountフィールドはスポンサーを表します。

このフィールドは署名フィールドとなります(トランザクション署名に含まれます)。

4.1.1.2. Flags

Flagsフィールドにより、ユーザはスポンサーシップタイプを指定できます。Sponsorフィールドがトランザクションに含まれる場合、少なくとも1つのフラグを指定する必要があります

サポートされるフラグ値は次の2つです。

  • 0x00000001: tfSponsorFee、トランザクション手数料のスポンサー(負担)
  • 0x00000002: tfSponsorReserve、トランザクションで作成されるオブジェクト準備金のスポンサー(負担)

このフィールドは署名フィールドとなります(トランザクション署名に含まれます)。

4.1.1.3. SigningPubKeySignature

これらのフィールドは、スポンサーが単一署名で署名する場合に含まれます(マルチシグとは対照的に)。このフィールドには、スポンサーからのトランザクションの署名が含まれ、このトランザクションへの承認を示します。Sponsor.AccountSponsor.Flagsを含むすべての署名フィールドが署名に含まれる必要があります。

最終的なトランザクションにはSignatureまたはSignersのいずれかが含まれている必要があります。

Signatureフィールドの使用に対して追加のトランザクション手数料は必要ありません。

Signatureは署名フィールドではありません(トランザクション署名には含まれませんが、レジャーに保存されるトランザクションには含まれます)。

4.1.1.4. Signers

このフィールドには、スポンサーの署名者からのトランザクションの署名の配列が含まれ、このトランザクションへの承認を示します。Sponsor.AccountSponsor.Flagsを含むすべての署名フィールドが含まれる必要があります。

最終的なトランザクションにはSignatureまたはSignersのいずれかが含まれている必要があります。

Signersフィールドが必要な場合、処理する必要のある追加の署名のため、トランザクションの総手数料は増加します。これはマルチシグの追加手数料と同様です。最小手数料は(\#signatures+1)*base\_feeとなります。

署名の総手数料計算は( 1+\#tx.Signers + \#tx.Sponsor.Signers) * base\_feeとなります。

このフィールドは署名フィールドではありません(トランザクション署名には含まれませんが、レジャーに保存されるトランザクションには含まれます)。

4.2. 失敗条件

4.2.1. 一般的な失敗

  • Sponsor.Signatureが無効
  • Sponsor.Signersが無効(署名者リストがアカウントに存在しない、定足数に達していない、または署名が無効)
  • スポンサーアカウントがレジャー上に存在しない
  • 無効なスポンサーシップフラグが使用されている

4.2.2. 手数料スポンサーシップの失敗

  • スポンサーがトランザクション手数料を支払うのに十分なXRPを持っていない

4.2.3. 準備金スポンサーシップの失敗

  • スポンサーが準備金を支払うのに十分なXRPを持っていない(tecINSUFFICIENT_RESERVE)
  • トランザクションが準備金のスポンサーシップをサポートしていない(セクション4.4参照)

4.3. ステートの変更

4.3. 状態変更

4.3.1. 手数料スポンサーシップの状態変更

手数料はSponseeではなくスポンサーから差し引かれます。以上です。

4.3.2. 準備金スポンサーシップの状態変更

トランザクションの一部として作成される任意のアカウント/オブジェクトにはSponsorフィールドが付与されます。

スポンサーのSponsoringOwnerCountフィールドは、トランザクションの一部としてスポンサーされるオブジェクトの数だけ増加し、SponsoringAccountCountフィールドは、トランザクションの一部として新しくスポンサーされるアカウントの数だけ増加します。

SponseeのSponsoredOwnerCountフィールドは、トランザクションの一部としてスポンサーされるオブジェクトの数だけ増加します。

これらのオブジェクト/アカウントが削除されると、SponsoredOwnerCountSponsoringOwnerCount、およびSponsoringAccountCountフィールドは減少します。

4.4. スポンサーシップをサポートしないトランザクション

すべてのトランザクション(pseudo-transactionを除く)は手数料が必要なため、tfSponsorFeeフラグを使用できます。

しかし、一部のトランザクションはtfSponsorReserveフラグをサポートしません。

  • Batch(XLS-56d)
    • Batch自身がそのフラグをサポートすることには意味がありません。代わりにサブトランザクションがtfSponsorReserveを使用すべきです。
  • すべてのpseudo-transaction(現在はEnableAmendmentSetFee、およびUNLModify)
    • これらのオブジェクトの準備金は特定のアカウントではなく、ネットワークによってカバーされます。

また、AccountSetのような新しいオブジェクトやアカウントを作成しないトランザクションの場合、tfSponsorReserveフラグを使用しても出力に変更はありません。

5. トランザクション: SponsorTransfer

このトランザクションは、特定のレジャーオブジェクトのオブジェクト準備金に対するスポンサー関係を移転します。スポンサー関係は新しいスポンサーに引き継がれるか、完全に解消される(Sponsee本人が準備金を負担する)かのいずれかです。スポンサーまたはSponseeは、いつでもこのトランザクションを送信できます。

5.1. フィールド

フィールド名 必須? JSONの型 内部の型
TransactionType ✔️ 文字列 UInt16
Account ✔️ 文字列 AccountID
LedgerIndex 文字列 UInt256
Sponsor オブジェクト STObject

5.1.1. LedgerIndex

このフィールドは、トランザクションがスポンサーされたアカウントではなくスポンサーされたオブジェクトを扱う場合に含める必要があります。このフィールドは、関係が変更されるオブジェクトを示します。

含まれない場合は、トランザクションを送信するアカウントを指します。

5.1.2. Sponsor

Sponsorフィールドは既にトランザクションの共通フィールドで追加されていますが(セクション4.1.1参照)、SponsorTransferトランザクションには追加のルールが関連付けられています。

SponsortfSponsorReserveフラグと共に含まれる場合、提供されたオブジェクトの準備金スポンサーシップは、レジャーオブジェクトの所有者に戻るのではなく、Sponsor.Accountに移転されます。

Sponsorフィールドがない場合、またはtfSponsorReserveフラグが含まれていない場合、準備金の負担はレジャーオブジェクトの所有者(以前のSponsee)に戻されます。

5.2. スポンサーされたオブジェクトのスポンサーシップの終了

スポンサーされたレジャーオブジェクトにはSponsorフィールドが付与されています。スポンサーされたオブジェクトのスポンサー関係を終了するには、LedgerIndexパラメータが必要で、これによりどのLedgerオブジェクトかを指定します。

スポンサーされたレジャーオブジェクトのスポンサー関係を終了するSponsorTransferを送信できるのはそのオブジェクトのスポンサーまたはそのオブジェクトの所有者(Sponsee)の2つのアカウントです。

5.3. スポンサーシップの新しいアカウントへの移行

スポンサーシップは、tfSponsorReserveフラグと共にSponsorフィールドを含めることで、新しいアカウントに移行できます。これはスポンサーされたアカウントとスポンサーされたレジャーオブジェクトの両方で可能です。

スポンサー関係を移行するSponsorTransferを送信できるのはスポンサーまたはSponseeの2つのアカウントです。

スポンサーがこれを行いたいのは稀でしょう(アカウントを移転する場合など)が、Sponseeはプロバイダーを変更する場合に移行を希望するかもしれません。

5.4. 失敗条件

  • スポンサーシップを移転する場合、新しいスポンサーがこのオブジェクト/アカウントの準備金のための十分なXRPを持っていない。
  • スポンサーシップを解消する場合、所有者がこのオブジェクト/アカウントの準備金のための十分なXRPを持っていない。
  • 新しいスポンサーが存在しない。

5.5. ステートの変更

  • オブジェクトのSponsorフィールドが変更または削除されます。
  • 古いスポンサーのSponsoringOwnerCount/SponsoringAccountCountが1減少します。
  • 新しいスポンサー(該当する場合)のSponsoringOwnerCount/SponsoringAccountCountが1増加します。
  • 新しいスポンサーがいない場合、所有者のSponsoredOwnerCountが1減少します。

6. RPC: account_objects

6.1. フィールド

account_objects RPCメソッドは既にXRP Ledgerに存在します。参考として、account_objectsが現在受け付けるフィールドは以下の通りです。

フィールド名 必須? JSONの型
account ✔️ 文字列
deletion_blockers_only 真偽値
ledger_hash 文字列
ledger_index 数値または文字列
limit 数値
marker 任意
type 文字列

以下の追加フィールドを提案します。

フィールド名 必須? JSONの型
sponsored 真偽値

6.2. sponsored

このフィールドが除外された場合、スポンサーされているかどうかに関わらずすべてのオブジェクトが含まれます。sponsored == trueの場合、スポンサーされたオブジェクトのみが含まれます。sponsored == falseの場合、スポンサーされていないオブジェクトのみが含まれます。

7. RPC: account_sponsoring

account_sponsoring RPCメソッドは、アカウントがスポンサーとなっているオブジェクトのリストを取得するために使用されます。具体的には、SponsorAccountが指定されたアカウントであるオブジェクトのリストです。これはaccount_objectsメソッドと非常によく似たAPIを持っています。

フィールド名 必須? JSONの型 説明
account ✔️ 文字列 対象となるスポンサー
deletion_blockers_only 真偽値 trueの場合、このアカウントの削除をブロックするオブジェクトのみがレスポンスに含まれます。デフォルトはfalseです
ledger_hash 文字列 使用するレジャーバージョンを表すハッシュ
ledger_index 数値または文字列 使用するレジャーインデックス、またはレジャーを自動的に選択するためのショートカット文字列
limit 数値 結果に含めるオブジェクトの最大数
marker 任意 以前のページネーションレスポンスからの値。そのレスポンスの続きからデータの取得を再開します
type 文字列 レジャーエントリータイプによる結果のフィルタリング。例えばofferescrowなど

8. セキュリティ

8.1. セキュリティの原則

Sponseeとスポンサーの両方がスポンサー関係を結ぶことに同意する必要があります。Sponseeはスポンサーが準備金を扱うことを了承し、スポンサーはその準備金を引き受けることを承諾する必要があります。両者からの署名により、これが確保されます。

スポンサーは、もはや支援したくないSponseeのアカウントやオブジェクトのスポンサーシップに縛られることはありません。なぜなら、いつでもSponsorTransferトランザクションを送信できるからです。

スポンサーの署名には常にAccountSequenceフィールドが含まれている必要があります。これは署名のリプレイ攻撃(スポンサーの署名が、スポンサーが支援を望まないオブジェクトやアカウントに再利用される)を防ぐためです。

トランザクション手数料をスポンサーする場合、スポンサーはトランザクションのFee値を承認する必要があります。これは、スポンサーが支払う金額だからです。

準備金をスポンサーする場合、スポンサーの署名には、アカウント/オブジェクトの準備金に関わる可能性のあるトランザクションのすべての側面が含まれている必要があります。これには、PaymentトランザクションのDestinationフィールド(および新規アカウントかどうか)や、TicketCreateトランザクションのTicketSequenceフィールド(作成されるTicketオブジェクトの数を決定し、それぞれがオブジェクト準備金を必要とする)が含まれます。

Sponseeはスポンサーの寛容さを悪用することはできません。なぜなら、スポンサーはレジャーオブジェクトのスポンサーになりたいすべてのトランザクションに署名する必要があるからです。また、Sponseeはスポンサーが望むスポンサーシップタイプを変更することはできません。これは、スポンサーのXRPを最大50まで拘束する可能性があるためです(1つのTicketCreateトランザクションで250枚のチケットが作成される場合)。

スコープ外の原則: Sponseeはスポンサーシップの移転に対して制御権を持ちません。これは、借り手が銀行による住宅ローンの他社への売却や、貸し手による債権回収会社への債権売却を制御できないのと同様です。

8.2. 署名

手数料スポンサーシップはFeeフィールドを承認する必要があり、準備金スポンサーシップは広範なトランザクションフィールドを承認する必要があるため、スポンサーは常にトランザクション全体に署名する必要があります。これにより、異なるスポンサーシップタイプに対して異なるスポンサーシッププロセスを持つ必要もなくなります。これにはSponsorオブジェクトの非署名部分(Sponsor.AccountSponsor.Flags)も含まれます。Sponseeのトランザクション署名についても同様です。Sponseeはスポンサーとスポンサーシップタイプを承認する必要があります。

スポンサーのSignatureは、別のトランザクションに再利用または添付することはできません。なぜなら、トランザクション全体(AccountSequence値を含む)に署名する必要があるからです。

9. 不変条件

不変条件は、XRPLの有効なすべてのステートの変更に対して常に真でなければならない文(通常は方程式)です。不変条件チェックはバグに対する最後の防衛線として機能します。不変条件が違反された場合(理想的には決して起こらないはず)、tecINVARIANT_FAILEDエラーがスローされます。

9.1. Owner Countの追跡

レジャーオブジェクトを作成するトランザクションは、アカウントのOwnerCountを1増加させるか、2つの別々のアカウントのSponsoringOwnerCountSponsoredOwnerCountを1増加させます。レジャーオブジェクトが削除される場合は、その逆が起こります。

SponsoringAccountCountについても同様のことが起こります。

9.2. SponsoredOwnerCountSponsoringOwnerCountのバランス

\\sum\_{accounts} Account.SponsoredOwnerCount = \\sum\_{accounts} Account.SponsoringOwnerCount

言い換えると、すべてのアカウントのSponsoredOwnerCountの合計は、すべてのアカウントのSponsoringOwnerCountの合計と等しくなければなりません。これにより、スポンサーされている各オブジェクトがスポンサーされているとして記録され、かつスポンサーを持っていることが保証されます。

10. 実装例

各例では、スポンサーとSponseeの両方がトランザクションに署名する前と後の両方のトランザクションの状態を示します。

未署名のトランザクションは、スポンサーに渡される前に自動入力(autofill)される必要があります。ツールは、マルチシグのためのヘルパー関数と同様に、スポンサーとSponseeの署名を組み合わせるように更新できます。

10.1. 手数料スポンサーシップ

10.1.1. 未署名のトランザクション

{
  TransactionType: "Payment",
  Account: "rOldB3E44wS6SM7KL3T3b6nHX3Jjua62wg",
  Destination: "rNewfcu9RJa5W1ncAuEgLH1Xpi4j1vzXjr",
  Amount: "20000000",
  Sequence: 3,
  Fee: "10",
  Sponsor: {
    Account: "rSponsor1VktvzBz8JF2oJC6qaww6RZ7Lw",
    Flags: 1
  }
}

10.1.2. 署名済みのトランザクション

{
  TransactionType: "Payment",
  Account: "rSender7NwD9vmNf5dvTbW4FQDNSRsfPv6",
  Destination: "rDestinationT6N5fJdaHnRqLpW1D8oFrZ",
  Amount: "20000000",
  Sequence: 3,
  Fee: "10",
  Sponsor: {
    Account: "rSponsor1VktvzBz8JF2oJC6qaww6RZ7Lw",
    Flags: 1,
    SigningPubKey: "03072BBE5F93D4906FC31A690A2C269F2B9A56D60DA9C2C6C0D88FB51B644C6F94", // rSponsor's public key
    Signature: "3045022100C15AFB7C0C4F5EDFEC4667B292DAB165B96DAF3FFA6C7BBB3361E9EE19E04BC70220106C04B90185B67DB2C67864EB0A11AE6FB62280588954C6E4D9C1EF3710904D"
  },
  SigningPubKey: "03A8D0093B0CD730F25E978BF414CA93084B3A2CBB290D5E0E312021ED2D2C1C8B", // rAccount's public key
  TxnSignature: "3045022100F2AAF90D8F9BB6C94C0C95BA31E320FC601C7BAFFF536CC07076A2833CB4C7FF02203F3C76EB34ABAD61A71CEBD42307169CDA65D9B3CA0EEE871210BEAB824E524B"
}

10.2. アカウントスポンサーシップ

アカウントを作成する唯一の方法はPaymentトランザクションを通じてです。そのため、スポンサー関係はPaymentトランザクション上で開始される必要があります。

10.2.1. 未署名のトランザクション

{
  TransactionType: "Payment",
  Account: "rOldB3E44wS6SM7KL3T3b6nHX3Jjua62wg",
  Destination: "rNewfcu9RJa5W1ncAuEgLH1Xpi4j1vzXjr",
  Amount: "20000000",
  Sequence: 3,
  Fee: "10",
  Sponsor: {
    Account: "rSponsor1VktvzBz8JF2oJC6qaww6RZ7Lw",
    Flags: 2
  }
}

10.2.2. 署名済みのトランザクション

{
  TransactionType: "Payment",
  Account: "rOldB3E44wS6SM7KL3T3b6nHX3Jjua62wg",
  Destination: "rNewfcu9RJa5W1ncAuEgLH1Xpi4j1vzXjr",
  Amount: "20000000",
  Sequence: 3,
  Fee: "10",
  Sponsor: {
    Account: "rSponsor1VktvzBz8JF2oJC6qaww6RZ7Lw",
    Flags: 2,
    SigningPubKey: "03072BBE5F93D4906FC31A690A2C269F2B9A56D60DA9C2C6C0D88FB51B644C6F94", // rSponsor's public key
    Signature: "30440220702ABC11419AD4940969CC32EB4D1BFDBFCA651F064F30D6E1646D74FBFC493902204E5B451B447B0F69904127F04FE71634BD825A8970B9467871DA89EEC4B021F8"
  },
  SigningPubKey: "03BC74CA0B765281E31E342017D97B3F6743A05FBA23D2114B98FC8AD26D92856C", // rAccount's public key
  TxnSignature: "30440220245217F931FDA0C5E68B935ABB4920211D5B6182878583124DE4663B19F00BEC022070BE036264760551CF40E9DAFC8B84036FA70E7EE7257BB7E39AEB7354B2EB86"
}

10.3. オブジェクトスポンサーシップ

10.3.1. 未署名のトランザクション

{
  TransactionType: "TicketCreate",
  Account: "rAccount4yjv1j2x79wXxRVXnFbwsjUWXo",
  TicketCount: 100,
  Sequence: 3,
  Fee: "10",
  Sponsor: {
    Account: "rSponsor1VktvzBz8JF2oJC6qaww6RZ7Lw",
    Flags: 2
  }
}

10.3.2. 署名済みのトランザクション

{
  TransactionType: "TicketCreate",
  Account: "rAccount4yjv1j2x79wXxRVXnFbwsjUWXo",
  TicketCount: 100,
  Sequence: 3,
  Fee: "10",
  Sponsor: {
    Account: "rSponsor1VktvzBz8JF2oJC6qaww6RZ7Lw",
    Flags: 2,
    SigningPubKey: "03072BBE5F93D4906FC31A690A2C269F2B9A56D60DA9C2C6C0D88FB51B644C6F94", // rSponsor's public key
    Signature: "30450221009878F3A321250341886FE344E0B50700C8020ABAA25301925BD84DDB5421D432022002A3C72C54BACB5E7DAEC48E2A1D75DCBB8BA3B2212C7FC22F070CCABAF76EC1"
  },
  SigningPubKey: "03BC74CA0B765281E31E342017D97B3F6743A05FBA23D2114B98FC8AD26D92856C", // rAccount's public key
  TxnSignature: "3044022047CB72DA297B067C0E69045B7828AD660F8198A6FA03982E31CB6D27F0946DDE022055844EB63E3BFF7D9ABFB26645AA4D2502E143F4ABEE2DE57EB87A1E5426E010"
}

付録

付録A: よくある質問

A.1: Sponseeは準備金のためのXRPを受け取りますか?

いいえ、スポンサーシップ関係ではXRPの移転は発生しません。XRPはスポンサーのアカウントに留まります。そのオブジェクト/アカウントの準備金の負担がスポンサーに移転されるだけです。

A.2: スポンサーされたオブジェクトを持っている状態でアカウントを削除しようとするとどうなりますか?

アカウント自体がスポンサーされている場合、削除できますが、AccountDeleteトランザクションの送信先(つまり、残りのXRPの行き先)は必ずスポンサーのアカウントでなければなりません。これにより、スポンサーが準備金を取り戻すことができ、Sponseeがそれらの資金を持ち逃げすることを防ぎます。

Sponseeがまだスポンサーされているオブジェクトを持っている場合、それらのオブジェクトは削除ブロッカーのルールに従います。スポンサーされているかどうかは関係ありません。

スポンサーされているオブジェクトが削除された場合(通常のオブジェクト削除プロセスによる場合や、削除ブロッカーではないオブジェクトの場合は所有者アカウントが削除された場合)、スポンサーの準備金は再び利用可能になります。

A.3: いくつかのオブジェクトをスポンサーしているスポンサーがアカウントを削除したい場合はどうなりますか?

アカウントは、いずれかの既存のアカウントやオブジェクトをスポンサーしている場合、削除できません。それらのオブジェクトを削除する(ように所有者に依頼する)か、SponsorTransferトランザクションを使用して制御を放棄する必要があります。

A.4: スポンサーは、準備金を支払っているオブジェクトに対して何か権限を持っていますか?例えば、オブジェクトを削除できますか?

いいえ。スポンサーがオブジェクトのサポートを継続したくない場合は、代わりにSponsorTransferトランザクションを使用できます。

A.5: スポンサーがアカウントのサポートを停止したい場合に、Sponseeがアカウントの削除を拒否した場合はどうなりますか?

スポンサーは債務者に連絡を取って支払いを求める一般的な問題に直面することになります。Sponseeが支払いのためのXRPを十分に持っている場合は、SponsorTransferトランザクションを使用してSponseeに負担を移すことができます。

A.6: スポンサーがSponsorTransferを試みたが、Sponseeが準備金をカバーするのに十分な資金を持っていない場合はどうなりますか?

スポンサーが本当に急いでスポンサー関係から抜け出す必要があり、準備金の価値を取り戻すことを諦める場合は、Sponseeに準備金をカバーするのに必要なXRPを支払うことができます。これらのステップはBatchトランザクションを通じてアトミックに実行でき、SponseeがSponsorTransferトランザクションが検証される前に資金を他の目的に使用することを防ぐことができます。

A.7: スポンサーされたアカウントはより低い準備金を持ちますか?

いいえ、現在のレベルで1XRPの準備金を持ち続けます。

A.8: 既存のスポンサーされていないレジャーオブジェクトやアカウントをスポンサーされたレジャーオブジェクトやアカウントにできますか?

はい、SponsorTransferトランザクションを使用して可能です。

A.9: スポンサーされたアカウントが他のアカウント/オブジェクトのスポンサーになることはできますか?

いいえ。

A.10: スポンサーされたアカウントはスポンサーされていないオブジェクトや、異なるスポンサーによってスポンサーされたオブジェクトを保持できますか?

はい。

A.11: 同じトランザクションに対して、トランザクション手数料と準備金で異なるスポンサーを持ちたい場合はどうしますか?

この提案ではサポートされません。このニーズがある場合は、ユースケースの例を提供してください。

A.12: トランザクションに2つの署名を追加するのは難しいのではないでしょうか?

これは良いツールで解決できる問題です。マルチシグが様々なツールでサポートされているのと同様に機能する可能性があります。

A.13: なぜ[他のデザイン]ではなくこのデザインなのですか?

検討された代替デザインとこのデザインが選ばれた理由については付録Bをご覧してください。他のデザインをお考えの場合は、コメントで説明していただければ議論できます。

A.14: このアカウントスポンサーシップモデルはXLS-23d、Liteアカウントとどう違う/優れているのですか?

  • スポンサーされたアカウントには制限がなく、オブジェクトを保持できます。
  • スポンサーされたアカウントは通常のアカウントと同じ準備金を必要とします(これはLiteアカウント提案への反対意見の1つでした)。
  • Liteアカウントはスポンサーによって削除できます。

A.15: 複数のアカウントが準備金を保持する可能性のあるトラストラインのようなオブジェクトの場合、これはどのように機能しますか?

この質問への回答はまだ検討中です。考えられる解決策の1つは、他の準備金を処理するために2番目のフィールドSponsor2を追加することです。

A.16: この提案はXLS-49dとどのように連携しますか?どの署名者リストが手数料や準備金をスポンサーする権限を持ちますか?

現在、グローバル署名者リストのみがサポートされています。スポンサーシップをサポートするために別のSignerListID値を追加することができます。トランザクション値はTransactionTypeフィールドがUInt16であるため2^{16}までしか使用できませんが、SignerListIDフィールドは2^{32}まで使用できるため、特定のトランザクションタイプに相関しない追加の値のためのスペースがデザインにあります。

付録B: 代替の設計

B.1: アカウントにSponsorを追加する

このデザインでは、ユーザがアカウントにSponsorを追加できるようにAccountSetを更新することを含んでいました(スポンサーからの署名も必要)。スポンサーは、そのフィールドがアクティブな間、そのアカウントからのすべてのオブジェクトをスポンサーすることになり、スポンサーまたはアカウントはいつでもスポンサーシップを解除できました。

これは仕様の以前のバージョンでしたが、関係をトランザクション/トランザクション固有にする方が理にかなっていました。これにより、乱用を防ぐことができます(スポンサーは、サポートしたいオブジェクトとサポートしたくないオブジェクトを決定できます)。

現在のデザインは、異なるオブジェクトに対して異なるスポンサーを持つことも可能にし、ユーザが1つのサービスやプラットフォームにロックインされるのではなく、幅広いサービスやプラットフォームを使用できるようにします。

B.2: ラッパートランザクション

スポンサーが署名するXLS-56dBatchに似たラッパートランザクション(仮称Relay)があり、Sponseeからのサブトランザクションを含むというデザインでした。

以下のような形になります。

フィールド名 必須? JSONの 内部の型
TransactionType ✔️ 文字列 UInt16
Account ✔️ 文字列 STAccount
Fee ✔️ 文字列 STAmount
Transaction ✔️ オブジェクト STTx

これは仕様の以前のバージョンの一部でした(Stellarのサンドイッチトランザクションデザインによって着想を得ました)が、既存のデザインの方がよりクリーンに感じられました。実装の観点からは、手数料支払者を既存のトランザクションの一部として持つ方が、ラッパートランザクションの一部として持つよりも簡単です。その情報をスタックの下層に渡す必要があるためです。また、ラッパートランザクションのパラダイムはXLS-56dで使用されますが、rippledコードでのフローが複雑になるため、必要な場合にのみ慎重に使用すべきです。

さらに、署名プロセスが複雑になります(XLS-56dの開発過程で発見されたように)。ラッパートランザクションに含めずに、スポンサーが署名済みのトランザクションをそのままネットワークに送信することを何らかの方法で防ぐ必要があります。

B.3: 作成-承認-キャンセルのフロー

このデザインの大まかなアイデアは、スポンサーが既存のオブジェクトの準備金を引き受けることができる新しい一連のトランザクション(例: SponsorCreate/SponsorAccept/SponsorCancel/SponsorFinish)を持つことでした。

このデザインは真剣に検討されませんでした。複雑すぎると感じられ、いくつかの新しいトランザクションを導入する必要があったためです。また、オブジェクト作成時にスポンサーを追加することをサポートしていませんでした。これは、所有者/Sponseeが一時的に準備金のためのXRPを保持する必要がないため、よりスムーズなUXを提供します。

Discussion